src/tunnelbridge_cmd.cpp
changeset 6181 b43f7753f4c3
parent 6103 7fa3e01134cb
child 6253 23983700e3d7
child 6317 c73bda71ac16
equal deleted inserted replaced
6180:91146a3bcbff 6181:b43f7753f4c3
   171  * - p2 = (bit 0- 7) - bridge type (hi bh)
   171  * - p2 = (bit 0- 7) - bridge type (hi bh)
   172  * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge.
   172  * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge.
   173  */
   173  */
   174 int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   174 int32 CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
   175 {
   175 {
   176 	int bridge_type;
   176 	uint bridge_type;
   177 	RailType railtype;
   177 	RailType railtype;
   178 	uint x;
   178 	uint x;
   179 	uint y;
   179 	uint y;
   180 	uint sx;
   180 	uint sx;
   181 	uint sy;
   181 	uint sy;
   189 	TileIndexDiff delta;
   189 	TileIndexDiff delta;
   190 	uint bridge_len;
   190 	uint bridge_len;
   191 	Axis direction;
   191 	Axis direction;
   192 	int32 cost, terraformcost, ret;
   192 	int32 cost, terraformcost, ret;
   193 	bool allow_on_slopes;
   193 	bool allow_on_slopes;
       
   194 	bool replace_bridge = false;
       
   195 	uint replaced_bridge_type;
   194 
   196 
   195 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   197 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   196 
   198 
   197 	/* unpack parameters */
   199 	/* unpack parameters */
   198 	bridge_type = GB(p2, 0, 8);
   200 	bridge_type = GB(p2, 0, 8);
   254 
   256 
   255 	// Towns are not allowed to use bridges on slopes.
   257 	// Towns are not allowed to use bridges on slopes.
   256 	allow_on_slopes = (!_is_old_ai_player
   258 	allow_on_slopes = (!_is_old_ai_player
   257 	                   && _current_player != OWNER_TOWN && _patches.build_on_slopes);
   259 	                   && _current_player != OWNER_TOWN && _patches.build_on_slopes);
   258 
   260 
   259 	/* Try and clear the start landscape */
   261 	TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL;
   260 
   262 
   261 	ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   263 	if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
   262 	if (CmdFailed(ret)) return ret;
   264 			GetOtherBridgeEnd(tile_start) == tile_end &&
   263 	cost = ret;
   265 			GetBridgeTransportType(tile_start) == transport_type) {
   264 
   266 		/* Replace a current bridge. */
   265 	terraformcost = CheckBridgeSlopeNorth(direction, tileh_start);
   267 
   266 	if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
   268 		/* If this is a railway bridge, make sure the railtypes match. */
   267 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   269 		if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
   268 	cost += terraformcost;
   270 			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   269 
   271 		}
   270 	/* Try and clear the end landscape */
   272 
   271 
   273 		/* Do not replace town bridges with lower speed bridges. */
   272 	ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   274 		if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
   273 	if (CmdFailed(ret)) return ret;
   275 				_bridge[bridge_type].speed < _bridge[GetBridgeType(tile_start)].speed) {
   274 	cost += ret;
   276 			Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
   275 
   277 
   276 	// false - end tile slope check
   278 			if (t == NULL) {
   277 	terraformcost = CheckBridgeSlopeSouth(direction, tileh_end);
   279 				return CMD_ERROR;
   278 	if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
   280 			} else {
   279 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
   281 				SetDParam(0, t->index);
   280 	cost += terraformcost;
   282 				return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
   281 
   283 			}
   282 	{
   284 		}
       
   285 
       
   286 		/* Do not replace the bridge with the same bridge type. */
       
   287 		if (!(flags & DC_QUERY_COST) && bridge_type == GetBridgeType(tile_start)) {
       
   288 			return_cmd_error(STR_1007_ALREADY_BUILT);
       
   289 		}
       
   290 
       
   291 		/* Do not allow replacing another player's bridges. */
       
   292 		if (!IsTileOwner(tile_start, _current_player) && !IsTileOwner(tile_start, OWNER_TOWN)) {
       
   293 			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
       
   294 		}
       
   295 
       
   296 		cost = (bridge_len + 1) * _price.clear_bridge; // The cost of clearing the current bridge.
       
   297 		replace_bridge = true;
       
   298 		replaced_bridge_type = GetBridgeType(tile_start);
       
   299 	} else {
       
   300 		/* Build a new bridge. */
       
   301 
       
   302 		/* Try and clear the start landscape */
       
   303 		ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   304 		if (CmdFailed(ret)) return ret;
       
   305 		cost = ret;
       
   306 
       
   307 		terraformcost = CheckBridgeSlopeNorth(direction, tileh_start);
       
   308 		if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
       
   309 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   310 		cost += terraformcost;
       
   311 
       
   312 		/* Try and clear the end landscape */
       
   313 		ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   314 		if (CmdFailed(ret)) return ret;
       
   315 		cost += ret;
       
   316 
       
   317 		// false - end tile slope check
       
   318 		terraformcost = CheckBridgeSlopeSouth(direction, tileh_end);
       
   319 		if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes))
       
   320 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   321 		cost += terraformcost;
       
   322 	}
       
   323 
       
   324 	if (!replace_bridge) {
   283 		TileIndex Heads[] = {tile_start, tile_end};
   325 		TileIndex Heads[] = {tile_start, tile_end};
   284 		int i;
   326 		int i;
   285 
   327 
   286 		for (i = 0; i < 2; i++) {
   328 		for (i = 0; i < 2; i++) {
   287 			if (MayHaveBridgeAbove(Heads[i])) {
   329 			if (MayHaveBridgeAbove(Heads[i])) {
   299 	}
   341 	}
   300 
   342 
   301 	/* do the drill? */
   343 	/* do the drill? */
   302 	if (flags & DC_EXEC) {
   344 	if (flags & DC_EXEC) {
   303 		DiagDirection dir = AxisToDiagDir(direction);
   345 		DiagDirection dir = AxisToDiagDir(direction);
       
   346 		Owner owner = (replace_bridge && IsTileOwner(tile_start, OWNER_TOWN)) ? OWNER_TOWN : _current_player;
   304 
   347 
   305 		if (railtype != INVALID_RAILTYPE) {
   348 		if (railtype != INVALID_RAILTYPE) {
   306 			MakeRailBridgeRamp(tile_start, _current_player, bridge_type, dir, railtype);
   349 			MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
   307 			MakeRailBridgeRamp(tile_end,   _current_player, bridge_type, ReverseDiagDir(dir), railtype);
   350 			MakeRailBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), railtype);
   308 		} else {
   351 		} else {
   309 			MakeRoadBridgeRamp(tile_start, _current_player, bridge_type, dir);
   352 			MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir);
   310 			MakeRoadBridgeRamp(tile_end,   _current_player, bridge_type, ReverseDiagDir(dir));
   353 			MakeRoadBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir));
   311 		}
   354 		}
   312 		MarkTileDirtyByTile(tile_start);
   355 		MarkTileDirtyByTile(tile_start);
   313 		MarkTileDirtyByTile(tile_end);
   356 		MarkTileDirtyByTile(tile_end);
   314 	}
   357 	}
   315 
   358 
   317 	for (tile = tile_start + delta; tile != tile_end; tile += delta) {
   360 	for (tile = tile_start + delta; tile != tile_end; tile += delta) {
   318 		uint z;
   361 		uint z;
   319 
   362 
   320 		if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
   363 		if (GetTileSlope(tile, &z) != SLOPE_FLAT && z >= z_start) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED);
   321 
   364 
   322 		if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
   365 		if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile) && !replace_bridge) {
   323 			/* Disallow crossing bridges for the time being */
   366 			/* Disallow crossing bridges for the time being */
   324 			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   367 			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   325 		}
   368 		}
   326 
   369 
   327 		switch (GetTileType(tile)) {
   370 		switch (GetTileType(tile)) {
   338 				if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) goto not_valid_below;
   381 				if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) goto not_valid_below;
   339 				break;
   382 				break;
   340 
   383 
   341 			case MP_TUNNELBRIDGE:
   384 			case MP_TUNNELBRIDGE:
   342 				if (IsTunnel(tile)) break;
   385 				if (IsTunnel(tile)) break;
       
   386 				if (replace_bridge) break;
   343 				if (direction == DiagDirToAxis(GetBridgeRampDirection(tile))) goto not_valid_below;
   387 				if (direction == DiagDirToAxis(GetBridgeRampDirection(tile))) goto not_valid_below;
   344 				if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
   388 				if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
   345 				break;
   389 				break;
   346 
   390 
   347 			case MP_UNMOVABLE:
   391 			case MP_UNMOVABLE:
   348 				if (!IsOwnedLand(tile)) goto not_valid_below;
   392 				if (!IsOwnedLand(tile)) goto not_valid_below;
   349 				break;
   393 				break;
   350 
   394 
   351 			case MP_CLEAR:
   395 			case MP_CLEAR:
   352 				if (IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   396 				if (!replace_bridge && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   353 				break;
   397 				break;
   354 
   398 
   355 			default:
   399 			default:
   356 not_valid_below:;
   400 not_valid_below:;
   357 				/* try and clear the middle landscape */
   401 				/* try and clear the middle landscape */