Update to OpenTTD 1.9.0-beta2

--HG--
branch : openttd
This commit is contained in:
Pavel Stupnikov
2019-02-13 15:17:23 +03:00
parent 42ec3bd611
commit 2bda8d4f34
1362 changed files with 22145 additions and 10644 deletions

View File

@@ -1,4 +1,4 @@
/* $Id: ship_cmd.cpp 27858 2017-04-23 09:19:32Z peter1138 $ */
/* $Id$ */
/*
* This file is part of OpenTTD.
@@ -34,6 +34,7 @@
#include "company_base.h"
#include "tunnelbridge_map.h"
#include "zoom_func.h"
#include "framerate_type.h"
#include "table/strings.h"
@@ -128,6 +129,8 @@ void Ship::GetImage(Direction direction, EngineImageType image_type, VehicleSpri
{
uint8 spritenum = this->spritenum;
if (image_type == EIT_ON_MAP) direction = this->rotation;
if (is_custom_sprite(spritenum)) {
GetCustomVehicleSprite(this, direction, image_type, result);
if (result->IsValid()) return;
@@ -192,7 +195,7 @@ static void CheckIfShipNeedsService(Vehicle *v)
}
v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
v->dest_tile = depot->xy;
v->SetDestTile(depot->xy);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}
@@ -296,7 +299,7 @@ TileIndex Ship::GetOrderStationLocation(StationID station)
}
}
void Ship::UpdateDeltaXY(Direction direction)
void Ship::UpdateDeltaXY()
{
static const int8 _delta_xy_table[8][4] = {
/* y_extent, x_extent, y_offs, x_offs */
@@ -310,12 +313,29 @@ void Ship::UpdateDeltaXY(Direction direction)
{32, 6, -16, -3}, // NW
};
const int8 *bb = _delta_xy_table[direction];
const int8 *bb = _delta_xy_table[this->rotation];
this->x_offs = bb[3];
this->y_offs = bb[2];
this->x_extent = bb[1];
this->y_extent = bb[0];
this->z_extent = 6;
if (this->direction != this->rotation) {
/* If we are rotating, then it is possible the ship was moved to its next position. In that
* case, because we are still showing the old direction, the ship will appear to glitch sideways
* slightly. We can work around this by applying an additional offset to make the ship appear
* where it was before it moved. */
this->x_offs -= this->x_pos - this->rotation_x_pos;
this->y_offs -= this->y_pos - this->rotation_y_pos;
}
}
/**
* Test-procedure for HasVehicleOnPos to check for a ship.
*/
static Vehicle *EnsureNoVisibleShipProc(Vehicle *v, void *data)
{
return v->type == VEH_SHIP && (v->vehstatus & VS_HIDDEN) == 0 ? v : NULL;
}
static bool CheckShipLeaveDepot(Ship *v)
@@ -329,6 +349,13 @@ static bool CheckShipLeaveDepot(Ship *v)
return true;
}
/* Don't leave depot if no destination set */
if (v->dest_tile == 0) return true;
/* 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, NULL, &EnsureNoVisibleShipProc)) return true;
TileIndex tile = v->tile;
Axis axis = GetShipDepotAxis(tile);
@@ -354,10 +381,10 @@ static bool CheckShipLeaveDepot(Ship *v)
if (north_tracks) {
/* Leave towards north */
v->direction = DiagDirToDir(north_dir);
v->rotation = v->direction = DiagDirToDir(north_dir);
} else if (south_tracks) {
/* Leave towards south */
v->direction = DiagDirToDir(south_dir);
v->rotation = v->direction = DiagDirToDir(south_dir);
} else {
/* Both ways blocked */
return false;
@@ -442,11 +469,41 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, Tr
bool path_found = true;
Track track;
switch (_settings_game.pf.pathfinder_for_ships) {
case VPF_OPF: track = OPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
case VPF_NPF: track = NPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
default: NOT_REACHED();
if (v->dest_tile == 0 || DistanceManhattan(tile, v->dest_tile) > SHIP_MAX_ORDER_DISTANCE + 5) {
/* No destination or destination too far, don't invoke pathfinder. */
track = TrackBitsToTrack(v->state);
if (!IsDiagonalTrack(track)) track = TrackToOppositeTrack(track);
if (!HasBit(tracks, track)) {
/* Can't continue in same direction so pick first available track. */
if (_settings_game.pf.forbid_90_deg) {
tracks &= ~TrackCrossesTracks(TrackdirToTrack(v->GetVehicleTrackdir()));
if (tracks == TRACK_BIT_NONE) return INVALID_TRACK;
}
track = FindFirstTrack(tracks);
}
path_found = false;
} else {
/* Attempt to follow cached path. */
if (!v->path.empty()) {
track = TrackdirToTrack(v->path.front());
if (HasBit(tracks, track)) {
v->path.pop_front();
/* HandlePathfindResult() is not called here because this is not a new pathfinder result. */
return track;
}
/* Cached path is invalid so continue with pathfinder. */
v->path.clear();
}
switch (_settings_game.pf.pathfinder_for_ships) {
case VPF_OPF: track = OPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break;
case VPF_NPF: track = NPFShipChooseTrack(v, path_found); break;
case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found, v->path); break;
default: NOT_REACHED();
}
}
v->HandlePathfindingResult(path_found);
@@ -493,11 +550,60 @@ static const byte _ship_subcoord[4][6][3] = {
}
};
/**
* Test if a ship is in the centre of a lock and should move up or down.
* @param v Ship being tested.
* @return 0 if ship is not moving in lock, or -1 to move down, 1 to move up.
*/
static int ShipTestUpDownOnLock(const Ship *v)
{
/* Suitable tile? */
if (!IsTileType(v->tile, MP_WATER) || !IsLock(v->tile) || GetLockPart(v->tile) != LOCK_PART_MIDDLE) return 0;
/* Must be at the centre of the lock */
if ((v->x_pos & 0xF) != 8 || (v->y_pos & 0xF) != 8) return 0;
DiagDirection diagdir = GetInclinedSlopeDirection(GetTileSlope(v->tile));
assert(IsValidDiagDirection(diagdir));
if (DirToDiagDir(v->direction) == diagdir) {
/* Move up */
return (v->z_pos < GetTileMaxZ(v->tile) * (int)TILE_HEIGHT) ? 1 : 0;
} else {
/* Move down */
return (v->z_pos > GetTileZ(v->tile) * (int)TILE_HEIGHT) ? -1 : 0;
}
}
/**
* Test and move a ship up or down in a lock.
* @param v Ship to move.
* @return true iff ship is moving up or down in a lock.
*/
static bool ShipMoveUpDownOnLock(Ship *v)
{
/* Moving up/down through lock */
int dz = ShipTestUpDownOnLock(v);
if (dz == 0) return false;
if (v->cur_speed != 0) {
v->cur_speed = 0;
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}
if ((v->tick_counter & 7) == 0) {
v->z_pos += dz;
v->UpdatePosition();
v->UpdateViewport(true, true);
}
return true;
}
static void ShipController(Ship *v)
{
uint32 r;
const byte *b;
Direction dir;
Track track;
TrackBits tracks;
@@ -517,6 +623,18 @@ static void ShipController(Ship *v)
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);
v->UpdateViewport(true, true);
}
return;
}
if (ShipMoveUpDownOnLock(v)) return;
if (!ShipAccelerate(v)) return;
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
@@ -537,6 +655,10 @@ static void ShipController(Ship *v)
if (v->current_order.IsType(OT_LEAVESTATION)) {
v->current_order.Free();
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
/* Test if continuing forward would lead to a dead-end, moving into the dock. */
DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
if (TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) goto reverse_direction;
} else if (v->dest_tile != 0) {
/* We have a target, let's see if we reached it... */
if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
@@ -603,7 +725,25 @@ static void ShipController(Ship *v)
if (old_wc != new_wc) v->UpdateCache();
}
v->direction = (Direction)b[2];
Direction new_direction = (Direction)b[2];
DirDiff diff = DirDifference(new_direction, v->direction);
switch (diff) {
case DIRDIFF_SAME:
case DIRDIFF_45RIGHT:
case DIRDIFF_45LEFT:
/* Continue at speed */
v->rotation = v->direction = new_direction;
break;
default:
/* Stop for rotation */
v->cur_speed = 0;
v->direction = new_direction;
/* Remember our current location to avoid movement glitch */
v->rotation_x_pos = v->x_pos;
v->rotation_y_pos = v->y_pos;
break;
}
}
} else {
/* On a bridge */
@@ -619,7 +759,6 @@ static void ShipController(Ship *v)
/* update image of ship, as well as delta XY */
v->x_pos = gp.x;
v->y_pos = gp.y;
v->z_pos = GetSlopePixelZ(gp.x, gp.y);
getout:
v->UpdatePosition();
@@ -627,13 +766,19 @@ getout:
return;
reverse_direction:
dir = ReverseDir(v->direction);
v->direction = dir;
v->direction = ReverseDir(v->direction);
/* Remember our current location to avoid movement glitch */
v->rotation_x_pos = v->x_pos;
v->rotation_y_pos = v->y_pos;
v->cur_speed = 0;
v->path.clear();
goto getout;
}
bool Ship::Tick()
{
PerformanceAccumulator framerate(PFE_GL_SHIPS);
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
ShipController(this);
@@ -641,13 +786,20 @@ bool Ship::Tick()
return true;
}
void Ship::SetDestTile(TileIndex tile)
{
if (tile == this->dest_tile) return;
this->path.clear();
this->dest_tile = tile;
}
/**
* Build a ship.
* @param tile tile of the depot where ship is built.
* @param flags type of operation.
* @param e the engine to build.
* @param data unused.
* @param ret[out] the vehicle that has been built.
* @param[out] ret the vehicle that has been built.
* @return the cost of this operation or an error.
*/
CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
@@ -670,7 +822,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, u
v->y_pos = y;
v->z_pos = GetSlopePixelZ(x, y);
v->UpdateDeltaXY(v->direction);
v->UpdateDeltaXY();
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
v->spritenum = svi->image_index;