--- a/src/station_cmd.cpp Sun Jun 17 21:31:00 2007 +0000
+++ b/src/station_cmd.cpp Tue Jun 26 23:40:58 2007 +0000
@@ -285,11 +285,7 @@
}
tmp = free_names & ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6) | (1 << 7) | (1 << 12) | (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30));
- if (tmp == 0) {
- _error_message = STR_3007_TOO_MANY_STATIONS_LOADING;
- return false;
- }
- found = FindFirstBit(tmp);
+ found = (tmp == 0) ? M(STR_SV_STNAME_FALLBACK) : FindFirstBit(tmp);
done:
st->string_id = found + STR_SV_STNAME;
@@ -355,7 +351,7 @@
uint mask = 0;
for (CargoID i = 0; i < NUM_CARGO; i++) {
- if (st->goods[i].waiting_acceptance & 0x8000) mask |= 1 << i;
+ if (st->goods[i].acceptance) mask |= 1 << i;
}
return mask;
}
@@ -536,7 +532,7 @@
(is_passengers && !(st->facilities & (byte)~FACIL_TRUCK_STOP)))
amt = 0;
- SB(st->goods[i].waiting_acceptance, 12, 4, amt);
+ st->goods[i].acceptance = (amt >= 8);
}
// Only show a message in case the acceptance was actually changed.
@@ -612,13 +608,13 @@
UpdateStationSignCoord(st);
}
-static int32 ClearTile_Station(TileIndex tile, byte flags);
+static CommandCost ClearTile_Station(TileIndex tile, byte flags);
// Tries to clear the given area. Returns the cost in case of success.
// Or an error code if it failed.
-int32 CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint invalid_dirs, StationID* station, bool check_clear = true)
+CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint invalid_dirs, StationID* station, bool check_clear = true)
{
- int32 cost = 0;
+ CommandCost cost;
int allowed_z = -1;
BEGIN_TILE_LOOP(tile_cur, w, h, tile) {
@@ -653,7 +649,7 @@
(invalid_dirs & 8 && !(tileh & SLOPE_NW) && (uint)h_cur == h)) {
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
}
- cost += _price.terraform;
+ cost.AddCost(_price.terraform);
flat_z += TILE_HEIGHT;
}
@@ -680,9 +676,9 @@
}
}
} else if (check_clear) {
- int32 ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
+ CommandCost ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(ret)) return ret;
- cost += ret;
+ cost.AddCost(ret);
}
} END_TILE_LOOP(tile_cur, w, h, tile)
@@ -801,10 +797,10 @@
* - p2 = (bit 8-15) - custom station class
* - p2 = (bit 16-23) - custom station id
*/
-int32 CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildRailroadStation(TileIndex tile_org, uint32 flags, uint32 p1, uint32 p2)
{
int w_org, h_org;
- int32 ret;
+ CommandCost ret;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -838,7 +834,7 @@
// for detail info, see: https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365
ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
if (CmdFailed(ret)) return ret;
- int32 cost = ret + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len;
+ CommandCost cost(ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len);
Station *st = NULL;
bool check_surrounding = true;
@@ -1054,7 +1050,7 @@
* @param p1 start_tile
* @param p2 unused
*/
-int32 CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
TileIndex start = p1 == 0 ? tile : p1;
@@ -1121,11 +1117,11 @@
/* If we've not removed any tiles, give an error */
if (quantity == 0) return CMD_ERROR;
- return _price.remove_rail_station * quantity;
+ return CommandCost(_price.remove_rail_station * quantity);
}
-static int32 RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
+static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
{
/* if there is flooding and non-uniform stations are enabled, remove platforms tile by tile */
if (_current_player == OWNER_WATER && _patches.nonuniform_stations)
@@ -1142,7 +1138,7 @@
assert(w != 0 && h != 0);
- int32 cost = 0;
+ CommandCost cost;
/* clear all areas of the station */
do {
int w_bak = w;
@@ -1151,7 +1147,7 @@
if (st->TileBelongsToRailStation(tile)) {
if (!EnsureNoVehicle(tile))
return CMD_ERROR;
- cost += _price.remove_rail_station;
+ cost.AddCost(_price.remove_rail_station);
if (flags & DC_EXEC) {
Track track = GetRailStationTrack(tile);
DoClearSquare(tile);
@@ -1191,7 +1187,7 @@
* @return The cost and state of the operation
* @retval CMD_ERROR An error occured during the operation.
*/
-int32 DoConvertStationRail(TileIndex tile, RailType totype, bool exec)
+CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec)
{
const Station* st = GetStationByTile(tile);
@@ -1211,7 +1207,7 @@
YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
}
- return _price.build_rail / 2;
+ return CommandCost(_price.build_rail / 2);
}
/**
@@ -1243,7 +1239,7 @@
* bit 2..4: the roadtypes
* bit 5: allow stations directly adjacent to other stations.
*/
-int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
bool type = HASBIT(p2, 0);
bool is_drive_through = HASBIT(p2, 1);
@@ -1267,7 +1263,7 @@
if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
- int32 cost = 0;
+ CommandCost cost;
/* Not allowed to build over this road */
if (build_over_road) {
@@ -1340,7 +1336,7 @@
st->sign.width_1 = 0;
}
- cost += (type) ? _price.build_truck_station : _price.build_bus_station;
+ cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station);
if (flags & DC_EXEC) {
// Insert into linked list of RoadStops
@@ -1371,7 +1367,7 @@
}
// Remove a bus station
-static int32 RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
+static CommandCost RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
{
if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) {
return CMD_ERROR;
@@ -1416,7 +1412,7 @@
DeleteStationIfEmpty(st);
}
- return (is_truck) ? _price.remove_truck_station : _price.remove_bus_station;
+ return CommandCost((is_truck) ? _price.remove_truck_station : _price.remove_bus_station);
}
/** Remove a bus or truck stop
@@ -1425,7 +1421,7 @@
* @param p1 not used
* @param p2 bit 0: 0 for Bus stops, 1 for truck stops
*/
-int32 CmdRemoveRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdRemoveRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
/* Make sure the specified tile is a road stop of the correct type */
if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile) || (uint32)GetRoadStopType(tile) != p2) return CMD_ERROR;
@@ -1438,10 +1434,10 @@
DiagDirToRoadBits(GetRoadStopDir(tile));
bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
- int32 ret = RemoveRoadStop(st, flags, tile);
+ CommandCost ret = RemoveRoadStop(st, flags, tile);
/* If the stop was a drive-through stop replace the road */
- if ((flags & DC_EXEC) && !CmdFailed(ret) && is_drive_through) {
+ if ((flags & DC_EXEC) && CmdSucceeded(ret) && is_drive_through) {
/* Rebuild the drive throuhg road stop. As a road stop can only be
* removed by the owner of the roadstop, _current_player is the
* owner of the road stop. */
@@ -1550,7 +1546,7 @@
* @param p1 airport type, @see airport.h
* @param p2 (bit 0) - allow airports directly adjacent to other airports.
*/
-int32 CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildAirport(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
bool airport_upgrade = true;
@@ -1582,9 +1578,9 @@
int w = afc->size_x;
int h = afc->size_y;
- int32 ret = CheckFlatLandBelow(tile, w, h, flags, 0, NULL);
+ CommandCost ret = CheckFlatLandBelow(tile, w, h, flags, 0, NULL);
if (CmdFailed(ret)) return ret;
- int32 cost = ret;
+ CommandCost cost(ret.GetCost());
Station *st = NULL;
@@ -1638,7 +1634,7 @@
}
}
- cost += _price.build_airport * w * h;
+ cost.AddCost(_price.build_airport * w * h);
if (flags & DC_EXEC) {
st->airport_tile = tile;
@@ -1676,7 +1672,7 @@
return cost;
}
-static int32 RemoveAirport(Station *st, uint32 flags)
+static CommandCost RemoveAirport(Station *st, uint32 flags)
{
if (_current_player != OWNER_WATER && !CheckOwnership(st->owner))
return CMD_ERROR;
@@ -1687,7 +1683,7 @@
int w = afc->size_x;
int h = afc->size_y;
- int32 cost = w * h * _price.remove_airport;
+ CommandCost cost(w * h * _price.remove_airport);
Vehicle *v;
FOR_ALL_VEHICLES(v) {
@@ -1730,7 +1726,7 @@
* @param p1 unused
* @param p2 unused
*/
-int32 CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1769,7 +1765,7 @@
st_auto_delete.Release();
}
- return _price.build_dock;
+ return CommandCost(_price.build_dock);
}
/* Checks if any ship is servicing the buoy specified. Returns yes or no */
@@ -1789,7 +1785,7 @@
return false;
}
-static int32 RemoveBuoy(Station *st, uint32 flags)
+static CommandCost RemoveBuoy(Station *st, uint32 flags)
{
/* XXX: strange stuff */
if (!IsValidPlayer(_current_player)) return_cmd_error(INVALID_STRING_ID);
@@ -1821,7 +1817,7 @@
DeleteStationIfEmpty(st);
}
- return _price.remove_truck_station;
+ return CommandCost(_price.remove_truck_station);
}
static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
@@ -1839,9 +1835,9 @@
* @param p1 (bit 0) - allow docks directly adjacent to other docks.
* @param p2 unused
*/
-int32 CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdBuildDock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- int32 cost;
+ CommandCost cost;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1935,10 +1931,10 @@
/* success, so don't delete the new station */
st_auto_delete.Release();
}
- return _price.build_dock;
+ return CommandCost(_price.build_dock);
}
-static int32 RemoveDock(Station *st, uint32 flags)
+static CommandCost RemoveDock(Station *st, uint32 flags)
{
if (!CheckOwnership(st->owner)) return CMD_ERROR;
@@ -1964,7 +1960,7 @@
DeleteStationIfEmpty(st);
}
- return _price.remove_dock;
+ return CommandCost(_price.remove_dock);
}
#include "table/station_land.h"
@@ -2347,11 +2343,10 @@
/* Slowly increase the rating back to his original level in the case we
* didn't deliver cargo yet to this station. This happens when a bribe
* failed while you didn't moved that cargo yet to a station. */
- if (ge->enroute_from == INVALID_STATION && ge->rating < INITIAL_STATION_RATING)
+ if (ge->days_since_pickup == 255 && ge->rating < INITIAL_STATION_RATING)
ge->rating++;
/* Only change the rating if we are moving this cargo */
- if (ge->enroute_from != INVALID_STATION) {
- byte_inc_sat(&ge->enroute_time);
+ if (ge->last_speed != 0) {
byte_inc_sat(&ge->days_since_pickup);
int rating = 0;
@@ -2383,7 +2378,7 @@
(rating += 35, true);
}
- int waiting = GB(ge->waiting_acceptance, 0, 12);
+ uint waiting = ge->cargo.Count();
(rating -= 90, waiting > 1500) ||
(rating += 55, waiting > 1000) ||
(rating += 35, waiting > 600) ||
@@ -2409,12 +2404,13 @@
if (rating <= 127 && waiting != 0) {
uint32 r = Random();
if (rating <= (int)GB(r, 0, 7)) {
- waiting = max(waiting - (int)GB(r, 8, 2) - 1, 0);
+ /* Need to have int, otherwise it will just overflow etc. */
+ waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0);
waiting_changed = true;
}
}
- if (waiting_changed) SB(ge->waiting_acceptance, 0, 12, waiting);
+ if (waiting_changed) ge->cargo.Truncate(waiting);
}
}
} while (++ge != endof(st->goods));
@@ -2467,7 +2463,7 @@
for (CargoID i = 0; i < NUM_CARGO; i++) {
GoodsEntry* ge = &st->goods[i];
- if (ge->enroute_from != INVALID_STATION) {
+ if (ge->days_since_pickup != 255) {
ge->rating = clamp(ge->rating + amount, 0, 255);
}
}
@@ -2477,13 +2473,8 @@
static void UpdateStationWaiting(Station *st, CargoID type, uint amount)
{
- SB(st->goods[type].waiting_acceptance, 0, 12,
- min(0xFFF, GB(st->goods[type].waiting_acceptance, 0, 12) + amount)
- );
-
- st->goods[type].enroute_time = 0;
- st->goods[type].enroute_from = st->index;
- st->goods[type].enroute_from_xy = st->xy;
+ st->goods[type].cargo.Append(new CargoPacket(st->index, amount));
+
InvalidateWindow(WC_STATION_VIEW, st->index);
st->MarkTilesDirty(true);
}
@@ -2494,7 +2485,7 @@
* @param p1 station ID that is to be renamed
* @param p2 unused
*/
-int32 CmdRenameStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+CommandCost CmdRenameStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
if (!IsValidStationID(p1) || _cmd_text[0] == '\0') return CMD_ERROR;
Station *st = GetStation(p1);
@@ -2516,7 +2507,7 @@
DeleteName(str);
}
- return 0;
+ return CommandCost();
}
@@ -2553,7 +2544,7 @@
if (around[i] == NULL) {
if (!st->IsBuoy() &&
(st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights
- st->goods[type].rating != 0 &&
+ st->goods[type].rating != 0 && st->goods[type].last_speed != 0 && // we actually service the station
(!_patches.selectgoods || st->goods[type].last_speed > 0) && // if last_speed is 0, no vehicle has been there.
((st->facilities & ~FACIL_BUS_STOP) != 0 || IsCargoInClass(type, CC_PASSENGERS)) && // if we have other fac. than a bus stop, or the cargo is passengers
((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
@@ -2683,10 +2674,8 @@
st->build_date = _date;
for (CargoID j = 0; j < NUM_CARGO; j++) {
- st->goods[j].waiting_acceptance = 0;
- st->goods[j].days_since_pickup = 0;
- st->goods[j].enroute_from = INVALID_STATION;
- st->goods[j].enroute_from_xy = INVALID_TILE;
+ st->goods[j].acceptance = false;
+ st->goods[j].days_since_pickup = 255;
st->goods[j].rating = INITIAL_STATION_RATING;
st->goods[j].last_speed = 0;
st->goods[j].last_age = 255;
@@ -2748,7 +2737,7 @@
CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_TRAM), OWNER_TOWN, &edge_road, ROADTYPE_TRAM);
}
-static int32 ClearTile_Station(TileIndex tile, byte flags)
+static CommandCost ClearTile_Station(TileIndex tile, byte flags)
{
if (flags & DC_AUTO) {
switch (GetStationType(tile)) {
@@ -2810,6 +2799,8 @@
st->speclist[i].spec = GetCustomStationSpecByGrf(st->speclist[i].grfid, st->speclist[i].localidx);
}
+
+ for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache();
}
}
@@ -2906,18 +2897,27 @@
SLE_END()
};
+static uint16 _waiting_acceptance;
+static uint16 _cargo_source;
+static uint32 _cargo_source_xy;
+static uint16 _cargo_days;
+static Money _cargo_feeder_share;
+
static const SaveLoad _goods_desc[] = {
- SLE_VAR(GoodsEntry, waiting_acceptance, SLE_UINT16),
- SLE_CONDVAR(GoodsEntry, unload_pending, SLE_UINT16, 51, SL_MAX_VERSION),
- SLE_VAR(GoodsEntry, days_since_pickup, SLE_UINT8),
- SLE_VAR(GoodsEntry, rating, SLE_UINT8),
- SLE_CONDVAR(GoodsEntry, enroute_from, SLE_FILE_U8 | SLE_VAR_U16, 0, 6),
- SLE_CONDVAR(GoodsEntry, enroute_from, SLE_UINT16, 7, SL_MAX_VERSION),
- SLE_CONDVAR(GoodsEntry, enroute_from_xy, SLE_UINT32, 44, SL_MAX_VERSION),
- SLE_VAR(GoodsEntry, enroute_time, SLE_UINT8),
- SLE_VAR(GoodsEntry, last_speed, SLE_UINT8),
- SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
- SLE_CONDVAR(GoodsEntry, feeder_profit, SLE_INT32, 14, SL_MAX_VERSION),
+ SLEG_CONDVAR( _waiting_acceptance, SLE_UINT16, 0, 67),
+ SLE_CONDVAR(GoodsEntry, acceptance, SLE_BOOL, 68, SL_MAX_VERSION),
+ SLE_CONDNULL(2, 51, 67),
+ SLE_VAR(GoodsEntry, days_since_pickup, SLE_UINT8),
+ SLE_VAR(GoodsEntry, rating, SLE_UINT8),
+ SLEG_CONDVAR( _cargo_source, SLE_FILE_U8 | SLE_VAR_U16, 0, 6),
+ SLEG_CONDVAR( _cargo_source, SLE_UINT16, 7, 67),
+ SLEG_CONDVAR( _cargo_source_xy, SLE_UINT32, 44, 67),
+ SLEG_CONDVAR( _cargo_days, SLE_UINT8, 0, 67),
+ SLE_VAR(GoodsEntry, last_speed, SLE_UINT8),
+ SLE_VAR(GoodsEntry, last_age, SLE_UINT8),
+ SLEG_CONDVAR( _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
+ SLEG_CONDVAR( _cargo_feeder_share, SLE_INT64, 65, 67),
+ SLE_CONDLST(GoodsEntry, cargo, REF_CARGO_PACKET, 68, SL_MAX_VERSION),
SLE_END()
};
@@ -2934,9 +2934,30 @@
{
SlObject(st, _station_desc);
+ _waiting_acceptance = 0;
+
uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
for (CargoID i = 0; i < num_cargo; i++) {
- SlObject(&st->goods[i], _goods_desc);
+ GoodsEntry *ge = &st->goods[i];
+ SlObject(ge, _goods_desc);
+ if (CheckSavegameVersion(68)) {
+ ge->acceptance = HASBIT(_waiting_acceptance, 15);
+ if (GB(_waiting_acceptance, 0, 12) != 0) {
+ /* Don't construct the packet with station here, because that'll fail with old savegames */
+ CargoPacket *cp = new CargoPacket();
+ /* In old versions, enroute_from used 0xFF as INVALID_STATION */
+ cp->source = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
+ cp->count = GB(_waiting_acceptance, 0, 12);
+ cp->days_in_transit = _cargo_days;
+ cp->feeder_share = _cargo_feeder_share;
+ cp->source_xy = _cargo_source_xy;
+ cp->days_in_transit = _cargo_days;
+ cp->feeder_share = _cargo_feeder_share;
+ ge->cargo.Append(cp);
+ } else {
+ ge->days_since_pickup = 255;
+ }
+ }
}
if (st->num_specs != 0) {