src/station_cmd.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6870 ca3fd1fbe311
child 6872 1c4a4a609f85
equal deleted inserted replaced
6870:ca3fd1fbe311 6871:5a9dc001e1ad
    42 #include "road.h"
    42 #include "road.h"
    43 #include "cargotype.h"
    43 #include "cargotype.h"
    44 #include "strings.h"
    44 #include "strings.h"
    45 #include "autoslope.h"
    45 #include "autoslope.h"
    46 #include "newgrf_fsmports.h"
    46 #include "newgrf_fsmports.h"
       
    47 #include "transparency.h"
       
    48 #include "water.h"
    47 
    49 
    48 DEFINE_OLD_POOL_GENERIC(Station, Station)
    50 DEFINE_OLD_POOL_GENERIC(Station, Station)
    49 DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop)
    51 DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop)
    50 
    52 
    51 
    53 
   152 
   154 
   153 	return num;
   155 	return num;
   154 }
   156 }
   155 
   157 
   156 
   158 
   157 /* Calculate the radius of the station. Basicly it is the biggest
   159 /** Calculate the radius of the station. Basicly it is the biggest
   158  *  radius that is available within the station */
   160  *  radius that is available within the station
       
   161  * @param st Station to query
       
   162  * @return the so calculated radius
       
   163  */
   159 static uint FindCatchmentRadius(const Station* st)
   164 static uint FindCatchmentRadius(const Station* st)
   160 {
   165 {
   161 	uint ret = CA_NONE;
   166 	uint ret = CA_NONE;
   162 
   167 
   163 	if (st->bus_stops   != NULL) ret = max<uint>(ret, CA_BUS);
   168 	if (st->bus_stops   != NULL) ret = max<uint>(ret, CA_BUS);
   283 	return false;
   288 	return false;
   284 }
   289 }
   285 
   290 
   286 #define M(x) ((x) - STR_SV_STNAME)
   291 #define M(x) ((x) - STR_SV_STNAME)
   287 
   292 
       
   293 enum StationNaming {
       
   294 	STATIONNAMING_RAIL = 0,
       
   295 	STATIONNAMING_ROAD = 0,
       
   296 	STATIONNAMING_AIRPORT,
       
   297 	STATIONNAMING_OILRIG,
       
   298 	STATIONNAMING_DOCK,
       
   299 	STATIONNAMING_BUOY,
       
   300 	STATIONNAMING_HELIPORT,
       
   301 };
       
   302 
   288 static bool GenerateStationName(Station *st, TileIndex tile, int flag)
   303 static bool GenerateStationName(Station *st, TileIndex tile, int flag)
   289 {
   304 {
   290 	static const uint32 _gen_station_name_bits[] = {
   305 	static const uint32 _gen_station_name_bits[] = {
   291 		0,                                      /* 0 */
   306 		0,                                      /* 0 */
   292 		1 << M(STR_SV_STNAME_AIRPORT),          /* 1 */
   307 		1 << M(STR_SV_STNAME_AIRPORT),          /* 1 */
   308 			if (s != st && s->town == t) {
   323 			if (s != st && s->town == t) {
   309 				uint str = M(s->string_id);
   324 				uint str = M(s->string_id);
   310 				if (str <= 0x20) {
   325 				if (str <= 0x20) {
   311 					if (str == M(STR_SV_STNAME_FOREST))
   326 					if (str == M(STR_SV_STNAME_FOREST))
   312 						str = M(STR_SV_STNAME_WOODS);
   327 						str = M(STR_SV_STNAME_WOODS);
   313 					CLRBIT(free_names, str);
   328 					ClrBit(free_names, str);
   314 				}
   329 				}
   315 			}
   330 			}
   316 		}
   331 		}
   317 	}
   332 	}
   318 
   333 
   322 		found = FindFirstBit(tmp);
   337 		found = FindFirstBit(tmp);
   323 		goto done;
   338 		goto done;
   324 	}
   339 	}
   325 
   340 
   326 	/* check mine? */
   341 	/* check mine? */
   327 	if (HASBIT(free_names, M(STR_SV_STNAME_MINES))) {
   342 	if (HasBit(free_names, M(STR_SV_STNAME_MINES))) {
   328 		if (CountMapSquareAround(tile, CMSAMine) >= 2) {
   343 		if (CountMapSquareAround(tile, CMSAMine) >= 2) {
   329 			found = M(STR_SV_STNAME_MINES);
   344 			found = M(STR_SV_STNAME_MINES);
   330 			goto done;
   345 			goto done;
   331 		}
   346 		}
   332 	}
   347 	}
   333 
   348 
   334 	/* check close enough to town to get central as name? */
   349 	/* check close enough to town to get central as name? */
   335 	if (DistanceMax(tile, t->xy) < 8) {
   350 	if (DistanceMax(tile, t->xy) < 8) {
   336 		found = M(STR_SV_STNAME);
   351 		found = M(STR_SV_STNAME);
   337 		if (HASBIT(free_names, M(STR_SV_STNAME))) goto done;
   352 		if (HasBit(free_names, M(STR_SV_STNAME))) goto done;
   338 
   353 
   339 		found = M(STR_SV_STNAME_CENTRAL);
   354 		found = M(STR_SV_STNAME_CENTRAL);
   340 		if (HASBIT(free_names, M(STR_SV_STNAME_CENTRAL))) goto done;
   355 		if (HasBit(free_names, M(STR_SV_STNAME_CENTRAL))) goto done;
   341 	}
   356 	}
   342 
   357 
   343 	/* Check lakeside */
   358 	/* Check lakeside */
   344 	if (HASBIT(free_names, M(STR_SV_STNAME_LAKESIDE)) &&
   359 	if (HasBit(free_names, M(STR_SV_STNAME_LAKESIDE)) &&
   345 			DistanceFromEdge(tile) < 20 &&
   360 			DistanceFromEdge(tile) < 20 &&
   346 			CountMapSquareAround(tile, CMSAWater) >= 5) {
   361 			CountMapSquareAround(tile, CMSAWater) >= 5) {
   347 		found = M(STR_SV_STNAME_LAKESIDE);
   362 		found = M(STR_SV_STNAME_LAKESIDE);
   348 		goto done;
   363 		goto done;
   349 	}
   364 	}
   350 
   365 
   351 	/* Check woods */
   366 	/* Check woods */
   352 	if (HASBIT(free_names, M(STR_SV_STNAME_WOODS)) && (
   367 	if (HasBit(free_names, M(STR_SV_STNAME_WOODS)) && (
   353 				CountMapSquareAround(tile, CMSATree) >= 8 ||
   368 				CountMapSquareAround(tile, CMSATree) >= 8 ||
   354 				CountMapSquareAround(tile, CMSAForest) >= 2)
   369 				CountMapSquareAround(tile, CMSAForest) >= 2)
   355 			) {
   370 			) {
   356 		found = _opt.landscape == LT_TROPIC ?
   371 		found = _opt.landscape == LT_TROPIC ?
   357 			M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS);
   372 			M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS);
   362 	{
   377 	{
   363 		uint z = GetTileZ(tile);
   378 		uint z = GetTileZ(tile);
   364 		uint z2 = GetTileZ(t->xy);
   379 		uint z2 = GetTileZ(t->xy);
   365 		if (z < z2) {
   380 		if (z < z2) {
   366 			found = M(STR_SV_STNAME_VALLEY);
   381 			found = M(STR_SV_STNAME_VALLEY);
   367 			if (HASBIT(free_names, M(STR_SV_STNAME_VALLEY))) goto done;
   382 			if (HasBit(free_names, M(STR_SV_STNAME_VALLEY))) goto done;
   368 		} else if (z > z2) {
   383 		} else if (z > z2) {
   369 			found = M(STR_SV_STNAME_HEIGHTS);
   384 			found = M(STR_SV_STNAME_HEIGHTS);
   370 			if (HASBIT(free_names, M(STR_SV_STNAME_HEIGHTS))) goto done;
   385 			if (HasBit(free_names, M(STR_SV_STNAME_HEIGHTS))) goto done;
   371 		}
   386 		}
   372 	}
   387 	}
   373 
   388 
   374 	/* check direction compared to town */
   389 	/* check direction compared to town */
   375 	{
   390 	{
   412 	}
   427 	}
   413 
   428 
   414 	return best_station;
   429 	return best_station;
   415 }
   430 }
   416 
   431 
   417 // Update the virtual coords needed to draw the station sign.
   432 /** Update the virtual coords needed to draw the station sign.
   418 // st = Station to update for.
   433  * @param st Station to update for.
       
   434  */
   419 static void UpdateStationVirtCoord(Station *st)
   435 static void UpdateStationVirtCoord(Station *st)
   420 {
   436 {
   421 	Point pt = RemapCoords2(TileX(st->xy) * TILE_SIZE, TileY(st->xy) * TILE_SIZE);
   437 	Point pt = RemapCoords2(TileX(st->xy) * TILE_SIZE, TileY(st->xy) * TILE_SIZE);
   422 
   438 
   423 	pt.y -= 32;
   439 	pt.y -= 32;
   426 	SetDParam(0, st->index);
   442 	SetDParam(0, st->index);
   427 	SetDParam(1, st->facilities);
   443 	SetDParam(1, st->facilities);
   428 	UpdateViewportSignPos(&st->sign, pt.x, pt.y, STR_305C_0);
   444 	UpdateViewportSignPos(&st->sign, pt.x, pt.y, STR_305C_0);
   429 }
   445 }
   430 
   446 
   431 // Update the virtual coords needed to draw the station sign for all stations.
   447 /** Update the virtual coords needed to draw the station sign for all stations. */
   432 void UpdateAllStationVirtCoord()
   448 void UpdateAllStationVirtCoord()
   433 {
   449 {
   434 	Station* st;
   450 	Station* st;
   435 
   451 
   436 	FOR_ALL_STATIONS(st) {
   452 	FOR_ALL_STATIONS(st) {
   451 	st->MarkDirty();
   467 	st->MarkDirty();
   452 	UpdateStationVirtCoord(st);
   468 	UpdateStationVirtCoord(st);
   453 	st->MarkDirty();
   469 	st->MarkDirty();
   454 }
   470 }
   455 
   471 
   456 // Get a mask of the cargo types that the station accepts.
   472 /** Get a mask of the cargo types that the station accepts.
       
   473  * @param st Station to query
       
   474  * @return the expected mask
       
   475  */
   457 static uint GetAcceptanceMask(const Station *st)
   476 static uint GetAcceptanceMask(const Station *st)
   458 {
   477 {
   459 	uint mask = 0;
   478 	uint mask = 0;
   460 
   479 
   461 	for (CargoID i = 0; i < NUM_CARGO; i++) {
   480 	for (CargoID i = 0; i < NUM_CARGO; i++) {
   462 		if (HASBIT(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << i;
   481 		if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << i;
   463 	}
   482 	}
   464 	return mask;
   483 	return mask;
   465 }
   484 }
   466 
   485 
   467 // Items contains the two cargo names that are to be accepted or rejected.
   486 /** Items contains the two cargo names that are to be accepted or rejected.
   468 // msg is the string id of the message to display.
   487  * msg is the string id of the message to display.
       
   488  */
   469 static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg)
   489 static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg)
   470 {
   490 {
   471 	for (uint i = 0; i < num_items; i++) {
   491 	for (uint i = 0; i < num_items; i++) {
   472 		SetDParam(i + 1, GetCargo(cargo[i])->name);
   492 		SetDParam(i + 1, GetCargo(cargo[i])->name);
   473 	}
   493 	}
   474 
   494 
   475 	SetDParam(0, st->index);
   495 	SetDParam(0, st->index);
   476 	AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0);
   496 	AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0);
   477 }
   497 }
   478 
   498 
   479 // Get a list of the cargo types being produced around the tile.
   499 /**
       
   500 * Get a list of the cargo types being produced around the tile (in a rectangle).
       
   501 * @param produced: Destination array of produced cargo
       
   502 * @param tile: Center of the search area
       
   503 * @param w: Width of the center
       
   504 * @param h: Height of the center
       
   505 * @param rad: Radius of the search area
       
   506 */
   480 void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile,
   507 void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile,
   481 	int w, int h, int rad)
   508 	int w, int h, int rad)
   482 {
   509 {
   483 	memset(produced, 0, sizeof(AcceptedCargo));
   510 	memset(produced, 0, sizeof(AcceptedCargo));
   484 
   511 
   485 	int x = TileX(tile);
   512 	int x = TileX(tile);
   486 	int y = TileY(tile);
   513 	int y = TileY(tile);
   487 
   514 
   488 	// expand the region by rad tiles on each side
   515 	/* expand the region by rad tiles on each side
   489 	// while making sure that we remain inside the board.
   516 	 * while making sure that we remain inside the board. */
   490 	int x2 = min(x + w + rad, MapSizeX());
   517 	int x2 = min(x + w + rad, MapSizeX());
   491 	int x1 = max(x - rad, 0);
   518 	int x1 = max(x - rad, 0);
   492 
   519 
   493 	int y2 = min(y + h + rad, MapSizeY());
   520 	int y2 = min(y + h + rad, MapSizeY());
   494 	int y1 = max(y - rad, 0);
   521 	int y1 = max(y - rad, 0);
   498 	assert(w > 0);
   525 	assert(w > 0);
   499 	assert(h > 0);
   526 	assert(h > 0);
   500 
   527 
   501 	for (int yc = y1; yc != y2; yc++) {
   528 	for (int yc = y1; yc != y2; yc++) {
   502 		for (int xc = x1; xc != x2; xc++) {
   529 		for (int xc = x1; xc != x2; xc++) {
   503 			if (!(IS_INSIDE_1D(xc, x, w) && IS_INSIDE_1D(yc, y, h))) {
   530 			if (!(IsInsideBS(xc, x, w) && IsInsideBS(yc, y, h))) {
   504 				TileIndex tile = TileXY(xc, yc);
   531 				TileIndex tile = TileXY(xc, yc);
   505 
   532 
   506 				GetProducedCargoProc *gpc = _tile_type_procs[GetTileType(tile)]->get_produced_cargo_proc;
   533 				GetProducedCargoProc *gpc = _tile_type_procs[GetTileType(tile)]->get_produced_cargo_proc;
   507 				if (gpc != NULL) {
   534 				if (gpc != NULL) {
   508 					CargoID cargos[2] = { CT_INVALID, CT_INVALID };
   535 					CargoID cargos[2] = { CT_INVALID, CT_INVALID };
   518 			}
   545 			}
   519 		}
   546 		}
   520 	}
   547 	}
   521 }
   548 }
   522 
   549 
   523 // Get a list of the cargo types that are accepted around the tile.
   550 /**
       
   551 * Get a list of the cargo types that are accepted around the tile.
       
   552 * @param accepts: Destination array of accepted cargo
       
   553 * @param tile: Center of the search area
       
   554 * @param w: Width of the center
       
   555 * @param h: Height of the center
       
   556 * @param rad: Radius of the rectangular search area
       
   557 */
   524 void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile,
   558 void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile,
   525 	int w, int h, int rad)
   559 	int w, int h, int rad)
   526 {
   560 {
   527 	memset(accepts, 0, sizeof(AcceptedCargo));
   561 	memset(accepts, 0, sizeof(AcceptedCargo));
   528 
   562 
   529 	int x = TileX(tile);
   563 	int x = TileX(tile);
   530 	int y = TileY(tile);
   564 	int y = TileY(tile);
   531 
   565 
   532 	// expand the region by rad tiles on each side
   566 	/* expand the region by rad tiles on each side
   533 	// while making sure that we remain inside the board.
   567 	 * while making sure that we remain inside the board. */
   534 	int x2 = min(x + w + rad, MapSizeX());
   568 	int x2 = min(x + w + rad, MapSizeX());
   535 	int y2 = min(y + h + rad, MapSizeY());
   569 	int y2 = min(y + h + rad, MapSizeY());
   536 	int x1 = max(x - rad, 0);
   570 	int x1 = max(x - rad, 0);
   537 	int y1 = max(y - rad, 0);
   571 	int y1 = max(y - rad, 0);
   538 
   572 
   571 	if (rect->min_y > y) rect->min_y = y;
   605 	if (rect->min_y > y) rect->min_y = y;
   572 	if (rect->max_x < x) rect->max_x = x;
   606 	if (rect->max_x < x) rect->max_x = x;
   573 	if (rect->max_y < y) rect->max_y = y;
   607 	if (rect->max_y < y) rect->max_y = y;
   574 }
   608 }
   575 
   609 
   576 // Update the acceptance for a station.
   610 /** Update the acceptance for a station.
   577 // show_msg controls whether to display a message that acceptance was changed.
   611  * @param st Station to update
       
   612  * @param show_msg controls whether to display a message that acceptance was changed.
       
   613  */
   578 static void UpdateStationAcceptance(Station *st, bool show_msg)
   614 static void UpdateStationAcceptance(Station *st, bool show_msg)
   579 {
   615 {
   580 	// Don't update acceptance for a buoy
   616 	/* Don't update acceptance for a buoy */
   581 	if (st->IsBuoy()) return;
   617 	if (st->IsBuoy()) return;
   582 
   618 
   583 	ottd_Rectangle rect;
   619 	ottd_Rectangle rect;
   584 	rect.min_x = MapSizeX();
   620 	rect.min_x = MapSizeX();
   585 	rect.min_y = MapSizeY();
   621 	rect.min_y = MapSizeY();
   587 	rect.max_y = 0;
   623 	rect.max_y = 0;
   588 
   624 
   589 	/* old accepted goods types */
   625 	/* old accepted goods types */
   590 	uint old_acc = GetAcceptanceMask(st);
   626 	uint old_acc = GetAcceptanceMask(st);
   591 
   627 
   592 	// Put all the tiles that span an area in the table.
   628 	/* Put all the tiles that span an area in the table. */
   593 	if (st->train_tile != 0) {
   629 	if (st->train_tile != 0) {
   594 		MergePoint(&rect, st->train_tile);
   630 		MergePoint(&rect, st->train_tile);
   595 		MergePoint(&rect,
   631 		MergePoint(&rect,
   596 			st->train_tile + TileDiffXY(st->trainst_w - 1, st->trainst_h - 1)
   632 			st->train_tile + TileDiffXY(st->trainst_w - 1, st->trainst_h - 1)
   597 		);
   633 		);
   614 
   650 
   615 	for (const RoadStop *rs = st->truck_stops; rs != NULL; rs = rs->next) {
   651 	for (const RoadStop *rs = st->truck_stops; rs != NULL; rs = rs->next) {
   616 		MergePoint(&rect, rs->xy);
   652 		MergePoint(&rect, rs->xy);
   617 	}
   653 	}
   618 
   654 
   619 	// And retrieve the acceptance.
   655 	/* And retrieve the acceptance. */
   620 	AcceptedCargo accepts;
   656 	AcceptedCargo accepts;
   621 	if (rect.max_x >= rect.min_x) {
   657 	if (rect.max_x >= rect.min_x) {
   622 		GetAcceptanceAroundTiles(
   658 		GetAcceptanceAroundTiles(
   623 			accepts,
   659 			accepts,
   624 			TileXY(rect.min_x, rect.min_y),
   660 			TileXY(rect.min_x, rect.min_y),
   628 		);
   664 		);
   629 	} else {
   665 	} else {
   630 		memset(accepts, 0, sizeof(accepts));
   666 		memset(accepts, 0, sizeof(accepts));
   631 	}
   667 	}
   632 
   668 
   633 	// Adjust in case our station only accepts fewer kinds of goods
   669 	/* Adjust in case our station only accepts fewer kinds of goods */
   634 	for (CargoID i = 0; i < NUM_CARGO; i++) {
   670 	for (CargoID i = 0; i < NUM_CARGO; i++) {
   635 		uint amt = min(accepts[i], 15);
   671 		uint amt = min(accepts[i], 15);
   636 
   672 
   637 		// Make sure the station can accept the goods type.
   673 		/* Make sure the station can accept the goods type. */
   638 		bool is_passengers = IsCargoInClass(i, CC_PASSENGERS);
   674 		bool is_passengers = IsCargoInClass(i, CC_PASSENGERS);
   639 		if ((!is_passengers && !(st->facilities & (byte)~FACIL_BUS_STOP)) ||
   675 		if ((!is_passengers && !(st->facilities & (byte)~FACIL_BUS_STOP)) ||
   640 				(is_passengers && !(st->facilities & (byte)~FACIL_TRUCK_STOP)))
   676 				(is_passengers && !(st->facilities & (byte)~FACIL_TRUCK_STOP)))
   641 			amt = 0;
   677 			amt = 0;
   642 
   678 
   643 		SB(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, amt >= 8);
   679 		SB(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, amt >= 8);
   644 	}
   680 	}
   645 
   681 
   646 	// Only show a message in case the acceptance was actually changed.
   682 	/* Only show a message in case the acceptance was actually changed. */
   647 	uint new_acc = GetAcceptanceMask(st);
   683 	uint new_acc = GetAcceptanceMask(st);
   648 	if (old_acc == new_acc)
   684 	if (old_acc == new_acc)
   649 		return;
   685 		return;
   650 
   686 
   651 	// show a message to report that the acceptance was changed?
   687 	/* show a message to report that the acceptance was changed? */
   652 	if (show_msg && st->owner == _local_player && st->facilities) {
   688 	if (show_msg && st->owner == _local_player && st->facilities) {
   653 		/* List of accept and reject strings for different number of
   689 		/* List of accept and reject strings for different number of
   654 		 * cargo types */
   690 		 * cargo types */
   655 		static const StringID accept_msg[] = {
   691 		static const StringID accept_msg[] = {
   656 			STR_3040_NOW_ACCEPTS,
   692 			STR_3040_NOW_ACCEPTS,
   667 		uint num_acc = 0;
   703 		uint num_acc = 0;
   668 		uint num_rej = 0;
   704 		uint num_rej = 0;
   669 
   705 
   670 		/* Test each cargo type to see if its acceptange has changed */
   706 		/* Test each cargo type to see if its acceptange has changed */
   671 		for (CargoID i = 0; i < NUM_CARGO; i++) {
   707 		for (CargoID i = 0; i < NUM_CARGO; i++) {
   672 			if (HASBIT(new_acc, i)) {
   708 			if (HasBit(new_acc, i)) {
   673 				if (!HASBIT(old_acc, i) && num_acc < lengthof(accepts)) {
   709 				if (!HasBit(old_acc, i) && num_acc < lengthof(accepts)) {
   674 					/* New cargo is accepted */
   710 					/* New cargo is accepted */
   675 					accepts[num_acc++] = i;
   711 					accepts[num_acc++] = i;
   676 				}
   712 				}
   677 			} else {
   713 			} else {
   678 				if (HASBIT(old_acc, i) && num_rej < lengthof(rejects)) {
   714 				if (HasBit(old_acc, i) && num_rej < lengthof(rejects)) {
   679 					/* Old cargo is no longer accepted */
   715 					/* Old cargo is no longer accepted */
   680 					rejects[num_rej++] = i;
   716 					rejects[num_rej++] = i;
   681 				}
   717 				}
   682 			}
   718 			}
   683 		}
   719 		}
   685 		/* Show news message if there are any changes */
   721 		/* Show news message if there are any changes */
   686 		if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
   722 		if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
   687 		if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
   723 		if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
   688 	}
   724 	}
   689 
   725 
   690 	// redraw the station view since acceptance changed
   726 	/* redraw the station view since acceptance changed */
   691 	InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4);
   727 	InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4);
   692 }
   728 }
   693 
   729 
   694 static void UpdateStationSignCoord(Station *st)
   730 static void UpdateStationSignCoord(Station *st)
   695 {
   731 {
   696 	const StationRect *r = &st->rect;
   732 	const StationRect *r = &st->rect;
   697 
   733 
   698 	if (r->IsEmpty()) return; // no tiles belong to this station
   734 	if (r->IsEmpty()) return; /* no tiles belong to this station */
   699 
   735 
   700 	// clamp sign coord to be inside the station rect
   736 	/* clamp sign coord to be inside the station rect */
   701 	st->xy = TileXY(clampu(TileX(st->xy), r->left, r->right), clampu(TileY(st->xy), r->top, r->bottom));
   737 	st->xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom));
   702 	UpdateStationVirtCoordDirty(st);
   738 	UpdateStationVirtCoordDirty(st);
   703 }
   739 }
   704 
   740 
   705 // This is called right after a station was deleted.
   741 /** This is called right after a station was deleted.
   706 // It checks if the whole station is free of substations, and if so, the station will be
   742  * It checks if the whole station is free of substations, and if so, the station will be
   707 // deleted after a little while.
   743  * deleted after a little while.
   708 static void DeleteStationIfEmpty(Station* st)
   744  * @param st Station
       
   745  */
       
   746 static void DeleteStationIfEmpty(Station *st)
   709 {
   747 {
   710 	if (st->facilities == 0) {
   748 	if (st->facilities == 0) {
   711 		st->delete_ctr = 0;
   749 		st->delete_ctr = 0;
   712 		RebuildStationLists();
   750 		RebuildStationLists();
   713 		InvalidateWindow(WC_STATION_LIST, st->owner);
   751 		InvalidateWindow(WC_STATION_LIST, st->owner);
   716 	UpdateStationSignCoord(st);
   754 	UpdateStationSignCoord(st);
   717 }
   755 }
   718 
   756 
   719 static CommandCost ClearTile_Station(TileIndex tile, byte flags);
   757 static CommandCost ClearTile_Station(TileIndex tile, byte flags);
   720 
   758 
   721 // Tries to clear the given area. Returns the cost in case of success.
   759 /** Tries to clear the given area.
   722 // Or an error code if it failed.
   760  * @param tile TileIndex to start check
       
   761  * @param w width of search area
       
   762  * @param h height of search area
       
   763  * @param flags operation to perform
       
   764  * @param invalid_dirs prohibited directions
       
   765  * @param station StationID to be queried and returned if available
       
   766  * @param check_clear if clearing tile should be performed (in wich case, cost will be added)
       
   767  * @return the cost in case of success, or an error code if it failed.
       
   768  */
   723 CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint32 invalid_dirs, StationID* station, const FSMportsSpec *fsmportspec, bool check_clear = true)
   769 CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint32 invalid_dirs, StationID* station, const FSMportsSpec *fsmportspec, bool check_clear = true)
   724 {
   770 {
   725 	CommandCost cost;
   771 	CommandCost cost;
   726 	int allowed_z = -1;
   772 	int allowed_z = -1;
   727 	byte layout_set = GB(invalid_dirs, 0, 3);
   773 	byte layout_set = GB(invalid_dirs, 0, 3);
   756 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   802 			return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   757 		}
   803 		}
   758 
   804 
   759 		int flat_z = z;
   805 		int flat_z = z;
   760 		if (tileh != SLOPE_FLAT) {
   806 		if (tileh != SLOPE_FLAT) {
   761 			// need to check so the entrance to the station is not pointing at a slope.
   807 			/* need to check so the entrance to the station is not pointing at a slope. */
   762 			if ((invalid_dirs & 1 && !(tileh & SLOPE_NE) && (uint)w_cur == w) ||
   808 			if ((invalid_dirs & 1 && !(tileh & SLOPE_NE) && (uint)w_cur == w) ||
   763 					(invalid_dirs & 2 && !(tileh & SLOPE_SE) && h_cur == 1) ||
   809 					(invalid_dirs & 2 && !(tileh & SLOPE_SE) && h_cur == 1) ||
   764 					(invalid_dirs & 4 && !(tileh & SLOPE_SW) && w_cur == 1) ||
   810 					(invalid_dirs & 4 && !(tileh & SLOPE_SW) && w_cur == 1) ||
   765 					(invalid_dirs & 8 && !(tileh & SLOPE_NW) && (uint)h_cur == h)) {
   811 					(invalid_dirs & 8 && !(tileh & SLOPE_NW) && (uint)h_cur == h)) {
   766 				return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   812 				return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
   775 			if ((byte)*b++ == (byte)255) {
   821 			if ((byte)*b++ == (byte)255) {
   776 				do_tile_test = false;
   822 				do_tile_test = false;
   777 			}
   823 			}
   778 		};
   824 		};
   779 
   825 
   780 		// get corresponding flat level and make sure that all parts of the station have the same level.
   826 		/* get corresponding flat level and make sure that all parts of the station have the same level. */
   781 		if (allowed_z == -1) {
   827 		if (allowed_z == -1) {
   782 			// first tile
   828 			/* first tile */
   783 			allowed_z = flat_z;
   829 			allowed_z = flat_z;
   784 		} else if (do_tile_test && (allowed_z != flat_z)) {
   830 		} else if (do_tile_test && (allowed_z != flat_z)) {
   785 			/* test here whether build on height permitted. for FSM ports with layout masks, this is not an error
   831 			/* test here whether build on height permitted. for FSM ports with layout masks, this is not an error
   786 			 * land checking is done in airport placement
   832 			 * land checking is done in airport placement
   787 			 */
   833 			 */
   802 					} else if (*station != st) {
   848 					} else if (*station != st) {
   803 						return_cmd_error(STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING);
   849 						return_cmd_error(STR_3006_ADJOINS_MORE_THAN_ONE_EXISTING);
   804 					}
   850 					}
   805 				}
   851 				}
   806 			} else if (check_clear) {
   852 			} else if (check_clear) {
   807 				bool water_tile = IsClearWaterTile(tile_cur);
   853 				bool water_tile = IsWaterTile(tile_cur);
   808 				CommandCost ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   854 				CommandCost ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   809 				if (CmdFailed(ret)) return ret;
   855 				if (CmdFailed(ret)) return ret;
   810 				if (!water_tile) cost.AddCost(ret);
   856 				if (!water_tile) cost.AddCost(ret);
   811 			}
   857 			}
   812 		}
   858 		}
   827 	TileIndex tile = fin[0];
   873 	TileIndex tile = fin[0];
   828 	uint w = fin[1];
   874 	uint w = fin[1];
   829 	uint h = fin[2];
   875 	uint h = fin[2];
   830 
   876 
   831 	if (_patches.nonuniform_stations) {
   877 	if (_patches.nonuniform_stations) {
   832 		// determine new size of train station region..
   878 		/* determine new size of train station region.. */
   833 		int x = min(TileX(st->train_tile), TileX(tile));
   879 		int x = min(TileX(st->train_tile), TileX(tile));
   834 		int y = min(TileY(st->train_tile), TileY(tile));
   880 		int y = min(TileY(st->train_tile), TileY(tile));
   835 		curw = max(TileX(st->train_tile) + curw, TileX(tile) + w) - x;
   881 		curw = max(TileX(st->train_tile) + curw, TileX(tile) + w) - x;
   836 		curh = max(TileY(st->train_tile) + curh, TileY(tile) + h) - y;
   882 		curh = max(TileY(st->train_tile) + curh, TileY(tile) + h) - y;
   837 		tile = TileXY(x, y);
   883 		tile = TileXY(x, y);
   838 	} else {
   884 	} else {
   839 		// check so the orientation is the same
   885 		/* check so the orientation is the same */
   840 		if (GetRailStationAxis(st->train_tile) != axis) {
   886 		if (GetRailStationAxis(st->train_tile) != axis) {
   841 			_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
   887 			_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
   842 			return false;
   888 			return false;
   843 		}
   889 		}
   844 
   890 
   845 		// check if the new station adjoins the old station in either direction
   891 		/* check if the new station adjoins the old station in either direction */
   846 		if (curw == w && st->train_tile == tile + TileDiffXY(0, h)) {
   892 		if (curw == w && st->train_tile == tile + TileDiffXY(0, h)) {
   847 			// above
   893 			/* above */
   848 			curh += h;
   894 			curh += h;
   849 		} else if (curw == w && st->train_tile == tile - TileDiffXY(0, curh)) {
   895 		} else if (curw == w && st->train_tile == tile - TileDiffXY(0, curh)) {
   850 			// below
   896 			/* below */
   851 			tile -= TileDiffXY(0, curh);
   897 			tile -= TileDiffXY(0, curh);
   852 			curh += h;
   898 			curh += h;
   853 		} else if (curh == h && st->train_tile == tile + TileDiffXY(w, 0)) {
   899 		} else if (curh == h && st->train_tile == tile + TileDiffXY(w, 0)) {
   854 			// to the left
   900 			/* to the left */
   855 			curw += w;
   901 			curw += w;
   856 		} else if (curh == h && st->train_tile == tile - TileDiffXY(curw, 0)) {
   902 		} else if (curh == h && st->train_tile == tile - TileDiffXY(curw, 0)) {
   857 			// to the right
   903 			/* to the right */
   858 			tile -= TileDiffXY(curw, 0);
   904 			tile -= TileDiffXY(curw, 0);
   859 			curw += w;
   905 			curw += w;
   860 		} else {
   906 		} else {
   861 			_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
   907 			_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
   862 			return false;
   908 			return false;
   863 		}
   909 		}
   864 	}
   910 	}
   865 	// make sure the final size is not too big.
   911 	/* make sure the final size is not too big. */
   866 	if (curw > _patches.station_spread || curh > _patches.station_spread) {
   912 	if (curw > _patches.station_spread || curh > _patches.station_spread) {
   867 		_error_message = STR_306C_STATION_TOO_SPREAD_OUT;
   913 		_error_message = STR_306C_STATION_TOO_SPREAD_OUT;
   868 		return false;
   914 		return false;
   869 	}
   915 	}
   870 
   916 
   871 	// now tile contains the new value for st->train_tile
   917 	/* now tile contains the new value for st->train_tile
   872 	// curw, curh contain the new value for width and height
   918 	 * curw, curh contain the new value for width and height */
   873 	fin[0] = tile;
   919 	fin[0] = tile;
   874 	fin[1] = curw;
   920 	fin[1] = curw;
   875 	fin[2] = curh;
   921 	fin[2] = curh;
   876 	return true;
   922 	return true;
   877 }
   923 }
   955 		w_org = numtracks;
  1001 		w_org = numtracks;
   956 	}
  1002 	}
   957 
  1003 
   958 	if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR;
  1004 	if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR;
   959 
  1005 
   960 	// these values are those that will be stored in train_tile and station_platforms
  1006 	/* these values are those that will be stored in train_tile and station_platforms */
   961 	uint finalvalues[3];
  1007 	uint finalvalues[3];
   962 	finalvalues[0] = tile_org;
  1008 	finalvalues[0] = tile_org;
   963 	finalvalues[1] = w_org;
  1009 	finalvalues[1] = w_org;
   964 	finalvalues[2] = h_org;
  1010 	finalvalues[2] = h_org;
   965 
  1011 
   966 	// Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station)
  1012 	/* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
   967 	StationID est = INVALID_STATION;
  1013 	StationID est = INVALID_STATION;
   968 	// If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug
  1014 	/* If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug
   969 	//  for detail info, see: https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365
  1015 	 * for detail info, see:
       
  1016 	 * https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365 */
   970 	ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
  1017 	ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
   971 	if (CmdFailed(ret)) return ret;
  1018 	if (CmdFailed(ret)) return ret;
   972 	CommandCost cost(ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len);
  1019 	CommandCost cost(ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len);
   973 
  1020 
   974 	Station *st = NULL;
  1021 	Station *st = NULL;
   975 	bool check_surrounding = true;
  1022 	bool check_surrounding = true;
   976 
  1023 
   977 	if (_patches.adjacent_stations) {
  1024 	if (_patches.adjacent_stations) {
   978 		if (est != INVALID_STATION) {
  1025 		if (est != INVALID_STATION) {
   979 			if (HASBIT(p1, 24)) {
  1026 			if (HasBit(p1, 24)) {
   980 				/* You can't build an adjacent station over the top of one that
  1027 				/* You can't build an adjacent station over the top of one that
   981 				 * already exists. */
  1028 				 * already exists. */
   982 				return_cmd_error(STR_MUST_REMOVE_RAILWAY_STATION_FIRST);
  1029 				return_cmd_error(STR_MUST_REMOVE_RAILWAY_STATION_FIRST);
   983 			} else {
  1030 			} else {
   984 				/* Extend the current station, and don't check whether it will
  1031 				/* Extend the current station, and don't check whether it will
   987 				check_surrounding = false;
  1034 				check_surrounding = false;
   988 			}
  1035 			}
   989 		} else {
  1036 		} else {
   990 			/* There's no station here. Don't check the tiles surrounding this
  1037 			/* There's no station here. Don't check the tiles surrounding this
   991 			 * one if the player wanted to build an adjacent station. */
  1038 			 * one if the player wanted to build an adjacent station. */
   992 			if (HASBIT(p1, 24)) check_surrounding = false;
  1039 			if (HasBit(p1, 24)) check_surrounding = false;
   993 		}
  1040 		}
   994 	}
  1041 	}
   995 
  1042 
   996 	if (check_surrounding) {
  1043 	if (check_surrounding) {
   997 		// Make sure there are no similar stations around us.
  1044 		/* Make sure there are no similar stations around us. */
   998 		st = GetStationAround(tile_org, w_org, h_org, est);
  1045 		st = GetStationAround(tile_org, w_org, h_org, est);
   999 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  1046 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  1000 	}
  1047 	}
  1001 
  1048 
  1002 	// See if there is a deleted station close to us.
  1049 	/* See if there is a deleted station close to us. */
  1003 	if (st == NULL) st = GetClosestStationFromTile(tile_org);
  1050 	if (st == NULL) st = GetClosestStationFromTile(tile_org);
  1004 
  1051 
  1005 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  1052 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  1006 	 * to test if everything is OK. In this case we need to delete it before return. */
  1053 	 * to test if everything is OK. In this case we need to delete it before return. */
  1007 	AutoPtrT<Station> st_auto_delete;
  1054 	AutoPtrT<Station> st_auto_delete;
  1008 
  1055 
  1009 	if (st != NULL) {
  1056 	if (st != NULL) {
  1010 		// Reuse an existing station.
  1057 		/* Reuse an existing station. */
  1011 		if (st->owner != _current_player)
  1058 		if (st->owner != _current_player)
  1012 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
  1059 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
  1013 
  1060 
  1014 		if (st->train_tile != 0) {
  1061 		if (st->train_tile != 0) {
  1015 			// check if we want to expanding an already existing station?
  1062 			/* check if we want to expanding an already existing station? */
  1016 			if (_is_old_ai_player || !_patches.join_stations)
  1063 			if (_is_old_ai_player || !_patches.join_stations)
  1017 				return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD);
  1064 				return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD);
  1018 			if (!CanExpandRailroadStation(st, finalvalues, axis))
  1065 			if (!CanExpandRailroadStation(st, finalvalues, axis))
  1019 				return CMD_ERROR;
  1066 				return CMD_ERROR;
  1020 		}
  1067 		}
  1021 
  1068 
  1022 		//XXX can't we pack this in the "else" part of the if above?
  1069 		/* XXX can't we pack this in the "else" part of the if above? */
  1023 		if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR;
  1070 		if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR;
  1024 	} else {
  1071 	} else {
  1025 		/* allocate and initialize new station */
  1072 		/* allocate and initialize new station */
  1026 		st = new Station(tile_org);
  1073 		st = new Station(tile_org);
  1027 		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1074 		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1028 
  1075 
  1029 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1076 		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
  1030 		st_auto_delete = st;
  1077 		st_auto_delete = st;
  1031 
  1078 
  1032 		st->town = ClosestTownFromTile(tile_org, (uint)-1);
  1079 		st->town = ClosestTownFromTile(tile_org, (uint)-1);
  1033 		if (!GenerateStationName(st, tile_org, 0)) return CMD_ERROR;
  1080 		if (!GenerateStationName(st, tile_org, STATIONNAMING_RAIL)) return CMD_ERROR;
  1034 
  1081 
  1035 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  1082 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  1036 			SETBIT(st->town->have_ratings, _current_player);
  1083 			SetBit(st->town->have_ratings, _current_player);
  1037 		}
  1084 		}
  1038 	}
  1085 	}
  1039 
  1086 
  1040 	/* Check if the given station class is valid */
  1087 	/* Check if the given station class is valid */
  1041 	if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR;
  1088 	if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR;
  1047 
  1094 
  1048 	if (statspec != NULL) {
  1095 	if (statspec != NULL) {
  1049 		/* Perform NewStation checks */
  1096 		/* Perform NewStation checks */
  1050 
  1097 
  1051 		/* Check if the station size is permitted */
  1098 		/* Check if the station size is permitted */
  1052 		if (HASBIT(statspec->disallowed_platforms, numtracks - 1) || HASBIT(statspec->disallowed_lengths, plat_len - 1)) {
  1099 		if (HasBit(statspec->disallowed_platforms, numtracks - 1) || HasBit(statspec->disallowed_lengths, plat_len - 1)) {
  1053 			return CMD_ERROR;
  1100 			return CMD_ERROR;
  1054 		}
  1101 		}
  1055 
  1102 
  1056 		/* Check if the station is buildable */
  1103 		/* Check if the station is buildable */
  1057 		if (HASBIT(statspec->callbackmask, CBM_STATION_AVAIL) && GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE) == 0) {
  1104 		if (HasBit(statspec->callbackmask, CBM_STATION_AVAIL) && GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE) == 0) {
  1058 			return CMD_ERROR;
  1105 			return CMD_ERROR;
  1059 		}
  1106 		}
  1060 	}
  1107 	}
  1061 
  1108 
  1062 	if (flags & DC_EXEC) {
  1109 	if (flags & DC_EXEC) {
  1063 		TileIndexDiff tile_delta;
  1110 		TileIndexDiff tile_delta;
  1064 		byte *layout_ptr;
  1111 		byte *layout_ptr;
  1065 		byte numtracks_orig;
  1112 		byte numtracks_orig;
  1066 		Track track;
  1113 		Track track;
  1067 
  1114 
  1068 		// Now really clear the land below the station
  1115 		/* Now really clear the land below the station
  1069 		// It should never return CMD_ERROR.. but you never know ;)
  1116 		 * It should never return CMD_ERROR.. but you never know ;)
  1070 		//  (a bit strange function name for it, but it really does clear the land, when DC_EXEC is in flags)
  1117 		 * (a bit strange function name for it, but it really does clear the land, when DC_EXEC is in flags) */
  1071 		ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
  1118 		ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
  1072 		if (CmdFailed(ret)) return ret;
  1119 		if (CmdFailed(ret)) return ret;
  1073 
  1120 
  1074 		st->train_tile = finalvalues[0];
  1121 		st->train_tile = finalvalues[0];
  1075 		st->AddFacility(FACIL_TRAIN, finalvalues[0]);
  1122 		st->AddFacility(FACIL_TRAIN, finalvalues[0]);
  1097 				SetStationTileRandomBits(tile, GB(Random(), 0, 4));
  1144 				SetStationTileRandomBits(tile, GB(Random(), 0, 4));
  1098 
  1145 
  1099 				if (statspec != NULL) {
  1146 				if (statspec != NULL) {
  1100 					/* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
  1147 					/* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
  1101 					uint32 platinfo = GetPlatformInfo(AXIS_X, 0, plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
  1148 					uint32 platinfo = GetPlatformInfo(AXIS_X, 0, plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
  1102 					uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, st, tile);
  1149 
       
  1150 					/* As the station is not yet completely finished, the station does not yet exist. */
       
  1151 					uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, NULL, tile);
  1103 					if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis);
  1152 					if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis);
  1104 				}
  1153 				}
  1105 
  1154 
  1106 				tile += tile_delta;
  1155 				tile += tile_delta;
  1107 			} while (--w);
  1156 			} while (--w);
  1128 	uint h = st->trainst_h;
  1177 	uint h = st->trainst_h;
  1129 	TileIndex tile = st->train_tile;
  1178 	TileIndex tile = st->train_tile;
  1130 
  1179 
  1131 restart:
  1180 restart:
  1132 
  1181 
  1133 	// too small?
  1182 	/* too small? */
  1134 	if (w != 0 && h != 0) {
  1183 	if (w != 0 && h != 0) {
  1135 		// check the left side, x = constant, y changes
  1184 		/* check the left side, x = constant, y changes */
  1136 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(0, i));) {
  1185 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(0, i));) {
  1137 			// the left side is unused?
  1186 			/* the left side is unused? */
  1138 			if (++i == h) {
  1187 			if (++i == h) {
  1139 				tile += TileDiffXY(1, 0);
  1188 				tile += TileDiffXY(1, 0);
  1140 				w--;
  1189 				w--;
  1141 				goto restart;
  1190 				goto restart;
  1142 			}
  1191 			}
  1143 		}
  1192 		}
  1144 
  1193 
  1145 		// check the right side, x = constant, y changes
  1194 		/* check the right side, x = constant, y changes */
  1146 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(w - 1, i));) {
  1195 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(w - 1, i));) {
  1147 			// the right side is unused?
  1196 			/* the right side is unused? */
  1148 			if (++i == h) {
  1197 			if (++i == h) {
  1149 				w--;
  1198 				w--;
  1150 				goto restart;
  1199 				goto restart;
  1151 			}
  1200 			}
  1152 		}
  1201 		}
  1153 
  1202 
  1154 		// check the upper side, y = constant, x changes
  1203 		/* check the upper side, y = constant, x changes */
  1155 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, 0));) {
  1204 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, 0));) {
  1156 			// the left side is unused?
  1205 			/* the left side is unused? */
  1157 			if (++i == w) {
  1206 			if (++i == w) {
  1158 				tile += TileDiffXY(0, 1);
  1207 				tile += TileDiffXY(0, 1);
  1159 				h--;
  1208 				h--;
  1160 				goto restart;
  1209 				goto restart;
  1161 			}
  1210 			}
  1162 		}
  1211 		}
  1163 
  1212 
  1164 		// check the lower side, y = constant, x changes
  1213 		/* check the lower side, y = constant, x changes */
  1165 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, h - 1));) {
  1214 		for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, h - 1));) {
  1166 			// the left side is unused?
  1215 			/* the left side is unused? */
  1167 			if (++i == w) {
  1216 			if (++i == w) {
  1168 				h--;
  1217 				h--;
  1169 				goto restart;
  1218 				goto restart;
  1170 			}
  1219 			}
  1171 		}
  1220 		}
  1215 			continue;
  1264 			continue;
  1216 		}
  1265 		}
  1217 
  1266 
  1218 		/* Check ownership of station */
  1267 		/* Check ownership of station */
  1219 		Station *st = GetStationByTile(tile2);
  1268 		Station *st = GetStationByTile(tile2);
  1220 		if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile2))) {
  1269 		if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicleOnGround(tile2))) {
  1221 			continue;
  1270 			continue;
  1222 		}
  1271 		}
  1223 
  1272 
  1224 		/* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
  1273 		/* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
  1225 		quantity++;
  1274 		quantity++;
  1232 			SetSignalsOnBothDir(tile2, track);
  1281 			SetSignalsOnBothDir(tile2, track);
  1233 			YapfNotifyTrackLayoutChange(tile2, track);
  1282 			YapfNotifyTrackLayoutChange(tile2, track);
  1234 
  1283 
  1235 			DeallocateSpecFromStation(st, specindex);
  1284 			DeallocateSpecFromStation(st, specindex);
  1236 
  1285 
  1237 			// now we need to make the "spanned" area of the railway station smaller if we deleted something at the edges.
  1286 			/* now we need to make the "spanned" area of the railway station smaller
  1238 			// we also need to adjust train_tile.
  1287 			 * if we deleted something at the edges.
       
  1288 			 * we also need to adjust train_tile. */
  1239 			MakeRailwayStationAreaSmaller(st);
  1289 			MakeRailwayStationAreaSmaller(st);
  1240 			st->MarkTilesDirty(false);
  1290 			st->MarkTilesDirty(false);
  1241 			UpdateStationSignCoord(st);
  1291 			UpdateStationSignCoord(st);
  1242 
  1292 
  1243 			// if we deleted the whole station, delete the train facility.
  1293 			/* if we deleted the whole station, delete the train facility. */
  1244 			if (st->train_tile == 0) {
  1294 			if (st->train_tile == 0) {
  1245 				st->facilities &= ~FACIL_TRAIN;
  1295 				st->facilities &= ~FACIL_TRAIN;
  1246 				UpdateStationVirtCoordDirty(st);
  1296 				UpdateStationVirtCoordDirty(st);
  1247 				DeleteStationIfEmpty(st);
  1297 				DeleteStationIfEmpty(st);
  1248 			}
  1298 			}
  1278 	do {
  1328 	do {
  1279 		int w_bak = w;
  1329 		int w_bak = w;
  1280 		do {
  1330 		do {
  1281 			// for nonuniform stations, only remove tiles that are actually train station tiles
  1331 			// for nonuniform stations, only remove tiles that are actually train station tiles
  1282 			if (st->TileBelongsToRailStation(tile)) {
  1332 			if (st->TileBelongsToRailStation(tile)) {
  1283 				if (!EnsureNoVehicle(tile))
  1333 				if (!EnsureNoVehicleOnGround(tile))
  1284 					return CMD_ERROR;
  1334 					return CMD_ERROR;
  1285 				cost.AddCost(_price.remove_rail_station);
  1335 				cost.AddCost(_price.remove_rail_station);
  1286 				if (flags & DC_EXEC) {
  1336 				if (flags & DC_EXEC) {
  1287 					Track track = GetRailStationTrack(tile);
  1337 					Track track = GetRailStationTrack(tile);
  1288 					DoClearSquare(tile);
  1338 					DoClearSquare(tile);
  1332 		MarkTileDirtyByTile(tile);
  1382 		MarkTileDirtyByTile(tile);
  1333 		YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
  1383 		YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
  1334 		VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
  1384 		VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
  1335 	}
  1385 	}
  1336 
  1386 
  1337 	return CommandCost(_price.build_rail / 2);
  1387 	return CommandCost(RailBuildCost(totype) / 2);
  1338 }
  1388 }
  1339 
  1389 
  1340 /**
  1390 /**
  1341  * @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
  1342  * @param st The Station to do the whole procedure for
  1392  * @param st The Station to do the whole procedure for
  1366  *           bit 2..4: the roadtypes
  1416  *           bit 2..4: the roadtypes
  1367  *           bit 5: allow stations directly adjacent to other stations.
  1417  *           bit 5: allow stations directly adjacent to other stations.
  1368  */
  1418  */
  1369 CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1419 CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1370 {
  1420 {
  1371 	bool type = HASBIT(p2, 0);
  1421 	bool type = HasBit(p2, 0);
  1372 	bool is_drive_through = HASBIT(p2, 1);
  1422 	bool is_drive_through = HasBit(p2, 1);
  1373 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
  1423 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
  1374 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
  1424 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
  1375 	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
  1425 	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
  1376 
  1426 
  1377 	if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR;
  1427 	if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR;
  1378 
  1428 
  1379 	/* Trams only have drive through stops */
  1429 	/* Trams only have drive through stops */
  1380 	if (!is_drive_through && HASBIT(rts, ROADTYPE_TRAM)) return CMD_ERROR;
  1430 	if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR;
  1381 
  1431 
  1382 	/* Saveguard the parameters */
  1432 	/* Saveguard the parameters */
  1383 	if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
  1433 	if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
  1384 	/* If it is a drive-through stop check for valid axis */
  1434 	/* If it is a drive-through stop check for valid axis */
  1385 	if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
  1435 	if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
  1399 
  1449 
  1400 		/* Don't allow building the roadstop when vehicles are already driving on it */
  1450 		/* Don't allow building the roadstop when vehicles are already driving on it */
  1401 		if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
  1451 		if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
  1402 
  1452 
  1403 		RoadTypes cur_rts = GetRoadTypes(tile);
  1453 		RoadTypes cur_rts = GetRoadTypes(tile);
  1404 		if (GetRoadOwner(tile, ROADTYPE_ROAD) != OWNER_TOWN && HASBIT(cur_rts, ROADTYPE_ROAD) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD))) return CMD_ERROR;
  1454 		if (GetRoadOwner(tile, ROADTYPE_ROAD) != OWNER_TOWN && HasBit(cur_rts, ROADTYPE_ROAD) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD))) return CMD_ERROR;
  1405 		if (HASBIT(cur_rts, ROADTYPE_TRAM) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR;
  1455 		if (HasBit(cur_rts, ROADTYPE_TRAM) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR;
  1406 
  1456 
  1407 		/* Do not remove roadtypes! */
  1457 		/* Do not remove roadtypes! */
  1408 		rts |= cur_rts;
  1458 		rts |= cur_rts;
  1409 	}
  1459 	}
  1410 	cost = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL, false, !build_over_road);
  1460 	cost = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL, false, !build_over_road);
  1411 	if (CmdFailed(cost)) return cost;
  1461 	if (CmdFailed(cost)) return cost;
  1412 
  1462 
  1413 	Station *st = NULL;
  1463 	Station *st = NULL;
  1414 
  1464 
  1415 	if (!_patches.adjacent_stations || !HASBIT(p2, 5)) {
  1465 	if (!_patches.adjacent_stations || !HasBit(p2, 5)) {
  1416 		st = GetStationAround(tile, 1, 1, INVALID_STATION);
  1466 		st = GetStationAround(tile, 1, 1, INVALID_STATION);
  1417 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  1467 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  1418 	}
  1468 	}
  1419 
  1469 
  1420 	/* Find a station close to us */
  1470 	/* Find a station close to us */
  1421 	if (st == NULL) st = GetClosestStationFromTile(tile);
  1471 	if (st == NULL) st = GetClosestStationFromTile(tile);
  1422 
  1472 
  1423 	//give us a road stop in the list, and check if something went wrong
  1473 	/* give us a road stop in the list, and check if something went wrong */
  1424 	RoadStop *road_stop = new RoadStop(tile);
  1474 	RoadStop *road_stop = new RoadStop(tile);
  1425 	if (road_stop == NULL) {
  1475 	if (road_stop == NULL) {
  1426 		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
  1476 		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
  1427 	}
  1477 	}
  1428 
  1478 
  1433 			GetNumRoadStopsInStation(st, RoadStop::BUS) + GetNumRoadStopsInStation(st, RoadStop::TRUCK) >= RoadStop::LIMIT) {
  1483 			GetNumRoadStopsInStation(st, RoadStop::BUS) + GetNumRoadStopsInStation(st, RoadStop::TRUCK) >= RoadStop::LIMIT) {
  1434 		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
  1484 		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
  1435 	}
  1485 	}
  1436 
  1486 
  1437 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  1487 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  1438 	* to test if everything is OK. In this case we need to delete it before return. */
  1488 	 * to test if everything is OK. In this case we need to delete it before return. */
  1439 	AutoPtrT<Station> st_auto_delete;
  1489 	AutoPtrT<Station> st_auto_delete;
  1440 
  1490 
  1441 	if (st != NULL) {
  1491 	if (st != NULL) {
  1442 		if (st->owner != _current_player) {
  1492 		if (st->owner != _current_player) {
  1443 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
  1493 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
  1452 		/* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */
  1502 		/* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */
  1453 		st_auto_delete = st;
  1503 		st_auto_delete = st;
  1454 
  1504 
  1455 
  1505 
  1456 		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
  1506 		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
  1457 		if (!GenerateStationName(st, tile, 0)) return CMD_ERROR;
  1507 		if (!GenerateStationName(st, tile, STATIONNAMING_ROAD)) return CMD_ERROR;
  1458 
  1508 
  1459 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  1509 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  1460 			SETBIT(t->have_ratings, _current_player);
  1510 			SetBit(t->have_ratings, _current_player);
  1461 		}
  1511 		}
  1462 
  1512 
  1463 		st->sign.width_1 = 0;
  1513 		st->sign.width_1 = 0;
  1464 	}
  1514 	}
  1465 
  1515 
  1466 	cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station);
  1516 	cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station);
  1467 
  1517 
  1468 	if (flags & DC_EXEC) {
  1518 	if (flags & DC_EXEC) {
  1469 		// Insert into linked list of RoadStops
  1519 		/* Insert into linked list of RoadStops */
  1470 		RoadStop **currstop = FindRoadStopSpot(type, st);
  1520 		RoadStop **currstop = FindRoadStopSpot(type, st);
  1471 		*currstop = road_stop;
  1521 		*currstop = road_stop;
  1472 
  1522 
  1473 		//initialize an empty station
  1523 		/*initialize an empty station */
  1474 		st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile);
  1524 		st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile);
  1475 
  1525 
  1476 		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
  1526 		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
  1477 
  1527 
  1478 		RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
  1528 		RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
  1491 		rs_auto_delete.Detach();
  1541 		rs_auto_delete.Detach();
  1492 	}
  1542 	}
  1493 	return cost;
  1543 	return cost;
  1494 }
  1544 }
  1495 
  1545 
  1496 // Remove a bus station
  1546 /** Remove a bus station
       
  1547  * @param st Station to remove
       
  1548  * @param flags operation to perform
       
  1549  * @param tile TileIndex been queried
       
  1550  * @return cost or failure of operation
       
  1551  */
  1497 static CommandCost RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
  1552 static CommandCost RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
  1498 {
  1553 {
  1499 	if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) {
  1554 	if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) {
  1500 		return CMD_ERROR;
  1555 		return CMD_ERROR;
  1501 	}
  1556 	}
  1512 		cur_stop = GetRoadStopByTile(tile, RoadStop::BUS);
  1567 		cur_stop = GetRoadStopByTile(tile, RoadStop::BUS);
  1513 	}
  1568 	}
  1514 
  1569 
  1515 	assert(cur_stop != NULL);
  1570 	assert(cur_stop != NULL);
  1516 
  1571 
  1517 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
  1572 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
  1518 
  1573 
  1519 	if (flags & DC_EXEC) {
  1574 	if (flags & DC_EXEC) {
  1520 		if (*primary_stop == cur_stop) {
  1575 		if (*primary_stop == cur_stop) {
  1521 			// removed the first stop in the list
  1576 			/* removed the first stop in the list */
  1522 			*primary_stop = cur_stop->next;
  1577 			*primary_stop = cur_stop->next;
  1523 			// removed the only stop?
  1578 			/* removed the only stop? */
  1524 			if (*primary_stop == NULL) {
  1579 			if (*primary_stop == NULL) {
  1525 				st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
  1580 				st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP);
  1526 			}
  1581 			}
  1527 		} else {
  1582 		} else {
  1528 			// tell the predecessor in the list to skip this stop
  1583 			/* tell the predecessor in the list to skip this stop */
  1529 			RoadStop *pred = *primary_stop;
  1584 			RoadStop *pred = *primary_stop;
  1530 			while (pred->next != cur_stop) pred = pred->next;
  1585 			while (pred->next != cur_stop) pred = pred->next;
  1531 			pred->next = cur_stop->next;
  1586 			pred->next = cur_stop->next;
  1532 		}
  1587 		}
  1533 
  1588 
  1594 	const uint32 airport_type_for_flat_check = (GB(p2, 8, 8) << 3) | layout_set;
  1649 	const uint32 airport_type_for_flat_check = (GB(p2, 8, 8) << 3) | layout_set;
  1595 
  1650 
  1596 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1651 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1597 
  1652 
  1598 	/* Check if a valid, buildable airport was chosen for construction */
  1653 	/* Check if a valid, buildable airport was chosen for construction */
  1599 	//if (p1 > lengthof(_airport_sections) || !HASBIT(GetValidAirports(), p1)) return CMD_ERROR;
  1654 	//if (p1 > lengthof(_airport_sections) || !HasBit(GetValidAirports(), p1)) return CMD_ERROR;
  1600 
  1655 
  1601 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
  1656 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
  1602 		return CMD_ERROR;
  1657 		return CMD_ERROR;
  1603 
  1658 
  1604 	Town *t = ClosestTownFromTile(tile, (uint)-1);
  1659 	Town *t = ClosestTownFromTile(tile, (uint)-1);
  1629 	/* Perform NewStation checks */
  1684 	/* Perform NewStation checks */
  1630 	byte w = fsmportsspec->size_x[layout_set];
  1685 	byte w = fsmportsspec->size_x[layout_set];
  1631 	byte h = fsmportsspec->size_y[layout_set];
  1686 	byte h = fsmportsspec->size_y[layout_set];
  1632 
  1687 
  1633 	/* Check if the station is buildable */
  1688 	/* Check if the station is buildable */
  1634 	if (HASBIT(fsmportsspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportsspec, NULL, INVALID_TILE) == 0) {
  1689 	if (HasBit(fsmportsspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportsspec, NULL, INVALID_TILE) == 0) {
  1635 		return CMD_ERROR;
  1690 		return CMD_ERROR;
  1636 	}
  1691 	}
  1637 
  1692 
  1638 	if (!_patches.adjacent_stations || !HASBIT(p1, 24)) {
  1693 	if (!_patches.adjacent_stations || !HasBit(p1, 24)) {
  1639 		st = GetStationAround(tile, w, h, INVALID_STATION);
  1694 		st = GetStationAround(tile, w, h, INVALID_STATION);
  1640 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  1695 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  1641 	}
  1696 	}
  1642 
  1697 
  1643 	/* Find a station close to us */
  1698 	/* Find a station close to us */
  1671 		st_auto_delete = st;
  1726 		st_auto_delete = st;
  1672 
  1727 
  1673 		st->town = t;
  1728 		st->town = t;
  1674 
  1729 
  1675 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  1730 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  1676 			SETBIT(t->have_ratings, _current_player);
  1731 			SetBit(t->have_ratings, _current_player);
  1677 		}
  1732 		}
  1678 
  1733 
  1679 		st->sign.width_1 = 0;
  1734 		st->sign.width_1 = 0;
  1680 
  1735 
  1681 		/* If only helicopters may use the airport generate a helicopter related (5)
  1736 		/* If only helicopters may use the airport generate a helicopter related (5)
  1682 		 * station name, otherwise generate a normal airport name (1) */
  1737 		 * station name, otherwise generate a normal airport name (1) */
  1683 		if (!GenerateStationName(st, tile, !(fsmportsspec->flags & AirportFTAClass::AIRPLANES) ? 5 : 1)) {
  1738 		if (!GenerateStationName(st, tile, !(fsmportsspec->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT)) {
  1684 			return CMD_ERROR;
  1739 			return CMD_ERROR;
  1685 		}
  1740 		}
  1686 	}
  1741 	}
  1687 
  1742 
  1688 	flags |= DC_NO_WATER;
  1743 	flags |= DC_NO_WATER;
  1697 		const byte *mask_ptr = fsmportsspec->layout_mask[layout_set] + 2;  // width*length flagbytes. Also skip orientation and "filler" byte
  1752 		const byte *mask_ptr = fsmportsspec->layout_mask[layout_set] + 2;  // width*length flagbytes. Also skip orientation and "filler" byte
  1698 		BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
  1753 		BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
  1699 			byte mask = *mask_ptr++;
  1754 			byte mask = *mask_ptr++;
  1700 			if (mask & 0x80) {
  1755 			if (mask & 0x80) {
  1701 				/* do water tests */
  1756 				/* do water tests */
  1702 				if (IsClearWaterTile(tile_cur)) {
  1757 				if (IsWaterTile(tile_cur)) {
  1703 					flags &= ~DC_NO_WATER;
  1758 					flags &= ~DC_NO_WATER;
  1704 					st->FSMport_flood_protected = true;
  1759 					st->FSMport_flood_protected = true;
  1705 				} else {
  1760 				} else {
  1706 					_error_message = STR_304B_SITE_UNSUITABLE;
  1761 					_error_message = STR_304B_SITE_UNSUITABLE;
  1707 					return CMD_ERROR;
  1762 					return CMD_ERROR;
  1708 				}
  1763 				}
  1709 			} else if (IsClearWaterTile(tile_cur)) {
  1764 			} else if (IsWaterTile(tile_cur)) {
  1710 				/* tile should be land, but is water */
  1765 				/* tile should be land, but is water */
  1711 				_error_message = STR_3807_CAN_T_BUILD_ON_WATER;
  1766 				_error_message = STR_3807_CAN_T_BUILD_ON_WATER;
  1712 				return CMD_ERROR;
  1767 				return CMD_ERROR;
  1713 			}
  1768 			}
  1714 			//TODO: add height comparison & validation code here
  1769 			//TODO: add height comparison & validation code here
  1844  */
  1899  */
  1845 CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1900 CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1846 {
  1901 {
  1847 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1902 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1848 
  1903 
  1849 	if (!IsClearWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1904 	if (!IsWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1850 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
  1905 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
  1851 
  1906 
  1852 	/* allocate and initialize new station */
  1907 	/* allocate and initialize new station */
  1853 	Station *st = new Station(tile);
  1908 	Station *st = new Station(tile);
  1854 	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1909 	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
  1857 	AutoPtrT<Station> st_auto_delete(st);
  1912 	AutoPtrT<Station> st_auto_delete(st);
  1858 
  1913 
  1859 	st->town = ClosestTownFromTile(tile, (uint)-1);
  1914 	st->town = ClosestTownFromTile(tile, (uint)-1);
  1860 	st->sign.width_1 = 0;
  1915 	st->sign.width_1 = 0;
  1861 
  1916 
  1862 	if (!GenerateStationName(st, tile, 4)) return CMD_ERROR;
  1917 	if (!GenerateStationName(st, tile, STATIONNAMING_BUOY)) return CMD_ERROR;
  1863 
  1918 
  1864 	if (flags & DC_EXEC) {
  1919 	if (flags & DC_EXEC) {
  1865 		st->dock_tile = tile;
  1920 		st->dock_tile = tile;
  1866 		st->facilities |= FACIL_DOCK;
  1921 		st->facilities |= FACIL_DOCK;
  1867 		/* Buoys are marked in the Station struct by this flag. Yes, it is this
  1922 		/* Buoys are marked in the Station struct by this flag. Yes, it is this
  1907 	if (!IsValidPlayer(_current_player))  return_cmd_error(INVALID_STRING_ID);
  1962 	if (!IsValidPlayer(_current_player))  return_cmd_error(INVALID_STRING_ID);
  1908 
  1963 
  1909 	TileIndex tile = st->dock_tile;
  1964 	TileIndex tile = st->dock_tile;
  1910 
  1965 
  1911 	if (CheckShipsOnBuoy(st))   return_cmd_error(STR_BUOY_IS_IN_USE);
  1966 	if (CheckShipsOnBuoy(st))   return_cmd_error(STR_BUOY_IS_IN_USE);
  1912 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
  1967 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
  1913 
  1968 
  1914 	if (flags & DC_EXEC) {
  1969 	if (flags & DC_EXEC) {
  1915 		st->dock_tile = 0;
  1970 		st->dock_tile = 0;
  1916 		/* Buoys are marked in the Station struct by this flag. Yes, it is this
  1971 		/* Buoys are marked in the Station struct by this flag. Yes, it is this
  1917 		 * braindead.. */
  1972 		 * braindead.. */
  1919 		st->had_vehicle_of_type &= ~HVOT_BUOY;
  1974 		st->had_vehicle_of_type &= ~HVOT_BUOY;
  1920 
  1975 
  1921 		/* We have to set the water tile's state to the same state as before the
  1976 		/* We have to set the water tile's state to the same state as before the
  1922 		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
  1977 		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
  1923 		 * remove it and flood the land (if the canal edge is at level 0) */
  1978 		 * remove it and flood the land (if the canal edge is at level 0) */
  1924 		Owner o = GetTileOwner(tile);
  1979 		MakeWaterOrCanalDependingOnSurroundings(tile, GetTileOwner(tile));
  1925 		if (o == OWNER_WATER) {
       
  1926 			MakeWater(tile);
       
  1927 		} else {
       
  1928 			MakeCanal(tile, o);
       
  1929 		}
       
  1930 		MarkTileDirtyByTile(tile);
  1980 		MarkTileDirtyByTile(tile);
  1931 
  1981 
  1932 		UpdateStationVirtCoordDirty(st);
  1982 		UpdateStationVirtCoordDirty(st);
  1933 		DeleteStationIfEmpty(st);
  1983 		DeleteStationIfEmpty(st);
  1934 	}
  1984 	}
  1990 	}
  2040 	}
  1991 
  2041 
  1992 	/* middle */
  2042 	/* middle */
  1993 	Station *st = NULL;
  2043 	Station *st = NULL;
  1994 
  2044 
  1995 	if (!_patches.adjacent_stations || !HASBIT(p1, 0)) {
  2045 	if (!_patches.adjacent_stations || !HasBit(p1, 0)) {
  1996 		st = GetStationAround(
  2046 		st = GetStationAround(
  1997 				tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
  2047 				tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
  1998 				_dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION);
  2048 				_dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION);
  1999 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  2049 		if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
  2000 	}
  2050 	}
  2001 
  2051 
  2002 	/* Find a station close to us */
  2052 	/* Find a station close to us */
  2003 	if (st == NULL) st = GetClosestStationFromTile(tile);
  2053 	if (st == NULL) st = GetClosestStationFromTile(tile);
  2004 
  2054 
  2005 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  2055 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
  2006 	* to test if everything is OK. In this case we need to delete it before return. */
  2056 	 * to test if everything is OK. In this case we need to delete it before return. */
  2007 	AutoPtrT<Station> st_auto_delete;
  2057 	AutoPtrT<Station> st_auto_delete;
  2008 
  2058 
  2009 	if (st != NULL) {
  2059 	if (st != NULL) {
  2010 		if (st->owner != _current_player)
  2060 		if (st->owner != _current_player)
  2011 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
  2061 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
  2022 		st_auto_delete = st;
  2072 		st_auto_delete = st;
  2023 
  2073 
  2024 		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
  2074 		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
  2025 
  2075 
  2026 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  2076 		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
  2027 			SETBIT(t->have_ratings, _current_player);
  2077 			SetBit(t->have_ratings, _current_player);
  2028 		}
  2078 		}
  2029 
  2079 
  2030 		st->sign.width_1 = 0;
  2080 		st->sign.width_1 = 0;
  2031 
  2081 
  2032 		if (!GenerateStationName(st, tile, 3)) return CMD_ERROR;
  2082 		if (!GenerateStationName(st, tile, STATIONNAMING_DOCK)) return CMD_ERROR;
  2033 	}
  2083 	}
  2034 
  2084 
  2035 	if (flags & DC_EXEC) {
  2085 	if (flags & DC_EXEC) {
  2036 		st->dock_tile = tile;
  2086 		st->dock_tile = tile;
  2037 		st->AddFacility(FACIL_DOCK, tile);
  2087 		st->AddFacility(FACIL_DOCK, tile);
  2055 	if (!CheckOwnership(st->owner)) return CMD_ERROR;
  2105 	if (!CheckOwnership(st->owner)) return CMD_ERROR;
  2056 
  2106 
  2057 	TileIndex tile1 = st->dock_tile;
  2107 	TileIndex tile1 = st->dock_tile;
  2058 	TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
  2108 	TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
  2059 
  2109 
  2060 	if (!EnsureNoVehicle(tile1)) return CMD_ERROR;
  2110 	if (!EnsureNoVehicleOnGround(tile1)) return CMD_ERROR;
  2061 	if (!EnsureNoVehicle(tile2)) return CMD_ERROR;
  2111 	if (!EnsureNoVehicleOnGround(tile2)) return CMD_ERROR;
  2062 
  2112 
  2063 	if (flags & DC_EXEC) {
  2113 	if (flags & DC_EXEC) {
  2064 		DoClearSquare(tile1);
  2114 		DoClearSquare(tile1);
  2065 		MakeWater(tile2);
  2115 		MakeWaterOrCanalDependingOnSurroundings(tile2, st->owner);
  2066 
  2116 
  2067 		st->rect.AfterRemoveTile(st, tile1);
  2117 		st->rect.AfterRemoveTile(st, tile1);
  2068 		st->rect.AfterRemoveTile(st, tile2);
  2118 		st->rect.AfterRemoveTile(st, tile2);
  2069 
  2119 
  2070 		MarkTileDirtyByTile(tile2);
  2120 		MarkTileDirtyByTile(tile2);
  2083 
  2133 
  2084 const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
  2134 const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx)
  2085 {
  2135 {
  2086 	return &_station_display_datas[st][gfx];
  2136 	return &_station_display_datas[st][gfx];
  2087 }
  2137 }
  2088 
       
  2089 /* For drawing canal edges on buoys */
       
  2090 extern void DrawCanalWater(TileIndex tile);
       
  2091 
  2138 
  2092 static void DrawTile_Station(TileInfo *ti)
  2139 static void DrawTile_Station(TileInfo *ti)
  2093 {
  2140 {
  2094 	const DrawTileSprites *t = NULL;
  2141 	const DrawTileSprites *t = NULL;
  2095 	RailType railtype;
  2142 	RailType railtype;
  2111 
  2158 
  2112 	SpriteID palette;
  2159 	SpriteID palette;
  2113 	if (IsValidPlayer(owner)) {
  2160 	if (IsValidPlayer(owner)) {
  2114 		palette = PLAYER_SPRITE_COLOR(owner);
  2161 		palette = PLAYER_SPRITE_COLOR(owner);
  2115 	} else {
  2162 	} else {
  2116 		// Some stations are not owner by a player, namely oil rigs
  2163 		/* Some stations are not owner by a player, namely oil rigs */
  2117 		palette = PALETTE_TO_GREY;
  2164 		palette = PALETTE_TO_GREY;
  2118 	}
  2165 	}
  2119 
  2166 
  2120 	// don't show foundation for docks
  2167 	/* don't show foundation for docks */
  2121 	if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile))
  2168 	if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile))
  2122 		DrawFoundation(ti, FOUNDATION_LEVELED);
  2169 		DrawFoundation(ti, FOUNDATION_LEVELED);
  2123 
  2170 
  2124 	if (IsCustomStationSpecIndex(ti->tile)) {
  2171 	if (IsCustomStationSpecIndex(ti->tile)) {
  2125 		// look for customization
  2172 		/* look for customization */
  2126 		st = GetStationByTile(ti->tile);
  2173 		st = GetStationByTile(ti->tile);
  2127 		int specindex = GetCustomStationSpecIndex(ti->tile);
  2174 		int specindex = GetCustomStationSpecIndex(ti->tile);
  2128 		FSMport = IsCustomFSMportsSpecIndex(ti->tile);
  2175 		FSMport = IsCustomFSMportsSpecIndex(ti->tile);
  2129 		if (FSMport) {
  2176 		if (FSMport) {
  2130 			fsmportspec = st->fsmportsspeclist[specindex].spec;
  2177 			fsmportspec = st->fsmportsspeclist[specindex].spec;
  2137 		if (statspec != NULL) {
  2184 		if (statspec != NULL) {
  2138 			uint tile = GetStationGfx(ti->tile);
  2185 			uint tile = GetStationGfx(ti->tile);
  2139 
  2186 
  2140 			relocation = GetCustomStationRelocation(statspec, st, ti->tile);
  2187 			relocation = GetCustomStationRelocation(statspec, st, ti->tile);
  2141 
  2188 
  2142 			if (HASBIT(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) {
  2189 			if (HasBit(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) {
  2143 				uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
  2190 				uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
  2144 				if (callback != CALLBACK_FAILED) tile = (callback & ~1) + GetRailStationAxis(ti->tile);
  2191 				if (callback != CALLBACK_FAILED) tile = (callback & ~1) + GetRailStationAxis(ti->tile);
  2145 			}
  2192 			}
  2146 
  2193 
  2147 			/* Ensure the chosen tile layout is valid for this custom station */
  2194 			/* Ensure the chosen tile layout is valid for this custom station */
  2167 	}
  2214 	}
  2168 
  2215 
  2169 	if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationType(ti->tile)][GetStationGfx(ti->tile)];
  2216 	if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationType(ti->tile)][GetStationGfx(ti->tile)];
  2170 
  2217 
  2171 	SpriteID image = t->ground_sprite;
  2218 	SpriteID image = t->ground_sprite;
  2172 	if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) {
  2219 	if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
  2173 		image += (FSMport)? GetCustomFSMportsGroundRelocation(fsmportspec, st, ti->tile) : GetCustomStationGroundRelocation(statspec, st, ti->tile);
  2220 		image += (FSMport)? GetCustomFSMportsGroundRelocation(fsmportspec, st, ti->tile) : GetCustomStationGroundRelocation(statspec, st, ti->tile);
  2174 		image += rti->custom_ground_offset;
  2221 		image += rti->custom_ground_offset;
  2175 	} else {
  2222 	} else {
  2176 		image += rti->total_offset;
  2223 		image += rti->total_offset;
  2177 	}
  2224 	}
  2178 
  2225 
  2179 	// if ground tile 0x0F8D, but tile is desert/snow, then choose desert/snow graphic
  2226 	// if ground tile 0x0F8D, but tile is desert/snow, then choose desert/snow graphic
  2180 	if ((image == 0x0F8D) && (GetTropicZone(ti->tile) == TROPICZONE_DESERT))
  2227 	if ((image == 0x0F8D) && (GetTropicZone(ti->tile) == TROPICZONE_DESERT))
  2181 		image = 0x11C6;  // snow tile (arctic) or desert tile (tropical)
  2228 		image = 0x11C6;  // snow tile (arctic) or desert tile (tropical)
  2182 
  2229 
  2183 	// station_land array has been increased from 82 elements to 114
  2230 	/* station_land array has been increased from 82 elements to 114
  2184 	// but this is something else. If AI builds station with 114 it looks all weird
  2231 	 * but this is something else. If AI builds station with 114 it looks all weird */
  2185 	DrawGroundSprite(image, HASBIT(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE);
  2232 	DrawGroundSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE);
  2186 
  2233 
  2187 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
  2234 	if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
  2188 
  2235 
  2189 	if (HASBIT(roadtypes, ROADTYPE_TRAM)) {
  2236 	if (HasBit(roadtypes, ROADTYPE_TRAM)) {
  2190 		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
  2237 		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
  2191 		DrawGroundSprite((HASBIT(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
  2238 		DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
  2192 		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
  2239 		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
  2193 	}
  2240 	}
  2194 
  2241 
  2195 	if (IsBuoyTile(ti->tile) && (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER))) DrawCanalWater(ti->tile);
  2242 	if (IsCanalBuoyTile(ti->tile)) DrawCanalWater(ti->tile);
  2196 
  2243 
  2197 	const DrawTileSeqStruct *dtss;
  2244 	const DrawTileSeqStruct *dtss;
  2198 	foreach_draw_tile_seq(dtss, t->seq) {
  2245 	foreach_draw_tile_seq(dtss, t->seq) {
  2199 		image = dtss->image;
  2246 		image = dtss->image;
  2200 		if (relocation == 0 || HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) {
  2247 		if (relocation == 0 || HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
  2201 			image += rti->total_offset;
  2248 			image += rti->total_offset;
  2202 		} else {
  2249 		} else {
  2203 			image += relocation;
  2250 			image += relocation;
  2204 		}
  2251 		}
  2205 
  2252 
  2206 		SpriteID pal;
  2253 		SpriteID pal;
  2207 		if (!HASBIT(_transparent_opt, TO_BUILDINGS) && HASBIT(image, PALETTE_MODIFIER_COLOR)) {
  2254 		if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
  2208 			pal = palette;
  2255 			pal = palette;
  2209 		} else {
  2256 		} else {
  2210 			pal = dtss->pal;
  2257 			pal = dtss->pal;
  2211 		}
  2258 		}
  2212 
  2259 
  2214 			AddSortableSpriteToDraw(
  2261 			AddSortableSpriteToDraw(
  2215 				image, pal,
  2262 				image, pal,
  2216 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
  2263 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
  2217 				dtss->size_x, dtss->size_y,
  2264 				dtss->size_x, dtss->size_y,
  2218 				dtss->size_z, ti->z + dtss->delta_z,
  2265 				dtss->size_z, ti->z + dtss->delta_z,
  2219 				HASBIT(_transparent_opt, TO_BUILDINGS)
  2266 				IsTransparencySet(TO_BUILDINGS)
  2220 			);
  2267 			);
  2221 		} else {
  2268 		} else {
  2222 			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_BUILDINGS));
  2269 			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, IsTransparencySet(TO_BUILDINGS));
  2223 		}
  2270 		}
  2224 	}
  2271 	}
  2225 }
  2272 }
  2226 
  2273 
  2227 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
  2274 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
  2229 	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
  2276 	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
  2230 	SpriteID pal = PLAYER_SPRITE_COLOR(_local_player);
  2277 	SpriteID pal = PLAYER_SPRITE_COLOR(_local_player);
  2231 	const DrawTileSprites *t = &_station_display_datas[st][image];
  2278 	const DrawTileSprites *t = &_station_display_datas[st][image];
  2232 
  2279 
  2233 	SpriteID img = t->ground_sprite;
  2280 	SpriteID img = t->ground_sprite;
  2234 	DrawSprite(img + rti->total_offset, HASBIT(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
  2281 	DrawSprite(img + rti->total_offset, HasBit(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
  2235 
  2282 
  2236 	if (roadtype == ROADTYPE_TRAM) {
  2283 	if (roadtype == ROADTYPE_TRAM) {
  2237 		DrawSprite(SPR_TRAMWAY_TRAM + (t->ground_sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
  2284 		DrawSprite(SPR_TRAMWAY_TRAM + (t->ground_sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
  2238 	}
  2285 	}
  2239 
  2286 
  2289 				return TrackToTrackBits(GetRailStationTrack(tile)) * 0x101;
  2336 				return TrackToTrackBits(GetRailStationTrack(tile)) * 0x101;
  2290 			}
  2337 			}
  2291 			break;
  2338 			break;
  2292 
  2339 
  2293 		case TRANSPORT_WATER:
  2340 		case TRANSPORT_WATER:
  2294 			// buoy is coded as a station, it is always on open water
  2341 			/* buoy is coded as a station, it is always on open water */
  2295 			if (IsBuoy(tile)) {
  2342 			if (IsBuoy(tile)) {
  2296 				TrackBits ts = TRACK_BIT_ALL;
  2343 				TrackBits ts = TRACK_BIT_ALL;
  2297 				// remove tracks that connect NE map edge
  2344 				/* remove tracks that connect NE map edge */
  2298 				if (TileX(tile) == 0) ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
  2345 				if (TileX(tile) == 0) ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
  2299 				// remove tracks that connect NW map edge
  2346 				/* remove tracks that connect NW map edge */
  2300 				if (TileY(tile) == 0) ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
  2347 				if (TileY(tile) == 0) ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER);
  2301 				return uint32(ts) * 0x101;
  2348 				return uint32(ts) * 0x101;
  2302 			}
  2349 			}
  2303 			break;
  2350 			break;
  2304 
  2351 
  2316 }
  2363 }
  2317 
  2364 
  2318 
  2365 
  2319 static void TileLoop_Station(TileIndex tile)
  2366 static void TileLoop_Station(TileIndex tile)
  2320 {
  2367 {
  2321 	// FIXME -- GetTileTrackStatus_Station -> animated stationtiles
  2368 	/* FIXME -- GetTileTrackStatus_Station -> animated stationtiles
  2322 	// hardcoded.....not good
  2369 	 * hardcoded.....not good */
  2323 	switch (GetStationType(tile)) {
  2370 	switch (GetStationType(tile)) {
  2324 		case STATION_AIRPORT:
  2371 		case STATION_AIRPORT:
  2325 			//TODO: animated tiles from newgrf
  2372 			//TODO: animated tiles from newgrf
  2326 			//switch (GetStationGfx(tile)) {
  2373 			//switch (GetStationGfx(tile)) {
  2327 			//	case GFX_RADAR_LARGE_FIRST:
  2374 			//	case GFX_RADAR_LARGE_FIRST:
  2435 					if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
  2482 					if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
  2436 
  2483 
  2437 					/* Check if the vehicle is stopping at this road stop */
  2484 					/* Check if the vehicle is stopping at this road stop */
  2438 					if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
  2485 					if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
  2439 							v->current_order.dest == GetStationIndex(tile)) {
  2486 							v->current_order.dest == GetStationIndex(tile)) {
  2440 						SETBIT(v->u.road.state, RVS_IS_STOPPING);
  2487 						SetBit(v->u.road.state, RVS_IS_STOPPING);
  2441 						rs->AllocateDriveThroughBay(side);
  2488 						rs->AllocateDriveThroughBay(side);
  2442 					}
  2489 					}
  2443 
  2490 
  2444 					/* Indicate if vehicle is using second bay. */
  2491 					/* Indicate if vehicle is using second bay. */
  2445 					if (side == 1) SETBIT(v->u.road.state, RVS_USING_SECOND_BAY);
  2492 					if (side == 1) SetBit(v->u.road.state, RVS_USING_SECOND_BAY);
  2446 					/* Indicate a drive-through stop */
  2493 					/* Indicate a drive-through stop */
  2447 					SETBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP);
  2494 					SetBit(v->u.road.state, RVS_IN_DT_ROAD_STOP);
  2448 					return VETSB_CONTINUE;
  2495 					return VETSB_CONTINUE;
  2449 				}
  2496 				}
  2450 
  2497 
  2451 				/* For normal (non drive-through) road stops */
  2498 				/* For normal (non drive-through) road stops */
  2452 				/* Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */
  2499 				/* Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */
  2453 				if (rs->IsEntranceBusy() || !rs->HasFreeBay() || RoadVehHasArticPart(v)) return VETSB_CANNOT_ENTER;
  2500 				if (rs->IsEntranceBusy() || !rs->HasFreeBay() || RoadVehHasArticPart(v)) return VETSB_CANNOT_ENTER;
  2454 
  2501 
  2455 				SETBIT(v->u.road.state, RVS_IN_ROAD_STOP);
  2502 				SetBit(v->u.road.state, RVS_IN_ROAD_STOP);
  2456 
  2503 
  2457 				/* Allocate a bay and update the road state */
  2504 				/* Allocate a bay and update the road state */
  2458 				uint bay_nr = rs->AllocateBay();
  2505 				uint bay_nr = rs->AllocateBay();
  2459 				SB(v->u.road.state, RVS_USING_SECOND_BAY, 1, bay_nr);
  2506 				SB(v->u.road.state, RVS_USING_SECOND_BAY, 1, bay_nr);
  2460 
  2507 
  2488 	GoodsEntry *ge = st->goods;
  2535 	GoodsEntry *ge = st->goods;
  2489 	do {
  2536 	do {
  2490 		/* Slowly increase the rating back to his original level in the case we
  2537 		/* Slowly increase the rating back to his original level in the case we
  2491 		 *  didn't deliver cargo yet to this station. This happens when a bribe
  2538 		 *  didn't deliver cargo yet to this station. This happens when a bribe
  2492 		 *  failed while you didn't moved that cargo yet to a station. */
  2539 		 *  failed while you didn't moved that cargo yet to a station. */
  2493 		if (!HASBIT(ge->acceptance_pickup, GoodsEntry::PICKUP) && ge->rating < INITIAL_STATION_RATING) {
  2540 		if (!HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP) && ge->rating < INITIAL_STATION_RATING) {
  2494 			ge->rating++;
  2541 			ge->rating++;
  2495 		}
  2542 		}
  2496 
  2543 
  2497 		/* Only change the rating if we are moving this cargo */
  2544 		/* Only change the rating if we are moving this cargo */
  2498 		if (HASBIT(ge->acceptance_pickup, GoodsEntry::PICKUP)) {
  2545 		if (HasBit(ge->acceptance_pickup, GoodsEntry::PICKUP)) {
  2499 			byte_inc_sat(&ge->days_since_pickup);
  2546 			byte_inc_sat(&ge->days_since_pickup);
  2500 
  2547 
  2501 			int rating = 0;
  2548 			int rating = 0;
  2502 
  2549 
  2503 			{
  2550 			{
  2512 				(rating += 10, age >= 2) ||
  2559 				(rating += 10, age >= 2) ||
  2513 				(rating += 10, age >= 1) ||
  2560 				(rating += 10, age >= 1) ||
  2514 				(rating += 13, true);
  2561 				(rating += 13, true);
  2515 			}
  2562 			}
  2516 
  2563 
  2517 			if (IsValidPlayer(st->owner) && HASBIT(st->town->statues, st->owner)) rating += 26;
  2564 			if (IsValidPlayer(st->owner) && HasBit(st->town->statues, st->owner)) rating += 26;
  2518 
  2565 
  2519 			{
  2566 			{
  2520 				byte days = ge->days_since_pickup;
  2567 				byte days = ge->days_since_pickup;
  2521 				if (st->last_vehicle_type == VEH_SHIP)
  2568 				if (st->last_vehicle_type == VEH_SHIP) days >>= 2;
  2522 							days >>= 2;
       
  2523 				(days > 21) ||
  2569 				(days > 21) ||
  2524 				(rating += 25, days > 12) ||
  2570 				(rating += 25, days > 12) ||
  2525 				(rating += 25, days > 6) ||
  2571 				(rating += 25, days > 6) ||
  2526 				(rating += 45, days > 3) ||
  2572 				(rating += 45, days > 3) ||
  2527 				(rating += 35, true);
  2573 				(rating += 35, true);
  2536 			(rating += 10, true);
  2582 			(rating += 10, true);
  2537 
  2583 
  2538 			{
  2584 			{
  2539 				int or_ = ge->rating; // old rating
  2585 				int or_ = ge->rating; // old rating
  2540 
  2586 
  2541 				// only modify rating in steps of -2, -1, 0, 1 or 2
  2587 				/* only modify rating in steps of -2, -1, 0, 1 or 2 */
  2542 				ge->rating = rating = or_ + clamp(clamp(rating, 0, 255) - or_, -2, 2);
  2588 				ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2);
  2543 
  2589 
  2544 				// if rating is <= 64 and more than 200 items waiting, remove some random amount of goods from the station
  2590 				/* if rating is <= 64 and more than 200 items waiting,
       
  2591 				 * remove some random amount of goods from the station */
  2545 				if (rating <= 64 && waiting >= 200) {
  2592 				if (rating <= 64 && waiting >= 200) {
  2546 					int dec = Random() & 0x1F;
  2593 					int dec = Random() & 0x1F;
  2547 					if (waiting < 400) dec &= 7;
  2594 					if (waiting < 400) dec &= 7;
  2548 					waiting -= dec + 1;
  2595 					waiting -= dec + 1;
  2549 					waiting_changed = true;
  2596 					waiting_changed = true;
  2550 				}
  2597 				}
  2551 
  2598 
  2552 				// if rating is <= 127 and there are any items waiting, maybe remove some goods.
  2599 				/* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
  2553 				if (rating <= 127 && waiting != 0) {
  2600 				if (rating <= 127 && waiting != 0) {
  2554 					uint32 r = Random();
  2601 					uint32 r = Random();
  2555 					if (rating <= (int)GB(r, 0, 7)) {
  2602 					if (rating <= (int)GB(r, 0, 7)) {
  2556 						/* Need to have int, otherwise it will just overflow etc. */
  2603 						/* Need to have int, otherwise it will just overflow etc. */
  2557 						waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0);
  2604 						waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0);
  2626 				DistanceManhattan(tile, st->xy) <= radius) {
  2673 				DistanceManhattan(tile, st->xy) <= radius) {
  2627 			for (CargoID i = 0; i < NUM_CARGO; i++) {
  2674 			for (CargoID i = 0; i < NUM_CARGO; i++) {
  2628 				GoodsEntry* ge = &st->goods[i];
  2675 				GoodsEntry* ge = &st->goods[i];
  2629 
  2676 
  2630 				if (ge->acceptance_pickup != 0) {
  2677 				if (ge->acceptance_pickup != 0) {
  2631 					ge->rating = clamp(ge->rating + amount, 0, 255);
  2678 					ge->rating = Clamp(ge->rating + amount, 0, 255);
  2632 				}
  2679 				}
  2633 			}
  2680 			}
  2634 		}
  2681 		}
  2635 	}
  2682 	}
  2636 }
  2683 }
  2637 
  2684 
  2638 static void UpdateStationWaiting(Station *st, CargoID type, uint amount)
  2685 static void UpdateStationWaiting(Station *st, CargoID type, uint amount)
  2639 {
  2686 {
  2640 	st->goods[type].cargo.Append(new CargoPacket(st->index, amount));
  2687 	st->goods[type].cargo.Append(new CargoPacket(st->index, amount));
  2641 	SETBIT(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
  2688 	SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP);
  2642 
  2689 
  2643 	InvalidateWindow(WC_STATION_VIEW, st->index);
  2690 	InvalidateWindow(WC_STATION_VIEW, st->index);
  2644 	st->MarkTilesDirty(true);
  2691 	st->MarkTilesDirty(true);
  2645 }
  2692 }
  2646 
  2693 
  2689 	}
  2736 	}
  2690 
  2737 
  2691 	return CommandCost();
  2738 	return CommandCost();
  2692 }
  2739 }
  2693 
  2740 
  2694 
  2741 /**
  2695 uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount)
  2742 * Find all (non-buoy) stations around an industry tile
  2696 {
  2743 *
  2697 	Station* around[8];
  2744 * @param tile: Center tile to search from
  2698 
  2745 * @param w: Width of the center
  2699 	for (uint i = 0; i < lengthof(around); i++) around[i] = NULL;
  2746 * @param h: Height of the center
  2700 
  2747 *
  2701 	int w_prod; //width and height of the "producer" of the cargo
  2748 * @return: Set of found stations
       
  2749 */
       
  2750 StationSet FindStationsAroundIndustryTile(TileIndex tile, int w, int h)
       
  2751 {
       
  2752 	StationSet station_set;
       
  2753 
       
  2754 	int w_prod; // width and height of the "producer" of the cargo
  2702 	int h_prod;
  2755 	int h_prod;
  2703 	int max_rad;
  2756 	int max_rad;
  2704 	if (_patches.modified_catchment) {
  2757 	if (_patches.modified_catchment) {
  2705 		w_prod = w;
  2758 		w_prod = w;
  2706 		h_prod = h;
  2759 		h_prod = h;
  2719 		cur_tile = TILE_MASK(cur_tile);
  2772 		cur_tile = TILE_MASK(cur_tile);
  2720 		if (!IsTileType(cur_tile, MP_STATION)) continue;
  2773 		if (!IsTileType(cur_tile, MP_STATION)) continue;
  2721 
  2774 
  2722 		Station *st = GetStationByTile(cur_tile);
  2775 		Station *st = GetStationByTile(cur_tile);
  2723 
  2776 
  2724 		for (uint i = 0; i != lengthof(around); i++) {
  2777 		if (st->IsBuoy()) continue; // bouys don't accept cargo
  2725 			if (around[i] == NULL) {
  2778 
  2726 				if (!st->IsBuoy() &&
  2779 
  2727 						(st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights
  2780 		if (_patches.modified_catchment) {
  2728 						st->goods[type].rating != 0 && // when you've got the lowest rating you can get, it's better not to give cargo anymore
  2781 			/* min and max coordinates of the producer relative */
  2729 						(!_patches.selectgoods || st->goods[type].last_speed != 0) && // we are servicing the station (or cargo is dumped on all stations)
  2782 			const int x_min_prod = max_rad + 1;
  2730 						((st->facilities & ~FACIL_BUS_STOP)   != 0 || IsCargoInClass(type, CC_PASSENGERS)) && // if we have other fac. than a bus stop, or the cargo is passengers
  2783 			const int x_max_prod = max_rad + w_prod;
  2731 						((st->facilities & ~FACIL_TRUCK_STOP) != 0 || !IsCargoInClass(type, CC_PASSENGERS))) { // if we have other fac. than a cargo bay or the cargo is not passengers
  2784 			const int y_min_prod = max_rad + 1;
  2732 					if (_patches.modified_catchment) {
  2785 			const int y_max_prod = max_rad + h_prod;
  2733 						// min and max coordinates of the producer relative
  2786 
  2734 						const int x_min_prod = max_rad + 1;
  2787 			int rad = FindCatchmentRadius(st);
  2735 						const int x_max_prod = max_rad + w_prod;
  2788 
  2736 						const int y_min_prod = max_rad + 1;
  2789 			int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur);
  2737 						const int y_max_prod = max_rad + h_prod;
  2790 			if (w_cur < x_min_prod) {
  2738 
  2791 				x_dist = x_min_prod - w_cur;
  2739 						int rad = FindCatchmentRadius(st);
  2792 			} else if (w_cur > x_max_prod) {
  2740 
  2793 				x_dist = w_cur - x_max_prod;
  2741 						int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur);
  2794 			}
  2742 						if (w_cur < x_min_prod) {
  2795 
  2743 							x_dist = x_min_prod - w_cur;
  2796 			if (x_dist > rad) continue;
  2744 						} else if (w_cur > x_max_prod) {
  2797 
  2745 							x_dist = w_cur - x_max_prod;
  2798 			int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur);
  2746 						}
  2799 			if (h_cur < y_min_prod) {
  2747 
  2800 				y_dist = y_min_prod - h_cur;
  2748 						int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur);
  2801 			} else if (h_cur > y_max_prod) {
  2749 						if (h_cur < y_min_prod) {
  2802 				y_dist = h_cur - y_max_prod;
  2750 							y_dist = y_min_prod - h_cur;
  2803 			}
  2751 						} else if (h_cur > y_max_prod) {
  2804 
  2752 							y_dist = h_cur - y_max_prod;
  2805 			if (y_dist > rad) continue;
  2753 						}
  2806 		}
  2754 
  2807 
  2755 						if (x_dist > rad || y_dist > rad) break;
  2808 		/* Insert the station in the set. This will fail if it has
  2756 					}
  2809 		 * already been added.
  2757 
  2810 		 */
  2758 					around[i] = st;
  2811 		station_set.insert(st);
  2759 				}
  2812 
  2760 				break;
       
  2761 			} else if (around[i] == st) {
       
  2762 				break;
       
  2763 			}
       
  2764 		}
       
  2765 	END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad))
  2813 	END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad))
  2766 
  2814 
       
  2815 	return station_set;
       
  2816 }
       
  2817 
       
  2818 uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount)
       
  2819 {
       
  2820 	Station *st1 = NULL;	// Station with best rating
       
  2821 	Station *st2 = NULL;	// Second best station
       
  2822 	uint best_rating1 = 0;	// rating of st1
       
  2823 	uint best_rating2 = 0;	// rating of st2
       
  2824 
       
  2825 	StationSet all_stations = FindStationsAroundIndustryTile(tile, w, h);
       
  2826 	for (StationSet::iterator st_iter = all_stations.begin(); st_iter != all_stations.end(); ++st_iter) {
       
  2827 		Station *st = *st_iter;
       
  2828 
       
  2829 		/* Is the station reserved exclusively for somebody else? */
       
  2830 		if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
       
  2831 
       
  2832 		if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
       
  2833 
       
  2834 		if (_patches.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one
       
  2835 
       
  2836 		if (IsCargoInClass(type, CC_PASSENGERS)) {
       
  2837 			if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
       
  2838 		} else {
       
  2839 			if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
       
  2840 		}
       
  2841 
       
  2842 		/* This station can be used, add it to st1/st2 */
       
  2843 		if (st1 == NULL || st->goods[type].rating >= best_rating1) {
       
  2844 			st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating;
       
  2845 		} else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
       
  2846 			st2 = st; best_rating2 = st->goods[type].rating;
       
  2847 		}
       
  2848 	}
       
  2849 
  2767 	/* no stations around at all? */
  2850 	/* no stations around at all? */
  2768 	if (around[0] == NULL) return 0;
  2851 	if (st1 == NULL) return 0;
  2769 
  2852 
  2770 	if (around[1] == NULL) {
  2853 	if (st2 == NULL) {
  2771 		/* only one station around */
  2854 		/* only one station around */
  2772 		uint moved = (amount * around[0]->goods[type].rating >> 8) + 1;
  2855 		uint moved = amount * best_rating1 / 256 + 1;
  2773 		UpdateStationWaiting(around[0], type, moved);
  2856 		UpdateStationWaiting(st1, type, moved);
  2774 		return moved;
  2857 		return moved;
  2775 	}
  2858 	}
  2776 
  2859 
  2777 	/* several stations around, find the two with the highest rating */
  2860 	/* several stations around, the best two (highest rating) are in st1 and st2 */
  2778 	Station *st1 = NULL;
       
  2779 	Station *st2 = NULL;
       
  2780 	uint best_rating  = 0;
       
  2781 	uint best_rating2 = 0;
       
  2782 
       
  2783 	for (uint i = 0; i != lengthof(around) && around[i] != NULL; i++) {
       
  2784 		if (around[i]->goods[type].rating >= best_rating) {
       
  2785 			best_rating2 = best_rating;
       
  2786 			st2 = st1;
       
  2787 
       
  2788 			best_rating = around[i]->goods[type].rating;
       
  2789 			st1 = around[i];
       
  2790 		} else if (around[i]->goods[type].rating >= best_rating2) {
       
  2791 			best_rating2 = around[i]->goods[type].rating;
       
  2792 			st2 = around[i];
       
  2793 		}
       
  2794 	}
       
  2795 
       
  2796 	assert(st1 != NULL);
  2861 	assert(st1 != NULL);
  2797 	assert(st2 != NULL);
  2862 	assert(st2 != NULL);
  2798 	assert(best_rating != 0 || best_rating2 != 0);
  2863 	assert(best_rating1 != 0 || best_rating2 != 0);
  2799 
  2864 
  2800 	/* the 2nd highest one gets a penalty */
  2865 	/* the 2nd highest one gets a penalty */
  2801 	best_rating2 >>= 1;
  2866 	best_rating2 >>= 1;
  2802 
  2867 
  2803 	/* amount given to station 1 */
  2868 	/* amount given to station 1 */
  2804 	uint t = (best_rating * (amount + 1)) / (best_rating + best_rating2);
  2869 	uint t = (best_rating1 * (amount + 1)) / (best_rating1 + best_rating2);
  2805 
  2870 
  2806 	uint moved = 0;
  2871 	uint moved = 0;
  2807 	if (t != 0) {
  2872 	if (t != 0) {
  2808 		moved = t * best_rating / 256 + 1;
  2873 		moved = t * best_rating1 / 256 + 1;
  2809 		amount -= t;
  2874 		amount -= t;
  2810 		UpdateStationWaiting(st1, type, moved);
  2875 		UpdateStationWaiting(st1, type, moved);
  2811 	}
  2876 	}
  2812 
  2877 
  2813 	if (amount != 0) {
  2878 	if (amount != 0) {
  2825 
  2890 
  2826 	if (st == NULL) {
  2891 	if (st == NULL) {
  2827 		DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
  2892 		DEBUG(misc, 0, "Can't allocate station for oilrig at 0x%X, reverting to oilrig only", tile);
  2828 		return;
  2893 		return;
  2829 	}
  2894 	}
  2830 	if (!GenerateStationName(st, tile, 2)) {
       
  2831 		DEBUG(misc, 0, "Can't allocate station-name for oilrig at 0x%X, reverting to oilrig only", tile);
       
  2832 		return;
       
  2833 	}
       
  2834 
  2895 
  2835 	st->town = ClosestTownFromTile(tile, (uint)-1);
  2896 	st->town = ClosestTownFromTile(tile, (uint)-1);
  2836 	st->sign.width_1 = 0;
  2897 	st->sign.width_1 = 0;
       
  2898 
       
  2899 	if (!GenerateStationName(st, tile, STATIONNAMING_OILRIG)) {
       
  2900 		DEBUG(misc, 0, "Can't allocate station-name for oilrig at 0x%X, reverting to oilrig only", tile);
       
  2901 		delete st;
       
  2902 		return;
       
  2903 	}
  2837 
  2904 
  2838 	MakeOilrig(tile, st->index);
  2905 	MakeOilrig(tile, st->index);
  2839 
  2906 
  2840 	st->owner = OWNER_NONE;
  2907 	st->owner = OWNER_NONE;
  2841 	st->airport_flags.ResetAll();
  2908 	st->airport_flags.ResetAll();
  2926 {
  2993 {
  2927 	if (flags & DC_AUTO) {
  2994 	if (flags & DC_AUTO) {
  2928 		switch (GetStationType(tile)) {
  2995 		switch (GetStationType(tile)) {
  2929 			case STATION_RAIL:    return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD);
  2996 			case STATION_RAIL:    return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD);
  2930 			case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST);
  2997 			case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST);
  2931 			case STATION_TRUCK:   return_cmd_error(HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION);
  2998 			case STATION_TRUCK:   return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION);
  2932 			case STATION_BUS:     return_cmd_error(HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION);
  2999 			case STATION_BUS:     return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION);
  2933 			case STATION_BUOY:    return_cmd_error(STR_306A_BUOY_IN_THE_WAY);
  3000 			case STATION_BUOY:    return_cmd_error(STR_306A_BUOY_IN_THE_WAY);
  2934 			case STATION_DOCK:    return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST);
  3001 			case STATION_DOCK:    return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST);
  2935 			case STATION_OILRIG:
  3002 			case STATION_OILRIG:
  2936 				SetDParam(0, STR_4807_OIL_RIG);
  3003 				SetDParam(0, STR_4807_OIL_RIG);
  2937 				return_cmd_error(STR_4800_IN_THE_WAY);
  3004 				return_cmd_error(STR_4800_IN_THE_WAY);
  3080 	SLE_CONDVAR(Station, dock_tile,                  SLE_UINT32,                  6, SL_MAX_VERSION),
  3147 	SLE_CONDVAR(Station, dock_tile,                  SLE_UINT32,                  6, SL_MAX_VERSION),
  3081 	    SLE_REF(Station, town,                       REF_TOWN),
  3148 	    SLE_REF(Station, town,                       REF_TOWN),
  3082 	    SLE_VAR(Station, trainst_w,                  SLE_UINT8),
  3149 	    SLE_VAR(Station, trainst_w,                  SLE_UINT8),
  3083 	SLE_CONDVAR(Station, trainst_h,                  SLE_UINT8,                   2, SL_MAX_VERSION),
  3150 	SLE_CONDVAR(Station, trainst_h,                  SLE_UINT8,                   2, SL_MAX_VERSION),
  3084 
  3151 
  3085 	// alpha_order was stored here in savegame format 0 - 3
  3152 	/* alpha_order was stored here in savegame format 0 - 3 */
  3086 	SLE_CONDNULL(1, 0, 3),
  3153 	SLE_CONDNULL(1, 0, 3),
  3087 
  3154 
  3088 	    SLE_VAR(Station, string_id,                  SLE_STRINGID),
  3155 	    SLE_VAR(Station, string_id,                  SLE_STRINGID),
  3089 	    SLE_VAR(Station, had_vehicle_of_type,        SLE_UINT16),
  3156 	    SLE_VAR(Station, had_vehicle_of_type,        SLE_UINT16),
  3090 
  3157 
  3104 	SLE_CONDARR(Station, airport_flags,              SLE_UINT64, 2,              NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION),
  3171 	SLE_CONDARR(Station, airport_flags,              SLE_UINT64, 2,              NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION),
  3105 
  3172 
  3106 	SLE_CONDNULL(2, 0, 25), /* Ex last-vehicle */
  3173 	SLE_CONDNULL(2, 0, 25), /* Ex last-vehicle */
  3107 	SLE_CONDVAR(Station, last_vehicle_type,          SLE_UINT8,                  26, SL_MAX_VERSION),
  3174 	SLE_CONDVAR(Station, last_vehicle_type,          SLE_UINT8,                  26, SL_MAX_VERSION),
  3108 
  3175 
  3109 	// Was custom station class and id
  3176 	/* Was custom station class and id */
  3110 	SLE_CONDNULL(2, 3, 25),
  3177 	SLE_CONDNULL(2, 3, 25),
  3111 	SLE_CONDVAR(Station, build_date,                 SLE_FILE_U16 | SLE_VAR_I32,  3, 30),
  3178 	SLE_CONDVAR(Station, build_date,                 SLE_FILE_U16 | SLE_VAR_I32,  3, 30),
  3112 	SLE_CONDVAR(Station, build_date,                 SLE_INT32,                  31, SL_MAX_VERSION),
  3179 	SLE_CONDVAR(Station, build_date,                 SLE_INT32,                  31, SL_MAX_VERSION),
  3113 
  3180 
  3114 	SLE_CONDREF(Station, bus_stops,                  REF_ROADSTOPS,               6, SL_MAX_VERSION),
  3181 	SLE_CONDREF(Station, bus_stops,                  REF_ROADSTOPS,               6, SL_MAX_VERSION),
  3123 	SLE_CONDVAR(Station, FSMport_orientation,        SLE_UINT8,                  NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION),
  3190 	SLE_CONDVAR(Station, FSMport_orientation,        SLE_UINT8,                  NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION),
  3124 	SLE_CONDVAR(Station, FSMport_flood_protected,    SLE_BOOL,                   NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION),
  3191 	SLE_CONDVAR(Station, FSMport_flood_protected,    SLE_BOOL,                   NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION),
  3125 
  3192 
  3126 	SLE_CONDLST(Station, loading_vehicles,           REF_VEHICLE,                57, SL_MAX_VERSION),
  3193 	SLE_CONDLST(Station, loading_vehicles,           REF_VEHICLE,                57, SL_MAX_VERSION),
  3127 
  3194 
  3128 	// reserve extra space in savegame here. (currently 32 bytes)
  3195 	/* reserve extra space in savegame here. (currently 32 bytes) */
  3129 	SLE_CONDNULL(32, 2, SL_MAX_VERSION),
  3196 	SLE_CONDNULL(32, 2, SL_MAX_VERSION),
  3130 
  3197 
  3131 	SLE_END()
  3198 	SLE_END()
  3132 };
  3199 };
  3133 
  3200 
  3181 	uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
  3248 	uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
  3182 	for (CargoID i = 0; i < num_cargo; i++) {
  3249 	for (CargoID i = 0; i < num_cargo; i++) {
  3183 		GoodsEntry *ge = &st->goods[i];
  3250 		GoodsEntry *ge = &st->goods[i];
  3184 		SlObject(ge, _goods_desc);
  3251 		SlObject(ge, _goods_desc);
  3185 		if (CheckSavegameVersion(68)) {
  3252 		if (CheckSavegameVersion(68)) {
  3186 			SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HASBIT(_waiting_acceptance, 15));
  3253 			SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
  3187 			if (GB(_waiting_acceptance, 0, 12) != 0) {
  3254 			if (GB(_waiting_acceptance, 0, 12) != 0) {
  3188 				/* Don't construct the packet with station here, because that'll fail with old savegames */
  3255 				/* Don't construct the packet with station here, because that'll fail with old savegames */
  3189 				CargoPacket *cp = new CargoPacket();
  3256 				CargoPacket *cp = new CargoPacket();
  3190 				/* In old versions, enroute_from used 0xFF as INVALID_STATION */
  3257 				/* In old versions, enroute_from used 0xFF as INVALID_STATION */
  3191 				cp->source          = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
  3258 				cp->source          = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
  3219 }
  3286 }
  3220 
  3287 
  3221 static void Save_STNS()
  3288 static void Save_STNS()
  3222 {
  3289 {
  3223 	Station *st;
  3290 	Station *st;
  3224 	// Write the stations
  3291 	/* Write the stations */
  3225 	FOR_ALL_STATIONS(st) {
  3292 	FOR_ALL_STATIONS(st) {
  3226 		SlSetArrayIndex(st->index);
  3293 		SlSetArrayIndex(st->index);
  3227 		SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
  3294 		SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
  3228 	}
  3295 	}
  3229 }
  3296 }
  3234 	while ((index = SlIterateArray()) != -1) {
  3301 	while ((index = SlIterateArray()) != -1) {
  3235 		Station *st = new (index) Station();
  3302 		Station *st = new (index) Station();
  3236 
  3303 
  3237 		SaveLoad_STNS(st);
  3304 		SaveLoad_STNS(st);
  3238 
  3305 
  3239 		// this means it's an oldstyle savegame without support for nonuniform stations
  3306 		/* this means it's an oldstyle savegame without support for nonuniform stations */
  3240 		if (st->train_tile != 0 && st->trainst_h == 0) {
  3307 		if (st->train_tile != 0 && st->trainst_h == 0) {
  3241 			uint w = GB(st->trainst_w, 4, 4);
  3308 			uint w = GB(st->trainst_w, 4, 4);
  3242 			uint h = GB(st->trainst_w, 0, 4);
  3309 			uint h = GB(st->trainst_w, 0, 4);
  3243 
  3310 
  3244 			if (GetRailStationAxis(st->train_tile) != AXIS_X) Swap(w, h);
  3311 			if (GetRailStationAxis(st->train_tile) != AXIS_X) Swap(w, h);