Changeset - r26014:71f8ae89abb6
[Not reviewed]
master
0 1 0
glx22 - 3 years ago 2021-10-05 15:58:19
glx@openttd.org
Change: Reverse ship when leaving docks if a better path exists
1 file changed with 17 insertions and 10 deletions:
0 comments (0 inline, 0 general)
src/ship_cmd.cpp
Show inline comments
 
@@ -326,24 +326,36 @@ void Ship::UpdateDeltaXY()
 
		this->y_offs -= this->y_pos - this->rotation_y_pos;
 
	}
 
}
 

	
 
/**
 
 * Test-procedure for HasVehicleOnPos to check for any ships which are visible and not stopped by the player.
 
 */
 
static Vehicle *EnsureNoMovingShipProc(Vehicle *v, void *data)
 
{
 
	return v->type == VEH_SHIP && (v->vehstatus & (VS_HIDDEN | VS_STOPPED)) == 0 ? v : nullptr;
 
}
 

	
 
static bool CheckReverseShip(const Ship *v)
 
{
 
	/* Ask pathfinder for best direction */
 
	bool reverse = false;
 
	switch (_settings_game.pf.pathfinder_for_ships) {
 
		case VPF_NPF: reverse = NPFShipCheckReverse(v); break;
 
		case VPF_YAPF: reverse = YapfShipCheckReverse(v); break;
 
		default: NOT_REACHED();
 
	}
 
	return reverse;
 
}
 

	
 
static bool CheckShipLeaveDepot(Ship *v)
 
{
 
	if (!v->IsChainInDepot()) return false;
 

	
 
	/* We are leaving a depot, but have to go to the exact same one; re-enter */
 
	if (v->current_order.IsType(OT_GOTO_DEPOT) &&
 
			IsShipDepotTile(v->tile) && GetDepotIndex(v->tile) == v->current_order.GetDestination()) {
 
		VehicleEnterDepot(v);
 
		return true;
 
	}
 

	
 
	/* Don't leave depot if no destination set */
 
@@ -355,32 +367,25 @@ static bool CheckShipLeaveDepot(Ship *v)
 

	
 
	TileIndex tile = v->tile;
 
	Axis axis = GetShipDepotAxis(tile);
 

	
 
	DiagDirection north_dir = ReverseDiagDir(AxisToDiagDir(axis));
 
	TileIndex north_neighbour = TILE_ADD(tile, TileOffsByDiagDir(north_dir));
 
	DiagDirection south_dir = AxisToDiagDir(axis);
 
	TileIndex south_neighbour = TILE_ADD(tile, 2 * TileOffsByDiagDir(south_dir));
 

	
 
	TrackBits north_tracks = DiagdirReachesTracks(north_dir) & GetTileShipTrackStatus(north_neighbour);
 
	TrackBits south_tracks = DiagdirReachesTracks(south_dir) & GetTileShipTrackStatus(south_neighbour);
 
	if (north_tracks && south_tracks) {
 
		/* Ask pathfinder for best direction */
 
		bool reverse = false;
 
		switch (_settings_game.pf.pathfinder_for_ships) {
 
			case VPF_NPF: reverse = NPFShipCheckReverse(v); break;
 
			case VPF_YAPF: reverse = YapfShipCheckReverse(v); break;
 
			default: NOT_REACHED();
 
		}
 
		if (reverse) north_tracks = TRACK_BIT_NONE;
 
		if (CheckReverseShip(v)) north_tracks = TRACK_BIT_NONE;
 
	}
 

	
 
	if (north_tracks) {
 
		/* Leave towards north */
 
		v->rotation = v->direction = DiagDirToDir(north_dir);
 
	} else if (south_tracks) {
 
		/* Leave towards south */
 
		v->rotation = v->direction = DiagDirToDir(south_dir);
 
	} else {
 
		/* Both ways blocked */
 
		return false;
 
	}
 
@@ -615,58 +620,60 @@ bool IsShipDestinationTile(TileIndex til
 
		}
 
		if (IsTileType(t, MP_STATION) && IsOilRig(t) && GetStationIndex(t) == station) return true;
 
	}
 
	return false;
 
}
 

	
 
static void ShipController(Ship *v)
 
{
 
	uint32 r;
 
	const byte *b;
 
	Track track;
 
	TrackBits tracks;
 
	GetNewVehiclePosResult gp;
 

	
 
	v->tick_counter++;
 
	v->current_order_time++;
 

	
 
	if (v->HandleBreakdown()) return;
 

	
 
	if (v->vehstatus & VS_STOPPED) return;
 

	
 
	ProcessOrders(v);
 
	if (ProcessOrders(v) && CheckReverseShip(v)) goto reverse_direction;
 

	
 
	v->HandleLoading();
 

	
 
	if (v->current_order.IsType(OT_LOADING)) return;
 

	
 
	if (CheckShipLeaveDepot(v)) return;
 

	
 
	v->ShowVisualEffect();
 

	
 
	/* Rotating on spot */
 
	if (v->direction != v->rotation) {
 
		if ((v->tick_counter & 7) == 0) {
 
			DirDiff diff = DirDifference(v->direction, v->rotation);
 
			v->rotation = ChangeDir(v->rotation, diff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
 
			/* Invalidate the sprite cache direction to force recalculation of viewport */
 
			v->sprite_cache.last_direction = INVALID_DIR;
 
			v->UpdateViewport(true, true);
 
		}
 
		return;
 
	}
 

	
 
	if (ShipMoveUpDownOnLock(v)) return;
 

	
 
	if (!ShipAccelerate(v)) return;
 

	
 
	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
 
	gp = GetNewVehiclePos(v);
 
	if (v->state != TRACK_BIT_WORMHOLE) {
 
		/* Not on a bridge */
 
		if (gp.old_tile == gp.new_tile) {
 
			/* Staying in tile */
 
			if (v->IsInDepot()) {
 
				gp.x = v->x_pos;
 
				gp.y = v->y_pos;
 
			} else {
 
				/* Not inside depot */
 
				r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
 
				if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;
 

	
0 comments (0 inline, 0 general)