(svn r11795) -Fix [FS#1616]: take town rating into account when testing if a command can be executed.

This commit is contained in:
glx 2008-01-09 17:47:05 +00:00
parent d133edd026
commit 785572ea32
6 changed files with 58 additions and 31 deletions

View File

@ -17,6 +17,7 @@
#include "strings_func.h" #include "strings_func.h"
#include "gfx_func.h" #include "gfx_func.h"
#include "functions.h" #include "functions.h"
#include "town.h"
const char *_cmd_text = NULL; const char *_cmd_text = NULL;
@ -388,7 +389,7 @@ byte GetCommandFlags(uint cmd)
return _command_proc_table[cmd & 0xFF].flags; 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. * 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. */ /* only execute the test call if it's toplevel, or we're not execing. */
if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) { if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
SetTownRatingTestMode(true);
res = proc(tile, flags & ~DC_EXEC, p1, p2); res = proc(tile, flags & ~DC_EXEC, p1, p2);
SetTownRatingTestMode(false);
if (CmdFailed(res)) { if (CmdFailed(res)) {
res.SetGlobalErrorMessage(); res.SetGlobalErrorMessage();
goto error; 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. * 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 * but by really destroying, your rating drops and at a certain point
* it will fail. so res and res2 are different * 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 * restrictions which may cause the test run to fail (the previous
* road fragments still stay there and the town won't let you * road fragments still stay there and the town won't let you
* disconnect the road system), but the exec will succeed and this * 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 = notest =
(cmd & 0xFF) == CMD_CLEAR_AREA || (cmd & 0xFF) == CMD_CLEAR_AREA ||
(cmd & 0xFF) == CMD_LEVEL_LAND || (cmd & 0xFF) == CMD_LEVEL_LAND ||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD || (cmd & 0xFF) == CMD_REMOVE_LONG_ROAD ||
(cmd & 0xFF) == CMD_CLONE_VEHICLE; (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)) { if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
/* first test if the command can be executed. */ /* first test if the command can be executed. */
SetTownRatingTestMode(true);
res = proc(tile, flags, p1, p2); res = proc(tile, flags, p1, p2);
SetTownRatingTestMode(false);
if (CmdFailed(res)) { if (CmdFailed(res)) {
res.SetGlobalErrorMessage(); res.SetGlobalErrorMessage();
goto show_error; goto show_error;

View File

@ -199,9 +199,8 @@ CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
c &= present; c &= present;
if (c == ROAD_NONE) return CMD_ERROR; if (c == ROAD_NONE) return CMD_ERROR;
ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
present ^= c; present ^= c;
if (present == ROAD_NONE) { if (present == ROAD_NONE) {
RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); 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 ;) */ * 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 (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) {
if (rt == ROADTYPE_ROAD) { ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); }
}
if (flags & DC_EXEC) {
RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
if (rts == ROADTYPES_NONE) { if (rts == ROADTYPES_NONE) {
MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile)); MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile));

View File

@ -106,6 +106,7 @@ struct Town : PoolItem<Town, TownID, &_Town_pool> {
PlayerByte exclusivity; ///< which player has exslusivity PlayerByte exclusivity; ///< which player has exslusivity
uint8 exclusive_counter; ///< months till the exclusivity expires uint8 exclusive_counter; ///< months till the exclusivity expires
int16 ratings[MAX_PLAYERS]; int16 ratings[MAX_PLAYERS];
int16 test_rating;
/* Maximum amount of passengers and mail that can be transported. */ /* Maximum amount of passengers and mail that can be transported. */
uint32 max_pass; uint32 max_pass;
@ -313,5 +314,6 @@ bool CheckIfAuthorityAllows(TileIndex tile);
Town *ClosestTownFromTile(TileIndex tile, uint threshold); Town *ClosestTownFromTile(TileIndex tile, uint threshold);
void ChangeTownRating(Town *t, int add, int max); void ChangeTownRating(Town *t, int add, int max);
uint GetTownRadiusGroup(const Town* t, TileIndex tile); uint GetTownRadiusGroup(const Town* t, TileIndex tile);
void SetTownRatingTestMode(bool mode);
#endif /* TOWN_H */ #endif /* TOWN_H */

View File

@ -522,8 +522,8 @@ static CommandCost ClearTile_Town(TileIndex tile, byte flags)
} }
} }
ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM);
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM);
ClearTownHouse(t, tile); 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) 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); 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 (add < 0) {
if (rating > max) { if (rating > max) {
@ -2283,7 +2300,11 @@ void ChangeTownRating(Town *t, int add, int max)
if (rating > max) rating = 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 */ /* 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]; 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); SetDParam(0, t->index);
_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
return false; return false;

View File

@ -328,16 +328,15 @@ CommandCost CmdPlantTree(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
default: break; 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) { if (flags & DC_EXEC) {
TreeType treetype; TreeType treetype;
uint growth; 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; treetype = (TreeType)p1;
if (treetype == TREE_INVALID) { if (treetype == TREE_INVALID) {
treetype = GetRandomTreeType(tile, GB(Random(), 24, 8)); treetype = GetRandomTreeType(tile, GB(Random(), 24, 8));
@ -486,10 +485,9 @@ static CommandCost ClearTile_Trees(TileIndex tile, byte flags)
{ {
uint num; uint num;
if ((flags & DC_EXEC) && IsValidPlayer(_current_player)) { if (IsValidPlayer(_current_player)) {
Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
if (t != NULL) if (t != NULL) ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM);
ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM);
} }
num = GetTreeCount(tile) + 1; num = GetTreeCount(tile) + 1;

View File

@ -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) { if (flags & DC_EXEC) {
/* We first need to request the direction before calling DoClearSquare /* We first need to request the direction before calling DoClearSquare
* else the direction is always 0.. dah!! ;) */ * else the direction is always 0.. dah!! ;) */
DiagDirection dir = GetTunnelBridgeDirection(tile); DiagDirection dir = GetTunnelBridgeDirection(tile);
Track track; 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(tile);
DoClearSquare(endtile); DoClearSquare(endtile);
UpdateSignalsOnSegment(tile, ReverseDiagDir(dir)); 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) { if (flags & DC_EXEC) {
TileIndex c; TileIndex c;
Track track; 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(tile);
DoClearSquare(endtile); DoClearSquare(endtile);
for (c = tile + delta; c != endtile; c += delta) { for (c = tile + delta; c != endtile; c += delta) {