00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "openttd.h"
00014 #include "landscape.h"
00015 #include "sprite.h"
00016 #include "viewport_func.h"
00017 #include "road_map.h"
00018 #include "command_func.h"
00019 #include "cheat_func.h"
00020 #include "animated_tile_func.h"
00021 #include "economy_func.h"
00022 #include "road_cmd.h"
00023 #include "company_func.h"
00024 #include "company_base.h"
00025 #include "settings_type.h"
00026 #include "trafficlight.h"
00027 #include "trafficlight_type.h"
00028 #include "date_func.h"
00029 #include "company_func.h"
00030
00031 #include "table/sprites.h"
00032 #include "table/strings.h"
00033
00034 #include <set>
00035
00036
00037
00038
00039 typedef std::set<TileIndex> TLC;
00040
00048 TLC *GetTrafficLightConsist(TileIndex tile, bool checkroadworks)
00049 {
00050 TLC *visited;
00051 TLC *candidates;
00052
00053 visited = new TLC;
00054 candidates = new TLC;
00055 candidates->insert(tile);
00056
00057 while (!candidates->empty()) {
00058 TLC::iterator cur = candidates->begin();
00059 if (checkroadworks && HasRoadWorks(*cur)) {
00060 delete visited;
00061 delete candidates;
00062 return 0;
00063 }
00064 uint8 distance_between_traffic_lights = _tlc_distance[_settings_game.construction.max_tlc_distance];
00065 for (int i = 0; i < distance_between_traffic_lights; i++) {
00066 TileIndex neighbor = *cur + ToTileIndexDiff(_tl_check_offsets[i]);
00067 if (HasTrafficLights(neighbor) && (visited->find(neighbor) == visited->end())) candidates->insert(neighbor);
00068 }
00069 visited->insert(*cur);
00070 candidates->erase(cur);
00071 }
00072 delete candidates;
00073 return visited;
00074 }
00075
00082 TileIndex GetTLCLowestTileIndexOrRoadWorks(TileIndex tile)
00083 {
00084 TLC *consist = GetTrafficLightConsist(tile, true);
00085 TileIndex result = 0;
00086 if (consist != 0) result = *(consist->begin());
00087 delete consist;
00088 return result;
00089 }
00090
00098 TrafficLightState GetTLState(TileIndex tile)
00099 {
00100 assert(HasTrafficLights(tile));
00101 if (_game_mode == GM_EDITOR) return TLS_OFF;
00102 tile = GetTLCLowestTileIndexOrRoadWorks(tile);
00103 if (tile == 0) return TLS_OFF;
00104
00105 uint16 tl_total = 16 * _settings_game.construction.traffic_lights_green_phase;
00106 uint16 tl_tick = ((_tick_counter / 16) + 5 * TileX(tile) + 7 * TileY(tile)) % tl_total;
00107
00108 if (tl_tick < ((tl_total / 2) - 2)) return TLS_X_GREEN_Y_RED;
00109 if (tl_tick < ((tl_total / 2) - 1)) return TLS_X_YELLOW_Y_RED;
00110 if (tl_tick < (tl_total / 2)) return TLS_X_RED_Y_REDYELLOW;
00111 if (tl_tick < (tl_total - 2)) return TLS_X_RED_Y_GREEN;
00112 if (tl_tick < (tl_total - 1)) return TLS_X_RED_Y_YELLOW;
00113 if (tl_tick < tl_total) return TLS_X_REDYELLOW_Y_RED;
00114
00115 NOT_REACHED();
00116 return TLS_OFF;
00117 }
00118
00122 static const TrackdirBits _tls_to_trackdir[7] = {
00123 TRACKDIR_BIT_MASK,
00124 TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE |
00125 TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LOWER_W |
00126 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_RIGHT_N,
00127 TRACKDIR_BIT_MASK,
00128 TRACKDIR_BIT_MASK,
00129 TRACKDIR_BIT_X_SW | TRACKDIR_BIT_X_NE |
00130 TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_LOWER_E |
00131 TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_RIGHT_S,
00132 TRACKDIR_BIT_MASK,
00133 TRACKDIR_BIT_MASK,
00134 };
00135
00141 TrackdirBits GetIntraTLCAllowedDirections(TileIndex tile)
00142 {
00143 TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
00144
00145 if (HasTrafficLights(tile + TileDiffXY( 1, 0)))
00146 trackdirbits |= TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N;
00147 if (HasTrafficLights(tile + TileDiffXY( 0, 1)))
00148 trackdirbits |= TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_RIGHT_N;
00149 if (HasTrafficLights(tile + TileDiffXY( 0, -1)))
00150 trackdirbits |= TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LEFT_S;
00151 if (HasTrafficLights(tile + TileDiffXY(-1, 0)))
00152 trackdirbits |= TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S;
00153
00154 return trackdirbits;
00155 }
00156
00162 TrackdirBits GetTrafficLightDisallowedDirections(TileIndex tile)
00163 {
00164 return (_tls_to_trackdir[GetTLState(tile)] & ~GetIntraTLCAllowedDirections(tile));
00165 }
00166
00172 bool CheckTLCSize(TileIndex tile)
00173 {
00174 if (_settings_game.construction.max_tlc_size == 0) return true;
00175 TLC *consist = GetTrafficLightConsist(tile, false);
00176 bool result = (consist->size() <= _settings_game.construction.max_tlc_size);
00177 delete consist;
00178 return result;
00179 }
00180
00189 CommandCost CmdBuildTrafficLights(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00190 {
00191
00192 if (!_settings_game.construction.traffic_lights) return CMD_ERROR;
00193
00194
00195 if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_NORMAL) return_cmd_error(STR_ERROR_THERE_IS_NO_ROAD);
00196
00197
00198 if (Company::IsValidID(_current_company)) {
00199 Owner owner = GetTileOwner(tile);
00200 if (owner == OWNER_TOWN) {
00201 if (!_settings_game.construction.allow_building_tls_in_towns) return_cmd_error(STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS);
00202 } else {
00203 if (owner != OWNER_NONE && !IsTileOwner(tile, _current_company)) return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER);
00204 }
00205 }
00206
00207
00208 if (CountBits(GetAllRoadBits(tile)) < 3) return_cmd_error(STR_ERROR_CAN_ONLY_BE_PLACED_ON_ROAD_JUNCTIONS);
00209 if (HasTrafficLights(tile)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
00210
00211 if (!CheckTLCSize(tile)) return_cmd_error(STR_ERROR_TRAFFIC_LIGHT_CONSIST_TOO_BIG);
00212
00213
00214 if (flags & DC_EXEC) {
00215 MakeTrafficLights(tile);
00216 AddAnimatedTile(tile);
00217 MarkTileDirtyByTile(tile);
00218 }
00219 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
00220 }
00221
00230 CommandCost CmdRemoveTrafficLights(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00231 {
00232
00233 if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_NORMAL || !HasTrafficLights(tile)) return CMD_ERROR;
00234
00235
00236 if (Company::IsValidID(_current_company)) {
00237 Owner owner = GetTileOwner(tile);
00238 if (owner == OWNER_TOWN) {
00239 if (!_settings_game.construction.allow_building_tls_in_towns && !_cheats.magic_bulldozer.value) return_cmd_error(STR_ERROR_TRAFFIC_LIGHTS_NOT_ALLOWED_ON_TOWN_ROADS);
00240 } else {
00241 if (owner != OWNER_NONE && !IsTileOwner(tile, _current_company)) return CMD_ERROR;
00242 }
00243 }
00244
00245
00246 if (flags & DC_EXEC) {
00247 DeleteAnimatedTile(tile);
00248 ClearTrafficLights(tile);
00249 MarkTileDirtyByTile(tile);
00250 }
00251 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_SIGNALS]);
00252 }
00256 void ClearAllTrafficLights()
00257 {
00258
00259 for (TileIndex tile = 0; tile < MapSize(); tile++) {
00260 if (HasTrafficLights(tile)) {
00261 DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_TRAFFICLIGHTS);
00262 }
00263 }
00264 }
00265
00270 void DrawTrafficLights(TileInfo* ti)
00271 {
00272 RoadBits road = GetAllRoadBits(ti->tile);
00273 TrafficLightState state = GetTLState(ti->tile);
00274
00275 const TileIndex neighbor[4] = { ti->tile + TileDiffXY(1, 0),
00276 ti->tile + TileDiffXY(0, 1),
00277 ti->tile + TileDiffXY(0, -1),
00278 ti->tile + TileDiffXY(-1, 0)};
00279 const RoadBits rb[4] = {ROAD_SW, ROAD_SE, ROAD_NW, ROAD_NE};
00280
00281
00282 byte rs = _settings_game.vehicle.road_side;
00283 for (int i = 0; i < 4; i++) {
00284 if (road & rb[i] && !HasTrafficLights(neighbor[i])) {
00285 DisallowedRoadDirections drd = DRD_NONE;
00286 if (IsTileType(neighbor[i], MP_ROAD) && IsNormalRoad(neighbor[i])) drd = GetDisallowedRoadDirections(neighbor[i]);
00287 if (drd != ((i % 2 == 0) ? DRD_SOUTHBOUND : DRD_NORTHBOUND) && drd != DRD_BOTH)
00288 DrawRoadDetail(_tls_to_sprites[state][i], ti, _tl_offsets[rs][i].x, _tl_offsets[rs][i].y, 12);
00289 }
00290 }
00291 }