From 785572ea32e11064375e9de0a789f46c73acac75 Mon Sep 17 00:00:00 2001 From: glx Date: Wed, 9 Jan 2008 17:47:05 +0000 Subject: (svn r11795) -Fix [FS#1616]: take town rating into account when testing if a command can be executed. --- src/command.cpp | 10 +++++++--- src/road_cmd.cpp | 11 +++++------ src/town.h | 2 ++ src/town_cmd.cpp | 29 +++++++++++++++++++++++++---- src/tree_cmd.cpp | 16 +++++++--------- src/tunnelbridge_cmd.cpp | 21 ++++++++++++--------- 6 files changed, 58 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/command.cpp b/src/command.cpp index 40161688b..38193d41c 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -17,6 +17,7 @@ #include "strings_func.h" #include "gfx_func.h" #include "functions.h" +#include "town.h" const char *_cmd_text = NULL; @@ -388,7 +389,7 @@ byte GetCommandFlags(uint cmd) return _command_proc_table[cmd & 0xFF].flags; } -static int _docommand_recursive; +static int _docommand_recursive = 0; /*! * This function executes a given command with the parameters from the #CommandProc parameter list. @@ -420,7 +421,9 @@ CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 /* only execute the test call if it's toplevel, or we're not execing. */ if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) { + SetTownRatingTestMode(true); res = proc(tile, flags & ~DC_EXEC, p1, p2); + SetTownRatingTestMode(false); if (CmdFailed(res)) { res.SetGlobalErrorMessage(); goto error; @@ -540,7 +543,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, * e.g.: if you demolish a whole town, the dryrun would say okay. * but by really destroying, your rating drops and at a certain point * it will fail. so res and res2 are different - * CMD_REMOVE_ROAD: This command has special local authority + * CMD_REMOVE_LONG_ROAD: This command has special local authority * restrictions which may cause the test run to fail (the previous * road fragments still stay there and the town won't let you * disconnect the road system), but the exec will succeed and this @@ -551,7 +554,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, notest = (cmd & 0xFF) == CMD_CLEAR_AREA || (cmd & 0xFF) == CMD_LEVEL_LAND || - (cmd & 0xFF) == CMD_REMOVE_ROAD || (cmd & 0xFF) == CMD_REMOVE_LONG_ROAD || (cmd & 0xFF) == CMD_CLONE_VEHICLE; @@ -581,7 +583,9 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) { /* first test if the command can be executed. */ + SetTownRatingTestMode(true); res = proc(tile, flags, p1, p2); + SetTownRatingTestMode(false); if (CmdFailed(res)) { res.SetGlobalErrorMessage(); goto show_error; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index b011345fe..9094884a3 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -199,9 +199,8 @@ CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) c &= present; if (c == ROAD_NONE) return CMD_ERROR; + ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); if (flags & DC_EXEC) { - ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); - present ^= c; if (present == ROAD_NONE) { RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); @@ -234,11 +233,11 @@ CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) * we can't draw the crossing without trambits ;) */ if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HasBit(p1, 6))) return CMD_ERROR; - if (flags & DC_EXEC) { - if (rt == ROADTYPE_ROAD) { - ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); - } + if (rt == ROADTYPE_ROAD) { + ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); + } + if (flags & DC_EXEC) { RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); if (rts == ROADTYPES_NONE) { MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile)); diff --git a/src/town.h b/src/town.h index 118c0ebff..50dbb171e 100644 --- a/src/town.h +++ b/src/town.h @@ -106,6 +106,7 @@ struct Town : PoolItem { PlayerByte exclusivity; ///< which player has exslusivity uint8 exclusive_counter; ///< months till the exclusivity expires int16 ratings[MAX_PLAYERS]; + int16 test_rating; /* Maximum amount of passengers and mail that can be transported. */ uint32 max_pass; @@ -313,5 +314,6 @@ bool CheckIfAuthorityAllows(TileIndex tile); Town *ClosestTownFromTile(TileIndex tile, uint threshold); void ChangeTownRating(Town *t, int add, int max); uint GetTownRadiusGroup(const Town* t, TileIndex tile); +void SetTownRatingTestMode(bool mode); #endif /* TOWN_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 1f9dbfdc4..ec7ca4e02 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -522,8 +522,8 @@ static CommandCost ClearTile_Town(TileIndex tile, byte flags) } } + ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM); if (flags & DC_EXEC) { - ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM); ClearTownHouse(t, tile); } @@ -2256,6 +2256,23 @@ Town *ClosestTownFromTile(TileIndex tile, uint threshold) } } +static bool _town_rating_test = false; + +void SetTownRatingTestMode(bool mode) +{ + static int ref_count = 0; + if (mode) { + if (ref_count == 0) { + Town *t; + FOR_ALL_TOWNS(t) t->test_rating = t->ratings[_current_player]; + } + ref_count++; + } else { + assert(ref_count > 0); + ref_count--; + } + _town_rating_test = !(ref_count == 0); +} void ChangeTownRating(Town *t, int add, int max) { @@ -2270,7 +2287,7 @@ void ChangeTownRating(Town *t, int add, int max) SetBit(t->have_ratings, _current_player); - rating = t->ratings[_current_player]; + rating = _town_rating_test ? t->test_rating : t->ratings[_current_player]; if (add < 0) { if (rating > max) { @@ -2283,7 +2300,11 @@ void ChangeTownRating(Town *t, int add, int max) if (rating > max) rating = max; } } - t->ratings[_current_player] = rating; + if (_town_rating_test) { + t->test_rating = rating; + } else { + t->ratings[_current_player] = rating; + } } /* penalty for removing town-owned stuff */ @@ -2308,7 +2329,7 @@ bool CheckforTownRating(uint32 flags, Town *t, byte type) */ modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type]; - if (t->ratings[_current_player] < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { + if ((_town_rating_test ? t->test_rating : t->ratings[_current_player]) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { SetDParam(0, t->index); _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; return false; diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index e73de21cb..aacfe21d2 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -328,16 +328,15 @@ CommandCost CmdPlantTree(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) default: break; } + if (_game_mode != GM_EDITOR && IsValidPlayer(_current_player)) { + Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); + if (t != NULL) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM); + } + if (flags & DC_EXEC) { TreeType treetype; uint growth; - if (_game_mode != GM_EDITOR && IsValidPlayer(_current_player)) { - Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); - if (t != NULL) - ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM); - } - treetype = (TreeType)p1; if (treetype == TREE_INVALID) { treetype = GetRandomTreeType(tile, GB(Random(), 24, 8)); @@ -486,10 +485,9 @@ static CommandCost ClearTile_Trees(TileIndex tile, byte flags) { uint num; - if ((flags & DC_EXEC) && IsValidPlayer(_current_player)) { + if (IsValidPlayer(_current_player)) { Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); - if (t != NULL) - ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM); + if (t != NULL) ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM); } num = GetTreeCount(tile) + 1; diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 239d7f7e7..9148c9255 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -596,16 +596,18 @@ static CommandCost DoClearTunnel(TileIndex tile, uint32 flags) } } + /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until + * you have a "Poor" (0) town rating */ + if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) { + ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); + } + if (flags & DC_EXEC) { /* We first need to request the direction before calling DoClearSquare * else the direction is always 0.. dah!! ;) */ DiagDirection dir = GetTunnelBridgeDirection(tile); Track track; - /* Adjust the town's player rating. Do this before removing the tile owner info. */ - if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) - ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); - DoClearSquare(tile); DoClearSquare(endtile); UpdateSignalsOnSegment(tile, ReverseDiagDir(dir)); @@ -645,15 +647,16 @@ static CommandCost DoClearBridge(TileIndex tile, uint32 flags) } } + /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until + * you have a "Poor" (0) town rating */ + if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) { + ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); + } + if (flags & DC_EXEC) { TileIndex c; Track track; - /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until - * you have a "Poor" (0) town rating */ - if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) - ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); - DoClearSquare(tile); DoClearSquare(endtile); for (c = tile + delta; c != endtile; c += delta) { -- cgit v1.2.3-70-g09d2