2 |
2 |
3 /** @file town_cmd.cpp */ |
3 /** @file town_cmd.cpp */ |
4 |
4 |
5 #include "stdafx.h" |
5 #include "stdafx.h" |
6 #include "openttd.h" |
6 #include "openttd.h" |
7 #include "functions.h" |
7 #include "tile_cmd.h" |
8 #include "debug.h" |
8 #include "debug.h" |
9 #include "strings.h" |
|
10 #include "road_map.h" |
9 #include "road_map.h" |
|
10 #include "road_internal.h" /* Cleaning up road bits */ |
11 #include "table/strings.h" |
11 #include "table/strings.h" |
12 #include "table/sprites.h" |
12 #include "table/sprites.h" |
13 #include "map.h" |
|
14 #include "landscape.h" |
13 #include "landscape.h" |
15 #include "tile.h" |
|
16 #include "town_map.h" |
14 #include "town_map.h" |
17 #include "tunnel_map.h" |
15 #include "tunnel_map.h" |
18 #include "viewport.h" |
16 #include "viewport_func.h" |
19 #include "town.h" |
17 #include "town.h" |
20 #include "command.h" |
18 #include "command_func.h" |
21 #include "gfx.h" |
|
22 #include "industry.h" |
19 #include "industry.h" |
23 #include "station.h" |
20 #include "station.h" |
24 #include "vehicle.h" |
|
25 #include "player.h" |
21 #include "player.h" |
26 #include "news.h" |
22 #include "news.h" |
27 #include "saveload.h" |
23 #include "saveload.h" |
28 #include "economy.h" |
|
29 #include "gui.h" |
24 #include "gui.h" |
30 #include "unmovable_map.h" |
25 #include "unmovable_map.h" |
31 #include "water_map.h" |
26 #include "water_map.h" |
32 #include "variables.h" |
27 #include "variables.h" |
33 #include "bridge.h" |
28 #include "bridge.h" |
34 #include "bridge_map.h" |
29 #include "bridge_map.h" |
35 #include "date.h" |
|
36 #include "table/town_land.h" |
30 #include "table/town_land.h" |
37 #include "genworld.h" |
31 #include "genworld.h" |
38 #include "newgrf.h" |
32 #include "newgrf.h" |
39 #include "newgrf_callbacks.h" |
33 #include "newgrf_callbacks.h" |
40 #include "newgrf_house.h" |
34 #include "newgrf_house.h" |
42 #include "newgrf_townname.h" |
36 #include "newgrf_townname.h" |
43 #include "misc/autoptr.hpp" |
37 #include "misc/autoptr.hpp" |
44 #include "autoslope.h" |
38 #include "autoslope.h" |
45 #include "waypoint.h" |
39 #include "waypoint.h" |
46 #include "transparency.h" |
40 #include "transparency.h" |
|
41 #include "tunnelbridge_map.h" |
|
42 #include "strings_func.h" |
|
43 #include "window_func.h" |
|
44 #include "string_func.h" |
|
45 |
47 |
46 |
48 /* Initialize the town-pool */ |
47 /* Initialize the town-pool */ |
49 DEFINE_OLD_POOL_GENERIC(Town, Town) |
48 DEFINE_OLD_POOL_GENERIC(Town, Town) |
50 |
49 |
51 Town::Town(TileIndex tile) |
50 Town::Town(TileIndex tile) |
309 UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, |
308 UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, |
310 _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); |
309 _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); |
311 MarkTownSignDirty(t); |
310 MarkTownSignDirty(t); |
312 } |
311 } |
313 |
312 |
|
313 /** Update the virtual coords needed to draw the town sign for all towns. */ |
|
314 void UpdateAllTownVirtCoords() |
|
315 { |
|
316 Town *t; |
|
317 FOR_ALL_TOWNS(t) { |
|
318 UpdateTownVirtCoord(t); |
|
319 } |
|
320 } |
|
321 |
314 /** |
322 /** |
315 * Change the towns population |
323 * Change the towns population |
316 * @param t Town which polulation has changed |
324 * @param t Town which polulation has changed |
317 * @param mod polulation change (can be positive or negative) |
325 * @param mod polulation change (can be positive or negative) |
318 */ |
326 */ |
404 |
412 |
405 /* If the lift has a destination, it is already an animated tile. */ |
413 /* If the lift has a destination, it is already an animated tile. */ |
406 if ((hs->building_flags & BUILDING_IS_ANIMATED) && |
414 if ((hs->building_flags & BUILDING_IS_ANIMATED) && |
407 house_id < NEW_HOUSE_OFFSET && |
415 house_id < NEW_HOUSE_OFFSET && |
408 !LiftHasDestination(tile) && |
416 !LiftHasDestination(tile) && |
409 CHANCE16(1, 2)) |
417 Chance16(1, 2)) |
410 AddAnimatedTile(tile); |
418 AddAnimatedTile(tile); |
411 |
419 |
412 t = GetTownByTile(tile); |
420 t = GetTownByTile(tile); |
413 |
421 |
414 r = Random(); |
422 r = Random(); |
492 } |
500 } |
493 |
501 |
494 static CommandCost ClearTile_Town(TileIndex tile, byte flags) |
502 static CommandCost ClearTile_Town(TileIndex tile, byte flags) |
495 { |
503 { |
496 int rating; |
504 int rating; |
497 CommandCost cost; |
505 CommandCost cost(EXPENSES_CONSTRUCTION); |
498 Town *t; |
506 Town *t; |
499 HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
507 HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
500 |
508 |
501 if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
509 if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
502 if (!CanDeleteHouse(tile)) return CMD_ERROR; |
510 if (!CanDeleteHouse(tile)) return CMD_ERROR; |
512 SetDParam(0, t->index); |
520 SetDParam(0, t->index); |
513 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
521 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
514 } |
522 } |
515 } |
523 } |
516 |
524 |
|
525 ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM); |
517 if (flags & DC_EXEC) { |
526 if (flags & DC_EXEC) { |
518 ChangeTownRating(t, -rating, RATING_HOUSE_MINIMUM); |
|
519 ClearTownHouse(t, tile); |
527 ClearTownHouse(t, tile); |
520 } |
528 } |
521 |
529 |
522 return cost; |
530 return cost; |
523 } |
531 } |
729 |
737 |
730 /* If the tile is not a slope in the right direction, then |
738 /* If the tile is not a slope in the right direction, then |
731 * maybe terraform some. */ |
739 * maybe terraform some. */ |
732 desired_slope = (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? SLOPE_NW : SLOPE_NE; |
740 desired_slope = (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? SLOPE_NW : SLOPE_NE; |
733 if (desired_slope != cur_slope && ComplementSlope(desired_slope) != cur_slope) { |
741 if (desired_slope != cur_slope && ComplementSlope(desired_slope) != cur_slope) { |
734 if (CHANCE16(1, 8)) { |
742 if (Chance16(1, 8)) { |
735 CommandCost res = CMD_ERROR; |
743 CommandCost res = CMD_ERROR; |
736 if (!_generating_world && CHANCE16(1, 10)) { |
744 if (!_generating_world && Chance16(1, 10)) { |
737 /* Note: Do not replace " ^ 0xF" with ComplementSlope(). The slope might be steep. */ |
745 /* Note: Do not replace " ^ 0xF" with ComplementSlope(). The slope might be steep. */ |
738 res = DoCommand(tile, CHANCE16(1, 16) ? cur_slope : cur_slope ^ 0xF, 0, |
746 res = DoCommand(tile, Chance16(1, 16) ? cur_slope : cur_slope ^ 0xF, 0, |
739 DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); |
747 DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); |
740 } |
748 } |
741 if (CmdFailed(res) && CHANCE16(1, 3)) { |
749 if (CmdFailed(res) && Chance16(1, 3)) { |
742 /* We can consider building on the slope, though. */ |
750 /* We can consider building on the slope, though. */ |
743 goto no_slope; |
751 goto no_slope; |
744 } |
752 } |
745 } |
753 } |
746 return false; |
754 return false; |
1000 case TL_ORIGINAL: |
1008 case TL_ORIGINAL: |
1001 if (!IsRoadAllowedHere(tile, target_dir)) return; |
1009 if (!IsRoadAllowedHere(tile, target_dir)) return; |
1002 |
1010 |
1003 DiagDirection source_dir = ReverseDiagDir(target_dir); |
1011 DiagDirection source_dir = ReverseDiagDir(target_dir); |
1004 |
1012 |
1005 if (CHANCE16(1, 4)) { |
1013 if (Chance16(1, 4)) { |
1006 /* Randomize a new target dir */ |
1014 /* Randomize a new target dir */ |
1007 do target_dir = RandomDiagDir(); while (target_dir == source_dir); |
1015 do target_dir = RandomDiagDir(); while (target_dir == source_dir); |
1008 } |
1016 } |
1009 |
1017 |
1010 if (!IsRoadAllowedHere(TileAddByDiagDir(tile, target_dir), target_dir)) { |
1018 if (!IsRoadAllowedHere(TileAddByDiagDir(tile, target_dir), target_dir)) { |
1051 } else { |
1059 } else { |
1052 bool allow_house = false; // Value which decides if we want to construct a house |
1060 bool allow_house = false; // Value which decides if we want to construct a house |
1053 |
1061 |
1054 /* Reached a tunnel/bridge? Then continue at the other side of it. */ |
1062 /* Reached a tunnel/bridge? Then continue at the other side of it. */ |
1055 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
1063 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
1056 if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) { |
1064 if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) { |
1057 *tile_ptr = GetOtherTunnelEnd(tile); |
1065 *tile_ptr = GetOtherTunnelBridgeEnd(tile); |
1058 } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_ROAD) { |
|
1059 *tile_ptr = GetOtherBridgeEnd(tile); |
|
1060 } |
1066 } |
1061 return; |
1067 return; |
1062 } |
1068 } |
1063 |
1069 |
1064 /* Possibly extend the road in a direction. |
1070 /* Possibly extend the road in a direction. |
1094 |
1100 |
1095 case TL_ORIGINAL: |
1101 case TL_ORIGINAL: |
1096 /* Allow a house at the edge. 60% chance or |
1102 /* Allow a house at the edge. 60% chance or |
1097 * always ok if no road allowed. */ |
1103 * always ok if no road allowed. */ |
1098 rcmd = DiagDirToRoadBits(target_dir); |
1104 rcmd = DiagDirToRoadBits(target_dir); |
1099 allow_house = (!IsRoadAllowedHere(house_tile, target_dir) || CHANCE16(6, 10)); |
1105 allow_house = (!IsRoadAllowedHere(house_tile, target_dir) || Chance16(6, 10)); |
1100 break; |
1106 break; |
1101 } |
1107 } |
1102 |
1108 |
1103 if (allow_house) { |
1109 if (allow_house) { |
1104 /* Build a house, but not if there already is a house there. */ |
1110 /* Build a house, but not if there already is a house there. */ |
1105 if (!IsTileType(house_tile, MP_HOUSE)) { |
1111 if (!IsTileType(house_tile, MP_HOUSE)) { |
1106 /* Level the land if possible */ |
1112 /* Level the land if possible */ |
1107 if (CHANCE16(1, 6)) LevelTownLand(house_tile); |
1113 if (Chance16(1, 6)) LevelTownLand(house_tile); |
1108 |
1114 |
1109 /* And build a house. |
1115 /* And build a house. |
1110 * Set result to -1 if we managed to build it. */ |
1116 * Set result to -1 if we managed to build it. */ |
1111 if (BuildTownHouse(t1, house_tile)) { |
1117 if (BuildTownHouse(t1, house_tile)) { |
1112 _grow_town_result = GROWTH_SUCCEED; |
1118 _grow_town_result = GROWTH_SUCCEED; |
1488 |
1494 |
1489 /* Only in the scenario editor */ |
1495 /* Only in the scenario editor */ |
1490 if (_game_mode != GM_EDITOR) return CMD_ERROR; |
1496 if (_game_mode != GM_EDITOR) return CMD_ERROR; |
1491 if (p2 > TSM_CITY) return CMD_ERROR; |
1497 if (p2 > TSM_CITY) return CMD_ERROR; |
1492 |
1498 |
1493 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
1494 |
|
1495 /* Check if too close to the edge of map */ |
1499 /* Check if too close to the edge of map */ |
1496 if (DistanceFromEdge(tile) < 12) |
1500 if (DistanceFromEdge(tile) < 12) |
1497 return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP); |
1501 return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP); |
1498 |
1502 |
1499 /* Can only build on clear flat areas, possibly with trees. */ |
1503 /* Can only build on clear flat areas, possibly with trees. */ |
1776 |
1780 |
1777 if (_generating_world) { |
1781 if (_generating_world) { |
1778 uint32 r = Random(); |
1782 uint32 r = Random(); |
1779 |
1783 |
1780 construction_stage = TOWN_HOUSE_COMPLETED; |
1784 construction_stage = TOWN_HOUSE_COMPLETED; |
1781 if (CHANCE16(1, 7)) construction_stage = GB(r, 0, 2); |
1785 if (Chance16(1, 7)) construction_stage = GB(r, 0, 2); |
1782 |
1786 |
1783 if (construction_stage == TOWN_HOUSE_COMPLETED) { |
1787 if (construction_stage == TOWN_HOUSE_COMPLETED) { |
1784 ChangePopulation(t, hs->population); |
1788 ChangePopulation(t, hs->population); |
1785 } else { |
1789 } else { |
1786 construction_counter = GB(r, 2, 2); |
1790 construction_counter = GB(r, 2, 2); |
1787 } |
1791 } |
1788 } |
1792 } |
1789 MakeTownHouse(tile, t->index, construction_counter, construction_stage, house, VehicleRandomBits()); |
1793 MakeTownHouse(tile, t->index, construction_counter, construction_stage, house, Random()); |
1790 } |
1794 } |
1791 } |
1795 } |
1792 |
1796 |
1793 static bool BuildTownHouse(Town *t, TileIndex tile) |
1797 static bool BuildTownHouse(Town *t, TileIndex tile) |
1794 { |
1798 { |
2089 * @param p1 town to do the action at |
2093 * @param p1 town to do the action at |
2090 * @param p2 action to perform, @see _town_action_proc for the list of available actions |
2094 * @param p2 action to perform, @see _town_action_proc for the list of available actions |
2091 */ |
2095 */ |
2092 CommandCost CmdDoTownAction(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
2096 CommandCost CmdDoTownAction(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
2093 { |
2097 { |
2094 CommandCost cost; |
|
2095 Town *t; |
2098 Town *t; |
2096 |
2099 |
2097 if (!IsValidTownID(p1) || p2 > lengthof(_town_action_proc)) return CMD_ERROR; |
2100 if (!IsValidTownID(p1) || p2 > lengthof(_town_action_proc)) return CMD_ERROR; |
2098 |
2101 |
2099 t = GetTown(p1); |
2102 t = GetTown(p1); |
2100 |
2103 |
2101 if (!HasBit(GetMaskOfTownActions(NULL, _current_player, t), p2)) return CMD_ERROR; |
2104 if (!HasBit(GetMaskOfTownActions(NULL, _current_player, t), p2)) return CMD_ERROR; |
2102 |
2105 |
2103 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
2106 CommandCost cost(EXPENSES_OTHER, (_price.build_industry >> 8) * _town_action_costs[p2]); |
2104 |
|
2105 cost.AddCost((_price.build_industry >> 8) * _town_action_costs[p2]); |
|
2106 |
2107 |
2107 if (flags & DC_EXEC) { |
2108 if (flags & DC_EXEC) { |
2108 _town_action_proc[p2](t); |
2109 _town_action_proc[p2](t); |
2109 InvalidateWindow(WC_TOWN_AUTHORITY, p1); |
2110 InvalidateWindow(WC_TOWN_AUTHORITY, p1); |
2110 } |
2111 } |
2153 if (t->fund_buildings_months != 0) { |
2154 if (t->fund_buildings_months != 0) { |
2154 m = _grow_count_values[0][min(n, 5)]; |
2155 m = _grow_count_values[0][min(n, 5)]; |
2155 t->fund_buildings_months--; |
2156 t->fund_buildings_months--; |
2156 } else { |
2157 } else { |
2157 m = _grow_count_values[1][min(n, 5)]; |
2158 m = _grow_count_values[1][min(n, 5)]; |
2158 if (n == 0 && !CHANCE16(1, 12)) return; |
2159 if (n == 0 && !Chance16(1, 12)) return; |
2159 } |
2160 } |
2160 |
2161 |
2161 if (_opt.landscape == LT_ARCTIC) { |
2162 if (_opt.landscape == LT_ARCTIC) { |
2162 if (TilePixelHeight(t->xy) >= GetSnowLine() && t->act_food == 0 && t->population > 90) |
2163 if (TilePixelHeight(t->xy) >= GetSnowLine() && t->act_food == 0 && t->population > 90) |
2163 return; |
2164 return; |
2253 } else { |
2254 } else { |
2254 return CalcClosestTownFromTile(tile, threshold); |
2255 return CalcClosestTownFromTile(tile, threshold); |
2255 } |
2256 } |
2256 } |
2257 } |
2257 |
2258 |
|
2259 static bool _town_rating_test = false; |
|
2260 |
|
2261 void SetTownRatingTestMode(bool mode) |
|
2262 { |
|
2263 static int ref_count = 0; |
|
2264 if (mode) { |
|
2265 if (ref_count == 0) { |
|
2266 Town *t; |
|
2267 FOR_ALL_TOWNS(t) t->test_rating = t->ratings[_current_player]; |
|
2268 } |
|
2269 ref_count++; |
|
2270 } else { |
|
2271 assert(ref_count > 0); |
|
2272 ref_count--; |
|
2273 } |
|
2274 _town_rating_test = !(ref_count == 0); |
|
2275 } |
2258 |
2276 |
2259 void ChangeTownRating(Town *t, int add, int max) |
2277 void ChangeTownRating(Town *t, int add, int max) |
2260 { |
2278 { |
2261 int rating; |
2279 int rating; |
2262 |
2280 |
2280 if (rating < max) { |
2298 if (rating < max) { |
2281 rating += add; |
2299 rating += add; |
2282 if (rating > max) rating = max; |
2300 if (rating > max) rating = max; |
2283 } |
2301 } |
2284 } |
2302 } |
2285 t->ratings[_current_player] = rating; |
2303 if (_town_rating_test) { |
|
2304 t->test_rating = rating; |
|
2305 } else { |
|
2306 t->ratings[_current_player] = rating; |
|
2307 } |
2286 } |
2308 } |
2287 |
2309 |
2288 /* penalty for removing town-owned stuff */ |
2310 /* penalty for removing town-owned stuff */ |
2289 static const int _default_rating_settings [3][3] = { |
2311 static const int _default_rating_settings [3][3] = { |
2290 /* ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE */ |
2312 /* ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE */ |
2305 * owned by a town no removal if rating is lower than ... depends now on |
2327 * owned by a town no removal if rating is lower than ... depends now on |
2306 * difficulty setting. Minimum town rating selected by difficulty level |
2328 * difficulty setting. Minimum town rating selected by difficulty level |
2307 */ |
2329 */ |
2308 modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type]; |
2330 modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type]; |
2309 |
2331 |
2310 if (t->ratings[_current_player] < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { |
2332 if ((_town_rating_test ? t->test_rating : t->ratings[_current_player]) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { |
2311 SetDParam(0, t->index); |
2333 SetDParam(0, t->index); |
2312 _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; |
2334 _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; |
2313 return false; |
2335 return false; |
2314 } |
2336 } |
2315 |
2337 |
2356 HouseID house = GetHouseType(tile); |
2378 HouseID house = GetHouseType(tile); |
2357 HouseSpec *hs = GetHouseSpecs(house); |
2379 HouseSpec *hs = GetHouseSpecs(house); |
2358 |
2380 |
2359 /* Here we differ from TTDP by checking TILE_NOT_SLOPED */ |
2381 /* Here we differ from TTDP by checking TILE_NOT_SLOPED */ |
2360 if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) && |
2382 if (((hs->building_flags & TILE_NOT_SLOPED) == 0) && !IsSteepSlope(tileh_new) && |
2361 (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) return _price.terraform; |
2383 (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
2362 } |
2384 } |
2363 |
2385 |
2364 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
2386 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
2365 } |
2387 } |
2366 |
2388 |