Use separate tile hash for each vehicle type
This commit is contained in:
@@ -307,7 +307,7 @@ static Vehicle *CountShipProc(Vehicle *v, void *data)
|
||||
{
|
||||
uint *count = (uint *)data;
|
||||
/* Ignore other vehicles (aircraft) and ships inside depot. */
|
||||
if (v->type == VEH_SHIP && (v->vehstatus & VS_HIDDEN) == 0) (*count)++;
|
||||
if ((v->vehstatus & VS_HIDDEN) == 0) (*count)++;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -331,7 +331,7 @@ static int32 NPFWaterPathCost(AyStar *as, AyStarNode *current, OpenListNode *par
|
||||
if (IsDockingTile(current->tile)) {
|
||||
/* Check docking tile for occupancy */
|
||||
uint count = 1;
|
||||
HasVehicleOnPos(current->tile, &count, &CountShipProc);
|
||||
HasVehicleOnPos(current->tile, VEH_SHIP, &count, &CountShipProc);
|
||||
cost += count * 3 * _trackdir_length[trackdir];
|
||||
}
|
||||
|
||||
|
@@ -268,7 +268,7 @@ public:
|
||||
{
|
||||
uint *count = (uint *)data;
|
||||
/* Ignore other vehicles (aircraft) and ships inside depot. */
|
||||
if (v->type == VEH_SHIP && (v->vehstatus & VS_HIDDEN) == 0) (*count)++;
|
||||
if ((v->vehstatus & VS_HIDDEN) == 0) (*count)++;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -288,7 +288,7 @@ public:
|
||||
if (IsDockingTile(n.GetTile())) {
|
||||
/* Check docking tile for occupancy */
|
||||
uint count = 1;
|
||||
HasVehicleOnPos(n.GetTile(), &count, &CountShipProc);
|
||||
HasVehicleOnPos(n.GetTile(), VEH_SHIP, &count, &CountShipProc);
|
||||
c += count * 3 * YAPF_TILE_LENGTH;
|
||||
}
|
||||
|
||||
|
17
src/pbs.cpp
17
src/pbs.cpp
@@ -330,7 +330,7 @@ static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
|
||||
{
|
||||
FindTrainOnTrackInfo *info = (FindTrainOnTrackInfo *)data;
|
||||
|
||||
if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return nullptr;
|
||||
if ((v->vehstatus & VS_CRASHED)) return nullptr;
|
||||
|
||||
Train *t = Train::From(v);
|
||||
if (t->track & TRACK_BIT_WORMHOLE) {
|
||||
@@ -372,7 +372,7 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
|
||||
ftoti.res = FollowReservation(v->owner, GetRailTypeInfo(v->railtype)->compatible_railtypes, tile, trackdir);
|
||||
ftoti.res.okay = IsSafeWaitingPosition(v, ftoti.res.tile, ftoti.res.trackdir, true, _settings_game.pf.forbid_90_deg);
|
||||
if (train_on_res != nullptr) {
|
||||
FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
|
||||
FindVehicleOnPos(ftoti.res.tile, VEH_TRAIN, &ftoti, FindTrainOnTrackEnum);
|
||||
if (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
|
||||
if (*train_on_res == nullptr && IsRailStationTile(ftoti.res.tile)) {
|
||||
/* The target tile is a rail station. The track follower
|
||||
@@ -381,13 +381,13 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
|
||||
* for a possible train. */
|
||||
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
|
||||
for (TileIndex st_tile = ftoti.res.tile + diff; *train_on_res == nullptr && IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
|
||||
FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
|
||||
FindVehicleOnPos(st_tile, VEH_TRAIN, &ftoti, FindTrainOnTrackEnum);
|
||||
if (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
|
||||
}
|
||||
}
|
||||
if (*train_on_res == nullptr && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE) && IsTrackAcrossTunnelBridge(ftoti.res.tile, TrackdirToTrack(ftoti.res.trackdir)) && !IsTunnelBridgeWithSignalSimulation(ftoti.res.tile)) {
|
||||
/* The target tile is a bridge/tunnel, also check the other end tile. */
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum);
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), VEH_TRAIN, &ftoti, FindTrainOnTrackEnum);
|
||||
if (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
|
||||
}
|
||||
}
|
||||
@@ -419,21 +419,21 @@ Train *GetTrainForReservation(TileIndex tile, Track track)
|
||||
FindTrainOnTrackInfo ftoti;
|
||||
ftoti.res = FollowReservation(GetTileOwner(tile), rts, tile, trackdir, true);
|
||||
|
||||
FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
|
||||
FindVehicleOnPos(ftoti.res.tile, VEH_TRAIN, &ftoti, FindTrainOnTrackEnum);
|
||||
if (ftoti.best != nullptr) return ftoti.best;
|
||||
|
||||
/* Special case for stations: check the whole platform for a vehicle. */
|
||||
if (IsRailStationTile(ftoti.res.tile)) {
|
||||
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
|
||||
for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
|
||||
FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
|
||||
FindVehicleOnPos(st_tile, VEH_TRAIN, &ftoti, FindTrainOnTrackEnum);
|
||||
if (ftoti.best != nullptr) return ftoti.best;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special case for bridges/tunnels: check the other end as well. */
|
||||
if (IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE) && IsTrackAcrossTunnelBridge(ftoti.res.tile, TrackdirToTrack(ftoti.res.trackdir))) {
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum);
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), VEH_TRAIN, &ftoti, FindTrainOnTrackEnum);
|
||||
if (ftoti.best != nullptr) return ftoti.best;
|
||||
}
|
||||
}
|
||||
@@ -608,8 +608,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
||||
TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
|
||||
if (HasAcrossTunnelBridgeReservation(other_end) && GetTunnelBridgeExitSignalState(other_end) == SIGNAL_STATE_RED) return false;
|
||||
Direction dir = DiagDirToDir(GetTunnelBridgeDirection(other_end));
|
||||
if (HasVehicleOnPos(other_end, &dir, [](Vehicle *v, void *data) -> Vehicle * {
|
||||
if (v->type != VEH_TRAIN) return nullptr;
|
||||
if (HasVehicleOnPos(other_end, VEH_TRAIN, &dir, [](Vehicle *v, void *data) -> Vehicle * {
|
||||
DirDiff diff = DirDifference(v->direction, *((Direction *) data));
|
||||
if (diff == DIRDIFF_SAME) return v;
|
||||
if (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT) {
|
||||
|
@@ -2015,8 +2015,6 @@ CommandCost CmdRemoveSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||
/** Update power of train under which is the railtype being converted */
|
||||
static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data)
|
||||
{
|
||||
if (v->type != VEH_TRAIN) return nullptr;
|
||||
|
||||
TrainList *affected_trains = static_cast<TrainList*>(data);
|
||||
include(*affected_trains, Train::From(v)->First());
|
||||
|
||||
@@ -2148,7 +2146,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
|
||||
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
|
||||
/* update power of train on this tile */
|
||||
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
||||
FindVehicleOnPos(tile, VEH_TRAIN, &affected_trains, &UpdateTrainPowerProc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2224,8 +2222,8 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
SetSecondaryRailType(tile, totype);
|
||||
SetSecondaryRailType(endtile, totype);
|
||||
|
||||
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
||||
FindVehicleOnPos(endtile, &affected_trains, &UpdateTrainPowerProc);
|
||||
FindVehicleOnPos(tile, VEH_TRAIN, &affected_trains, &UpdateTrainPowerProc);
|
||||
FindVehicleOnPos(endtile, VEH_TRAIN, &affected_trains, &UpdateTrainPowerProc);
|
||||
|
||||
/* notify YAPF about the track layout change */
|
||||
yapf_notify_track_change(tile, GetTunnelBridgeTrackBits(tile));
|
||||
@@ -3808,7 +3806,7 @@ static CommandCost TestAutoslopeOnRailTile(TileIndex tile, uint flags, int z_old
|
||||
*/
|
||||
static Vehicle *EnsureNoShipProc(Vehicle *v, void *data)
|
||||
{
|
||||
return v->type == VEH_SHIP ? v : nullptr;
|
||||
return v;
|
||||
}
|
||||
|
||||
static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
|
||||
@@ -3821,7 +3819,7 @@ static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlag flags, int
|
||||
bool was_water = (GetRailGroundType(tile) == RAIL_GROUND_WATER && IsSlopeWithOneCornerRaised(tileh_old));
|
||||
|
||||
/* Allow clearing the water only if there is no ship */
|
||||
if (was_water && HasVehicleOnPos(tile, nullptr, &EnsureNoShipProc)) return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY);
|
||||
if (was_water && HasVehicleOnPos(tile, VEH_SHIP, nullptr, &EnsureNoShipProc)) return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY);
|
||||
|
||||
if (was_water && _game_mode != GM_EDITOR && !_settings_game.construction.enable_remove_water && !(flags & DC_ALLOW_REMOVE_WATER)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
|
||||
|
||||
|
@@ -2479,8 +2479,6 @@ static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlag flags, int z
|
||||
/** Update power of road vehicle under which is the roadtype being converted */
|
||||
static Vehicle *UpdateRoadVehPowerProc(Vehicle *v, void *data)
|
||||
{
|
||||
if (v->type != VEH_ROAD) return nullptr;
|
||||
|
||||
RoadVehicleList *affected_rvs = static_cast<RoadVehicleList*>(data);
|
||||
include(*affected_rvs, RoadVehicle::From(v)->First());
|
||||
|
||||
@@ -2637,7 +2635,7 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
MarkTileDirtyByTile(tile);
|
||||
|
||||
/* update power of train on this tile */
|
||||
FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||
FindVehicleOnPos(tile, VEH_ROAD, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||
|
||||
if (IsRoadDepotTile(tile)) {
|
||||
/* Update build vehicle window related to this depot */
|
||||
@@ -2710,8 +2708,8 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
SetRoadType(tile, rtt, to_type);
|
||||
if (include_middle) SetRoadType(endtile, rtt, to_type);
|
||||
|
||||
FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||
FindVehicleOnPos(endtile, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||
FindVehicleOnPos(tile, VEH_ROAD, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||
FindVehicleOnPos(endtile, VEH_ROAD, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||
|
||||
if (IsBridge(tile)) {
|
||||
MarkBridgeDirty(tile);
|
||||
|
@@ -329,7 +329,7 @@ Vehicle *FindVehiclesInRoadStop(Vehicle *v, void *data)
|
||||
{
|
||||
RoadStopEntryRebuilderHelper *rserh = (RoadStopEntryRebuilderHelper*)data;
|
||||
/* Not a RV or not in the right direction or crashed :( */
|
||||
if (v->type != VEH_ROAD || DirToDiagDir(v->direction) != rserh->dir || !v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) return nullptr;
|
||||
if (DirToDiagDir(v->direction) != rserh->dir || !v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) return nullptr;
|
||||
|
||||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
/* Don't add ones not in a road stop */
|
||||
@@ -363,7 +363,7 @@ void RoadStop::Entry::Rebuild(const RoadStop *rs, int side)
|
||||
TileIndexDiff offset = abs(TileOffsByDiagDir(dir));
|
||||
for (TileIndex tile = rs->xy; IsDriveThroughRoadStopContinuation(rs->xy, tile); tile += offset) {
|
||||
this->length += TILE_SIZE;
|
||||
FindVehicleOnPos(tile, &rserh, FindVehiclesInRoadStop);
|
||||
FindVehicleOnPos(tile, VEH_ROAD, &rserh, FindVehiclesInRoadStop);
|
||||
}
|
||||
|
||||
this->occupied = 0;
|
||||
|
@@ -560,8 +560,7 @@ static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
|
||||
{
|
||||
CheckRoadVehCrashTrainInfo *info = (CheckRoadVehCrashTrainInfo*) data;
|
||||
|
||||
if (v->type == VEH_TRAIN &&
|
||||
abs(v->z_pos - info->u->z_pos) <= 6 &&
|
||||
if (abs(v->z_pos - info->u->z_pos) <= 6 &&
|
||||
abs(v->x_pos - info->u->x_pos) <= 4 &&
|
||||
abs(v->y_pos - info->u->y_pos) <= 4) {
|
||||
info->found = true;
|
||||
@@ -617,7 +616,7 @@ static bool RoadVehCheckTrainCrash(RoadVehicle *v)
|
||||
if (!IsLevelCrossingTile(tile)) continue;
|
||||
|
||||
CheckRoadVehCrashTrainInfo info(u);
|
||||
FindVehicleOnPosXY(v->x_pos, v->y_pos, &info, EnumCheckRoadVehCrashTrain);
|
||||
FindVehicleOnPosXY(v->x_pos, v->y_pos, VEH_TRAIN, &info, EnumCheckRoadVehCrashTrain);
|
||||
if (info.found) {
|
||||
RoadVehCrash(v);
|
||||
return true;
|
||||
@@ -671,8 +670,7 @@ static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
||||
short x_diff = v->x_pos - rvf->x;
|
||||
short y_diff = v->y_pos - rvf->y;
|
||||
|
||||
if (v->type == VEH_ROAD &&
|
||||
!v->IsInDepot() &&
|
||||
if (!v->IsInDepot() &&
|
||||
abs(v->z_pos - rvf->veh->z_pos) < 6 &&
|
||||
v->direction == rvf->dir &&
|
||||
rvf->veh->First() != v->First() &&
|
||||
@@ -705,10 +703,10 @@ static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction d
|
||||
rvf.best_diff = UINT_MAX;
|
||||
|
||||
if (front->state == RVSB_WORMHOLE) {
|
||||
FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
|
||||
FindVehicleOnPos(v->tile, VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||
} else {
|
||||
FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
|
||||
FindVehicleOnPosXY(x, y, VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||
}
|
||||
|
||||
/* This code protects a roadvehicle from being blocked for ever
|
||||
@@ -822,7 +820,7 @@ static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
|
||||
{
|
||||
const OvertakeData *od = (OvertakeData*)data;
|
||||
|
||||
return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : nullptr;
|
||||
return (v->First() == v && v != od->u && v != od->v) ? v : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -843,7 +841,7 @@ static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
|
||||
if (!HasBit(trackdirbits, od->trackdir) || (trackbits & ~TRACK_BIT_CROSS) || (red_signals != TRACKDIR_BIT_NONE)) return true;
|
||||
|
||||
/* Are there more vehicles on the tile except the two vehicles involved in overtaking */
|
||||
return HasVehicleOnPos(od->tile, od, EnumFindVehBlockingOvertake);
|
||||
return HasVehicleOnPos(od->tile, VEH_ROAD, od, EnumFindVehBlockingOvertake);
|
||||
}
|
||||
|
||||
static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||
|
@@ -343,7 +343,7 @@ void Ship::UpdateDeltaXY()
|
||||
*/
|
||||
static Vehicle *EnsureNoVisibleShipProc(Vehicle *v, void *data)
|
||||
{
|
||||
return v->type == VEH_SHIP && (v->vehstatus & VS_HIDDEN) == 0 ? v : nullptr;
|
||||
return (v->vehstatus & VS_HIDDEN) == 0 ? v : nullptr;
|
||||
}
|
||||
|
||||
static bool CheckShipLeaveDepot(Ship *v)
|
||||
@@ -369,7 +369,7 @@ static bool CheckShipLeaveDepot(Ship *v)
|
||||
|
||||
/* Don't leave depot if another vehicle is already entering/leaving */
|
||||
/* This helps avoid CPU load if many ships are set to start at the same time */
|
||||
if (HasVehicleOnPos(v->tile, nullptr, &EnsureNoVisibleShipProc)) return true;
|
||||
if (HasVehicleOnPos(v->tile, VEH_SHIP, nullptr, &EnsureNoVisibleShipProc)) return true;
|
||||
|
||||
TileIndex tile = v->tile;
|
||||
Axis axis = GetShipDepotAxis(tile);
|
||||
@@ -588,8 +588,6 @@ struct ShipCollideChecker {
|
||||
/** Helper function for collision avoidance. */
|
||||
static Vehicle *FindShipOnTile(Vehicle *v, void *data)
|
||||
{
|
||||
if (v->type != VEH_SHIP) return nullptr;
|
||||
|
||||
ShipCollideChecker *scc = (ShipCollideChecker*)data;
|
||||
|
||||
/* Don't detect vehicles on different parallel tracks. */
|
||||
@@ -624,8 +622,8 @@ static bool HandleSpeedOnAqueduct(Ship *v, TileIndex tile, TileIndex ramp)
|
||||
if (scc.search_tile == INVALID_TILE) return false;
|
||||
|
||||
if (IsValidTile(scc.search_tile) &&
|
||||
(HasVehicleOnPos(ramp, &scc, FindShipOnTile) ||
|
||||
HasVehicleOnPos(GetOtherTunnelBridgeEnd(ramp), &scc, FindShipOnTile))) {
|
||||
(HasVehicleOnPos(ramp, VEH_SHIP, &scc, FindShipOnTile) ||
|
||||
HasVehicleOnPos(GetOtherTunnelBridgeEnd(ramp), VEH_SHIP, &scc, FindShipOnTile))) {
|
||||
v->cur_speed /= 4;
|
||||
}
|
||||
return false;
|
||||
@@ -664,7 +662,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
||||
scc.track_bits = track_bits;
|
||||
scc.search_tile = tile;
|
||||
|
||||
bool found = HasVehicleOnPos(tile, &scc, FindShipOnTile);
|
||||
bool found = HasVehicleOnPos(tile, VEH_SHIP, &scc, FindShipOnTile);
|
||||
|
||||
if (!found) {
|
||||
/* Bridge entrance */
|
||||
@@ -675,7 +673,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
||||
scc.search_tile = TileAddWrap(tile, ti.x, ti.y);
|
||||
if (scc.search_tile == INVALID_TILE) return;
|
||||
|
||||
found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile);
|
||||
found = HasVehicleOnPos(scc.search_tile, VEH_SHIP, &scc, FindShipOnTile);
|
||||
}
|
||||
if (!found) {
|
||||
scc.track_bits = track_bits;
|
||||
@@ -683,7 +681,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
||||
scc.search_tile = TileAddWrap(scc.search_tile, ti.x, ti.y);
|
||||
if (scc.search_tile == INVALID_TILE) return;
|
||||
|
||||
found = HasVehicleOnPos(scc.search_tile, &scc, FindShipOnTile);
|
||||
found = HasVehicleOnPos(scc.search_tile, VEH_SHIP, &scc, FindShipOnTile);
|
||||
}
|
||||
if (found) {
|
||||
|
||||
@@ -701,7 +699,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
||||
TileIndex tile_check = TileAddWrap(tile, ti.x, ti.y);
|
||||
if (tile_check == INVALID_TILE) continue;
|
||||
|
||||
if (HasVehicleOnPos(tile_check, &scc, FindShipOnTile)) continue;
|
||||
if (HasVehicleOnPos(tile_check, VEH_SHIP, &scc, FindShipOnTile)) continue;
|
||||
|
||||
TrackBits bits = GetTileShipTrackStatus(tile_check) & DiagdirReachesTracks(_ship_search_directions[track][diagdir]);
|
||||
if (!IsDiagonalTrack(track)) bits &= TRACK_BIT_CROSS; // No 90 degree turns.
|
||||
|
@@ -205,7 +205,7 @@ static uint _num_signals_evaluated; ///< Number of programmable pre-signals eval
|
||||
/** Check whether there is a train on rail, not in a depot */
|
||||
static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
||||
{
|
||||
if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
|
||||
if (Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
|
||||
|
||||
return v;
|
||||
}
|
||||
@@ -214,8 +214,8 @@ static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
||||
static Vehicle *TrainInWormholeTileEnum(Vehicle *v, void *data)
|
||||
{
|
||||
/* Only look for front engine or last wagon. */
|
||||
if (v->type != VEH_TRAIN || (v->Previous() != nullptr && v->Next() != nullptr)) return nullptr;
|
||||
TileIndex tile = *(TileIndex *)data;
|
||||
if ((v->Previous() != nullptr && v->Next() != nullptr)) return nullptr;
|
||||
TileIndex tile = (TileIndex) reinterpret_cast<uintptr_t>(data);
|
||||
if (tile != TileVirtXY(v->x_pos, v->y_pos)) return nullptr;
|
||||
if (!(Train::From(v)->track & TRACK_BIT_WORMHOLE) && !(Train::From(v)->track & GetAcrossTunnelBridgeTrackBits(tile))) return nullptr;
|
||||
return v;
|
||||
@@ -313,13 +313,13 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
|
||||
if (IsRailDepot(tile)) {
|
||||
if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
exitdir = GetRailDepotDirection(tile);
|
||||
tile += TileOffsByDiagDir(exitdir);
|
||||
enterdir = ReverseDiagDir(exitdir);
|
||||
break;
|
||||
} else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
@@ -336,7 +336,7 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
if (!(info.flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) info.flags |= SF_TRAIN;
|
||||
} else {
|
||||
if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
}
|
||||
|
||||
if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
|
||||
@@ -390,7 +390,7 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
|
||||
if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
|
||||
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
tile += TileOffsByDiagDir(exitdir);
|
||||
break;
|
||||
|
||||
@@ -399,7 +399,7 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
|
||||
if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
|
||||
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (_settings_game.vehicle.safer_crossings) info.flags |= SF_PBS;
|
||||
tile += TileOffsByDiagDir(exitdir);
|
||||
break;
|
||||
@@ -422,7 +422,7 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
return EnsureNoTrainOnTrackBits(tile, tracks & (~across_tracks)).Failed();
|
||||
}
|
||||
} else {
|
||||
return HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum);
|
||||
return HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -433,8 +433,8 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
if (enterdir == INVALID_DIAGDIR) {
|
||||
// incoming from the wormhole, onto signal
|
||||
if (!(info.flags & SF_TRAIN) && IsTunnelBridgeSignalSimulationExit(tile)) { // tunnel entrance is ignored
|
||||
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), VEH_TRAIN, reinterpret_cast<void *>(tile), &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, VEH_TRAIN, reinterpret_cast<void *>(tile), &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
}
|
||||
if (IsTunnelBridgeSignalSimulationExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) {
|
||||
info.flags |= SF_FULL;
|
||||
@@ -456,9 +456,9 @@ static SigInfo ExploreSegment(Owner owner)
|
||||
}
|
||||
}
|
||||
if (!(info.flags & SF_TRAIN)) {
|
||||
if (HasVehicleOnPos(tile, &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (HasVehicleOnPos(tile, VEH_TRAIN, reinterpret_cast<void *>(tile), &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (!(info.flags & SF_TRAIN) && IsTunnelBridgeSignalSimulationExit(tile)) {
|
||||
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), &tile, &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(tile), VEH_TRAIN, reinterpret_cast<void *>(tile), &TrainInWormholeTileEnum)) info.flags |= SF_TRAIN;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
@@ -2092,7 +2092,6 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
|
||||
static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
||||
{
|
||||
if (v->type == VEH_ROAD) {
|
||||
/* Okay... we are a road vehicle on a drive through road stop.
|
||||
* But that road stop has just been removed, so we need to make
|
||||
* sure we are in a valid state... however, vehicles can also
|
||||
@@ -2101,7 +2100,6 @@ static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
||||
* we'll end up clearing the turn around bits. */
|
||||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
if (HasBit(rv->state, RVS_IN_DT_ROAD_STOP)) rv->state &= RVSB_ROAD_STOP_TRACKDIR_MASK;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -2139,7 +2137,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||
/* don't do the check for drive-through road stops when company bankrupts */
|
||||
if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
|
||||
/* remove the 'going through road stop' status from all vehicles on that tile */
|
||||
if (flags & DC_EXEC) FindVehicleOnPos(tile, nullptr, &ClearRoadStopStatusEnum);
|
||||
if (flags & DC_EXEC) FindVehicleOnPos(tile, VEH_ROAD, nullptr, &ClearRoadStopStatusEnum);
|
||||
} else {
|
||||
CommandCost ret = EnsureNoVehicleOnGround(tile);
|
||||
if (ret.Failed()) return ret;
|
||||
|
@@ -1914,7 +1914,7 @@ void ReverseTrainSwapVeh(Train *v, int l, int r)
|
||||
*/
|
||||
static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
||||
{
|
||||
return (v->type == VEH_TRAIN) ? v : nullptr;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -1926,12 +1926,12 @@ static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
||||
*/
|
||||
static Vehicle *TrainApproachingCrossingEnum(Vehicle *v, void *data)
|
||||
{
|
||||
if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return nullptr;
|
||||
if ((v->vehstatus & VS_CRASHED)) return nullptr;
|
||||
|
||||
Train *t = Train::From(v);
|
||||
if (!t->IsFrontEngine()) return nullptr;
|
||||
|
||||
TileIndex tile = *(TileIndex *)data;
|
||||
TileIndex tile = (TileIndex) reinterpret_cast<uintptr_t>(data);
|
||||
|
||||
if (TrainApproachingCrossingTile(t) != tile) return nullptr;
|
||||
|
||||
@@ -1952,12 +1952,12 @@ static bool TrainApproachingCrossing(TileIndex tile)
|
||||
DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
|
||||
TileIndex tile_from = tile + TileOffsByDiagDir(dir);
|
||||
|
||||
if (HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum)) return true;
|
||||
if (HasVehicleOnPos(tile_from, VEH_TRAIN, reinterpret_cast<void *>(tile), &TrainApproachingCrossingEnum)) return true;
|
||||
|
||||
dir = ReverseDiagDir(dir);
|
||||
tile_from = tile + TileOffsByDiagDir(dir);
|
||||
|
||||
return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum);
|
||||
return HasVehicleOnPos(tile_from, VEH_TRAIN, reinterpret_cast<void *>(tile), &TrainApproachingCrossingEnum);
|
||||
}
|
||||
|
||||
/** Check if the crossing should be closed
|
||||
@@ -1966,7 +1966,7 @@ static bool TrainApproachingCrossing(TileIndex tile)
|
||||
static inline bool CheckLevelCrossing(TileIndex tile)
|
||||
{
|
||||
/* reserved || train on crossing || train approaching crossing */
|
||||
return HasCrossingReservation(tile) || HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
|
||||
return HasCrossingReservation(tile) || HasVehicleOnPos(tile, VEH_TRAIN, nullptr, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3676,8 +3676,8 @@ static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data)
|
||||
{
|
||||
TrainCollideChecker *tcc = (TrainCollideChecker*)data;
|
||||
|
||||
/* not a train or in depot */
|
||||
if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
|
||||
/* not in depot */
|
||||
if (Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
|
||||
|
||||
if (_settings_game.vehicle.no_train_crash_other_company) {
|
||||
/* do not crash into trains of another company. */
|
||||
@@ -3734,10 +3734,10 @@ static bool CheckTrainCollision(Train *v)
|
||||
|
||||
/* find colliding vehicles */
|
||||
if (v->track & TRACK_BIT_WORMHOLE) {
|
||||
FindVehicleOnPos(v->tile, &tcc, FindTrainCollideEnum);
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum);
|
||||
FindVehicleOnPos(v->tile, VEH_TRAIN, &tcc, FindTrainCollideEnum);
|
||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), VEH_TRAIN, &tcc, FindTrainCollideEnum);
|
||||
} else {
|
||||
FindVehicleOnPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
|
||||
FindVehicleOnPosXY(v->x_pos, v->y_pos, VEH_TRAIN, &tcc, FindTrainCollideEnum);
|
||||
}
|
||||
|
||||
/* any dead -> no crash */
|
||||
@@ -3753,7 +3753,7 @@ static bool CheckTrainCollision(Train *v)
|
||||
|
||||
static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
|
||||
{
|
||||
if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return nullptr;
|
||||
if ((v->vehstatus & VS_CRASHED)) return nullptr;
|
||||
|
||||
Train *t = Train::From(v);
|
||||
DiagDirection exitdir = *(DiagDirection *)data;
|
||||
@@ -3776,7 +3776,7 @@ struct FindSpaceBetweenTrainsChecker {
|
||||
static Vehicle *FindSpaceBetweenTrainsEnum(Vehicle *v, void *data)
|
||||
{
|
||||
/* Don't look at wagons between front and back of train. */
|
||||
if (v->type != VEH_TRAIN || (v->Previous() != nullptr && v->Next() != nullptr)) return nullptr;
|
||||
if ((v->Previous() != nullptr && v->Next() != nullptr)) return nullptr;
|
||||
|
||||
if (!IsDiagonalDirection(v->direction)) {
|
||||
/* Check for vehicles on non-across track pieces of custom bridge head */
|
||||
@@ -3815,7 +3815,7 @@ static bool IsTooCloseBehindTrain(Vehicle *v, TileIndex tile, uint16 distance, b
|
||||
case DIAGDIR_NW: checker.pos = (TileY(tile) * TILE_SIZE) + TILE_UNIT_MASK; break;
|
||||
}
|
||||
|
||||
if (HasVehicleOnPos(t->tile, &checker, &FindSpaceBetweenTrainsEnum)) {
|
||||
if (HasVehicleOnPos(t->tile, VEH_TRAIN, &checker, &FindSpaceBetweenTrainsEnum)) {
|
||||
/* Revert train if not going with tunnel direction. */
|
||||
if (checker.direction != GetTunnelBridgeDirection(t->tile)) {
|
||||
SetBit(t->flags, VRF_REVERSING);
|
||||
@@ -3824,7 +3824,7 @@ static bool IsTooCloseBehindTrain(Vehicle *v, TileIndex tile, uint16 distance, b
|
||||
}
|
||||
/* Cover blind spot at end of tunnel bridge. */
|
||||
if (check_endtile){
|
||||
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(t->tile), &checker, &FindSpaceBetweenTrainsEnum)) {
|
||||
if (HasVehicleOnPos(GetOtherTunnelBridgeEnd(t->tile), VEH_TRAIN, &checker, &FindSpaceBetweenTrainsEnum)) {
|
||||
/* Revert train if not going with tunnel direction. */
|
||||
if (checker.direction != GetTunnelBridgeDirection(t->tile)) {
|
||||
SetBit(t->flags, VRF_REVERSING);
|
||||
@@ -4097,7 +4097,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
exitdir = ReverseDiagDir(exitdir);
|
||||
|
||||
/* check if a train is waiting on the other side */
|
||||
if (!HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal)) return false;
|
||||
if (!HasVehicleOnPos(o_tile, VEH_TRAIN, &exitdir, &CheckTrainAtSignal)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4546,7 +4546,7 @@ static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data)
|
||||
{
|
||||
TrackBits *trackbits = (TrackBits *)data;
|
||||
|
||||
if (v->type == VEH_TRAIN && (v->vehstatus & VS_CRASHED) != 0) {
|
||||
if ((v->vehstatus & VS_CRASHED) != 0) {
|
||||
if (Train::From(v)->track != TRACK_BIT_DEPOT) {
|
||||
*trackbits |= GetTrackbitsFromCrashedVehicle(Train::From(v));
|
||||
}
|
||||
@@ -4619,7 +4619,7 @@ static void DeleteLastWagon(Train *v)
|
||||
|
||||
/* If there are still crashed vehicles on the tile, give the track reservation to them */
|
||||
TrackBits remaining_trackbits = TRACK_BIT_NONE;
|
||||
FindVehicleOnPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum);
|
||||
FindVehicleOnPos(tile, VEH_TRAIN, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum);
|
||||
|
||||
/* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */
|
||||
assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1);
|
||||
|
137
src/vehicle.cpp
137
src/vehicle.cpp
@@ -468,13 +468,13 @@ const int TOTAL_HASH_MASK = TOTAL_HASH_SIZE - 1;
|
||||
* Profiling results show that 0 is fastest. */
|
||||
const int HASH_RES = 0;
|
||||
|
||||
static Vehicle *_vehicle_tile_hash[TOTAL_HASH_SIZE];
|
||||
static Vehicle *_vehicle_tile_hash[TOTAL_HASH_SIZE * 4];
|
||||
|
||||
static Vehicle *VehicleFromTileHash(int xl, int yl, int xu, int yu, void *data, VehicleFromPosProc *proc, bool find_first)
|
||||
static Vehicle *VehicleFromTileHash(int xl, int yl, int xu, int yu, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first)
|
||||
{
|
||||
for (int y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
|
||||
for (int x = xl; ; x = (x + 1) & HASH_MASK) {
|
||||
Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
|
||||
Vehicle *v = _vehicle_tile_hash[((x + y) & TOTAL_HASH_MASK) + (TOTAL_HASH_SIZE * type)];
|
||||
for (; v != nullptr; v = v->hash_tile_next) {
|
||||
Vehicle *a = proc(v, data);
|
||||
if (find_first && a != nullptr) return a;
|
||||
@@ -499,7 +499,7 @@ static Vehicle *VehicleFromTileHash(int xl, int yl, int xu, int yu, void *data,
|
||||
* all vehicles
|
||||
* @return the best matching or first vehicle (depending on find_first).
|
||||
*/
|
||||
static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *proc, bool find_first)
|
||||
Vehicle *VehicleFromPosXY(int x, int y, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first)
|
||||
{
|
||||
const int COLL_DIST = 6;
|
||||
|
||||
@@ -509,42 +509,7 @@ static Vehicle *VehicleFromPosXY(int x, int y, void *data, VehicleFromPosProc *p
|
||||
int yl = GB((y - COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
|
||||
int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
|
||||
|
||||
return VehicleFromTileHash(xl, yl, xu, yu, data, proc, find_first);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a vehicle from a specific location. It will call proc for ALL vehicles
|
||||
* on the tile and YOU must make SURE that the "best one" is stored in the
|
||||
* data value and is ALWAYS the same regardless of the order of the vehicles
|
||||
* where proc was called on!
|
||||
* When you fail to do this properly you create an almost untraceable DESYNC!
|
||||
* @note The return value of proc will be ignored.
|
||||
* @note Use this when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param x The X location on the map
|
||||
* @param y The Y location on the map
|
||||
* @param data Arbitrary data passed to proc
|
||||
* @param proc The proc that determines whether a vehicle will be "found".
|
||||
*/
|
||||
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
VehicleFromPosXY(x, y, data, proc, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a vehicle in on a specific location. It will call proc for
|
||||
* vehicles until it returns non-nullptr.
|
||||
* @note Use FindVehicleOnPosXY when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param x The X location on the map
|
||||
* @param y The Y location on the map
|
||||
* @param data Arbitrary data passed to proc
|
||||
* @param proc The proc that determines whether a vehicle will be "found".
|
||||
* @return True if proc returned non-nullptr.
|
||||
*/
|
||||
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
return VehicleFromPosXY(x, y, data, proc, true) != nullptr;
|
||||
return VehicleFromTileHash(xl, yl, xu, yu, type, data, proc, find_first);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -557,12 +522,12 @@ bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
|
||||
* all vehicles
|
||||
* @return the best matching or first vehicle (depending on find_first).
|
||||
*/
|
||||
static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first)
|
||||
Vehicle *VehicleFromPos(TileIndex tile, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first)
|
||||
{
|
||||
int x = GB(TileX(tile), HASH_RES, HASH_BITS);
|
||||
int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS;
|
||||
|
||||
Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
|
||||
Vehicle *v = _vehicle_tile_hash[((x + y) & TOTAL_HASH_MASK) + (TOTAL_HASH_SIZE * type)];
|
||||
for (; v != nullptr; v = v->hash_tile_next) {
|
||||
if (v->tile != tile) continue;
|
||||
|
||||
@@ -574,36 +539,18 @@ static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *p
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a vehicle from a specific location. It will call \a proc for ALL vehicles
|
||||
* on the tile and YOU must make SURE that the "best one" is stored in the
|
||||
* data value and is ALWAYS the same regardless of the order of the vehicles
|
||||
* where proc was called on!
|
||||
* When you fail to do this properly you create an almost untraceable DESYNC!
|
||||
* @note The return value of \a proc will be ignored.
|
||||
* @note Use this function when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param tile The location on the map
|
||||
* @param data Arbitrary data passed to \a proc.
|
||||
* @param proc The proc that determines whether a vehicle will be "found".
|
||||
* Callback that returns 'real' vehicles lower or at height \c *(int*)data .
|
||||
* @param v Vehicle to examine.
|
||||
* @param data Pointer to height data.
|
||||
* @return \a v if conditions are met, else \c nullptr.
|
||||
*/
|
||||
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
||||
static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
|
||||
{
|
||||
VehicleFromPos(tile, data, proc, false);
|
||||
}
|
||||
int z = static_cast<int>(reinterpret_cast<intptr_t>(data));
|
||||
|
||||
/**
|
||||
* Checks whether a vehicle is on a specific location. It will call \a proc for
|
||||
* vehicles until it returns non-nullptr.
|
||||
* @note Use #FindVehicleOnPos when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param tile The location on the map
|
||||
* @param data Arbitrary data passed to \a proc.
|
||||
* @param proc The \a proc that determines whether a vehicle will be "found".
|
||||
* @return True if proc returned non-nullptr.
|
||||
*/
|
||||
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
return VehicleFromPos(tile, data, proc, true) != nullptr;
|
||||
if (v->z_pos > z) return nullptr;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -612,11 +559,11 @@ bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
||||
* @param data Pointer to height data.
|
||||
* @return \a v if conditions are met, else \c nullptr.
|
||||
*/
|
||||
static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data)
|
||||
static Vehicle *EnsureNoAircraftProcZ(Vehicle *v, void *data)
|
||||
{
|
||||
int z = *(int*)data;
|
||||
int z = static_cast<int>(reinterpret_cast<intptr_t>(data));
|
||||
|
||||
if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return nullptr;
|
||||
if (v->subtype == AIR_SHADOW) return nullptr;
|
||||
if (v->z_pos > z) return nullptr;
|
||||
|
||||
return v;
|
||||
@@ -635,27 +582,21 @@ CommandCost EnsureNoVehicleOnGround(TileIndex tile)
|
||||
* error message only (which may be different for different machines).
|
||||
* Such a message does not affect MP synchronisation.
|
||||
*/
|
||||
Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true);
|
||||
if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
|
||||
if (VehicleFromPos(tile, VEH_TRAIN, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &EnsureNoVehicleProcZ, true) != nullptr) {
|
||||
return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY);
|
||||
}
|
||||
if (VehicleFromPos(tile, VEH_ROAD, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &EnsureNoVehicleProcZ, true) != nullptr) {
|
||||
return_cmd_error(STR_ERROR_ROAD_VEHICLE_IN_THE_WAY);
|
||||
}
|
||||
if (VehicleFromPos(tile, VEH_SHIP, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &EnsureNoVehicleProcZ, true) != nullptr) {
|
||||
return_cmd_error(STR_ERROR_SHIP_IN_THE_WAY);
|
||||
}
|
||||
if (VehicleFromPos(tile, VEH_AIRCRAFT, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &EnsureNoAircraftProcZ, true) != nullptr) {
|
||||
return_cmd_error(STR_ERROR_AIRCRAFT_IN_THE_WAY);
|
||||
}
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback that returns 'real' vehicles lower or at height \c *(int*)data, for road vehicles.
|
||||
* @param v Vehicle to examine.
|
||||
* @param data Pointer to height data.
|
||||
* @return \a v if conditions are met, else \c nullptr.
|
||||
*/
|
||||
static Vehicle *EnsureNoRoadVehicleProcZ(Vehicle *v, void *data)
|
||||
{
|
||||
int z = *(int*)data;
|
||||
|
||||
if (v->type != VEH_ROAD) return nullptr;
|
||||
if (v->z_pos > z) return nullptr;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure there is no road vehicle at the ground at the given position.
|
||||
* @param tile Position to examine.
|
||||
@@ -669,7 +610,7 @@ CommandCost EnsureNoRoadVehicleOnGround(TileIndex tile)
|
||||
* error message only (which may be different for different machines).
|
||||
* Such a message does not affect MP synchronisation.
|
||||
*/
|
||||
Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoRoadVehicleProcZ, true);
|
||||
Vehicle *v = VehicleFromPos(tile, VEH_ROAD, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &EnsureNoVehicleProcZ, true);
|
||||
if (v != nullptr) return_cmd_error(STR_ERROR_ROAD_VEHICLE_IN_THE_WAY);
|
||||
return CommandCost();
|
||||
}
|
||||
@@ -684,7 +625,6 @@ struct GetVehicleTunnelBridgeProcData {
|
||||
static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
|
||||
{
|
||||
const GetVehicleTunnelBridgeProcData *info = (GetVehicleTunnelBridgeProcData*) data;
|
||||
if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return nullptr;
|
||||
if (v == info->v) return nullptr;
|
||||
|
||||
if (v->type == VEH_TRAIN && info->across_only && IsBridge(info->t)) {
|
||||
@@ -713,10 +653,11 @@ CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle
|
||||
data.v = ignore;
|
||||
data.t = tile;
|
||||
data.across_only = across_only;
|
||||
Vehicle *v = VehicleFromPos(tile, &data, &GetVehicleTunnelBridgeProc, true);
|
||||
VehicleType type = static_cast<VehicleType>(GetTunnelBridgeTransportType(tile));
|
||||
Vehicle *v = VehicleFromPos(tile, type, &data, &GetVehicleTunnelBridgeProc, true);
|
||||
if (v == nullptr) {
|
||||
data.t = endtile;
|
||||
v = VehicleFromPos(endtile, &data, &GetVehicleTunnelBridgeProc, true);
|
||||
v = VehicleFromPos(endtile, type, &data, &GetVehicleTunnelBridgeProc, true);
|
||||
}
|
||||
|
||||
if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
|
||||
@@ -727,8 +668,6 @@ static Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
|
||||
{
|
||||
TrackBits rail_bits = *(TrackBits *)data;
|
||||
|
||||
if (v->type != VEH_TRAIN) return nullptr;
|
||||
|
||||
Train *t = Train::From(v);
|
||||
if (rail_bits & TRACK_BIT_WORMHOLE) {
|
||||
if (t->track & TRACK_BIT_WORMHOLE) return v;
|
||||
@@ -755,7 +694,7 @@ CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
|
||||
* error message only (which may be different for different machines).
|
||||
* Such a message does not affect MP synchronisation.
|
||||
*/
|
||||
Vehicle *v = VehicleFromPos(tile, &track_bits, &EnsureNoTrainOnTrackProc, true);
|
||||
Vehicle *v = VehicleFromPos(tile, VEH_TRAIN, &track_bits, &EnsureNoTrainOnTrackProc, true);
|
||||
if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
|
||||
return CommandCost();
|
||||
}
|
||||
@@ -770,7 +709,7 @@ void UpdateVehicleTileHash(Vehicle *v, bool remove)
|
||||
} else {
|
||||
int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
|
||||
int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
|
||||
new_hash = &_vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
|
||||
new_hash = &_vehicle_tile_hash[((x + y) & TOTAL_HASH_MASK) + (TOTAL_HASH_SIZE * v->type)];
|
||||
}
|
||||
|
||||
if (old_hash == new_hash) return;
|
||||
@@ -799,7 +738,7 @@ bool ValidateVehicleTileHash(const Vehicle *v)
|
||||
|
||||
int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
|
||||
int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << HASH_BITS;
|
||||
return v->hash_tile_current == &_vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK];
|
||||
return v->hash_tile_current == &_vehicle_tile_hash[((x + y) & TOTAL_HASH_MASK) + (TOTAL_HASH_SIZE * v->type)];
|
||||
}
|
||||
|
||||
static Vehicle *_vehicle_viewport_hash[1 << (GEN_HASHX_BITS + GEN_HASHY_BITS)];
|
||||
|
@@ -40,10 +40,79 @@ typedef Vehicle *VehicleFromPosProc(Vehicle *v, void *data);
|
||||
|
||||
void VehicleServiceInDepot(Vehicle *v);
|
||||
uint CountVehiclesInChain(const Vehicle *v);
|
||||
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
|
||||
void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc);
|
||||
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
|
||||
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc);
|
||||
|
||||
/**
|
||||
* Find a vehicle from a specific location. It will call \a proc for ALL vehicles
|
||||
* on the tile and YOU must make SURE that the "best one" is stored in the
|
||||
* data value and is ALWAYS the same regardless of the order of the vehicles
|
||||
* where proc was called on!
|
||||
* When you fail to do this properly you create an almost untraceable DESYNC!
|
||||
* @note The return value of \a proc will be ignored.
|
||||
* @note Use this function when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param tile The location on the map
|
||||
* @param data Arbitrary data passed to \a proc.
|
||||
* @param proc The proc that determines whether a vehicle will be "found".
|
||||
*/
|
||||
inline void FindVehicleOnPos(TileIndex tile, VehicleType type, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
extern Vehicle *VehicleFromPos(TileIndex tile, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first);
|
||||
VehicleFromPos(tile, type, data, proc, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a vehicle is on a specific location. It will call \a proc for
|
||||
* vehicles until it returns non-nullptr.
|
||||
* @note Use #FindVehicleOnPos when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param tile The location on the map
|
||||
* @param data Arbitrary data passed to \a proc.
|
||||
* @param proc The \a proc that determines whether a vehicle will be "found".
|
||||
* @return True if proc returned non-nullptr.
|
||||
*/
|
||||
inline bool HasVehicleOnPos(TileIndex tile, VehicleType type, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
extern Vehicle *VehicleFromPos(TileIndex tile, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first);
|
||||
return VehicleFromPos(tile, type, data, proc, true) != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a vehicle from a specific location. It will call proc for ALL vehicles
|
||||
* on the tile and YOU must make SURE that the "best one" is stored in the
|
||||
* data value and is ALWAYS the same regardless of the order of the vehicles
|
||||
* where proc was called on!
|
||||
* When you fail to do this properly you create an almost untraceable DESYNC!
|
||||
* @note The return value of proc will be ignored.
|
||||
* @note Use this when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param x The X location on the map
|
||||
* @param y The Y location on the map
|
||||
* @param data Arbitrary data passed to proc
|
||||
* @param proc The proc that determines whether a vehicle will be "found".
|
||||
*/
|
||||
inline void FindVehicleOnPosXY(int x, int y, VehicleType type, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
extern Vehicle *VehicleFromPosXY(int x, int y, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first);
|
||||
VehicleFromPosXY(x, y, type, data, proc, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a vehicle in on a specific location. It will call proc for
|
||||
* vehicles until it returns non-nullptr.
|
||||
* @note Use FindVehicleOnPosXY when you have the intention that all vehicles
|
||||
* should be iterated over.
|
||||
* @param x The X location on the map
|
||||
* @param y The Y location on the map
|
||||
* @param data Arbitrary data passed to proc
|
||||
* @param proc The proc that determines whether a vehicle will be "found".
|
||||
* @return True if proc returned non-nullptr.
|
||||
*/
|
||||
inline bool HasVehicleOnPosXY(int x, int y, VehicleType type, void *data, VehicleFromPosProc *proc)
|
||||
{
|
||||
extern Vehicle *VehicleFromPosXY(int x, int y, VehicleType type, void *data, VehicleFromPosProc *proc, bool find_first);
|
||||
return VehicleFromPosXY(x, y, type, data, proc, true) != nullptr;
|
||||
}
|
||||
|
||||
void CallVehicleTicks();
|
||||
uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour);
|
||||
uint8 CalcPercentVehicleFilledOfCargo(const Vehicle *v, CargoID cargo);
|
||||
|
@@ -1010,39 +1010,48 @@ static void FloodVehicle(Vehicle *v)
|
||||
* @param data The z of level to flood.
|
||||
* @return nullptr as we always want to remove everything.
|
||||
*/
|
||||
static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
|
||||
static Vehicle *FloodAircraftProc(Vehicle *v, void *data)
|
||||
{
|
||||
if ((v->vehstatus & VS_CRASHED) != 0) return nullptr;
|
||||
|
||||
switch (v->type) {
|
||||
default: break;
|
||||
|
||||
case VEH_AIRCRAFT: {
|
||||
if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
|
||||
if (v->subtype == AIR_SHADOW) break;
|
||||
if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) return nullptr;
|
||||
if (v->subtype == AIR_SHADOW) return nullptr;
|
||||
|
||||
/* We compare v->z_pos against delta_z + 1 because the shadow
|
||||
* is at delta_z and the actual aircraft at delta_z + 1. */
|
||||
const Station *st = Station::GetByTile(v->tile);
|
||||
const AirportFTAClass *airport = st->airport.GetFTA();
|
||||
if (v->z_pos != airport->delta_z + 1) break;
|
||||
if (v->z_pos != airport->delta_z + 1) return nullptr;
|
||||
|
||||
FloodVehicle(v);
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_TRAIN:
|
||||
case VEH_ROAD: {
|
||||
int z = *(int*)data;
|
||||
if (v->z_pos > z) break;
|
||||
FloodVehicle(v->First());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flood a vehicle if we are allowed to flood it, i.e. when it is on the ground.
|
||||
* @param v The vehicle to test for flooding.
|
||||
* @param data The z of level to flood.
|
||||
* @return nullptr as we always want to remove everything.
|
||||
*/
|
||||
static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
|
||||
{
|
||||
if ((v->vehstatus & VS_CRASHED) != 0) return nullptr;
|
||||
|
||||
int z = static_cast<int>(reinterpret_cast<intptr_t>(data));
|
||||
if (v->z_pos > z) return nullptr;
|
||||
FloodVehicle(v->First());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void FindFloodVehicle(TileIndex tile, int z)
|
||||
{
|
||||
FindVehicleOnPos(tile, VEH_AIRCRAFT, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &FloodAircraftProc);
|
||||
FindVehicleOnPos(tile, VEH_TRAIN, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &FloodVehicleProc);
|
||||
FindVehicleOnPos(tile, VEH_ROAD, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &FloodVehicleProc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a vehicle to flood.
|
||||
* It does not find vehicles that are already crashed on bridges, i.e. flooded.
|
||||
@@ -1055,7 +1064,7 @@ static void FloodVehicles(TileIndex tile)
|
||||
if (IsAirportTile(tile)) {
|
||||
const Station *st = Station::GetByTile(tile);
|
||||
TILE_AREA_LOOP(tile, st->airport) {
|
||||
if (st->TileBelongsToAirport(tile)) FindVehicleOnPos(tile, &z, &FloodVehicleProc);
|
||||
if (st->TileBelongsToAirport(tile)) FindFloodVehicle(tile, z);
|
||||
}
|
||||
|
||||
/* No vehicle could be flooded on this airport anymore */
|
||||
@@ -1063,15 +1072,15 @@ static void FloodVehicles(TileIndex tile)
|
||||
}
|
||||
|
||||
if (!IsBridgeTile(tile)) {
|
||||
FindVehicleOnPos(tile, &z, &FloodVehicleProc);
|
||||
FindFloodVehicle(tile, z);
|
||||
return;
|
||||
}
|
||||
|
||||
TileIndex end = GetOtherBridgeEnd(tile);
|
||||
z = GetBridgePixelHeight(tile);
|
||||
|
||||
FindVehicleOnPos(tile, &z, &FloodVehicleProc);
|
||||
FindVehicleOnPos(end, &z, &FloodVehicleProc);
|
||||
FindFloodVehicle(tile, z);
|
||||
FindFloodVehicle(end, z);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user