Hmm, I see your approach is global. Everything that makes use of EnsureNoVehicleOnGround will be doing that ship check. I kind of like the idea of a global approach, but at the same time, it's risky, without knowing for sure if it's going to get desired results.
My approach is only limited to locks, docks and ship depots placement.
I'm currently testing your approach. Be back later.
EDIT: Thanks for reminding me of Aqueduct and Buoy tiles, I totally forgot about them. It's not too obvious to work with water tiles.
EDIT2: Here's a list of everything that uses EnsureNoVehicleOnGround, according to View Call Hierarchy by Visual Studio
station_cmd.cpp - CheckBuildableTile(TileIndex tile, uint invalid_dirs, int & allowed_z, bool allow_steep, bool check_bridge)
industry_cmd.cpp - CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable * it, uint itspec_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool * custom_shape_check)
rail_cmd.cpp - ClearTile_Track(TileIndex tile, DoCommandFlag flags)
water_cmd.cpp - ClearTile_Water(TileIndex tile, DoCommandFlag flags)
object_cmd.cpp - CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
road_cmd.cpp - CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char * text)
rail_cmd.cpp - CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char * text)
rail_cmd.cpp - CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char * text)
rail_cmd.cpp - CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char * text)
rail_cmd.cpp - CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char * text)
disaster_vehicle.cpp - DisasterClearSquare(TileIndex tile)
water_cmd.cpp - DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags)
waypoint_cmd.cpp - IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID * waypoint)
station_cmd.cpp - RemoveAirport(TileIndex tile, DoCommandFlag flags)
waypoint_cmd.cpp - RemoveBuoy(TileIndex tile, DoCommandFlag flags)
station_cmd.cpp - RemoveDock(TileIndex tile, DoCommandFlag flags)
station_cmd.cpp - RemoveFromRailBaseStation(TileArea ta, SmallVector<T *, 4U> &affected_stations, DoCommandFlag flags, Money removal_cost, bool keep_rail)
water_cmd.cpp - RemoveLock(TileIndex tile, DoCommandFlag flags)
road_cmd.cpp - RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true)
road_cmd.cpp - RemoveRoadDepot(TileIndex tile, DoCommandFlag flags)
station_cmd.cpp - RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
water_cmd.cpp - RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
rail_cmd.cpp - RemoveTrainDepot(TileIndex tile, DoCommandFlag flags)
road_cmd.cpp - TileLoop_Road(TileIndex tile)
I've edited part of your code and it now looks like this:
Code: Select all
Index: src/vehicle.cpp
===================================================================
--- src/vehicle.cpp (revision 27653)
+++ src/vehicle.cpp (working copy)
@@ -47,6 +47,7 @@
#include "effectvehicle_base.h"
#include "vehiclelist.h"
#include "bridge_map.h"
+#include "tunnelbridge_map.h"
#include "tunnel_map.h"
#include "depot_map.h"
#include "gamelog.h"
@@ -481,6 +482,19 @@
*/
Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true);
if (v != NULL) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
+
+ if ((TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0)) & TRACK_BIT_ALL) != TRACK_BIT_NONE) {
+ Ship *s;
+ FOR_ALL_SHIPS(s) {
+ if (DistanceManhattan(tile, s->tile) != 1) continue;
+ /* Don't care about ships on aqueducts. Those kind of tiles don't cause problems. */
+ /* The same can be applied to locks and ship depots. */
+ if (IsTileType(s->tile, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(s->tile) == TRANSPORT_WATER ||
+ IsTileType(s->tile, MP_WATER) && IsLock(s->tile) || IsShipDepotTile(s->tile)) continue;
+ if (s->state & DiagdirReachesTracks(DiagdirBetweenTiles(tile, s->tile))) return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY);
+ }
+ }
+
return CommandCost();
}
Now, to make sure if that whole list of functions are behaving as intended will be the hardest part.