Use separate tile hash for each vehicle type

pull/135/head
Jonathan G Rennison 4 years ago
parent 4020719227
commit 4108672cf6

@ -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;
}

@ -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,16 +2092,14 @@ 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
* turn on road stop tiles, so only clear the 'road stop' state
* bits and only when the state was 'in road stop', otherwise
* 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;
}
/* 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
* turn on road stop tiles, so only clear the 'road stop' state
* bits and only when the state was 'in road stop', otherwise
* 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);

@ -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;
if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) return nullptr;
if (v->subtype == AIR_SHADOW) return nullptr;
case VEH_AIRCRAFT: {
if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
if (v->subtype == AIR_SHADOW) break;
/* 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) 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;
FloodVehicle(v);
FloodVehicle(v);
break;
}
return nullptr;
}
case VEH_TRAIN:
case VEH_ROAD: {
int z = *(int*)data;
if (v->z_pos > z) break;
FloodVehicle(v->First());
break;
}
}
/**
* 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);
}
/**

Loading…
Cancel
Save