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;
|
uint *count = (uint *)data;
|
||||||
/* Ignore other vehicles (aircraft) and ships inside depot. */
|
/* 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -331,7 +331,7 @@ static int32 NPFWaterPathCost(AyStar *as, AyStarNode *current, OpenListNode *par
|
|||||||
if (IsDockingTile(current->tile)) {
|
if (IsDockingTile(current->tile)) {
|
||||||
/* Check docking tile for occupancy */
|
/* Check docking tile for occupancy */
|
||||||
uint count = 1;
|
uint count = 1;
|
||||||
HasVehicleOnPos(current->tile, &count, &CountShipProc);
|
HasVehicleOnPos(current->tile, VEH_SHIP, &count, &CountShipProc);
|
||||||
cost += count * 3 * _trackdir_length[trackdir];
|
cost += count * 3 * _trackdir_length[trackdir];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -268,7 +268,7 @@ public:
|
|||||||
{
|
{
|
||||||
uint *count = (uint *)data;
|
uint *count = (uint *)data;
|
||||||
/* Ignore other vehicles (aircraft) and ships inside depot. */
|
/* 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ public:
|
|||||||
if (IsDockingTile(n.GetTile())) {
|
if (IsDockingTile(n.GetTile())) {
|
||||||
/* Check docking tile for occupancy */
|
/* Check docking tile for occupancy */
|
||||||
uint count = 1;
|
uint count = 1;
|
||||||
HasVehicleOnPos(n.GetTile(), &count, &CountShipProc);
|
HasVehicleOnPos(n.GetTile(), VEH_SHIP, &count, &CountShipProc);
|
||||||
c += count * 3 * YAPF_TILE_LENGTH;
|
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;
|
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);
|
Train *t = Train::From(v);
|
||||||
if (t->track & TRACK_BIT_WORMHOLE) {
|
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 = 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);
|
ftoti.res.okay = IsSafeWaitingPosition(v, ftoti.res.tile, ftoti.res.trackdir, true, _settings_game.pf.forbid_90_deg);
|
||||||
if (train_on_res != nullptr) {
|
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 (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
|
||||||
if (*train_on_res == nullptr && IsRailStationTile(ftoti.res.tile)) {
|
if (*train_on_res == nullptr && IsRailStationTile(ftoti.res.tile)) {
|
||||||
/* The target tile is a rail station. The track follower
|
/* 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. */
|
* for a possible train. */
|
||||||
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
|
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) {
|
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 (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)) {
|
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. */
|
/* 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();
|
if (ftoti.best != nullptr) *train_on_res = ftoti.best->First();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,21 +419,21 @@ Train *GetTrainForReservation(TileIndex tile, Track track)
|
|||||||
FindTrainOnTrackInfo ftoti;
|
FindTrainOnTrackInfo ftoti;
|
||||||
ftoti.res = FollowReservation(GetTileOwner(tile), rts, tile, trackdir, true);
|
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;
|
if (ftoti.best != nullptr) return ftoti.best;
|
||||||
|
|
||||||
/* Special case for stations: check the whole platform for a vehicle. */
|
/* Special case for stations: check the whole platform for a vehicle. */
|
||||||
if (IsRailStationTile(ftoti.res.tile)) {
|
if (IsRailStationTile(ftoti.res.tile)) {
|
||||||
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
|
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) {
|
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;
|
if (ftoti.best != nullptr) return ftoti.best;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special case for bridges/tunnels: check the other end as well. */
|
/* 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))) {
|
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;
|
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);
|
TileIndex other_end = GetOtherTunnelBridgeEnd(tile);
|
||||||
if (HasAcrossTunnelBridgeReservation(other_end) && GetTunnelBridgeExitSignalState(other_end) == SIGNAL_STATE_RED) return false;
|
if (HasAcrossTunnelBridgeReservation(other_end) && GetTunnelBridgeExitSignalState(other_end) == SIGNAL_STATE_RED) return false;
|
||||||
Direction dir = DiagDirToDir(GetTunnelBridgeDirection(other_end));
|
Direction dir = DiagDirToDir(GetTunnelBridgeDirection(other_end));
|
||||||
if (HasVehicleOnPos(other_end, &dir, [](Vehicle *v, void *data) -> Vehicle * {
|
if (HasVehicleOnPos(other_end, VEH_TRAIN, &dir, [](Vehicle *v, void *data) -> Vehicle * {
|
||||||
if (v->type != VEH_TRAIN) return nullptr;
|
|
||||||
DirDiff diff = DirDifference(v->direction, *((Direction *) data));
|
DirDiff diff = DirDifference(v->direction, *((Direction *) data));
|
||||||
if (diff == DIRDIFF_SAME) return v;
|
if (diff == DIRDIFF_SAME) return v;
|
||||||
if (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT) {
|
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 */
|
/** Update power of train under which is the railtype being converted */
|
||||||
static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data)
|
static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
if (v->type != VEH_TRAIN) return nullptr;
|
|
||||||
|
|
||||||
TrainList *affected_trains = static_cast<TrainList*>(data);
|
TrainList *affected_trains = static_cast<TrainList*>(data);
|
||||||
include(*affected_trains, Train::From(v)->First());
|
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);
|
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
|
||||||
/* update power of train on this tile */
|
/* 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(tile, totype);
|
||||||
SetSecondaryRailType(endtile, totype);
|
SetSecondaryRailType(endtile, totype);
|
||||||
|
|
||||||
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
FindVehicleOnPos(tile, VEH_TRAIN, &affected_trains, &UpdateTrainPowerProc);
|
||||||
FindVehicleOnPos(endtile, &affected_trains, &UpdateTrainPowerProc);
|
FindVehicleOnPos(endtile, VEH_TRAIN, &affected_trains, &UpdateTrainPowerProc);
|
||||||
|
|
||||||
/* notify YAPF about the track layout change */
|
/* notify YAPF about the track layout change */
|
||||||
yapf_notify_track_change(tile, GetTunnelBridgeTrackBits(tile));
|
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)
|
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)
|
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));
|
bool was_water = (GetRailGroundType(tile) == RAIL_GROUND_WATER && IsSlopeWithOneCornerRaised(tileh_old));
|
||||||
|
|
||||||
/* Allow clearing the water only if there is no ship */
|
/* 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);
|
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 */
|
/** Update power of road vehicle under which is the roadtype being converted */
|
||||||
static Vehicle *UpdateRoadVehPowerProc(Vehicle *v, void *data)
|
static Vehicle *UpdateRoadVehPowerProc(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
if (v->type != VEH_ROAD) return nullptr;
|
|
||||||
|
|
||||||
RoadVehicleList *affected_rvs = static_cast<RoadVehicleList*>(data);
|
RoadVehicleList *affected_rvs = static_cast<RoadVehicleList*>(data);
|
||||||
include(*affected_rvs, RoadVehicle::From(v)->First());
|
include(*affected_rvs, RoadVehicle::From(v)->First());
|
||||||
|
|
||||||
@@ -2637,7 +2635,7 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
MarkTileDirtyByTile(tile);
|
MarkTileDirtyByTile(tile);
|
||||||
|
|
||||||
/* update power of train on this tile */
|
/* update power of train on this tile */
|
||||||
FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
|
FindVehicleOnPos(tile, VEH_ROAD, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||||
|
|
||||||
if (IsRoadDepotTile(tile)) {
|
if (IsRoadDepotTile(tile)) {
|
||||||
/* Update build vehicle window related to this depot */
|
/* 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);
|
SetRoadType(tile, rtt, to_type);
|
||||||
if (include_middle) SetRoadType(endtile, rtt, to_type);
|
if (include_middle) SetRoadType(endtile, rtt, to_type);
|
||||||
|
|
||||||
FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc);
|
FindVehicleOnPos(tile, VEH_ROAD, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||||
FindVehicleOnPos(endtile, &affected_rvs, &UpdateRoadVehPowerProc);
|
FindVehicleOnPos(endtile, VEH_ROAD, &affected_rvs, &UpdateRoadVehPowerProc);
|
||||||
|
|
||||||
if (IsBridge(tile)) {
|
if (IsBridge(tile)) {
|
||||||
MarkBridgeDirty(tile);
|
MarkBridgeDirty(tile);
|
||||||
|
@@ -329,7 +329,7 @@ Vehicle *FindVehiclesInRoadStop(Vehicle *v, void *data)
|
|||||||
{
|
{
|
||||||
RoadStopEntryRebuilderHelper *rserh = (RoadStopEntryRebuilderHelper*)data;
|
RoadStopEntryRebuilderHelper *rserh = (RoadStopEntryRebuilderHelper*)data;
|
||||||
/* Not a RV or not in the right direction or crashed :( */
|
/* 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);
|
RoadVehicle *rv = RoadVehicle::From(v);
|
||||||
/* Don't add ones not in a road stop */
|
/* 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));
|
TileIndexDiff offset = abs(TileOffsByDiagDir(dir));
|
||||||
for (TileIndex tile = rs->xy; IsDriveThroughRoadStopContinuation(rs->xy, tile); tile += offset) {
|
for (TileIndex tile = rs->xy; IsDriveThroughRoadStopContinuation(rs->xy, tile); tile += offset) {
|
||||||
this->length += TILE_SIZE;
|
this->length += TILE_SIZE;
|
||||||
FindVehicleOnPos(tile, &rserh, FindVehiclesInRoadStop);
|
FindVehicleOnPos(tile, VEH_ROAD, &rserh, FindVehiclesInRoadStop);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->occupied = 0;
|
this->occupied = 0;
|
||||||
|
@@ -560,8 +560,7 @@ static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
|
|||||||
{
|
{
|
||||||
CheckRoadVehCrashTrainInfo *info = (CheckRoadVehCrashTrainInfo*) data;
|
CheckRoadVehCrashTrainInfo *info = (CheckRoadVehCrashTrainInfo*) data;
|
||||||
|
|
||||||
if (v->type == VEH_TRAIN &&
|
if (abs(v->z_pos - info->u->z_pos) <= 6 &&
|
||||||
abs(v->z_pos - info->u->z_pos) <= 6 &&
|
|
||||||
abs(v->x_pos - info->u->x_pos) <= 4 &&
|
abs(v->x_pos - info->u->x_pos) <= 4 &&
|
||||||
abs(v->y_pos - info->u->y_pos) <= 4) {
|
abs(v->y_pos - info->u->y_pos) <= 4) {
|
||||||
info->found = true;
|
info->found = true;
|
||||||
@@ -617,7 +616,7 @@ static bool RoadVehCheckTrainCrash(RoadVehicle *v)
|
|||||||
if (!IsLevelCrossingTile(tile)) continue;
|
if (!IsLevelCrossingTile(tile)) continue;
|
||||||
|
|
||||||
CheckRoadVehCrashTrainInfo info(u);
|
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) {
|
if (info.found) {
|
||||||
RoadVehCrash(v);
|
RoadVehCrash(v);
|
||||||
return true;
|
return true;
|
||||||
@@ -671,8 +670,7 @@ static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
|||||||
short x_diff = v->x_pos - rvf->x;
|
short x_diff = v->x_pos - rvf->x;
|
||||||
short y_diff = v->y_pos - rvf->y;
|
short y_diff = v->y_pos - rvf->y;
|
||||||
|
|
||||||
if (v->type == VEH_ROAD &&
|
if (!v->IsInDepot() &&
|
||||||
!v->IsInDepot() &&
|
|
||||||
abs(v->z_pos - rvf->veh->z_pos) < 6 &&
|
abs(v->z_pos - rvf->veh->z_pos) < 6 &&
|
||||||
v->direction == rvf->dir &&
|
v->direction == rvf->dir &&
|
||||||
rvf->veh->First() != v->First() &&
|
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;
|
rvf.best_diff = UINT_MAX;
|
||||||
|
|
||||||
if (front->state == RVSB_WORMHOLE) {
|
if (front->state == RVSB_WORMHOLE) {
|
||||||
FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose);
|
FindVehicleOnPos(v->tile, VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose);
|
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||||
} else {
|
} else {
|
||||||
FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose);
|
FindVehicleOnPosXY(x, y, VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code protects a roadvehicle from being blocked for ever
|
/* 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;
|
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;
|
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 */
|
/* 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)
|
static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||||
|
@@ -343,7 +343,7 @@ void Ship::UpdateDeltaXY()
|
|||||||
*/
|
*/
|
||||||
static Vehicle *EnsureNoVisibleShipProc(Vehicle *v, void *data)
|
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)
|
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 */
|
/* 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 */
|
/* 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;
|
TileIndex tile = v->tile;
|
||||||
Axis axis = GetShipDepotAxis(tile);
|
Axis axis = GetShipDepotAxis(tile);
|
||||||
@@ -588,8 +588,6 @@ struct ShipCollideChecker {
|
|||||||
/** Helper function for collision avoidance. */
|
/** Helper function for collision avoidance. */
|
||||||
static Vehicle *FindShipOnTile(Vehicle *v, void *data)
|
static Vehicle *FindShipOnTile(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
if (v->type != VEH_SHIP) return nullptr;
|
|
||||||
|
|
||||||
ShipCollideChecker *scc = (ShipCollideChecker*)data;
|
ShipCollideChecker *scc = (ShipCollideChecker*)data;
|
||||||
|
|
||||||
/* Don't detect vehicles on different parallel tracks. */
|
/* 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 (scc.search_tile == INVALID_TILE) return false;
|
||||||
|
|
||||||
if (IsValidTile(scc.search_tile) &&
|
if (IsValidTile(scc.search_tile) &&
|
||||||
(HasVehicleOnPos(ramp, &scc, FindShipOnTile) ||
|
(HasVehicleOnPos(ramp, VEH_SHIP, &scc, FindShipOnTile) ||
|
||||||
HasVehicleOnPos(GetOtherTunnelBridgeEnd(ramp), &scc, FindShipOnTile))) {
|
HasVehicleOnPos(GetOtherTunnelBridgeEnd(ramp), VEH_SHIP, &scc, FindShipOnTile))) {
|
||||||
v->cur_speed /= 4;
|
v->cur_speed /= 4;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -664,7 +662,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
|||||||
scc.track_bits = track_bits;
|
scc.track_bits = track_bits;
|
||||||
scc.search_tile = tile;
|
scc.search_tile = tile;
|
||||||
|
|
||||||
bool found = HasVehicleOnPos(tile, &scc, FindShipOnTile);
|
bool found = HasVehicleOnPos(tile, VEH_SHIP, &scc, FindShipOnTile);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
/* Bridge entrance */
|
/* Bridge entrance */
|
||||||
@@ -675,7 +673,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
|||||||
scc.search_tile = TileAddWrap(tile, ti.x, ti.y);
|
scc.search_tile = TileAddWrap(tile, ti.x, ti.y);
|
||||||
if (scc.search_tile == INVALID_TILE) return;
|
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) {
|
if (!found) {
|
||||||
scc.track_bits = track_bits;
|
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);
|
scc.search_tile = TileAddWrap(scc.search_tile, ti.x, ti.y);
|
||||||
if (scc.search_tile == INVALID_TILE) return;
|
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) {
|
if (found) {
|
||||||
|
|
||||||
@@ -701,7 +699,7 @@ static void CheckDistanceBetweenShips(TileIndex tile, Ship *v, TrackBits tracks,
|
|||||||
TileIndex tile_check = TileAddWrap(tile, ti.x, ti.y);
|
TileIndex tile_check = TileAddWrap(tile, ti.x, ti.y);
|
||||||
if (tile_check == INVALID_TILE) continue;
|
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]);
|
TrackBits bits = GetTileShipTrackStatus(tile_check) & DiagdirReachesTracks(_ship_search_directions[track][diagdir]);
|
||||||
if (!IsDiagonalTrack(track)) bits &= TRACK_BIT_CROSS; // No 90 degree turns.
|
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 */
|
/** Check whether there is a train on rail, not in a depot */
|
||||||
static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
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;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -214,8 +214,8 @@ static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
|||||||
static Vehicle *TrainInWormholeTileEnum(Vehicle *v, void *data)
|
static Vehicle *TrainInWormholeTileEnum(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
/* Only look for front engine or last wagon. */
|
/* Only look for front engine or last wagon. */
|
||||||
if (v->type != VEH_TRAIN || (v->Previous() != nullptr && v->Next() != nullptr)) return nullptr;
|
if ((v->Previous() != nullptr && v->Next() != nullptr)) return nullptr;
|
||||||
TileIndex tile = *(TileIndex *)data;
|
TileIndex tile = (TileIndex) reinterpret_cast<uintptr_t>(data);
|
||||||
if (tile != TileVirtXY(v->x_pos, v->y_pos)) return nullptr;
|
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;
|
if (!(Train::From(v)->track & TRACK_BIT_WORMHOLE) && !(Train::From(v)->track & GetAcrossTunnelBridgeTrackBits(tile))) return nullptr;
|
||||||
return v;
|
return v;
|
||||||
@@ -313,13 +313,13 @@ static SigInfo ExploreSegment(Owner owner)
|
|||||||
|
|
||||||
if (IsRailDepot(tile)) {
|
if (IsRailDepot(tile)) {
|
||||||
if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
|
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);
|
exitdir = GetRailDepotDirection(tile);
|
||||||
tile += TileOffsByDiagDir(exitdir);
|
tile += TileOffsByDiagDir(exitdir);
|
||||||
enterdir = ReverseDiagDir(exitdir);
|
enterdir = ReverseDiagDir(exitdir);
|
||||||
break;
|
break;
|
||||||
} else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
|
} 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;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
@@ -336,7 +336,7 @@ static SigInfo ExploreSegment(Owner owner)
|
|||||||
if (!(info.flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) info.flags |= SF_TRAIN;
|
if (!(info.flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) info.flags |= SF_TRAIN;
|
||||||
} else {
|
} else {
|
||||||
if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
|
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
|
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 (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
|
||||||
if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
|
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);
|
tile += TileOffsByDiagDir(exitdir);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -399,7 +399,7 @@ static SigInfo ExploreSegment(Owner owner)
|
|||||||
if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
|
if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
|
||||||
if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
|
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;
|
if (_settings_game.vehicle.safer_crossings) info.flags |= SF_PBS;
|
||||||
tile += TileOffsByDiagDir(exitdir);
|
tile += TileOffsByDiagDir(exitdir);
|
||||||
break;
|
break;
|
||||||
@@ -422,7 +422,7 @@ static SigInfo ExploreSegment(Owner owner)
|
|||||||
return EnsureNoTrainOnTrackBits(tile, tracks & (~across_tracks)).Failed();
|
return EnsureNoTrainOnTrackBits(tile, tracks & (~across_tracks)).Failed();
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
if (enterdir == INVALID_DIAGDIR) {
|
||||||
// incoming from the wormhole, onto signal
|
// incoming from the wormhole, onto signal
|
||||||
if (!(info.flags & SF_TRAIN) && IsTunnelBridgeSignalSimulationExit(tile)) { // tunnel entrance is ignored
|
if (!(info.flags & SF_TRAIN) && IsTunnelBridgeSignalSimulationExit(tile)) { // tunnel entrance is ignored
|
||||||
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;
|
||||||
if (!(info.flags & SF_TRAIN) && HasVehicleOnPos(tile, &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)) {
|
if (IsTunnelBridgeSignalSimulationExit(tile) && !_tbuset.Add(tile, INVALID_TRACKDIR)) {
|
||||||
info.flags |= SF_FULL;
|
info.flags |= SF_FULL;
|
||||||
@@ -456,9 +456,9 @@ static SigInfo ExploreSegment(Owner owner)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(info.flags & SF_TRAIN)) {
|
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 (!(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;
|
continue;
|
||||||
|
@@ -2092,7 +2092,6 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||||||
|
|
||||||
static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
||||||
{
|
{
|
||||||
if (v->type == VEH_ROAD) {
|
|
||||||
/* Okay... we are a road vehicle on a drive through road stop.
|
/* 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
|
* But that road stop has just been removed, so we need to make
|
||||||
* sure we are in a valid state... however, vehicles can also
|
* 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. */
|
* we'll end up clearing the turn around bits. */
|
||||||
RoadVehicle *rv = RoadVehicle::From(v);
|
RoadVehicle *rv = RoadVehicle::From(v);
|
||||||
if (HasBit(rv->state, RVS_IN_DT_ROAD_STOP)) rv->state &= RVSB_ROAD_STOP_TRACKDIR_MASK;
|
if (HasBit(rv->state, RVS_IN_DT_ROAD_STOP)) rv->state &= RVSB_ROAD_STOP_TRACKDIR_MASK;
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
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 */
|
/* don't do the check for drive-through road stops when company bankrupts */
|
||||||
if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
|
if (IsDriveThroughStopTile(tile) && (flags & DC_BANKRUPT)) {
|
||||||
/* remove the 'going through road stop' status from all vehicles on that tile */
|
/* 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 {
|
} else {
|
||||||
CommandCost ret = EnsureNoVehicleOnGround(tile);
|
CommandCost ret = EnsureNoVehicleOnGround(tile);
|
||||||
if (ret.Failed()) return ret;
|
if (ret.Failed()) return ret;
|
||||||
|
@@ -1914,7 +1914,7 @@ void ReverseTrainSwapVeh(Train *v, int l, int r)
|
|||||||
*/
|
*/
|
||||||
static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
|
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)
|
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);
|
Train *t = Train::From(v);
|
||||||
if (!t->IsFrontEngine()) return nullptr;
|
if (!t->IsFrontEngine()) return nullptr;
|
||||||
|
|
||||||
TileIndex tile = *(TileIndex *)data;
|
TileIndex tile = (TileIndex) reinterpret_cast<uintptr_t>(data);
|
||||||
|
|
||||||
if (TrainApproachingCrossingTile(t) != tile) return nullptr;
|
if (TrainApproachingCrossingTile(t) != tile) return nullptr;
|
||||||
|
|
||||||
@@ -1952,12 +1952,12 @@ static bool TrainApproachingCrossing(TileIndex tile)
|
|||||||
DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
|
DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
|
||||||
TileIndex tile_from = tile + TileOffsByDiagDir(dir);
|
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);
|
dir = ReverseDiagDir(dir);
|
||||||
tile_from = tile + TileOffsByDiagDir(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
|
/** Check if the crossing should be closed
|
||||||
@@ -1966,7 +1966,7 @@ static bool TrainApproachingCrossing(TileIndex tile)
|
|||||||
static inline bool CheckLevelCrossing(TileIndex tile)
|
static inline bool CheckLevelCrossing(TileIndex tile)
|
||||||
{
|
{
|
||||||
/* reserved || train on crossing || train approaching crossing */
|
/* 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;
|
TrainCollideChecker *tcc = (TrainCollideChecker*)data;
|
||||||
|
|
||||||
/* not a train or in depot */
|
/* not in depot */
|
||||||
if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
|
if (Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
|
||||||
|
|
||||||
if (_settings_game.vehicle.no_train_crash_other_company) {
|
if (_settings_game.vehicle.no_train_crash_other_company) {
|
||||||
/* do not crash into trains of another company. */
|
/* do not crash into trains of another company. */
|
||||||
@@ -3734,10 +3734,10 @@ static bool CheckTrainCollision(Train *v)
|
|||||||
|
|
||||||
/* find colliding vehicles */
|
/* find colliding vehicles */
|
||||||
if (v->track & TRACK_BIT_WORMHOLE) {
|
if (v->track & TRACK_BIT_WORMHOLE) {
|
||||||
FindVehicleOnPos(v->tile, &tcc, FindTrainCollideEnum);
|
FindVehicleOnPos(v->tile, VEH_TRAIN, &tcc, FindTrainCollideEnum);
|
||||||
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum);
|
FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), VEH_TRAIN, &tcc, FindTrainCollideEnum);
|
||||||
} else {
|
} 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 */
|
/* any dead -> no crash */
|
||||||
@@ -3753,7 +3753,7 @@ static bool CheckTrainCollision(Train *v)
|
|||||||
|
|
||||||
static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
|
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);
|
Train *t = Train::From(v);
|
||||||
DiagDirection exitdir = *(DiagDirection *)data;
|
DiagDirection exitdir = *(DiagDirection *)data;
|
||||||
@@ -3776,7 +3776,7 @@ struct FindSpaceBetweenTrainsChecker {
|
|||||||
static Vehicle *FindSpaceBetweenTrainsEnum(Vehicle *v, void *data)
|
static Vehicle *FindSpaceBetweenTrainsEnum(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
/* Don't look at wagons between front and back of train. */
|
/* 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)) {
|
if (!IsDiagonalDirection(v->direction)) {
|
||||||
/* Check for vehicles on non-across track pieces of custom bridge head */
|
/* 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;
|
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. */
|
/* Revert train if not going with tunnel direction. */
|
||||||
if (checker.direction != GetTunnelBridgeDirection(t->tile)) {
|
if (checker.direction != GetTunnelBridgeDirection(t->tile)) {
|
||||||
SetBit(t->flags, VRF_REVERSING);
|
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. */
|
/* Cover blind spot at end of tunnel bridge. */
|
||||||
if (check_endtile){
|
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. */
|
/* Revert train if not going with tunnel direction. */
|
||||||
if (checker.direction != GetTunnelBridgeDirection(t->tile)) {
|
if (checker.direction != GetTunnelBridgeDirection(t->tile)) {
|
||||||
SetBit(t->flags, VRF_REVERSING);
|
SetBit(t->flags, VRF_REVERSING);
|
||||||
@@ -4097,7 +4097,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||||||
exitdir = ReverseDiagDir(exitdir);
|
exitdir = ReverseDiagDir(exitdir);
|
||||||
|
|
||||||
/* check if a train is waiting on the other side */
|
/* 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;
|
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) {
|
if (Train::From(v)->track != TRACK_BIT_DEPOT) {
|
||||||
*trackbits |= GetTrackbitsFromCrashedVehicle(Train::From(v));
|
*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 */
|
/* If there are still crashed vehicles on the tile, give the track reservation to them */
|
||||||
TrackBits remaining_trackbits = TRACK_BIT_NONE;
|
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 */
|
/* 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);
|
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. */
|
* Profiling results show that 0 is fastest. */
|
||||||
const int HASH_RES = 0;
|
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 y = yl; ; y = (y + (1 << HASH_BITS)) & (HASH_MASK << HASH_BITS)) {
|
||||||
for (int x = xl; ; x = (x + 1) & HASH_MASK) {
|
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) {
|
for (; v != nullptr; v = v->hash_tile_next) {
|
||||||
Vehicle *a = proc(v, data);
|
Vehicle *a = proc(v, data);
|
||||||
if (find_first && a != nullptr) return a;
|
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
|
* all vehicles
|
||||||
* @return the best matching or first vehicle (depending on find_first).
|
* @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;
|
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 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;
|
int yu = GB((y + COLL_DIST) / TILE_SIZE, HASH_RES, HASH_BITS) << HASH_BITS;
|
||||||
|
|
||||||
return VehicleFromTileHash(xl, yl, xu, yu, data, proc, find_first);
|
return VehicleFromTileHash(xl, yl, xu, yu, type, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -557,12 +522,12 @@ bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc)
|
|||||||
* all vehicles
|
* all vehicles
|
||||||
* @return the best matching or first vehicle (depending on find_first).
|
* @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 x = GB(TileX(tile), HASH_RES, HASH_BITS);
|
||||||
int y = GB(TileY(tile), HASH_RES, HASH_BITS) << 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) {
|
for (; v != nullptr; v = v->hash_tile_next) {
|
||||||
if (v->tile != tile) continue;
|
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
|
* Callback that returns 'real' vehicles lower or at height \c *(int*)data .
|
||||||
* on the tile and YOU must make SURE that the "best one" is stored in the
|
* @param v Vehicle to examine.
|
||||||
* data value and is ALWAYS the same regardless of the order of the vehicles
|
* @param data Pointer to height data.
|
||||||
* where proc was called on!
|
* @return \a v if conditions are met, else \c nullptr.
|
||||||
* 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".
|
|
||||||
*/
|
*/
|
||||||
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));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (v->z_pos > z) return nullptr;
|
||||||
* Checks whether a vehicle is on a specific location. It will call \a proc for
|
|
||||||
* vehicles until it returns non-nullptr.
|
return v;
|
||||||
* @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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -612,11 +559,11 @@ bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
|
|||||||
* @param data Pointer to height data.
|
* @param data Pointer to height data.
|
||||||
* @return \a v if conditions are met, else \c nullptr.
|
* @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;
|
if (v->z_pos > z) return nullptr;
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
@@ -635,27 +582,21 @@ CommandCost EnsureNoVehicleOnGround(TileIndex tile)
|
|||||||
* error message only (which may be different for different machines).
|
* error message only (which may be different for different machines).
|
||||||
* Such a message does not affect MP synchronisation.
|
* Such a message does not affect MP synchronisation.
|
||||||
*/
|
*/
|
||||||
Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true);
|
if (VehicleFromPos(tile, VEH_TRAIN, reinterpret_cast<void *>(static_cast<intptr_t>(z)), &EnsureNoVehicleProcZ, true) != nullptr) {
|
||||||
if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
|
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();
|
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.
|
* Ensure there is no road vehicle at the ground at the given position.
|
||||||
* @param tile Position to examine.
|
* @param tile Position to examine.
|
||||||
@@ -669,7 +610,7 @@ CommandCost EnsureNoRoadVehicleOnGround(TileIndex tile)
|
|||||||
* error message only (which may be different for different machines).
|
* error message only (which may be different for different machines).
|
||||||
* Such a message does not affect MP synchronisation.
|
* 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);
|
if (v != nullptr) return_cmd_error(STR_ERROR_ROAD_VEHICLE_IN_THE_WAY);
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
}
|
}
|
||||||
@@ -684,7 +625,6 @@ struct GetVehicleTunnelBridgeProcData {
|
|||||||
static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
|
static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
const GetVehicleTunnelBridgeProcData *info = (GetVehicleTunnelBridgeProcData*) 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 == info->v) return nullptr;
|
||||||
|
|
||||||
if (v->type == VEH_TRAIN && info->across_only && IsBridge(info->t)) {
|
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.v = ignore;
|
||||||
data.t = tile;
|
data.t = tile;
|
||||||
data.across_only = across_only;
|
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) {
|
if (v == nullptr) {
|
||||||
data.t = endtile;
|
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);
|
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;
|
TrackBits rail_bits = *(TrackBits *)data;
|
||||||
|
|
||||||
if (v->type != VEH_TRAIN) return nullptr;
|
|
||||||
|
|
||||||
Train *t = Train::From(v);
|
Train *t = Train::From(v);
|
||||||
if (rail_bits & TRACK_BIT_WORMHOLE) {
|
if (rail_bits & TRACK_BIT_WORMHOLE) {
|
||||||
if (t->track & TRACK_BIT_WORMHOLE) return v;
|
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).
|
* error message only (which may be different for different machines).
|
||||||
* Such a message does not affect MP synchronisation.
|
* 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);
|
if (v != nullptr) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
}
|
}
|
||||||
@@ -770,7 +709,7 @@ void UpdateVehicleTileHash(Vehicle *v, bool remove)
|
|||||||
} else {
|
} else {
|
||||||
int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
|
int x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
|
||||||
int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << 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;
|
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 x = GB(TileX(v->tile), HASH_RES, HASH_BITS);
|
||||||
int y = GB(TileY(v->tile), HASH_RES, HASH_BITS) << 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)];
|
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);
|
void VehicleServiceInDepot(Vehicle *v);
|
||||||
uint CountVehiclesInChain(const 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);
|
* Find a vehicle from a specific location. It will call \a proc for ALL vehicles
|
||||||
bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc);
|
* 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();
|
void CallVehicleTicks();
|
||||||
uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour);
|
uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour);
|
||||||
uint8 CalcPercentVehicleFilledOfCargo(const Vehicle *v, CargoID cargo);
|
uint8 CalcPercentVehicleFilledOfCargo(const Vehicle *v, CargoID cargo);
|
||||||
|
@@ -1010,39 +1010,48 @@ static void FloodVehicle(Vehicle *v)
|
|||||||
* @param data The z of level to flood.
|
* @param data The z of level to flood.
|
||||||
* @return nullptr as we always want to remove everything.
|
* @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;
|
if ((v->vehstatus & VS_CRASHED) != 0) return nullptr;
|
||||||
|
|
||||||
switch (v->type) {
|
if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) return nullptr;
|
||||||
default: break;
|
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
|
/* We compare v->z_pos against delta_z + 1 because the shadow
|
||||||
* is at delta_z and the actual aircraft at delta_z + 1. */
|
* is at delta_z and the actual aircraft at delta_z + 1. */
|
||||||
const Station *st = Station::GetByTile(v->tile);
|
const Station *st = Station::GetByTile(v->tile);
|
||||||
const AirportFTAClass *airport = st->airport.GetFTA();
|
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);
|
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;
|
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.
|
* Finds a vehicle to flood.
|
||||||
* It does not find vehicles that are already crashed on bridges, i.e. flooded.
|
* 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)) {
|
if (IsAirportTile(tile)) {
|
||||||
const Station *st = Station::GetByTile(tile);
|
const Station *st = Station::GetByTile(tile);
|
||||||
TILE_AREA_LOOP(tile, st->airport) {
|
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 */
|
/* No vehicle could be flooded on this airport anymore */
|
||||||
@@ -1063,15 +1072,15 @@ static void FloodVehicles(TileIndex tile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IsBridgeTile(tile)) {
|
if (!IsBridgeTile(tile)) {
|
||||||
FindVehicleOnPos(tile, &z, &FloodVehicleProc);
|
FindFloodVehicle(tile, z);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TileIndex end = GetOtherBridgeEnd(tile);
|
TileIndex end = GetOtherBridgeEnd(tile);
|
||||||
z = GetBridgePixelHeight(tile);
|
z = GetBridgePixelHeight(tile);
|
||||||
|
|
||||||
FindVehicleOnPos(tile, &z, &FloodVehicleProc);
|
FindFloodVehicle(tile, z);
|
||||||
FindVehicleOnPos(end, &z, &FloodVehicleProc);
|
FindFloodVehicle(end, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user