Merge branch 'save_ext' into cargo_type_order

# Conflicts:
#	src/core/smallstack_type.hpp
This commit is contained in:
Jonathan G Rennison
2018-07-02 18:52:22 +01:00
534 changed files with 24037 additions and 9447 deletions

View File

@@ -57,27 +57,6 @@ bool IsValidImageIndex<VEH_TRAIN>(uint8 image_index)
return image_index < lengthof(_engine_sprite_base);
}
/**
* Determine the side in which the train will leave the tile
*
* @param direction vehicle direction
* @param track vehicle track bits
* @return side of tile the train will leave
*/
static inline DiagDirection TrainExitDir(Direction direction, TrackBits track)
{
static const TrackBits state_dir_table[DIAGDIR_END] = { TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER };
DiagDirection diagdir = DirToDiagDir(direction);
/* Determine the diagonal direction in which we will exit this tile */
if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) {
diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT);
}
return diagdir;
}
/**
* Return the cargo weight multiplier to use for a rail vehicle
@@ -482,41 +461,40 @@ static SpriteID GetDefaultTrainSprite(uint8 spritenum, Direction direction)
* @param image_type Visualisation context.
* @return Sprite to display.
*/
SpriteID Train::GetImage(Direction direction, EngineImageType image_type) const
void Train::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
SpriteID sprite;
if (HasBit(this->flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
if (is_custom_sprite(spritenum)) {
sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)), image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_TRAIN>(spritenum));
sprite = GetDefaultTrainSprite(spritenum, direction);
SpriteID sprite = GetDefaultTrainSprite(spritenum, direction);
if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _wagon_full_adder[spritenum];
return sprite;
result->Set(sprite);
}
static SpriteID GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType image_type)
static void GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
Direction dir = rear_head ? DIR_E : DIR_W;
uint8 spritenum = e->u.rail.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, dir, image_type);
if (sprite != 0) {
GetCustomVehicleIcon(engine, dir, image_type, result);
if (result->IsValid()) {
if (e->GetGRF() != NULL) {
y += ScaleGUITrad(e->GetGRF()->traininfo_vehicle_pitch);
}
return sprite;
return;
}
spritenum = Engine::Get(engine)->original_image_index;
@@ -524,7 +502,7 @@ static SpriteID GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImage
if (rear_head) spritenum++;
return GetDefaultTrainSprite(spritenum, DIR_W);
result->Set(GetDefaultTrainSprite(spritenum, DIR_W));
}
void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
@@ -533,24 +511,31 @@ void DrawTrainEngine(int left, int right, int preferred_x, int y, EngineID engin
int yf = y;
int yr = y;
SpriteID spritef = GetRailIcon(engine, false, yf, image_type);
SpriteID spriter = GetRailIcon(engine, true, yr, image_type);
const Sprite *real_spritef = GetSprite(spritef, ST_NORMAL);
const Sprite *real_spriter = GetSprite(spriter, ST_NORMAL);
VehicleSpriteSeq seqf, seqr;
GetRailIcon(engine, false, yf, image_type, &seqf);
GetRailIcon(engine, true, yr, image_type, &seqr);
Rect rectf, rectr;
seqf.GetBounds(&rectf);
seqr.GetBounds(&rectr);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_spritef->x_offs) + ScaleGUITrad(14),
right - UnScaleGUI(real_spriter->width) - UnScaleGUI(real_spriter->x_offs) - ScaleGUITrad(15));
left - UnScaleGUI(rectf.left) + ScaleGUITrad(14),
right - UnScaleGUI(rectr.right) - ScaleGUITrad(15));
DrawSprite(spritef, pal, preferred_x - ScaleGUITrad(14), yf);
DrawSprite(spriter, pal, preferred_x + ScaleGUITrad(15), yr);
seqf.Draw(preferred_x - ScaleGUITrad(14), yf, pal, pal == PALETTE_CRASH);
seqr.Draw(preferred_x + ScaleGUITrad(15), yr, pal, pal == PALETTE_CRASH);
} else {
SpriteID sprite = GetRailIcon(engine, false, y, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetRailIcon(engine, false, y, image_type, &seq);
Rect rect;
seq.GetBounds(&rect);
preferred_x = Clamp(preferred_x,
left - UnScaleGUI(real_sprite->x_offs),
right - UnScaleGUI(real_sprite->width) - UnScaleGUI(real_sprite->x_offs));
DrawSprite(sprite, pal, preferred_x, y);
left - UnScaleGUI(rect.left),
right - UnScaleGUI(rect.right));
seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
}
}
@@ -567,23 +552,26 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs,
{
int y = 0;
SpriteID sprite = GetRailIcon(engine, false, y, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetRailIcon(engine, false, y, image_type, &seq);
width = UnScaleGUI(real_sprite->width);
height = UnScaleGUI(real_sprite->height);
xoffs = UnScaleGUI(real_sprite->x_offs);
yoffs = UnScaleGUI(real_sprite->y_offs);
Rect rect;
seq.GetBounds(&rect);
width = UnScaleGUI(rect.right - rect.left + 1);
height = UnScaleGUI(rect.bottom - rect.top + 1);
xoffs = UnScaleGUI(rect.left);
yoffs = UnScaleGUI(rect.top);
if (RailVehInfo(engine)->railveh_type == RAILVEH_MULTIHEAD) {
sprite = GetRailIcon(engine, true, y, image_type);
real_sprite = GetSprite(sprite, ST_NORMAL);
GetRailIcon(engine, true, y, image_type, &seq);
seq.GetBounds(&rect);
/* Calculate values relative to an imaginary center between the two sprites. */
width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(real_sprite->width) + UnScaleGUI(real_sprite->x_offs) - xoffs;
height = max<uint>(height, UnScaleGUI(real_sprite->height));
width = ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) + UnScaleGUI(rect.right) - xoffs;
height = max<uint>(height, UnScaleGUI(rect.bottom - rect.top + 1));
xoffs = xoffs - ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) / 2;
yoffs = min(yoffs, UnScaleGUI(real_sprite->y_offs));
yoffs = min(yoffs, UnScaleGUI(rect.top));
}
}
@@ -638,7 +626,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
v->date_of_last_service = _date;
v->build_year = _cur_year;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
v->group_id = DEFAULT_GROUP;
@@ -706,7 +694,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v)
u->engine_type = v->engine_type;
u->date_of_last_service = v->date_of_last_service;
u->build_year = v->build_year;
u->cur_image = SPR_IMG_QUERY;
u->sprite_seq.Set(SPR_IMG_QUERY);
u->random_bits = VehicleRandomBits();
v->SetMultiheaded();
u->SetMultiheaded();
@@ -772,7 +760,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains);
v->date_of_last_service = _date;
v->build_year = _cur_year;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
@@ -1442,7 +1430,7 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint3
return cost;
}
void Train::UpdateDeltaXY(Direction direction)
void Train::UpdateDeltaXY()
{
/* Set common defaults. */
this->x_offs = -1;
@@ -1453,7 +1441,7 @@ void Train::UpdateDeltaXY(Direction direction)
this->x_bb_offs = 0;
this->y_bb_offs = 0;
if (!IsDiagonalDirection(direction)) {
if (!IsDiagonalDirection(this->direction)) {
static const int _sign_table[] =
{
/* x, y */
@@ -1466,12 +1454,12 @@ void Train::UpdateDeltaXY(Direction direction)
int half_shorten = (VEHICLE_LENGTH - this->gcache.cached_veh_length) / 2;
/* For all straight directions, move the bound box to the centre of the vehicle, but keep the size. */
this->x_offs -= half_shorten * _sign_table[direction];
this->y_offs -= half_shorten * _sign_table[direction + 1];
this->x_offs -= half_shorten * _sign_table[this->direction];
this->y_offs -= half_shorten * _sign_table[this->direction + 1];
this->x_extent += this->x_bb_offs = half_shorten * _sign_table[direction];
this->y_extent += this->y_bb_offs = half_shorten * _sign_table[direction + 1];
} else {
switch (direction) {
switch (this->direction) {
/* Shorten southern corner of the bounding box according the vehicle length
* and center the bounding box on the vehicle. */
case DIR_NE:
@@ -1700,8 +1688,8 @@ void UpdateLevelCrossing(TileIndex tile, bool sound)
{
assert(IsLevelCrossingTile(tile));
/* train on crossing || train approaching crossing || reserved */
bool new_state = HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile) || HasCrossingReservation(tile);
/* reserved || train on crossing || train approaching crossing */
bool new_state = HasCrossingReservation(tile) || HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
if (new_state != IsCrossingBarred(tile)) {
if (new_state && sound) {
@@ -1872,9 +1860,9 @@ void ReverseTrainDirection(Train *v)
return;
}
/* TrainExitDir does not always produce the desired dir for depots and
/* VehicleExitDir does not always produce the desired dir for depots and
* tunnels/bridges that is needed for UpdateSignalsOnSegment. */
DiagDirection dir = TrainExitDir(v->direction, v->track);
DiagDirection dir = VehicleExitDir(v->direction, v->track);
if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR;
if (UpdateSignalsOnSegment(v->tile, dir, v->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {
@@ -2254,16 +2242,14 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_
/**
* Free the reserved path in front of a vehicle.
* @param v %Train owning the reserved path.
* @param origin %Tile to start clearing (if #INVALID_TILE, use the current tile of \a v).
* @param orig_td Track direction (if #INVALID_TRACKDIR, use the track direction of \a v).
*/
void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_td)
void FreeTrainTrackReservation(const Train *v)
{
assert(v->IsFrontEngine());
TileIndex tile = origin != INVALID_TILE ? origin : v->tile;
Trackdir td = orig_td != INVALID_TRACKDIR ? orig_td : v->GetVehicleTrackdir();
bool free_tile = tile != v->tile || !(IsRailStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
TileIndex tile = v->tile;
Trackdir td = v->GetVehicleTrackdir();
bool free_tile = !(IsRailStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
StationID station_id = IsRailStationTile(v->tile) ? GetStationIndex(v->tile) : INVALID_STATION;
/* Can't be holding a reservation if we enter a depot. */
@@ -2504,6 +2490,7 @@ public:
case OT_GOTO_DEPOT:
/* Skip service in depot orders when the train doesn't need service. */
if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !this->v->NeedsServicing()) break;
FALLTHROUGH;
case OT_GOTO_STATION:
case OT_GOTO_WAYPOINT:
this->v->current_order = *order;
@@ -3099,7 +3086,7 @@ static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
/* not front engine of a train, inside wormhole or depot, crashed */
if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return NULL;
if (t->cur_speed > 5 || TrainExitDir(t->direction, t->track) != exitdir) return NULL;
if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return NULL;
return t;
}
@@ -3362,7 +3349,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
}
/* update image of train, as well as delta XY */
v->UpdateDeltaXY(v->direction);
v->UpdateDeltaXY();
v->x_pos = gp.x;
v->y_pos = gp.y;
@@ -3530,14 +3517,14 @@ static void ChangeTrainDirRandomly(Train *v)
/* We don't need to twist around vehicles if they're not visible */
if (!(v->vehstatus & VS_HIDDEN)) {
v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
v->UpdateDeltaXY(v->direction);
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
/* Refrain from updating the z position of the vehicle when on
* a bridge, because UpdateInclination() will put the vehicle under
* the bridge in that case */
if (v->track != TRACK_BIT_WORMHOLE) {
v->UpdatePosition();
v->UpdateInclination(false, false);
v->UpdateInclination(false, true);
} else {
v->UpdateViewport(false, true);
}
}
} while ((v = v->Next()) != NULL);
@@ -3610,7 +3597,7 @@ static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse)
* for other directions, it will be 1, 3, 5, ..., 15 */
switch (v->direction) {
case DIR_N : x = ~x + ~y + 25; break;
case DIR_NW: x = y; // FALL THROUGH
case DIR_NW: x = y; FALLTHROUGH;
case DIR_NE: x = ~x + 16; break;
case DIR_E : x = ~x + y + 9; break;
case DIR_SE: x = y; break;
@@ -3682,7 +3669,7 @@ static TileIndex TrainApproachingCrossingTile(const Train *v)
if (!TrainCanLeaveTile(v)) return INVALID_TILE;
DiagDirection dir = TrainExitDir(v->direction, v->track);
DiagDirection dir = VehicleExitDir(v->direction, v->track);
TileIndex tile = v->tile + TileOffsByDiagDir(dir);
/* not a crossing || wrong axis || unusable rail (wrong type or owner) */
@@ -3719,7 +3706,7 @@ static bool TrainCheckIfLineEnds(Train *v, bool reverse)
if (!TrainCanLeaveTile(v)) return true;
/* Determine the non-diagonal direction in which we will exit this tile */
DiagDirection dir = TrainExitDir(v->direction, v->track);
DiagDirection dir = VehicleExitDir(v->direction, v->track);
/* Calculate next tile */
TileIndex tile = v->tile + TileOffsByDiagDir(dir);
@@ -3787,7 +3774,7 @@ static bool TrainLocoHandler(Train *v, bool mode)
/* Try to reserve a path when leaving the station as we
* might not be marked as wanting a reservation, e.g.
* when an overlength train gets turned around in a station. */
DiagDirection dir = TrainExitDir(v->direction, v->track);
DiagDirection dir = VehicleExitDir(v->direction, v->track);
if (IsRailDepotTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE)) dir = INVALID_DIAGDIR;
if (UpdateSignalsOnSegment(v->tile, dir, v->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {