Merge branch 'master' into save_ext

This commit is contained in:
Jonathan G Rennison
2016-11-11 18:27:24 +00:00
66 changed files with 1058 additions and 375 deletions

View File

@@ -93,7 +93,7 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
void UpdateDeltaXY(Direction direction);
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_INC : EXPENSES_AIRCRAFT_RUN; }
bool IsPrimaryVehicle() const { return this->IsNormalAircraft(); }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->cur_speed; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
int GetSpeedOldUnits() const { return this->vcache.cached_max_speed * 10 / 128; }
@@ -141,7 +141,7 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
*/
#define FOR_ALL_AIRCRAFT(var) FOR_ALL_VEHICLES_OF_TYPE(Aircraft, var)
SpriteID GetRotorImage(const Aircraft *v, EngineImageType image_type);
void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result);
Station *GetTargetAirportIfValid(const Aircraft *v);

View File

@@ -152,64 +152,69 @@ static StationID FindNearestHangar(const Aircraft *v)
return index;
}
SpriteID Aircraft::GetImage(Direction direction, EngineImageType image_type) const
void Aircraft::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleSprite(this, direction, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, direction, image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
return direction + _aircraft_sprite[spritenum];
result->Set(direction + _aircraft_sprite[spritenum]);
}
SpriteID GetRotorImage(const Aircraft *v, EngineImageType image_type)
void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result)
{
assert(v->subtype == AIR_HELICOPTER);
const Aircraft *w = v->Next()->Next();
if (is_custom_sprite(v->spritenum)) {
SpriteID sprite = GetCustomRotorSprite(v, false, image_type);
if (sprite != 0) return sprite;
GetCustomRotorSprite(v, false, image_type, result);
if (result->IsValid()) return;
}
/* Return standard rotor sprites if there are no custom sprites for this helicopter */
return SPR_ROTOR_STOPPED + w->state;
result->Set(SPR_ROTOR_STOPPED + w->state);
}
static SpriteID GetAircraftIcon(EngineID engine, EngineImageType image_type)
static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
uint8 spritenum = e->u.air.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
spritenum = e->original_image_index;
}
assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
return DIR_W + _aircraft_sprite[spritenum];
result->Set(DIR_W + _aircraft_sprite[spritenum]);
}
void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
SpriteID sprite = GetAircraftIcon(engine, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetAircraftIcon(engine, 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);
if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) {
SpriteID rotor_sprite = GetCustomRotorIcon(engine, image_type);
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
DrawSprite(rotor_sprite, PAL_NONE, preferred_x, y - ScaleGUITrad(5));
VehicleSpriteSeq rotor_seq;
GetCustomRotorIcon(engine, image_type, &rotor_seq);
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
rotor_seq.Draw(preferred_x, y - ScaleGUITrad(5), PAL_NONE, false);
}
}
@@ -224,12 +229,16 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en
*/
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type), ST_NORMAL);
VehicleSpriteSeq seq;
GetAircraftIcon(engine, image_type, &seq);
width = UnScaleGUI(spr->width);
height = UnScaleGUI(spr->height);
xoffs = UnScaleGUI(spr->x_offs);
yoffs = UnScaleGUI(spr->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);
}
/**
@@ -317,7 +326,8 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
v->date_of_last_service = _date;
v->build_year = u->build_year = _cur_year;
v->cur_image = u->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
u->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
u->random_bits = VehicleRandomBits();
@@ -349,7 +359,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
w->spritenum = 0xFF;
w->subtype = AIR_ROTOR;
w->cur_image = SPR_ROTOR_STOPPED;
w->sprite_seq.Set(SPR_ROTOR_STOPPED);
w->random_bits = VehicleRandomBits();
/* Use rotor's air.state to store the rotor animation frame */
w->state = HRS_ROTOR_STOPPED;
@@ -468,21 +478,21 @@ static void HelicopterTickHandler(Aircraft *v)
int tick = ++u->tick_counter;
int spd = u->cur_speed >> 4;
SpriteID img;
VehicleSpriteSeq seq;
if (spd == 0) {
u->state = HRS_ROTOR_STOPPED;
img = GetRotorImage(v, EIT_ON_MAP);
if (u->cur_image == img) return;
GetRotorImage(v, EIT_ON_MAP, &seq);
if (u->sprite_seq == seq) return;
} else if (tick >= spd) {
u->tick_counter = 0;
u->state++;
if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
img = GetRotorImage(v, EIT_ON_MAP);
GetRotorImage(v, EIT_ON_MAP, &seq);
} else {
return;
}
u->cur_image = img;
u->sprite_seq = seq;
u->UpdatePositionAndViewport();
}
@@ -502,7 +512,9 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
v->UpdatePosition();
v->UpdateViewport(true, false);
if (v->subtype == AIR_HELICOPTER) v->Next()->Next()->cur_image = GetRotorImage(v, EIT_ON_MAP);
if (v->subtype == AIR_HELICOPTER) {
GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
}
Aircraft *u = v->Next();
@@ -513,7 +525,7 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
u->z_pos = GetSlopePixelZ(safe_x, safe_y);
u->cur_image = v->cur_image;
u->sprite_seq.CopyWithoutPalette(v->sprite_seq); // the shadow is never coloured
u->UpdatePositionAndViewport();
@@ -1237,7 +1249,9 @@ void Aircraft::MarkDirty()
{
this->colourmap = PAL_NONE;
this->UpdateViewport(true, false);
if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this, EIT_ON_MAP);
if (this->subtype == AIR_HELICOPTER) {
GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq);
}
}

View File

@@ -83,11 +83,14 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
{
bool rtl = _current_text_dir == TD_RTL;
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
int width = UnScaleGUI(real_sprite->width);
int x_offs = UnScaleGUI(real_sprite->x_offs);
Rect rect;
seq.GetBounds(&rect);
int width = UnScaleGUI(rect.right - rect.left + 1);
int x_offs = UnScaleGUI(rect.left);
int x = rtl ? right - width - x_offs : left - x_offs;
bool helicopter = v->subtype == AIR_HELICOPTER;
@@ -95,17 +98,18 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
int heli_offs = 0;
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(sprite, pal, x, y + y_offs);
seq.Draw(x, y + y_offs, pal, v->vehstatus & VS_CRASHED);
if (helicopter) {
const Aircraft *a = Aircraft::From(v);
SpriteID rotor_sprite = GetCustomRotorSprite(a, true, image_type);
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
VehicleSpriteSeq rotor_seq;
GetCustomRotorSprite(a, true, image_type, &rotor_seq);
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
heli_offs = ScaleGUITrad(5);
DrawSprite(rotor_sprite, PAL_NONE, x, y + y_offs - heli_offs);
rotor_seq.Draw(x, y + y_offs - heli_offs, PAL_NONE, false);
}
if (v->index == selection) {
x += x_offs;
y += UnScaleGUI(real_sprite->y_offs) + y_offs - heli_offs;
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(real_sprite->height) + heli_offs + 1, COLOUR_WHITE, FR_BORDERONLY);
y += UnScaleGUI(rect.top) + y_offs - heli_offs;
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(rect.bottom - rect.top + 1) + heli_offs + 1, COLOUR_WHITE, FR_BORDERONLY);
}
}

View File

@@ -441,7 +441,7 @@ void AddArticulatedParts(Vehicle *first)
v->max_age = 0;
v->engine_type = engine_type;
v->value = 0;
v->cur_image = SPR_IMG_QUERY;
v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = VehicleRandomBits();
if (flip_image) v->spritenum++;

View File

@@ -56,7 +56,7 @@ void DrawHillyLandTile(const TileInfo *ti)
if (ti->tileh != SLOPE_FLAT) {
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
} else {
DrawGroundSprite(_landscape_clear_sprites_rough[GB(ti->x ^ ti->y, 4, 3)], PAL_NONE);
DrawGroundSprite(_landscape_clear_sprites_rough[GB(TileHash(ti->x, ti->y), 0, 3)], PAL_NONE);
}
}

View File

@@ -112,7 +112,7 @@ void DisasterVehicle::UpdateImage()
{
SpriteID img = this->image_override;
if (img == 0) img = _disaster_images[this->subtype][this->direction];
this->cur_image = img;
this->sprite_seq.Set(img);
}
/**
@@ -499,7 +499,8 @@ static bool DisasterTick_Helicopter_Rotors(DisasterVehicle *v)
v->tick_counter++;
if (HasBit(v->tick_counter, 0)) return true;
if (++v->cur_image > SPR_ROTOR_MOVING_3) v->cur_image = SPR_ROTOR_MOVING_1;
SpriteID &cur_image = v->sprite_seq.seq[0].sprite;
if (++cur_image > SPR_ROTOR_MOVING_3) cur_image = SPR_ROTOR_MOVING_1;
v->UpdatePositionAndViewport();

View File

@@ -22,10 +22,26 @@
#include "safeguards.h"
/**
* Increment the sprite unless it has reached the end of the animation.
* @param v Vehicle to increment sprite of.
* @param last Last sprite of animation.
* @return true if the sprite was incremented, false if the end was reached.
*/
static bool IncrementSprite(EffectVehicle *v, SpriteID last)
{
if (v->sprite_seq.seq[0].sprite != last) {
v->sprite_seq.seq[0].sprite++;
return true;
} else {
return false;
}
}
static void ChimneySmokeInit(EffectVehicle *v)
{
uint32 r = Random();
v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3);
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3));
v->progress = GB(r, 16, 3);
}
@@ -40,10 +56,8 @@ static bool ChimneySmokeTick(EffectVehicle *v)
return false;
}
if (v->cur_image != SPR_CHIMNEY_SMOKE_7) {
v->cur_image++;
} else {
v->cur_image = SPR_CHIMNEY_SMOKE_0;
if (!IncrementSprite(v, SPR_CHIMNEY_SMOKE_7)) {
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0);
}
v->progress = 7;
v->UpdatePositionAndViewport();
@@ -54,7 +68,7 @@ static bool ChimneySmokeTick(EffectVehicle *v)
static void SteamSmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_STEAM_SMOKE_0;
v->sprite_seq.Set(SPR_STEAM_SMOKE_0);
v->progress = 12;
}
@@ -70,9 +84,7 @@ static bool SteamSmokeTick(EffectVehicle *v)
}
if ((v->progress & 0xF) == 4) {
if (v->cur_image != SPR_STEAM_SMOKE_4) {
v->cur_image++;
} else {
if (!IncrementSprite(v, SPR_STEAM_SMOKE_4)) {
delete v;
return false;
}
@@ -86,7 +98,7 @@ static bool SteamSmokeTick(EffectVehicle *v)
static void DieselSmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_DIESEL_SMOKE_0;
v->sprite_seq.Set(SPR_DIESEL_SMOKE_0);
v->progress = 0;
}
@@ -98,13 +110,11 @@ static bool DieselSmokeTick(EffectVehicle *v)
v->z_pos++;
v->UpdatePositionAndViewport();
} else if ((v->progress & 7) == 1) {
if (v->cur_image != SPR_DIESEL_SMOKE_5) {
v->cur_image++;
v->UpdatePositionAndViewport();
} else {
if (!IncrementSprite(v, SPR_DIESEL_SMOKE_5)) {
delete v;
return false;
}
v->UpdatePositionAndViewport();
}
return true;
@@ -112,7 +122,7 @@ static bool DieselSmokeTick(EffectVehicle *v)
static void ElectricSparkInit(EffectVehicle *v)
{
v->cur_image = SPR_ELECTRIC_SPARK_0;
v->sprite_seq.Set(SPR_ELECTRIC_SPARK_0);
v->progress = 1;
}
@@ -122,13 +132,12 @@ static bool ElectricSparkTick(EffectVehicle *v)
v->progress++;
} else {
v->progress = 0;
if (v->cur_image != SPR_ELECTRIC_SPARK_5) {
v->cur_image++;
v->UpdatePositionAndViewport();
} else {
if (!IncrementSprite(v, SPR_ELECTRIC_SPARK_5)) {
delete v;
return false;
}
v->UpdatePositionAndViewport();
}
return true;
@@ -136,7 +145,7 @@ static bool ElectricSparkTick(EffectVehicle *v)
static void SmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_SMOKE_0;
v->sprite_seq.Set(SPR_SMOKE_0);
v->progress = 12;
}
@@ -152,9 +161,7 @@ static bool SmokeTick(EffectVehicle *v)
}
if ((v->progress & 0xF) == 4) {
if (v->cur_image != SPR_SMOKE_4) {
v->cur_image++;
} else {
if (!IncrementSprite(v, SPR_SMOKE_4)) {
delete v;
return false;
}
@@ -168,7 +175,7 @@ static bool SmokeTick(EffectVehicle *v)
static void ExplosionLargeInit(EffectVehicle *v)
{
v->cur_image = SPR_EXPLOSION_LARGE_0;
v->sprite_seq.Set(SPR_EXPLOSION_LARGE_0);
v->progress = 0;
}
@@ -176,13 +183,11 @@ static bool ExplosionLargeTick(EffectVehicle *v)
{
v->progress++;
if ((v->progress & 3) == 0) {
if (v->cur_image != SPR_EXPLOSION_LARGE_F) {
v->cur_image++;
v->UpdatePositionAndViewport();
} else {
if (!IncrementSprite(v, SPR_EXPLOSION_LARGE_F)) {
delete v;
return false;
}
v->UpdatePositionAndViewport();
}
return true;
@@ -190,7 +195,7 @@ static bool ExplosionLargeTick(EffectVehicle *v)
static void BreakdownSmokeInit(EffectVehicle *v)
{
v->cur_image = SPR_BREAKDOWN_SMOKE_0;
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
v->progress = 0;
}
@@ -198,10 +203,8 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
{
v->progress++;
if ((v->progress & 7) == 0) {
if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) {
v->cur_image++;
} else {
v->cur_image = SPR_BREAKDOWN_SMOKE_0;
if (!IncrementSprite(v, SPR_BREAKDOWN_SMOKE_3)) {
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
}
v->UpdatePositionAndViewport();
}
@@ -217,7 +220,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
static void ExplosionSmallInit(EffectVehicle *v)
{
v->cur_image = SPR_EXPLOSION_SMALL_0;
v->sprite_seq.Set(SPR_EXPLOSION_SMALL_0);
v->progress = 0;
}
@@ -225,13 +228,11 @@ static bool ExplosionSmallTick(EffectVehicle *v)
{
v->progress++;
if ((v->progress & 3) == 0) {
if (v->cur_image != SPR_EXPLOSION_SMALL_B) {
v->cur_image++;
v->UpdatePositionAndViewport();
} else {
if (!IncrementSprite(v, SPR_EXPLOSION_SMALL_B)) {
delete v;
return false;
}
v->UpdatePositionAndViewport();
}
return true;
@@ -239,7 +240,7 @@ static bool ExplosionSmallTick(EffectVehicle *v)
static void BulldozerInit(EffectVehicle *v)
{
v->cur_image = SPR_BULLDOZER_NE;
v->sprite_seq.Set(SPR_BULLDOZER_NE);
v->progress = 0;
v->animation_state = 0;
v->animation_substate = 0;
@@ -290,7 +291,7 @@ static bool BulldozerTick(EffectVehicle *v)
if ((v->progress & 7) == 0) {
const BulldozerMovement *b = &_bulldozer_movement[v->animation_state];
v->cur_image = SPR_BULLDOZER_NE + b->image;
v->sprite_seq.Set(SPR_BULLDOZER_NE + b->image);
v->x_pos += _inc_by_dir[b->direction].x;
v->y_pos += _inc_by_dir[b->direction].y;
@@ -312,7 +313,7 @@ static bool BulldozerTick(EffectVehicle *v)
static void BubbleInit(EffectVehicle *v)
{
v->cur_image = SPR_BUBBLE_GENERATE_0;
v->sprite_seq.Set(SPR_BUBBLE_GENERATE_0);
v->spritenum = 0;
v->progress = 0;
}
@@ -475,8 +476,8 @@ static bool BubbleTick(EffectVehicle *v)
if ((v->progress & 3) != 0) return true;
if (v->spritenum == 0) {
v->cur_image++;
if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
v->sprite_seq.seq[0].sprite++;
if (v->sprite_seq.seq[0].sprite < SPR_BUBBLE_GENERATE_3) {
v->UpdatePositionAndViewport();
return true;
}
@@ -521,7 +522,7 @@ static bool BubbleTick(EffectVehicle *v)
v->x_pos += b->x;
v->y_pos += b->y;
v->z_pos += b->z;
v->cur_image = SPR_BUBBLE_0 + b->image;
v->sprite_seq.Set(SPR_BUBBLE_0 + b->image);
v->UpdatePositionAndViewport();

View File

@@ -89,7 +89,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
{
switch (GetTileType(t)) {
case MP_RAILWAY:
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
switch (GetRailTileType(t)) {
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
return GetTrackBits(t);
@@ -99,7 +99,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
break;
case MP_TUNNELBRIDGE:
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (override != NULL && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
*override = 1 << GetTunnelBridgeDirection(t);
}
@@ -107,12 +107,12 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
case MP_ROAD:
if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
return GetCrossingRailBits(t);
case MP_STATION:
if (!HasStationRail(t)) return TRACK_BIT_NONE;
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
return TrackToTrackBits(GetRailStationTrack(t));
default:
@@ -135,7 +135,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
* axis that still display wires to preserve visual continuity. */
TileIndex next_tile = TileAddByDiagDir(t, d);
RailType rt = GetTileRailType(next_tile);
if (rt == INVALID_RAILTYPE || !HasCatenary(rt) ||
if (rt == INVALID_RAILTYPE || !HasRailCatenary(rt) ||
((TrackStatusToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTracks(d)) == TRACK_BIT_NONE &&
(!HasStationTileRail(next_tile) || GetRailStationAxis(next_tile) != DiagDirToAxis(d) || !CanStationTileHaveWires(next_tile)))) {
neighbour_tdb |= DiagdirReachesTrackdirs(ReverseDiagDir(d));
@@ -241,7 +241,7 @@ static int GetPCPElevation(TileIndex tile, DiagDirection PCPpos)
*
* @param ti The Tileinfo to draw the tile for
*/
void DrawCatenaryOnTunnel(const TileInfo *ti)
void DrawRailCatenaryOnTunnel(const TileInfo *ti)
{
/* xmin, ymin, xmax + 1, ymax + 1 of BB */
static const int _tunnel_wire_BB[4][4] = {
@@ -255,7 +255,7 @@ void DrawCatenaryOnTunnel(const TileInfo *ti)
SpriteID wire_base = GetWireBase(ti->tile);
const SortableSpriteStruct *sss = &CatenarySpriteData_Tunnel[dir];
const SortableSpriteStruct *sss = &RailCatenarySpriteData_Tunnel[dir];
const int *BB_data = _tunnel_wire_BB[dir];
AddSortableSpriteToDraw(
wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
@@ -270,7 +270,7 @@ void DrawCatenaryOnTunnel(const TileInfo *ti)
* Draws wires and, if required, pylons on a given tile
* @param ti The Tileinfo to draw the tile for
*/
static void DrawCatenaryRailway(const TileInfo *ti)
static void DrawRailCatenaryRailway(const TileInfo *ti)
{
/* Pylons are placed on a tile edge, so we need to take into account
* the track configuration of 2 adjacent tiles. trackconfig[0] stores the
@@ -379,7 +379,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
if (IsTileType(neighbour, MP_STATION) || IsTileType(neighbour, MP_ROAD)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
/* Read the foundations if they are present, and adjust the tileh */
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
if (IsBridgeTile(neighbour)) {
foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetTunnelBridgeDirection(neighbour)));
}
@@ -442,7 +442,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
}
}
/* The wire above the tunnel is drawn together with the tunnel-roof (see DrawCatenaryOnTunnel()) */
/* The wire above the tunnel is drawn together with the tunnel-roof (see DrawRailCatenaryOnTunnel()) */
if (IsTunnelTile(ti->tile)) return;
/* Don't draw a wire under a low bridge */
@@ -478,7 +478,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
assert(PCPconfig != 0); // We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that)
assert(!IsSteepSlope(tileh[TS_HOME]));
sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
sss = &RailCatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
/*
* The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE.
@@ -498,7 +498,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
*
* @param ti The Tileinfo to draw the tile for
*/
void DrawCatenaryOnBridge(const TileInfo *ti)
void DrawRailCatenaryOnBridge(const TileInfo *ti)
{
TileIndex end = GetSouthernBridgeEnd(ti->tile);
TileIndex start = GetOtherBridgeEnd(end);
@@ -511,15 +511,15 @@ void DrawCatenaryOnBridge(const TileInfo *ti)
Axis axis = GetBridgeAxis(ti->tile);
TLG tlg = GetTLG(ti->tile);
CatenarySprite offset = (CatenarySprite)(axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH);
RailCatenarySprite offset = (RailCatenarySprite)(axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH);
if ((length % 2) && num == length) {
/* Draw the "short" wire on the southern end of the bridge
* only needed if the length of the bridge is odd */
sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
sss = &RailCatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
} else {
/* Draw "long" wires on all other tiles of the bridge (one pylon every two tiles) */
sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
sss = &RailCatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
}
height = GetBridgePixelHeight(end);
@@ -558,14 +558,14 @@ void DrawCatenaryOnBridge(const TileInfo *ti)
/**
* Draws overhead wires and pylons for electric railways.
* @param ti The TileInfo struct of the tile being drawn
* @see DrawCatenaryRailway
* @see DrawRailCatenaryRailway
*/
void DrawCatenary(const TileInfo *ti)
void DrawRailCatenary(const TileInfo *ti)
{
switch (GetTileType(ti->tile)) {
case MP_RAILWAY:
if (IsRailDepot(ti->tile)) {
const SortableSpriteStruct *sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
const SortableSpriteStruct *sss = &RailCatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
SpriteID wire_base = GetWireBase(ti->tile);
@@ -587,7 +587,7 @@ void DrawCatenary(const TileInfo *ti)
default: return;
}
DrawCatenaryRailway(ti);
DrawRailCatenaryRailway(ti);
}
bool SettingsDisableElrail(int32 p1)

View File

@@ -20,7 +20,7 @@
* Test if a rail type has catenary
* @param rt Rail type to test
*/
static inline bool HasCatenary(RailType rt)
static inline bool HasRailCatenary(RailType rt)
{
return HasBit(GetRailTypeInfo(rt)->flags, RTF_CATENARY);
}
@@ -29,14 +29,14 @@ static inline bool HasCatenary(RailType rt)
* Test if we should draw rail catenary
* @param rt Rail type to test
*/
static inline bool HasCatenaryDrawn(RailType rt)
static inline bool HasRailCatenaryDrawn(RailType rt)
{
return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_settings_game.vehicle.disable_elrails;
return HasRailCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_settings_game.vehicle.disable_elrails;
}
void DrawCatenary(const TileInfo *ti);
void DrawCatenaryOnTunnel(const TileInfo *ti);
void DrawCatenaryOnBridge(const TileInfo *ti);
void DrawRailCatenary(const TileInfo *ti);
void DrawRailCatenaryOnTunnel(const TileInfo *ti);
void DrawRailCatenaryOnBridge(const TileInfo *ti);
bool SettingsDisableElrail(int32 p1); ///< _settings_game.disable_elrail callback

View File

@@ -158,6 +158,7 @@ enum EngineMiscFlags {
EF_AUTO_REFIT = 4, ///< Automatic refitting is allowed
EF_NO_DEFAULT_CARGO_MULTIPLIER = 5, ///< Use the new capacity algorithm. The default cargotype of the vehicle does not affect capacity multipliers. CB 15 is also called in purchase list.
EF_NO_BREAKDOWN_SMOKE = 6, ///< Do not show black smoke during a breakdown.
EF_SPRITE_STACK = 7, ///< Draw vehicle by stacking multiple sprites.
};
/**

View File

@@ -331,7 +331,7 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
_gw.thread = NULL;
}
if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&_GenerateWorld, NULL, &_gw.thread)) {
if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&_GenerateWorld, NULL, &_gw.thread, "ottd:genworld")) {
DEBUG(misc, 1, "Cannot create genworld thread, reverting to single-threaded mode");
_gw.threaded = false;
_modal_progress_work_mutex->EndCritical();

View File

@@ -2874,7 +2874,7 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Gå til
STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Tidligere grafikelement
STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Fortsæt til den forrige normal sprite, springe over nogen pseudo / recolour / FONT sprites og indpakning rundt fra den første sprite til det sidste
STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Repræsentation af den markerede sprite. Justeringen ignoreres når denne sprite tegnes.
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Flyt spriten rundt for at ændre X- og Y-forskydningen
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Flyt spriten rundt for at ændre X- og Y-forskydningen. Ctrl+Klik for at flytte spriten otte enheder af gangen
STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Nulstil relativ
STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Nulstil den nuværende relative forskydning
STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}X-forskydning: {NUM}, Y-forskydning: {NUM} (Absolut)

View File

@@ -845,6 +845,7 @@ STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS :{WHITE}{VEHICLE
STR_NEWS_VEHICLE_HAS_VOID_ORDER :{WHITE}{VEHICLE} tem uma ordem nula
STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY :{WHITE}{VEHICLE} tem ordens duplicadas
STR_NEWS_VEHICLE_HAS_INVALID_ENTRY :{WHITE}{VEHICLE} tem uma ordem inválida no seu horário
STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY :{WHITE}{VEHICLE} tem um aeroporto nas ordens cuja pista de aterragem é muito curta
STR_NEWS_VEHICLE_IS_GETTING_OLD :{WHITE}{VEHICLE} está a ficar velho
STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD :{WHITE}{VEHICLE} está a ficar muito velho
@@ -1288,17 +1289,21 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Mostrar a popul
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Grossura das linhas nos gráficos: {STRING}
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Largura da linha nos gráficos. Uma linha mais estreita é de leitura mais precisa, enquanto uma linha mais espessa é mais fácil de ver e as cores distinguem-se melhor.
STR_CONFIG_SETTING_LAND_GENERATOR :Gerador de terra: {STRING}
STR_CONFIG_SETTING_LANDSCAPE :Cenário: {STRING}
STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Os estilos dos cenários definem a jogabilidade base, cada um com cargas e requerimentos diferentes para o desenvolvimento das cidades. NewGRF e Scripts de Jogo permitem um controlo mais refinado
STR_CONFIG_SETTING_LAND_GENERATOR :Gerador de terreno: {STRING}
STR_CONFIG_SETTING_LAND_GENERATOR_HELPTEXT :O gerador original é dependente do conjunto gráfico base, e compõe formas de terreno já afixadas. TerraGenesis é um gerador baseado no algoritmo de ruído de Perlin que permite definições mais refinadas
STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Original
STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis
STR_CONFIG_SETTING_TERRAIN_TYPE :Tipo de terreno: {STRING}
STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(Apenas TerraGenesis) Relevo do terreno
STR_CONFIG_SETTING_INDUSTRY_DENSITY :Densidade industrial: {STRING}
STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Define quantas indústrias devem ser geradas e que nível deve ser mantido durante o jogo
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Distância máxima entre o limite do mapa e Refinarias de Petróleo: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Refinarias de petróleo são construídas apenas próximo da borda do mapa, isto é, na costa para mapas de ilha
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Altura da linha de neve: {STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Controla a que altura a neve começa em paisagens sub-árticas. A neve também afecta a geração de indústrias e os requisitos de crescimento das cidades
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Rudeza do terreno (apenas TerraGenesis) : {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Rudeza do terreno: {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(Apenas TerraGenesis) Escolhe a frequência de montes: paisagens macias têm menos montes e mais espalhados. Paisagens duras têm muitos montes, que podem parecer repetitivos
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Muito suave
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :Suave
@@ -1597,8 +1602,8 @@ STR_CONFIG_SETTING_LARGER_TOWNS :Proporção de
STR_CONFIG_SETTING_LARGER_TOWNS_HELPTEXT :Quantidade de povoações que se tornarão cidades, logo cidades que começarão maiores e crescerão mais depressa
STR_CONFIG_SETTING_LARGER_TOWNS_VALUE :1 em {COMMA}
STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :Nenhum
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Multiplicador inicial para dimensão da metrópole: {STRING}
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Tamanho relativo das cidades em relação ao tamanho normal das mesmas aquando o inicio do jogo
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Multiplicador inicial para a dimensão das metrópoles: {STRING}
STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Tamanho relativo das metrópoles em relação ao tamanho normal das cidades aquando o início do jogo
STR_CONFIG_SETTING_LINKGRAPH_INTERVAL :Actualizar gráfico de distribuição a cada {STRING} dia{P 0:2 "" s}
STR_CONFIG_SETTING_LINKGRAPH_INTERVAL_HELPTEXT :Tempo entre recalculos subsequentes de cada gráfico. Cada recalculo calcula os planos para cada componente do gráfico. Isto significa que um valor X para essa configuração não indica que o gráfico será todo actualizado a cada X dias. Apenas alguns componentes serão. Quanto mais curto o definir, mais tempo será necessário ao CPU para o calcular. Quanto mais longo, mais tempo levará até que a distribuição da carga inicie em novas rotas.
@@ -1661,13 +1666,23 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrico (m)
STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m)
STR_CONFIG_SETTING_LOCALISATION :{ORANGE}Localização
STR_CONFIG_SETTING_GRAPHICS :{ORANGE}Gráficos
STR_CONFIG_SETTING_SOUND :{ORANGE}Efeitos sonoros
STR_CONFIG_SETTING_INTERFACE :{ORANGE}Interface
STR_CONFIG_SETTING_INTERFACE_GENERAL :{ORANGE}Geral
STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Visualizadores
STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Construção
STR_CONFIG_SETTING_ADVISORS :{ORANGE}Notícias / Assessores
STR_CONFIG_SETTING_COMPANY :{ORANGE}Empresa
STR_CONFIG_SETTING_ACCOUNTING :{ORANGE}Contabilidade
STR_CONFIG_SETTING_VEHICLES :{ORANGE}Veículos
STR_CONFIG_SETTING_VEHICLES_PHYSICS :{ORANGE}Física
STR_CONFIG_SETTING_VEHICLES_ROUTING :{ORANGE}Em rota
STR_CONFIG_SETTING_LIMITATIONS :{ORANGE}Limitações
STR_CONFIG_SETTING_ACCIDENTS :{ORANGE}Desastres / Acidentes
STR_CONFIG_SETTING_GENWORLD :{ORANGE}Geração do mundo
STR_CONFIG_SETTING_ENVIRONMENT :{ORANGE}Meio Ambiente
STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES :{ORANGE}Autoridades
STR_CONFIG_SETTING_ENVIRONMENT_TOWNS :{ORANGE}Cidades
STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES :{ORANGE}Industrias
STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST :{ORANGE}Distribuição de Carga
@@ -1741,7 +1756,7 @@ STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE :{BLACK}Seleccio
STR_INTRO_TOOLTIP_GAME_OPTIONS :{BLACK}Mostrar opções de jogo
STR_INTRO_TOOLTIP_HIGHSCORE :{BLACK}Mostrar tabela de classificações
STR_INTRO_TOOLTIP_CONFIG_SETTINGS_TREE :{BLACK}Definições de Display
STR_INTRO_TOOLTIP_CONFIG_SETTINGS_TREE :{BLACK}Mostrar definições
STR_INTRO_TOOLTIP_NEWGRF_SETTINGS :{BLACK}Mostrar definições de NewGRF
STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Verificar conteúdo novo e actualizado para descarga
STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}Mostrar definições de IA e de script de jogo
@@ -2860,7 +2875,11 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Ir para
STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Gráfico anterior
STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Proceder ao gráfico normal anterior, ignorando quaisquer gráficos pseudo/recolorir/tipo-de-letra e dando a volta no início
STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Representação do gráfico seleccionado actualmente. O alinhamento é ignorado a desenhar este gráfico
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mover o gráfico, mudando os desvios X e Y
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Desloca o gráfico, alterando os intervalos X e Y. Ctrl+Clique desloca o gráfico 8 unidades de uma só vez
STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Repor relativo
STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Repor intervalos relativos atuais
STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}Intervalo X: {NUM}, Intervalo Y: {NUM} (Absoluto)
STR_SPRITE_ALIGNER_OFFSETS_REL :{BLACK}Intervalo X: {NUM}, Intervalo Y: {NUM} (Relativo)
STR_SPRITE_ALIGNER_PICKER_BUTTON :{BLACK}Escolher gráfico
STR_SPRITE_ALIGNER_PICKER_TOOLTIP :{BLACK}Escolha um gráfico de qualquer lado no ecrã
@@ -3338,6 +3357,7 @@ STR_GROUP_RENAME_TOOLTIP :{BLACK}Mudar o
STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clique para proteger este grupo da autosubstituição global
STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Apagar Grupo
STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Tem a certeza de que quer apagar este grupo e quaisquer descendentes?
STR_GROUP_ADD_SHARED_VEHICLE :Adic. veíc. partilh.
STR_GROUP_REMOVE_ALL_VEHICLES :Remover todos os veículos
@@ -3879,6 +3899,10 @@ STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Viagem (sem pro
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Viajar no máximo a {2:VELOCITY} (sem programação)
STR_TIMETABLE_TRAVEL_FOR :Viajar durante {STRING}
STR_TIMETABLE_TRAVEL_FOR_SPEED :Viajar por {STRING} no máximo a {VELOCITY}
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Viajar (durante {STRING}, sem programação)
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Viajar (por {STRING}, sem programação) no máximo a {VELOCITY}
STR_TIMETABLE_STAY_FOR_ESTIMATED :(permanecer durante {STRING}, sem programação)
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :(viajar durante {STRING}, sem programação)
STR_TIMETABLE_STAY_FOR :e ficar durante {STRING}
STR_TIMETABLE_AND_TRAVEL_FOR :e viaja para {STRING}
STR_TIMETABLE_DAYS :{COMMA} dia{P "" s}

View File

@@ -1114,6 +1114,7 @@ STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU :Setări joc (st
STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME :Setări joc (stocate în salvări; afectează doar jocul curent)
STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU :Setări companie (stocate în salvări; afectează doar jocurile noi)
STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME :Setări compenia (stocate în salvări; afectează doar compania curentă)
STR_CONFIG_SETTINGS_NONE :{WHITE}- Nespecificat -
STR_CONFIG_SETTING_OFF :Inactiv
STR_CONFIG_SETTING_ON :Activ
@@ -1280,18 +1281,25 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Afișează popu
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Grosimea liniilor din grafice: {STRING}
STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Grosimea liniilor din grafice. O linie subțire este mai informativă, o linie mai groasă este mai ușor de văzut și are culorile mai usor de distins
STR_CONFIG_SETTING_LANDSCAPE :Peisaj: {STRING}
STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Peisajele definesc scenariile de bază a jocului cu cerințe diferite pentru încărcături și dezvoltare a orașelor. NewGRF și scripturile de joc permit un control mai fin
STR_CONFIG_SETTING_LAND_GENERATOR :Generator teren: {STRING}
STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Original
STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis
STR_CONFIG_SETTING_TERRAIN_TYPE :Tip teren: {STRING}
STR_CONFIG_SETTING_INDUSTRY_DENSITY :Densitatea industriei: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Distanța maximă de la marginea hărții pentru rafinării: {STRING}
STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Rafinăriile de petrol vor fi construite doar la marginea hărţii, sau pe coastă, în cazul harţilor insulare
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Grosimea stratului de zăpadă: {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Duritatea terenului (doar pt TerraGenesis) : {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(Doar TerraGenesis) Alegeți frecvența dealurilor: Peisajele line au dealuri mai puține și mai întinse. Peisajele dure au multe dealuri și pot arăta repetitiv
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Foarte fin
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :Fin
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :Dur
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :Foarte dur
STR_CONFIG_SETTING_VARIETY :Distribuția varietății: {STRING}
STR_CONFIG_SETTING_TREE_PLACER :Algoritm amplasare arbori: {STRING}
STR_CONFIG_SETTING_TREE_PLACER_HELPTEXT :Alegeți distribuția copacilor pe hartă: 'Original' plantează copacii dispersați uniform, 'Îmbunătățit' îi plantează grupat
STR_CONFIG_SETTING_TREE_PLACER_NONE :Niciunul
STR_CONFIG_SETTING_TREE_PLACER_ORIGINAL :Original
STR_CONFIG_SETTING_TREE_PLACER_IMPROVED :Îmbunătăţit
@@ -1552,6 +1560,7 @@ STR_CONFIG_SETTING_SOFT_LIMIT :Numărul maxim
STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA}
STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :dezactivat
STR_CONFIG_SETTING_ZOOM_MIN :Nivelul maxim de apropiere imagine: {STRING}
STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Nivelul maxim de apropiere a câmpului vizual. Luați aminte că nivelele înalte ridică necesarul de memorie
STR_CONFIG_SETTING_ZOOM_MAX :Nivelul maxim de îndepărtare imagine: {STRING}
STR_CONFIG_SETTING_ZOOM_LVL_MIN :x4
STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :x2
@@ -1579,7 +1588,9 @@ STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manual
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :asimetric
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :simetric
STR_CONFIG_SETTING_DISTRIBUTION_PAX :Modalitatea de distribuire a pasagerilor: {STRING}
STR_CONFIG_SETTING_DISTRIBUTION_PAX_HELPTEXT :"simetric" înseamnă că aproximativ același număr de pasageri va fi transportat din stația A spre stația B, precum de la B la A. "asimetric" presupune transportul unui număr arbitrar de pasageri în fiecare direcție. "manual" înseamnă că repartizarea pasagerilor nu va fi automatizată.
STR_CONFIG_SETTING_DISTRIBUTION_MAIL :Modalitatea de distribuire a poştei: {STRING}
STR_CONFIG_SETTING_DISTRIBUTION_MAIL_HELPTEXT :"simetric" înseamnă că aproximativ aceeași cantitate de poștă va fi expediată din stația A spre stația B, precum de la B la A. "asimetric" presupune expedierea de cantități arbitrare de poștă în fiecare direcție. "manual" înseamnă că repartizarea poștei nu va fi automatizată.
STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED :Modalitatea de distribuire pentru clasa de cargo BLINDAT: {STRING}
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Modalitatea de distribuire pentru alte clase de cargo: {STRING}
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Acurateţea distribuţiei: {STRING}
@@ -1626,9 +1637,15 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m)
STR_CONFIG_SETTING_LOCALISATION :{ORANGE}Localizare
STR_CONFIG_SETTING_SOUND :{ORANGE}Efecte sonore
STR_CONFIG_SETTING_INTERFACE :{ORANGE}Interfaţă
STR_CONFIG_SETTING_INTERFACE_VIEWPORTS :{ORANGE}Câmpuri vizuale
STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}Construcţie
STR_CONFIG_SETTING_ADVISORS :{ORANGE}Știri / Consilieri
STR_CONFIG_SETTING_COMPANY :{ORANGE}Companie
STR_CONFIG_SETTING_VEHICLES :{ORANGE}Vehicule
STR_CONFIG_SETTING_VEHICLES_ROUTING :{ORANGE}Direcţionare
STR_CONFIG_SETTING_ACCIDENTS :{ORANGE}Dezastre / Accidente
STR_CONFIG_SETTING_GENWORLD :{ORANGE}Generare lume
STR_CONFIG_SETTING_ENVIRONMENT :{ORANGE}Mediu
STR_CONFIG_SETTING_ENVIRONMENT_TOWNS :{ORANGE}Oraşe
STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES :{ORANGE}Industrii
STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST :{ORANGE}Distribuţie cargo
@@ -2537,6 +2554,7 @@ STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF:
STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}Încărcături acceptate: {LTBLUE}
STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING})
STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Limită viteză pe calea ferată: {LTBLUE}{VELOCITY}
STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Viteza limită a drumului: {LTBLUE}{VELOCITY}
# Description of land area of different tiles
STR_LAI_CLEAR_DESCRIPTION_ROCKS :Stânci
@@ -2652,6 +2670,7 @@ STR_SAVELOAD_SAVE_BUTTON :{BLACK}Salveaz
STR_SAVELOAD_SAVE_TOOLTIP :{BLACK}Salvează cu numele selectat jocul curent
STR_SAVELOAD_LOAD_BUTTON :{BLACK}Încarcă
STR_SAVELOAD_LOAD_TOOLTIP :{BLACK}Încarcă salvarea selectată
STR_SAVELOAD_LOAD_HEIGHTMAP_TOOLTIP :{BLACK}Încarcă harta selectată
STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Detalii joc
STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}Nicio informaţie disponibilă
STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING}
@@ -2754,6 +2773,8 @@ STR_NEWGRF_SETTINGS_MOVEUP :{BLACK}Mută î
STR_NEWGRF_SETTINGS_MOVEUP_TOOLTIP :{BLACK}Mută fişierul NewGRF selectat mai sus în listă
STR_NEWGRF_SETTINGS_MOVEDOWN :{BLACK}Mută în jos
STR_NEWGRF_SETTINGS_MOVEDOWN_TOOLTIP :{BLACK}Mută fişierul NewGRF selectat mai jos în listă
STR_NEWGRF_SETTINGS_UPGRADE :{BLACK}Upgrade
STR_NEWGRF_SETTINGS_UPGRADE_TOOLTIP :{BLACK}Actualizați fișierele NewGRF pentru care aveți o versiune mai nouă instalată
STR_NEWGRF_SETTINGS_FILE_TOOLTIP :{BLACK}O listă a fişierelor NewGRF instalate
STR_NEWGRF_SETTINGS_SET_PARAMETERS :{BLACK}Setează parametri
@@ -2779,6 +2800,9 @@ STR_NEWGRF_SETTINGS_DISABLED :{RED}Dezactivat
STR_NEWGRF_SETTINGS_INCOMPATIBLE :{RED}Incompatibil cu această versiune de OpenTTD
# NewGRF save preset window
STR_SAVE_PRESET_CANCEL :{BLACK}Anulează
STR_SAVE_PRESET_CANCEL_TOOLTIP :{BLACK}Nu schimba setarea implicită
STR_SAVE_PRESET_SAVE_TOOLTIP :{BLACK}Salvează setarea pe numele selectat
# NewGRF parameters window
STR_NEWGRF_PARAMETERS_CAPTION :{WHITE}Schimbă parametrii NewGRF
@@ -2809,7 +2833,7 @@ STR_SPRITE_ALIGNER_GOTO_TOOLTIP :{BLACK}Mergi la
STR_SPRITE_ALIGNER_PREVIOUS_BUTTON :{BLACK}Imaginea precedentă
STR_SPRITE_ALIGNER_PREVIOUS_TOOLTIP :{BLACK}Mergi la precedenta imagine normală, sărind peste pseudo-imagini, recolorări sau fonturi şi reporneşte când s-a ajuns la sfârşit
STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Reprezentarea imaginii curente. Aliniamentul este ignorat
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mişcă imaginea schimbând distanţele pe axele X şi Y
STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mișcă imaginea schimbând distanțele pe axele X şi Y. Ctrl+Clic pentru mutarea imaginii câte opt unități la un pas
STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Resetează relativele
STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Resetază limitele relative actuale
STR_SPRITE_ALIGNER_OFFSETS_ABS :{BLACK}Limita X: {NUM}, Limita Y: {NUM} (Absolut)
@@ -3825,11 +3849,14 @@ STR_TIMETABLE_ORDER_VIEW_TOOLTIP :{BLACK}Schimba
STR_TIMETABLE_TOOLTIP :{BLACK}Orar - click pe un ordin pentru a-l selecta
STR_TIMETABLE_NO_TRAVEL :NU este calatorie
STR_TIMETABLE_NOT_TIMETABLEABLE :Călătorie (automat; orar generat de următorul ordin manual)
STR_TIMETABLE_NOT_TIMETABLEABLE :Călătorie (automat; programată după următoarea comandă manuală)
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Calatorie (fara orar)
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Mergi cu maxim {2:VELOCITY} (fără planificare)
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Călătoriți (neplanificat) cu maxim {2:VELOCITY}
STR_TIMETABLE_TRAVEL_FOR :Calatorii pentru {STRING}
STR_TIMETABLE_TRAVEL_FOR_SPEED :Mergi către {STRING} cu maxim {VELOCITY}
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Călătorie (pentru {STRING}, neplanificată)
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Călătoriți (pentru {STRING}, neprogramat) cu cel mult {VELOCITY}
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :(călătorie pentru {STRING}, neprogramată)
STR_TIMETABLE_STAY_FOR :şi opreşte pentru {STRING}
STR_TIMETABLE_AND_TRAVEL_FOR :şi călătoreşte pentru {STRING}
STR_TIMETABLE_DAYS :{COMMA} zi{P "" le}
@@ -3958,6 +3985,8 @@ STR_AI_SETTINGS_START_DELAY :Perioada (în z
STR_TEXTFILE_README_CAPTION :{WHITE}{STRING}, fișier readme al {STRING}
STR_TEXTFILE_CHANGELOG_CAPTION :{WHITE}{STRING}, lista de modificări a {STRING}
STR_TEXTFILE_LICENCE_CAPTION :{WHITE}{STRING}, licența fișierului {STRING}
STR_TEXTFILE_WRAP_TEXT :{WHITE}Încadrează textul
STR_TEXTFILE_WRAP_TEXT_TOOLTIP :{BLACK}Încadrează textul ferestrei ca să fie vizibil integral, fără derulare
STR_TEXTFILE_VIEW_README :{BLACK}Vezi fișierul readme
STR_TEXTFILE_VIEW_CHANGELOG :{BLACK}Listă modificări
STR_TEXTFILE_VIEW_LICENCE :{BLACK}Licenţă

View File

@@ -250,6 +250,7 @@ STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC :{BLACK}ทำ
# Show engines button
STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :ถ้าได้อนุญาตที่ปุ่มนี้แล้ว อากาศยานที่ซ่อนจะถูกแสดงออกมา
# Query window
STR_BUTTON_DEFAULT :{BLACK}ค่าปกติ
@@ -970,6 +971,7 @@ STR_GAME_OPTIONS_RESOLUTION :{BLACK}คว
STR_GAME_OPTIONS_RESOLUTION_TOOLTIP :{BLACK}เลือกความละเอียดของหน้าจอที่จะใช้
STR_GAME_OPTIONS_RESOLUTION_OTHER :อื่นๆ
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}ขนาดของแผงควบคุม
STR_GAME_OPTIONS_BASE_GRF :{BLACK}ตั้งค่า Graphic พื้นฐาน
@@ -1086,6 +1088,7 @@ STR_CONFIG_SETTING_TYPE_COMPANY_MENU :ตั้งค
STR_CONFIG_SETTING_TYPE_COMPANY_INGAME :ตั้งค่าองค์กร (ถูกเก็บไว้ในการบันทึกเกม; มีผลเฉพาะเกมปัจจุบัน)
STR_CONFIG_SETTING_RESTRICT_CATEGORY :{BLACK}หมวดหมู่:
STR_CONFIG_SETTING_RESTRICT_TYPE :{BLACK}ชนิด:
STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT :{BLACK}จำกัดรายการด้านล่างให้แสดงเฉพาะการตั้งค่าที่มีการเปลี่ยนแปลง
STR_CONFIG_SETTING_RESTRICT_BASIC :ตั้งค่าพื้นฐาน
STR_CONFIG_SETTING_RESTRICT_ADVANCED :ตั้งค่าขั้นสูง
@@ -1270,6 +1273,7 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :โรงกล
STR_CONFIG_SETTING_SNOWLINE_HEIGHT :ระดับความสูงแนวหิมะ: {STRING}
STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :ควบคุมความสูงเริ่มต้นของหิมะบนพื้นภูมิทัศน์อาร์ติคย่อยๆ, หิมะยังมีผลการสร้างอุตสาหกรรม และการเติบโตของเมือง
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :ความหยาบของพื้นที่ (เฉพาะ TerraGenesis): {STRING}
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesis only) Choose the frequency of hills: Smooth landscapes have fewer, more wide-spread hills. Rough landscapes have many hills, which may look repetitive
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :ราบเรียบมาก
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :ราบเรียบ
STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :หยาบ
@@ -1626,6 +1630,7 @@ STR_CONFIG_SETTING_SOUND :{ORANGE}เส
STR_CONFIG_SETTING_INTERFACE :{ORANGE}ส่วนเชื่อมต่อผู้ใช้
STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :{ORANGE}การก่อสร้าง
STR_CONFIG_SETTING_VEHICLES :{ORANGE}ยานพาหนะ
STR_CONFIG_SETTING_VEHICLES_PHYSICS :กายภาพ
STR_CONFIG_SETTING_VEHICLES_ROUTING :{ORANGE}การค้นหาเส้นทางของพาหนะ
STR_CONFIG_SETTING_ENVIRONMENT :{ORANGE}สิ่งแวดล้อม
STR_CONFIG_SETTING_ENVIRONMENT_TOWNS :{ORANGE}เมือง
@@ -1701,6 +1706,7 @@ STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE :{BLACK}เล
STR_INTRO_TOOLTIP_GAME_OPTIONS :{BLACK}แสดงตัวเลือกเกม
STR_INTRO_TOOLTIP_HIGHSCORE :{BLACK}แสดงตารางคะแนนสูงสุด
STR_INTRO_TOOLTIP_CONFIG_SETTINGS_TREE :{BLACK}การตั้งค่า หน้าจอ
STR_INTRO_TOOLTIP_NEWGRF_SETTINGS :{BLACK}แสดงการกำหนดค่า NewGRF
STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}ตรวจสอบเนื้อหาใหม่และการปรับปรุงสำหรับดาวโหลด
STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}แสดงการตั้งค่า AI/Game script
@@ -2663,6 +2669,7 @@ STR_MAPGEN_BY :{BLACK}*
STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}จำนวนเมือง
STR_MAPGEN_DATE :{BLACK}วันที่:
STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}จำนวนอุตสาหกรรม:
STR_MAPGEN_MAX_HEIGHTLEVEL :{BLACK}ขนาดความสูงของแผนที่สูงสุด:
STR_MAPGEN_SNOW_LINE_HEIGHT :{BLACK}เส้นความสูงเขตหิมะ:
STR_MAPGEN_SNOW_LINE_UP :{BLACK}ปรับเปลี่ยนความสูงของหิมะขึ้นไป 1 ระดับ
STR_MAPGEN_SNOW_LINE_DOWN :{BLACK}ปรับเปลี่ยนความสูงของหิมะลงมา 1 ระดับ
@@ -2773,6 +2780,7 @@ STR_NEWGRF_SETTINGS_DISABLED :{RED}ไม่
STR_NEWGRF_SETTINGS_INCOMPATIBLE :{RED}ไม่รองรับกับ OpenTTD เวอร์ชั่นนี้
# NewGRF save preset window
STR_SAVE_PRESET_SAVE_TOOLTIP :บันทึก ชุดการตั้งค่า ตามที่ได้เลือกไว้
# NewGRF parameters window
STR_NEWGRF_PARAMETERS_CAPTION :{WHITE}เปลี่ยนแปลง NewGRF parameters
@@ -3342,10 +3350,12 @@ STR_BUY_VEHICLE_ROAD_VEHICLE_RENAME_TOOLTIP :{BLACK}เป
STR_BUY_VEHICLE_SHIP_RENAME_TOOLTIP :{BLACK}เปลี่ยนชื่อชนิดของเรือ
STR_BUY_VEHICLE_AIRCRAFT_RENAME_TOOLTIP :{BLACK}เปลี่ยนชื่อชนิดของเครื่องบิน
STR_BUY_VEHICLE_AIRCRAFT_HIDE_TOGGLE_BUTTON :ซ่อน
STR_BUY_VEHICLE_TRAIN_SHOW_TOGGLE_BUTTON :{BLACK}การแสดงผล
STR_BUY_VEHICLE_ROAD_VEHICLE_SHOW_TOGGLE_BUTTON :{BLACK}การแสดงผล
STR_BUY_VEHICLE_AIRCRAFT_HIDE_SHOW_TOGGLE_TOOLTIP :{BLACK}ปรับเปลี่ยน ซ่อน/แสดง ของชนิดเครื่องอากาศยาน
STR_QUERY_RENAME_TRAIN_TYPE_CAPTION :{WHITE}เปลี่ยนชื่อชนิดของรถไฟ
STR_QUERY_RENAME_ROAD_VEHICLE_TYPE_CAPTION :{WHITE}เปลี่ยนชื่อชนิดของรถ
@@ -3451,6 +3461,7 @@ STR_REPLACE_VEHICLE_ROAD_VEHICLE :ยานพา
STR_REPLACE_VEHICLE_SHIP :ยานพาหนะทางน้ำ
STR_REPLACE_VEHICLE_AIRCRAFT :อากาศยาน
STR_REPLACE_VEHICLE_VEHICLES_IN_USE :{YELLOW}พาหนะถูกใช้งานอยู่
STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}เลือกประเภทของรถจักรที่จะแทนที่
STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}เลือกประเภทของพาหนะที่จะแทนที่ทางซ้ายมือ

View File

@@ -61,7 +61,7 @@ void LinkGraphJob::EraseFlows(NodeID from)
*/
void LinkGraphJob::SpawnThread()
{
if (!ThreadObject::New(&(LinkGraphSchedule::Run), this, &this->thread)) {
if (!ThreadObject::New(&(LinkGraphSchedule::Run), this, &this->thread, "ottd:linkgraph")) {
this->thread = NULL;
/* Of course this will hang a bit.
* On the other hand, if you want to play games which make this hang noticably

View File

@@ -30,6 +30,10 @@
#include "../safeguards.h"
#if !defined(HAVE_OSX_1011_SDK)
#define kMusicSequenceFile_AnyType 0
#endif
static FMusicDriver_Cocoa iFMusicDriver_Cocoa;
@@ -68,7 +72,7 @@ static void DoSetVolume()
* risk compilation errors. The header AudioComponent.h
* was introduced in 10.6 so use it to decide which
* type definition to use. */
#ifdef __AUDIOCOMPONENT_H__
#if defined(__AUDIOCOMPONENT_H__) || defined(HAVE_OSX_107_SDK)
AudioComponentDescription desc;
#else
ComponentDescription desc;
@@ -159,7 +163,7 @@ void MusicDriver_Cocoa::PlaySong(const char *filename)
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (MacOSVersionIsAtLeast(10, 5, 0)) {
if (MusicSequenceFileLoad(_sequence, url, 0, 0) != noErr) {
if (MusicSequenceFileLoad(_sequence, url, kMusicSequenceFile_AnyType, 0) != noErr) {
DEBUG(driver, 0, "cocoa_m: Failed to load MIDI file");
CFRelease(url);
return;

View File

@@ -14,6 +14,7 @@
#include "win32_m.h"
#include <windows.h>
#include <mmsystem.h>
#include "../os/windows/win32.h"
#include "../safeguards.h"
@@ -105,6 +106,8 @@ static bool MidiIntIsSongPlaying()
static DWORD WINAPI MidiThread(LPVOID arg)
{
SetWin32ThreadName(-1, "ottd:win-midi");
do {
char *s;
int vol;

View File

@@ -35,7 +35,7 @@ TCPConnecter::TCPConnecter(const NetworkAddress &address) :
address(address)
{
*_tcp_connecters.Append() = this;
if (!ThreadObject::New(TCPConnecter::ThreadEntry, this, &this->thread)) {
if (!ThreadObject::New(TCPConnecter::ThreadEntry, this, &this->thread, "ottd:tcp")) {
this->Connect();
}
}

View File

@@ -109,7 +109,7 @@ static void NetworkUDPQueryServerThread(void *pntr)
void NetworkUDPQueryServer(NetworkAddress address, bool manually)
{
NetworkUDPQueryServerInfo *info = new NetworkUDPQueryServerInfo(address, manually);
if (address.IsResolved() || !ThreadObject::New(NetworkUDPQueryServerThread, info)) {
if (address.IsResolved() || !ThreadObject::New(NetworkUDPQueryServerThread, info, NULL, "ottd:udp-query")) {
NetworkUDPQueryServerThread(info);
}
}
@@ -565,7 +565,7 @@ void NetworkUDPRemoveAdvertise(bool blocking)
/* Check if we are advertising */
if (!_networking || !_network_server || !_network_udp_server) return;
if (blocking || !ThreadObject::New(NetworkUDPRemoveAdvertiseThread, NULL)) {
if (blocking || !ThreadObject::New(NetworkUDPRemoveAdvertiseThread, NULL, NULL, "ottd:udp-advert")) {
NetworkUDPRemoveAdvertiseThread(NULL);
}
}
@@ -648,7 +648,7 @@ void NetworkUDPAdvertise()
if (_next_advertisement < _last_advertisement) _next_advertisement = UINT32_MAX;
if (_next_retry < _last_advertisement) _next_retry = UINT32_MAX;
if (!ThreadObject::New(NetworkUDPAdvertiseThread, NULL)) {
if (!ThreadObject::New(NetworkUDPAdvertiseThread, NULL, NULL, "ottd:udp-advert")) {
NetworkUDPAdvertiseThread(NULL);
}
}

View File

@@ -5584,7 +5584,7 @@ static const Action5Type _action5_types[] = {
/* 0x02 */ { A5BLOCK_INVALID, 0, 0, 0, "Type 0x02" },
/* 0x03 */ { A5BLOCK_INVALID, 0, 0, 0, "Type 0x03" },
/* 0x04 */ { A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT, "Signal graphics" },
/* 0x05 */ { A5BLOCK_ALLOW_OFFSET, SPR_ELRAIL_BASE, 1, ELRAIL_SPRITE_COUNT, "Catenary graphics" },
/* 0x05 */ { A5BLOCK_ALLOW_OFFSET, SPR_ELRAIL_BASE, 1, ELRAIL_SPRITE_COUNT, "Rail catenary graphics" },
/* 0x06 */ { A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT, "Foundation graphics" },
/* 0x07 */ { A5BLOCK_INVALID, 0, 75, 0, "TTDP GUI graphics" }, // Not used by OTTD.
/* 0x08 */ { A5BLOCK_ALLOW_OFFSET, SPR_CANALS_BASE, 1, CANALS_SPRITE_COUNT, "Canal graphics" },

View File

@@ -786,7 +786,7 @@ void ScanNewGRFFiles(NewGRFScanCallback *callback)
/* Only then can we really start, especially by marking the whole screen dirty. Get those other windows hidden!. */
MarkWholeScreenDirty();
if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&DoScanNewGRFFiles, callback, NULL)) {
if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&DoScanNewGRFFiles, callback, NULL, "ottd:newgrf-scan")) {
_modal_progress_work_mutex->EndCritical();
_modal_progress_paint_mutex->EndCritical();
DoScanNewGRFFiles(callback);

View File

@@ -1023,17 +1023,29 @@ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type)
void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type, VehicleSpriteSeq *result)
{
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK, image_type);
const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_CACHED, false, CBID_NO_CALLBACK);
result->Clear();
return group->GetResult() + (direction % group->GetNumResults());
bool sprite_stack = HasBit(EngInfo(engine)->misc_flags, EF_SPRITE_STACK);
uint max_stack = sprite_stack ? lengthof(result->seq) : 1;
for (uint stack = 0; stack < max_stack; ++stack) {
object.ResetState();
object.callback_param1 = image_type | (stack << 8);
const SpriteGroup *group = object.Resolve();
uint32 reg100 = sprite_stack ? GetRegister(0x100) : 0;
if (group != NULL && group->GetNumResults() != 0) {
result->seq[result->count].sprite = group->GetResult() + (direction % group->GetNumResults());
result->seq[result->count].pal = GB(reg100, 0, 16); // zero means default recolouring
result->count++;
}
if (!HasBit(reg100, 31)) break;
}
}
SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_view, EngineImageType image_type)
void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
@@ -1041,14 +1053,24 @@ SpriteID GetRotorOverrideSprite(EngineID engine, const Aircraft *v, bool info_vi
assert(e->type == VEH_AIRCRAFT);
assert(!(e->u.air.subtype & AIR_CTOL));
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK, image_type);
VehicleResolverObject object(engine, v, VehicleResolverObject::WO_SELF, info_view, CBID_NO_CALLBACK);
result->Clear();
uint rotor_pos = v == NULL || info_view ? 0 : v->Next()->Next()->state;
bool sprite_stack = HasBit(e->info.misc_flags, EF_SPRITE_STACK);
uint max_stack = sprite_stack ? lengthof(result->seq) : 1;
for (uint stack = 0; stack < max_stack; ++stack) {
object.ResetState();
object.callback_param1 = image_type | (stack << 8);
const SpriteGroup *group = object.Resolve();
if (group == NULL || group->GetNumResults() == 0) return 0;
if (v == NULL || info_view) return group->GetResult();
return group->GetResult() + (v->Next()->Next()->state % group->GetNumResults());
uint32 reg100 = sprite_stack ? GetRegister(0x100) : 0;
if (group != NULL && group->GetNumResults() != 0) {
result->seq[result->count].sprite = group->GetResult() + (rotor_pos % group->GetNumResults());
result->seq[result->count].pal = GB(reg100, 0, 16); // zero means default recolouring
result->count++;
}
if (!HasBit(reg100, 31)) break;
}
}

View File

@@ -64,13 +64,19 @@ static const uint TRAININFO_DEFAULT_VEHICLE_WIDTH = 29;
static const uint ROADVEHINFO_DEFAULT_VEHICLE_WIDTH = 32;
static const uint VEHICLEINFO_FULL_VEHICLE_WIDTH = 32;
struct VehicleSpriteSeq;
void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const struct SpriteGroup *group, EngineID *train_id, uint trains);
const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine);
void SetCustomEngineSprites(EngineID engine, byte cargo, const struct SpriteGroup *group);
SpriteID GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type);
SpriteID GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type);
#define GetCustomRotorSprite(v, i, image_type) GetRotorOverrideSprite(v->engine_type, v, i, image_type)
#define GetCustomRotorIcon(et, image_type) GetRotorOverrideSprite(et, NULL, true, image_type)
void GetCustomEngineSprite(EngineID engine, const Vehicle *v, Direction direction, EngineImageType image_type, VehicleSpriteSeq *result);
#define GetCustomVehicleSprite(v, direction, image_type, result) GetCustomEngineSprite(v->engine_type, v, direction, image_type, result)
#define GetCustomVehicleIcon(et, direction, image_type, result) GetCustomEngineSprite(et, NULL, direction, image_type, result)
void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, bool info_view, EngineImageType image_type, VehicleSpriteSeq *result);
#define GetCustomRotorSprite(v, i, image_type, result) GetRotorOverrideSprite(v->engine_type, v, i, image_type, result)
#define GetCustomRotorIcon(et, image_type, result) GetRotorOverrideSprite(et, NULL, true, image_type, result)
/* Forward declaration of GRFFile, to avoid unnecessary inclusion of newgrf.h
* elsewhere... */
@@ -81,8 +87,6 @@ void SetEngineGRF(EngineID engine, const struct GRFFile *file);
uint16 GetVehicleCallback(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v);
uint16 GetVehicleCallbackParent(CallbackID callback, uint32 param1, uint32 param2, EngineID engine, const Vehicle *v, const Vehicle *parent);
bool UsesWagonOverride(const Vehicle *v);
#define GetCustomVehicleSprite(v, direction, image_type) GetCustomEngineSprite(v->engine_type, v, direction, image_type)
#define GetCustomVehicleIcon(et, direction, image_type) GetCustomEngineSprite(et, NULL, direction, image_type)
/* Handler to Evaluate callback 36. If the callback fails (i.e. most of the
* time) orig_value is returned */

View File

@@ -770,6 +770,8 @@ static void ChangeTileOwner_Object(TileIndex tile, Owner old_owner, Owner new_ow
{
if (!IsTileOwner(tile, old_owner)) return;
bool do_clear = false;
if (IsObjectType(tile, OBJECT_OWNED_LAND) && new_owner != INVALID_OWNER) {
SetTileOwner(tile, new_owner);
} else if (IsObjectType(tile, OBJECT_STATUE)) {
@@ -780,12 +782,18 @@ static void ChangeTileOwner_Object(TileIndex tile, Owner old_owner, Owner new_ow
SetBit(t->statues, new_owner);
SetTileOwner(tile, new_owner);
} else {
ReallyClearObjectTile(Object::GetByTile(tile));
do_clear = true;
}
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
} else {
do_clear = true;
}
if (do_clear) {
ReallyClearObjectTile(Object::GetByTile(tile));
/* When clearing objects, they may turn into canal, which may require transfering ownership. */
ChangeTileOwner(tile, old_owner, new_owner);
}
}

View File

@@ -13,6 +13,17 @@
#define MACOS_STDAFX_H
#include <AvailabilityMacros.h>
/* We assume if these macros are defined, the SDK is also at least this version or later. */
#ifdef MAC_OS_X_VERSION_10_7
#define HAVE_OSX_107_SDK
#endif
#ifdef MAC_OS_X_VERSION_10_11
#define HAVE_OSX_1011_SDK
#endif
/* It would seem that to ensure backward compability we have to ensure that we have defined MAC_OS_X_VERSION_10_x everywhere */
#ifndef MAC_OS_X_VERSION_10_3
#define MAC_OS_X_VERSION_10_3 1030
@@ -57,8 +68,6 @@
# error "Compiling 64 bits without _SQ64 set! (or vice versa)"
#endif
#include <AvailabilityMacros.h>
/* Name conflict */
#define Rect OTTDRect
#define Point OTTDPoint

View File

@@ -785,3 +785,36 @@ uint GetCPUCoreCount()
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
#ifdef _MSC_VER
/* Code from MSDN: https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx */
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
typedef struct {
DWORD dwType; ///< Must be 0x1000.
LPCSTR szName; ///< Pointer to name (in user addr space).
DWORD dwThreadID; ///< Thread ID (-1=caller thread).
DWORD dwFlags; ///< Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
/**
* Signal thread name to any attached debuggers.
*/
void SetWin32ThreadName(DWORD dwThreadID, const char* threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
__try {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
#pragma warning(pop)
}
#endif

View File

@@ -39,4 +39,10 @@ HRESULT OTTDSHGetFolderPath(HWND, int, HANDLE, DWORD, LPTSTR);
#define SHGFP_TYPE_CURRENT 0
#endif /* __MINGW32__ */
#ifdef _MSC_VER
void SetWin32ThreadName(DWORD dwThreadID, const char* threadName);
#else
static inline void SetWin32ThreadName(DWORD dwThreadID, const char* threadName) {}
#endif
#endif /* WIN32_H */

View File

@@ -2394,7 +2394,7 @@ static void DrawTile_Track(TileInfo *ti)
if (HasBit(_display_opt, DO_FULL_DETAIL)) DrawTrackDetails(ti, rti);
if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails, rti);
} else {
@@ -2469,7 +2469,7 @@ static void DrawTile_Track(TileInfo *ti)
int depot_sprite = GetCustomRailSprite(rti, ti->tile, RTSG_DEPOT);
relocation = depot_sprite != 0 ? depot_sprite - SPR_RAIL_DEPOT_SE_1 : rti->GetRailtypeSpriteOffset();
if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
DrawRailTileSeq(ti, dts, TO_BUILDINGS, relocation, 0, _drawtile_track_palette);
}

View File

@@ -1191,7 +1191,7 @@ static bool DrawRoadAsSnowDesert(TileIndex tile, Roadside roadside)
* @param ti information about the tile (slopes, height etc)
* @param tram the roadbits for the tram
*/
void DrawTramCatenary(const TileInfo *ti, RoadBits tram)
void DrawRoadCatenary(const TileInfo *ti, RoadBits tram)
{
/* Do not draw catenary if it is invisible */
if (IsInvisibilitySet(TO_CATENARY)) return;
@@ -1298,7 +1298,7 @@ static void DrawRoadBits(TileInfo *ti)
return;
}
if (tram != ROAD_NONE) DrawTramCatenary(ti, tram);
if (tram != ROAD_NONE) DrawRoadCatenary(ti, tram);
/* Return if full detail is disabled, or we are zoomed fully out. */
if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return;
@@ -1388,9 +1388,9 @@ static void DrawTile_Road(TileInfo *ti)
if (HasTileRoadType(ti->tile, ROADTYPE_TRAM)) {
DrawGroundSprite(SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal);
DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile));
DrawRoadCatenary(ti, GetCrossingRoadBits(ti->tile));
}
if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
break;
}

View File

@@ -19,6 +19,6 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb);
CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, DoCommandFlag flags, bool town_check = true);
void DrawTramCatenary(const TileInfo *ti, RoadBits tram);
void DrawRoadCatenary(const TileInfo *ti, RoadBits tram);
#endif /* ROAD_INTERNAL_H */

View File

@@ -108,7 +108,7 @@ struct RoadVehicle FINAL : public GroundVehicle<RoadVehicle, VEH_ROAD> {
void UpdateDeltaXY(Direction direction);
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_ROADVEH_INC : EXPENSES_ROADVEH_RUN; }
bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->gcache.last_speed / 2; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
Money GetRunningCost() const;

View File

@@ -113,40 +113,39 @@ int RoadVehicle::GetDisplayImageWidth(Point *offset) const
return ScaleGUITrad(this->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH);
}
static SpriteID GetRoadVehIcon(EngineID engine, EngineImageType image_type)
static void GetRoadVehIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
uint8 spritenum = e->u.road.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
spritenum = e->original_image_index;
}
assert(IsValidImageIndex<VEH_ROAD>(spritenum));
return DIR_W + _roadveh_images[spritenum];
result->Set(DIR_W + _roadveh_images[spritenum]);
}
SpriteID RoadVehicle::GetImage(Direction direction, EngineImageType image_type) const
void RoadVehicle::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
SpriteID sprite;
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_ROAD>(spritenum));
sprite = direction + _roadveh_images[spritenum];
SpriteID sprite = direction + _roadveh_images[spritenum];
if (this->cargo.StoredCount() >= this->cargo_cap / 2U) sprite += _roadveh_full_adder[spritenum];
return sprite;
result->Set(sprite);
}
/**
@@ -160,12 +159,16 @@ SpriteID RoadVehicle::GetImage(Direction direction, EngineImageType image_type)
*/
void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
SpriteID sprite = GetRoadVehIcon(engine, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetRoadVehIcon(engine, 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);
}
/**
@@ -179,12 +182,16 @@ void DrawRoadVehEngine(int left, int right, int preferred_x, int y, EngineID eng
*/
void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetRoadVehIcon(engine, image_type), ST_NORMAL);
VehicleSpriteSeq seq;
GetRoadVehIcon(engine, image_type, &seq);
width = UnScaleGUI(spr->width);
height = UnScaleGUI(spr->height);
xoffs = UnScaleGUI(spr->x_offs);
yoffs = UnScaleGUI(spr->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);
}
/**
@@ -306,7 +313,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin
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->SetFrontEngine();

View File

@@ -149,7 +149,9 @@ void DrawRoadVehImage(const Vehicle *v, int left, int right, int y, VehicleID se
if (rtl ? px + width > 0 : px - width < max_width) {
PaletteID pal = (u->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(u);
DrawSprite(u->GetImage(dir, image_type), pal, px + (rtl ? -offset.x : offset.x), ScaleGUITrad(6) + offset.y);
VehicleSpriteSeq seq;
u->GetImage(dir, image_type, &seq);
seq.Draw(px + (rtl ? -offset.x : offset.x), ScaleGUITrad(6) + offset.y, pal, u->vehstatus & VS_CRASHED);
}
px += rtl ? -width : width;

View File

@@ -1165,7 +1165,7 @@ static const OldChunks vehicle_chunk[] = {
OCL_SVAR( OC_UINT8, Vehicle, owner ),
OCL_SVAR( OC_TILE, Vehicle, tile ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, cur_image ),
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, sprite_seq.seq[0].sprite ),
OCL_NULL( 8 ), ///< Vehicle sprite box, calculated automatically
@@ -1258,7 +1258,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
if (v == NULL) continue;
v->refit_cap = v->cargo_cap;
SpriteID sprite = v->cur_image;
SpriteID sprite = v->sprite_seq.seq[0].sprite;
/* no need to override other sprites */
if (IsInsideMM(sprite, 1460, 1465)) {
sprite += 580; // aircraft smoke puff
@@ -1269,7 +1269,7 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
} else if (IsInsideMM(sprite, 2516, 2539)) {
sprite += 1385; // rotor or disaster-related vehicles
}
v->cur_image = sprite;
v->sprite_seq.seq[0].sprite = sprite;
switch (v->type) {
case VEH_TRAIN: {

View File

@@ -2674,7 +2674,7 @@ static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
SlSaveChunks();
SaveFileStart();
if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread)) {
if (!threaded || !ThreadObject::New(&SaveFileToDiskThread, NULL, &_save_thread, "ottd:savegame")) {
if (threaded) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode...");
SaveOrLoadResult result = SaveFileToDisk(false);

View File

@@ -436,21 +436,21 @@ void AfterLoadVehicles(bool part_of_load)
case VEH_TRAIN:
case VEH_SHIP:
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
break;
case VEH_AIRCRAFT:
if (Aircraft::From(v)->IsNormalAircraft()) {
v->cur_image = v->GetImage(v->direction, EIT_ON_MAP);
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
/* The plane's shadow will have the same image as the plane */
/* The plane's shadow will have the same image as the plane, but no colour */
Vehicle *shadow = v->Next();
shadow->cur_image = v->cur_image;
shadow->sprite_seq.CopyWithoutPalette(v->sprite_seq);
/* In the case of a helicopter we will update the rotor sprites */
if (v->subtype == AIR_HELICOPTER) {
Vehicle *rotor = shadow->Next();
rotor->cur_image = GetRotorImage(Aircraft::From(v), EIT_ON_MAP);
GetRotorImage(Aircraft::From(v), EIT_ON_MAP, &rotor->sprite_seq);
}
UpdateAircraftCache(Aircraft::From(v), true);
@@ -796,7 +796,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
SLE_CONDVAR(Vehicle, z_pos, SLE_FILE_U8 | SLE_VAR_I32, 0, 163),
SLE_CONDVAR(Vehicle, z_pos, SLE_INT32, 164, SL_MAX_VERSION),
SLE_VAR(Vehicle, cur_image, SLE_FILE_U16 | SLE_VAR_U32),
SLE_VAR(Vehicle, sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
SLE_CONDNULL(5, 0, 57),
SLE_VAR(Vehicle, progress, SLE_UINT8),
SLE_VAR(Vehicle, vehstatus, SLE_UINT8),
@@ -836,7 +836,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
SLE_CONDVAR(Vehicle, current_order.dest, SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
SLE_CONDVAR(Vehicle, current_order.dest, SLE_UINT16, 5, SL_MAX_VERSION),
SLE_VAR(Vehicle, cur_image, SLE_FILE_U16 | SLE_VAR_U32),
SLE_VAR(Vehicle, sprite_seq.seq[0].sprite, SLE_FILE_U16 | SLE_VAR_U32),
SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
SLE_CONDVAR(Vehicle, age, SLE_INT32, 31, SL_MAX_VERSION),
SLE_VAR(Vehicle, tick_counter, SLE_UINT8),

View File

@@ -34,7 +34,7 @@ struct Ship FINAL : public SpecializedVehicle<Ship, VEH_SHIP> {
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_SHIP_INC : EXPENSES_SHIP_RUN; }
void PlayLeaveStationSound() const;
bool IsPrimaryVehicle() const { return true; }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->cur_speed / 2; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed / 2; }
int GetCurrentMaxSpeed() const { return min(this->vcache.cached_max_speed, this->current_order.GetMaxSpeed() * 2); }

View File

@@ -70,30 +70,34 @@ static inline TrackBits GetTileShipTrackStatus(TileIndex tile)
return TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0));
}
static SpriteID GetShipIcon(EngineID engine, EngineImageType image_type)
static void GetShipIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
{
const Engine *e = Engine::Get(engine);
uint8 spritenum = e->u.ship.image_index;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
if (result->IsValid()) return;
spritenum = e->original_image_index;
}
assert(IsValidImageIndex<VEH_SHIP>(spritenum));
return DIR_W + _ship_sprites[spritenum];
result->Set(DIR_W + _ship_sprites[spritenum]);
}
void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
{
SpriteID sprite = GetShipIcon(engine, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
GetShipIcon(engine, 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);
}
/**
@@ -107,27 +111,31 @@ void DrawShipEngine(int left, int right, int preferred_x, int y, EngineID engine
*/
void GetShipSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
{
const Sprite *spr = GetSprite(GetShipIcon(engine, image_type), ST_NORMAL);
VehicleSpriteSeq seq;
GetShipIcon(engine, image_type, &seq);
width = UnScaleGUI(spr->width);
height = UnScaleGUI(spr->height);
xoffs = UnScaleGUI(spr->x_offs);
yoffs = UnScaleGUI(spr->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);
}
SpriteID Ship::GetImage(Direction direction, EngineImageType image_type) const
void Ship::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
{
uint8 spritenum = this->spritenum;
if (is_custom_sprite(spritenum)) {
SpriteID sprite = GetCustomVehicleSprite(this, direction, image_type);
if (sprite != 0) return sprite;
GetCustomVehicleSprite(this, direction, image_type, result);
if (result->IsValid()) return;
spritenum = this->GetEngine()->original_image_index;
}
assert(IsValidImageIndex<VEH_SHIP>(spritenum));
return _ship_sprites[spritenum] + direction;
result->Set(_ship_sprites[spritenum] + direction);
}
static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
@@ -710,7 +718,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, u
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships);
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->UpdateCache();

View File

@@ -35,20 +35,23 @@ void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selec
{
bool rtl = _current_text_dir == TD_RTL;
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
int width = UnScaleGUI(real_sprite->width);
int x_offs = UnScaleGUI(real_sprite->x_offs);
Rect rect;
seq.GetBounds(&rect);
int width = UnScaleGUI(rect.right - rect.left + 1);
int x_offs = UnScaleGUI(rect.left);
int x = rtl ? right - width - x_offs : left - x_offs;
y += ScaleGUITrad(10);
DrawSprite(sprite, GetVehiclePalette(v), x, y);
seq.Draw(x, y, GetVehiclePalette(v), false);
if (v->index == selection) {
x += x_offs;
y += UnScaleGUI(real_sprite->y_offs);
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(real_sprite->height) + 1, COLOUR_WHITE, FR_BORDERONLY);
y += UnScaleGUI(rect.top);
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(rect.bottom - rect.top + 1) + 1, COLOUR_WHITE, FR_BORDERONLY);
}
}

View File

@@ -19,6 +19,7 @@
#include "win32_s.h"
#include <windows.h>
#include <mmsystem.h>
#include "../os/windows/win32.h"
#include "../safeguards.h"
@@ -41,6 +42,8 @@ static void PrepareHeader(WAVEHDR *hdr)
static DWORD WINAPI SoundThread(LPVOID arg)
{
SetWin32ThreadName(-1, "ottd:win-sound");
do {
for (WAVEHDR *hdr = _wave_hdr; hdr != endof(_wave_hdr); hdr++) {
if ((hdr->dwFlags & WHDR_INQUEUE) != 0) continue;

View File

@@ -2897,12 +2897,12 @@ draw_default_foundation:
}
}
if (HasStationRail(ti->tile) && HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
if (HasStationRail(ti->tile) && HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
if (HasBit(roadtypes, ROADTYPE_TRAM)) {
Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
DrawRoadCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
}
if (IsRailWaypoint(ti->tile)) {

View File

@@ -331,7 +331,7 @@ static const uint ELRAIL_ELEVATION = 10;
/** Wires that a draw one level higher than the north corner. */
static const uint ELRAIL_ELEVRAISE = ELRAIL_ELEVATION + TILE_HEIGHT;
static const SortableSpriteStruct CatenarySpriteData[] = {
static const SortableSpriteStruct RailCatenarySpriteData[] = {
/* X direction
* Flat tiles:
* Wires */
@@ -392,14 +392,14 @@ static const SortableSpriteStruct CatenarySpriteData[] = {
{ WSO_EW_E, 15, 8, 3, 3, 1, ELRAIL_ELEVATION } //!33: LOWER trackbit wire, pylon on both ends
};
static const SortableSpriteStruct CatenarySpriteData_Depot[] = {
static const SortableSpriteStruct RailCatenarySpriteData_Depot[] = {
{ WSO_ENTRANCE_NE, 0, 7, 15, 1, 1, ELRAIL_ELEVATION }, //! Wire for NE depot exit
{ WSO_ENTRANCE_SE, 7, 0, 1, 15, 1, ELRAIL_ELEVATION }, //! Wire for SE depot exit
{ WSO_ENTRANCE_SW, 0, 7, 15, 1, 1, ELRAIL_ELEVATION }, //! Wire for SW depot exit
{ WSO_ENTRANCE_NW, 7, 0, 1, 15, 1, ELRAIL_ELEVATION } //! Wire for NW depot exit
};
static const SortableSpriteStruct CatenarySpriteData_Tunnel[] = {
static const SortableSpriteStruct RailCatenarySpriteData_Tunnel[] = {
{ WSO_ENTRANCE_NE, 0, 7, 15, 1, 1, ELRAIL_ELEVATION }, //! Wire for NE tunnel exit
{ WSO_ENTRANCE_SE, 7, 0, 1, 15, 1, ELRAIL_ELEVATION }, //! Wire for SE tunnel exit
{ WSO_ENTRANCE_SW, 0, 7, 15, 1, 1, ELRAIL_ELEVATION }, //! Wire for SW tunnel exit
@@ -419,7 +419,7 @@ static const SortableSpriteStruct CatenarySpriteData_Tunnel[] = {
* <li>Position of the Pylon relative to the track</li>
* <li>Position of the Pylon inside the tile</li></ol>
*/
enum CatenarySprite {
enum RailCatenarySprite {
WIRE_X_FLAT_SW,
WIRE_X_FLAT_NE,
WIRE_X_FLAT_BOTH,
@@ -471,7 +471,7 @@ enum CatenarySprite {
* c) the second
* d) both
* PCP exists.*/
static const CatenarySprite Wires[5][TRACK_END][4] = {
static const RailCatenarySprite Wires[5][TRACK_END][4] = {
{ // Tileh == 0
{INVALID_CATENARY, WIRE_X_FLAT_NE, WIRE_X_FLAT_SW, WIRE_X_FLAT_BOTH},
{INVALID_CATENARY, WIRE_Y_FLAT_SE, WIRE_Y_FLAT_NW, WIRE_Y_FLAT_BOTH},

View File

@@ -44,9 +44,10 @@ public:
* @param proc The procedure to call inside the thread.
* @param param The params to give with 'proc'.
* @param thread Place to store a pointer to the thread in. May be NULL.
* @param name A name for the thread. May be NULL.
* @return True if the thread was started correctly.
*/
static bool New(OTTDThreadFunc proc, void *param, ThreadObject **thread = NULL);
static bool New(OTTDThreadFunc proc, void *param, ThreadObject **thread = NULL, const char *name = NULL);
};
/**

View File

@@ -193,7 +193,7 @@ private:
}
};
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
{
ThreadObject *to = new ThreadObject_MorphOS(proc, param, thread == NULL);
if (thread != NULL) *thread = to;

View File

@@ -14,7 +14,7 @@
#include "../safeguards.h"
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
{
if (thread != NULL) *thread = NULL;
return false;

View File

@@ -83,7 +83,7 @@ private:
}
};
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
{
ThreadObject *to = new ThreadObject_OS2(proc, param, thread == NULL);
if (thread != NULL) *thread = to;

View File

@@ -25,16 +25,18 @@ private:
OTTDThreadFunc proc; ///< External thread procedure.
void *param; ///< Parameter for the external thread procedure.
bool self_destruct; ///< Free ourselves when done?
const char *name; ///< Name for the thread
public:
/**
* Create a pthread and start it, calling proc(param).
*/
ThreadObject_pthread(OTTDThreadFunc proc, void *param, bool self_destruct) :
ThreadObject_pthread(OTTDThreadFunc proc, void *param, bool self_destruct, const char *name) :
thread(0),
proc(proc),
param(param),
self_destruct(self_destruct)
self_destruct(self_destruct),
name(name)
{
pthread_create(&this->thread, NULL, &stThreadProc, this);
}
@@ -60,7 +62,15 @@ private:
*/
static void *stThreadProc(void *thr)
{
((ThreadObject_pthread *)thr)->ThreadProc();
ThreadObject_pthread *self = (ThreadObject_pthread *) thr;
#if defined(__GLIBC__)
#if __GLIBC_PREREQ(2, 12)
if (self->name) {
pthread_setname_np(pthread_self(), self->name);
}
#endif
#endif
self->ThreadProc();
pthread_exit(NULL);
}
@@ -85,9 +95,9 @@ private:
}
};
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
{
ThreadObject *to = new ThreadObject_pthread(proc, param, thread == NULL);
ThreadObject *to = new ThreadObject_pthread(proc, param, thread == NULL, name);
if (thread != NULL) *thread = to;
return true;
}

View File

@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <windows.h>
#include <process.h>
#include "../os/windows/win32.h"
#include "../safeguards.h"
@@ -29,17 +30,19 @@ private:
OTTDThreadFunc proc; ///< External thread procedure.
void *param; ///< Parameter for the external thread procedure.
bool self_destruct; ///< Free ourselves when done?
const char *name; ///< Thread name.
public:
/**
* Create a win32 thread and start it, calling proc(param).
*/
ThreadObject_Win32(OTTDThreadFunc proc, void *param, bool self_destruct) :
ThreadObject_Win32(OTTDThreadFunc proc, void *param, bool self_destruct, const char *name) :
thread(NULL),
id(0),
proc(proc),
param(param),
self_destruct(self_destruct)
self_destruct(self_destruct),
name(name)
{
this->thread = (HANDLE)_beginthreadex(NULL, 0, &stThreadProc, this, CREATE_SUSPENDED, &this->id);
if (this->thread == NULL) return;
@@ -85,6 +88,10 @@ private:
*/
void ThreadProc()
{
#ifdef _MSC_VER
/* Set thread name for debuggers. Has to be done from the thread due to a race condition in older MS debuggers. */
SetWin32ThreadName(-1, this->name);
#endif
try {
this->proc(this->param);
} catch (OTTDThreadExitSignal) {
@@ -96,9 +103,9 @@ private:
}
};
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread)
/* static */ bool ThreadObject::New(OTTDThreadFunc proc, void *param, ThreadObject **thread, const char *name)
{
ThreadObject *to = new ThreadObject_Win32(proc, param, thread == NULL);
ThreadObject *to = new ThreadObject_Win32(proc, param, thread == NULL, name);
if (thread != NULL) *thread = to;
return true;
}

View File

@@ -1469,36 +1469,302 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
{
static const uint SMALLEST_ARRANGEMENT = 14;
static const uint BIGGEST_ARRANGEMENT = 20;
/* The number of buttons of each row of the toolbar should match the number of items which we want to be visible.
* The total number of buttons should be equal to arrangable_count * 2.
* No bad things happen, but we could see strange behaviours if we have buttons < (arrangable_count * 2) like a
* pause button appearing on the right of the lower toolbar and weird resizing of the widgets even if there is
* enough space.
*/
static const byte arrange14[] = {
0, 1, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 29,
2, 3, 4, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_SETTINGS,
WID_TN_SAVE,
WID_TN_SMALL_MAP,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_GRAPHS,
WID_TN_INDUSTRIES,
WID_TN_MUSIC_SOUND,
WID_TN_MESSAGES,
WID_TN_HELP,
WID_TN_SWITCH_BAR,
};
static const byte arrange15[] = {
0, 1, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
0, 2, 4, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SMALL_MAP,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_PAUSE,
WID_TN_SETTINGS,
WID_TN_SMALL_MAP,
WID_TN_SAVE,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_GRAPHS,
WID_TN_INDUSTRIES,
WID_TN_MUSIC_SOUND,
WID_TN_MESSAGES,
WID_TN_HELP,
WID_TN_SWITCH_BAR,
};
static const byte arrange16[] = {
0, 1, 2, 4, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
0, 1, 3, 5, 6, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SETTINGS,
WID_TN_SMALL_MAP,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SAVE,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_GRAPHS,
WID_TN_INDUSTRIES,
WID_TN_MUSIC_SOUND,
WID_TN_MESSAGES,
WID_TN_HELP,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
};
static const byte arrange17[] = {
0, 1, 2, 4, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 19, 20, 29,
0, 1, 3, 4, 6, 5, 7, 8, 9, 12, 14, 26, 27, 28, 19, 20, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SETTINGS,
WID_TN_SMALL_MAP,
WID_TN_SUBSIDIES,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SAVE,
WID_TN_SMALL_MAP,
WID_TN_SUBSIDIES,
WID_TN_TOWNS,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_GRAPHS,
WID_TN_INDUSTRIES,
WID_TN_MUSIC_SOUND,
WID_TN_MESSAGES,
WID_TN_HELP,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
};
static const byte arrange18[] = {
0, 1, 2, 4, 5, 6, 7, 8, 9, 14, 21, 22, 23, 24, 25, 19, 20, 29,
0, 1, 3, 4, 5, 6, 7, 12, 15, 16, 17, 18, 26, 27, 28, 19, 20, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SETTINGS,
WID_TN_SMALL_MAP,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_INDUSTRIES,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SAVE,
WID_TN_SMALL_MAP,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_STATIONS,
WID_TN_GRAPHS,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_MUSIC_SOUND,
WID_TN_MESSAGES,
WID_TN_HELP,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
};
static const byte arrange19[] = {
0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 19, 20, 29,
0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 28, 19, 20, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SETTINGS,
WID_TN_SMALL_MAP,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_MUSIC_SOUND,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SAVE,
WID_TN_SMALL_MAP,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_GRAPHS,
WID_TN_INDUSTRIES,
WID_TN_MESSAGES,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_HELP,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
};
static const byte arrange20[] = {
0, 1, 2, 4, 5, 6, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 11, 19, 20, 29,
0, 1, 3, 4, 7, 8, 9, 12, 14, 27, 21, 22, 23, 24, 25, 10, 28, 19, 20, 29,
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SETTINGS,
WID_TN_SMALL_MAP,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_MUSIC_SOUND,
WID_TN_GOAL,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
// lower toolbar
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SAVE,
WID_TN_SMALL_MAP,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_GRAPHS,
WID_TN_INDUSTRIES,
WID_TN_MESSAGES,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_STORY,
WID_TN_HELP,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_SWITCH_BAR,
};
static const byte arrange_all[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
WID_TN_PAUSE,
WID_TN_FAST_FORWARD,
WID_TN_SETTINGS,
WID_TN_SAVE,
WID_TN_SMALL_MAP,
WID_TN_TOWNS,
WID_TN_SUBSIDIES,
WID_TN_STATIONS,
WID_TN_FINANCES,
WID_TN_COMPANIES,
WID_TN_STORY,
WID_TN_GOAL,
WID_TN_GRAPHS,
WID_TN_LEAGUE,
WID_TN_INDUSTRIES,
WID_TN_TRAINS,
WID_TN_ROADVEHS,
WID_TN_SHIPS,
WID_TN_AIRCRAFTS,
WID_TN_ZOOM_IN,
WID_TN_ZOOM_OUT,
WID_TN_RAILS,
WID_TN_ROADS,
WID_TN_WATER,
WID_TN_AIR,
WID_TN_LANDSCAPE,
WID_TN_MUSIC_SOUND,
WID_TN_MESSAGES,
WID_TN_HELP
};
/* If at least BIGGEST_ARRANGEMENT fit, just spread all the buttons nicely */
@@ -1540,14 +1806,65 @@ class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
/* virtual */ const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const
{
static const byte arrange_all[] = {
0, 1, 2, 3, 4, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
WID_TE_PAUSE,
WID_TE_FAST_FORWARD,
WID_TE_SETTINGS,
WID_TE_SAVE,
WID_TE_SPACER,
WID_TE_DATE_PANEL,
WID_TE_SMALL_MAP,
WID_TE_ZOOM_IN,
WID_TE_ZOOM_OUT,
WID_TE_LAND_GENERATE,
WID_TE_TOWN_GENERATE,
WID_TE_INDUSTRY,
WID_TE_ROADS,
WID_TE_WATER,
WID_TE_TREES,
WID_TE_SIGNS,
WID_TE_MUSIC_SOUND,
WID_TE_HELP,
};
static const byte arrange_nopanel[] = {
0, 1, 2, 3, 18, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 26, 28,
WID_TE_PAUSE,
WID_TE_FAST_FORWARD,
WID_TE_SETTINGS,
WID_TE_SAVE,
WID_TE_DATE_PANEL,
WID_TE_SMALL_MAP,
WID_TE_ZOOM_IN,
WID_TE_ZOOM_OUT,
WID_TE_LAND_GENERATE,
WID_TE_TOWN_GENERATE,
WID_TE_INDUSTRY,
WID_TE_ROADS,
WID_TE_WATER,
WID_TE_TREES,
WID_TE_SIGNS,
WID_TE_MUSIC_SOUND,
WID_TE_HELP,
};
static const byte arrange_switch[] = {
18, 8, 11, 12, 13, 14, 15, 16, 17, 29,
0, 1, 2, 3, 18, 9, 10, 26, 28, 29,
WID_TE_DATE_PANEL,
WID_TE_SMALL_MAP,
WID_TE_LAND_GENERATE,
WID_TE_TOWN_GENERATE,
WID_TE_INDUSTRY,
WID_TE_ROADS,
WID_TE_WATER,
WID_TE_TREES,
WID_TE_SIGNS,
WID_TE_SWITCH_BAR,
// lower toolbar
WID_TE_PAUSE,
WID_TE_FAST_FORWARD,
WID_TE_SETTINGS,
WID_TE_SAVE,
WID_TE_DATE_PANEL,
WID_TE_ZOOM_IN,
WID_TE_ZOOM_OUT,
WID_TE_MUSIC_SOUND,
WID_TE_HELP, WID_TE_SWITCH_BAR,
};
/* If we can place all buttons *and* the panels, show them. */
@@ -1901,7 +2218,14 @@ static NWidgetBase *MakeMainToolbar(int *biggest_index)
NWidgetMainToolbarContainer *hor = new NWidgetMainToolbarContainer();
for (uint i = 0; i < WID_TN_END; i++) {
switch (i) {
case 4: case 8: case 15: case 19: case 21: case 26: hor->Add(new NWidgetSpacer(0, 0)); break;
case WID_TN_SMALL_MAP:
case WID_TN_FINANCES:
case WID_TN_VEHICLE_START:
case WID_TN_ZOOM_IN:
case WID_TN_BUILDING_TOOLS_START:
case WID_TN_MUSIC_SOUND:
hor->Add(new NWidgetSpacer(0, 0));
break;
}
hor->Add(new NWidgetLeaf(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, toolbar_button_sprites[i], STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i));
}

View File

@@ -114,7 +114,7 @@ struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
void PlayLeaveStationSound() const;
bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
int GetDisplaySpeed() const { return this->gcache.last_speed; }
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
Money GetRunningCost() const;

View File

@@ -482,41 +482,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 +523,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 +532,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 +573,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 +647,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 +715,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 +781,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);
@@ -3521,14 +3530,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);

View File

@@ -124,7 +124,9 @@ void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID select
if (rtl ? px + width > 0 : px - width < max_width) {
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(v->GetImage(dir, image_type), pal, px + (rtl ? -offset.x : offset.x), height / 2 + offset.y);
VehicleSpriteSeq seq;
v->GetImage(dir, image_type, &seq);
seq.Draw(px + (rtl ? -offset.x : offset.x), height / 2 + offset.y, pal, v->vehstatus & VS_CRASHED);
}
if (!v->IsArticulatedPart()) sel_articulated = false;
@@ -383,7 +385,9 @@ void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_po
pitch = ScaleGUITrad(e->GetGRF()->traininfo_vehicle_pitch);
}
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
DrawSprite(u->GetImage(dir, EIT_IN_DETAILS), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + pitch);
VehicleSpriteSeq seq;
u->GetImage(dir, EIT_IN_DETAILS, &seq);
seq.Draw(px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + pitch, pal, v->vehstatus & VS_CRASHED);
}
px += rtl ? -width : width;
dx += width;

View File

@@ -1216,14 +1216,14 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
}
}
if (HasCatenaryDrawn(GetRailType(ti->tile))) {
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) {
/* Maybe draw pylons on the entry side */
DrawCatenary(ti);
DrawRailCatenary(ti);
catenary = true;
StartSpriteCombine();
/* Draw wire above the ramp */
DrawCatenaryOnTunnel(ti);
DrawRailCatenaryOnTunnel(ti);
}
}
@@ -1341,8 +1341,8 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
}
EndSpriteCombine();
if (HasCatenaryDrawn(GetRailType(ti->tile))) {
DrawCatenary(ti);
if (HasRailCatenaryDrawn(GetRailType(ti->tile))) {
DrawRailCatenary(ti);
}
}
@@ -1392,7 +1392,7 @@ void DrawBridgeMiddle(const TileInfo *ti)
{
/* Sectional view of bridge bounding boxes:
*
* 1 2 1,2 = SpriteCombine of Bridge front/(back&floor) and TramCatenary
* 1 2 1,2 = SpriteCombine of Bridge front/(back&floor) and RoadCatenary
* 1 2 3 = empty helper BB
* 1 7 2 4,5 = pillars under higher bridges
* 1 6 88888 6 2 6 = elrail-pylons
@@ -1491,8 +1491,8 @@ void DrawBridgeMiddle(const TileInfo *ti)
EndSpriteCombine();
if (HasCatenaryDrawn(GetRailType(rampsouth))) {
DrawCatenaryOnBridge(ti);
if (HasRailCatenaryDrawn(GetRailType(rampsouth))) {
DrawRailCatenaryOnBridge(ti);
}
}

View File

@@ -68,6 +68,47 @@ uint16 _returned_mail_refit_capacity; ///< Stores the mail capacity after a refi
VehiclePool _vehicle_pool("Vehicle");
INSTANTIATE_POOL_METHODS(Vehicle)
/**
* Determine shared bounds of all sprites.
* @param [out] bounds Shared bounds.
*/
void VehicleSpriteSeq::GetBounds(Rect *bounds) const
{
bounds->left = bounds->top = bounds->right = bounds->bottom = 0;
for (uint i = 0; i < this->count; ++i) {
const Sprite *spr = GetSprite(this->seq[i].sprite, ST_NORMAL);
if (i == 0) {
bounds->left = spr->x_offs;
bounds->top = spr->y_offs;
bounds->right = spr->width + spr->x_offs - 1;
bounds->bottom = spr->height + spr->y_offs - 1;
} else {
if (spr->x_offs < bounds->left) bounds->left = spr->x_offs;
if (spr->y_offs < bounds->top) bounds->top = spr->y_offs;
int right = spr->width + spr->x_offs - 1;
int bottom = spr->height + spr->y_offs - 1;
if (right > bounds->right) bounds->right = right;
if (bottom > bounds->bottom) bounds->bottom = bottom;
}
}
}
/**
* Draw the sprite sequence.
* @param x X position
* @param y Y position
* @param default_pal Vehicle palette
* @param force_pal Whether to ignore individual palettes, and draw everything with \a default_pal.
*/
void VehicleSpriteSeq::Draw(int x, int y, PaletteID default_pal, bool force_pal) const
{
for (uint i = 0; i < this->count; ++i) {
PaletteID pal = force_pal || !this->seq[i].pal ? default_pal : this->seq[i].pal;
DrawSprite(this->seq[i].sprite, pal, x, y);
}
}
/**
* Function to tell if a vehicle needs to be autorenewed
* @param *c The vehicle owner
@@ -1008,7 +1049,6 @@ void CallVehicleTicks()
*/
static void DoDrawVehicle(const Vehicle *v)
{
SpriteID image = v->cur_image;
PaletteID pal = PAL_NONE;
if (v->vehstatus & VS_DEFPAL) pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
@@ -1023,9 +1063,15 @@ static void DoDrawVehicle(const Vehicle *v)
if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
}
AddSortableSpriteToDraw(image, pal, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
StartSpriteCombine();
for (uint i = 0; i < v->sprite_seq.count; ++i) {
PaletteID pal2 = v->sprite_seq.seq[i].pal;
if (!pal2 || (v->vehstatus & VS_CRASHED)) pal2 = pal;
AddSortableSpriteToDraw(v->sprite_seq.seq[i].sprite, pal2, v->x_pos + v->x_offs, v->y_pos + v->y_offs,
v->x_extent, v->y_extent, v->z_extent, v->z_pos, shadowed, v->x_bb_offs, v->y_bb_offs);
}
EndSpriteCombine();
}
/**
* Add the vehicle sprites that should be drawn at a part of the screen.
@@ -1487,20 +1533,19 @@ void Vehicle::UpdatePosition()
*/
void Vehicle::UpdateViewport(bool dirty)
{
int img = this->cur_image;
Rect new_coord;
this->sprite_seq.GetBounds(&new_coord);
Point pt = RemapCoords(this->x_pos + this->x_offs, this->y_pos + this->y_offs, this->z_pos);
const Sprite *spr = GetSprite(img, ST_NORMAL);
new_coord.left += pt.x;
new_coord.top += pt.y;
new_coord.right += pt.x + 2 * ZOOM_LVL_BASE;
new_coord.bottom += pt.y + 2 * ZOOM_LVL_BASE;
pt.x += spr->x_offs;
pt.y += spr->y_offs;
UpdateVehicleViewportHash(this, pt.x, pt.y);
UpdateVehicleViewportHash(this, new_coord.left, new_coord.top);
Rect old_coord = this->coord;
this->coord.left = pt.x;
this->coord.top = pt.y;
this->coord.right = pt.x + spr->width + 2 * ZOOM_LVL_BASE;
this->coord.bottom = pt.y + spr->height + 2 * ZOOM_LVL_BASE;
this->coord = new_coord;
if (dirty) {
if (old_coord.left == INVALID_COORD) {

View File

@@ -126,6 +126,63 @@ struct VehicleCache {
byte cached_vis_effect; ///< Visual effect to show (see #VisualEffect)
};
/** Sprite sequence for a vehicle part. */
struct VehicleSpriteSeq {
PalSpriteID seq[4];
uint count;
bool operator==(const VehicleSpriteSeq &other) const
{
return this->count == other.count && MemCmpT<PalSpriteID>(this->seq, other.seq, this->count) == 0;
}
bool operator!=(const VehicleSpriteSeq &other) const
{
return !this->operator==(other);
}
/**
* Check whether the sequence contains any sprites.
*/
bool IsValid() const
{
return this->count != 0;
}
/**
* Clear all information.
*/
void Clear()
{
this->count = 0;
}
/**
* Assign a single sprite to the sequence.
*/
void Set(SpriteID sprite)
{
this->count = 1;
this->seq[0].sprite = sprite;
this->seq[0].pal = 0;
}
/**
* Copy data from another sprite sequence, while dropping all recolouring information.
*/
void CopyWithoutPalette(const VehicleSpriteSeq &src)
{
this->count = src.count;
for (uint i = 0; i < src.count; ++i) {
this->seq[i].sprite = src.seq[i].sprite;
this->seq[i].pal = 0;
}
}
void GetBounds(Rect *bounds) const;
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const;
};
/** A vehicle pool for a little over 1 million vehicles. */
typedef Pool<Vehicle, VehicleID, 512, 0xFF000> VehiclePool;
extern VehiclePool _vehicle_pool;
@@ -220,7 +277,7 @@ public:
* 0xff == reserved for another custom sprite
*/
byte spritenum;
SpriteID cur_image; ///< sprite number for this vehicle
VehicleSpriteSeq sprite_seq; ///< Vehicle appearance.
byte x_extent; ///< x-extent of vehicle bounding box
byte y_extent; ///< y-extent of vehicle bounding box
byte z_extent; ///< z-extent of vehicle bounding box
@@ -380,9 +437,9 @@ public:
/**
* Gets the sprite to show for the given direction
* @param direction the direction the vehicle is facing
* @return the sprite for the given vehicle in the given direction
* @param [out] result Vehicle sprite sequence.
*/
virtual SpriteID GetImage(Direction direction, EngineImageType image_type) const { return 0; }
virtual void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const { result->Clear(); }
const GRFFile *GetGRF() const;
uint32 GetGRFID() const;
@@ -940,7 +997,10 @@ struct SpecializedVehicle : public Vehicle {
/**
* Set vehicle type correctly
*/
inline SpecializedVehicle<T, Type>() : Vehicle(Type) { }
inline SpecializedVehicle<T, Type>() : Vehicle(Type)
{
this->sprite_seq.count = 1;
}
/**
* Get the first vehicle in the chain
@@ -1079,9 +1139,12 @@ struct SpecializedVehicle : public Vehicle {
/* Explicitly choose method to call to prevent vtable dereference -
* it gives ~3% runtime improvements in games with many vehicles */
if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
SpriteID old_image = this->cur_image;
this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
if (force_update || this->cur_image != old_image) this->Vehicle::UpdateViewport(true);
VehicleSpriteSeq seq;
((T *)this)->T::GetImage(this->direction, EIT_ON_MAP, &seq);
if (force_update || this->sprite_seq != seq) {
this->sprite_seq = seq;
this->Vehicle::UpdateViewport(true);
}
}
};

View File

@@ -606,7 +606,7 @@ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32
bool vehicle_list_window = HasBit(p1, 1);
VehicleListIdentifier vli;
if (!vli.Unpack(p2)) return CMD_ERROR;
if (!vli.UnpackIfValid(p2)) return CMD_ERROR;
if (!IsCompanyBuildableVehicleType(vli.vtype)) return CMD_ERROR;
if (vehicle_list_window) {
@@ -1001,7 +1001,7 @@ CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1
if (p1 & DEPOT_MASS_SEND) {
/* Mass goto depot requested */
VehicleListIdentifier vli;
if (!vli.Unpack(p2)) return CMD_ERROR;
if (!vli.UnpackIfValid(p2)) return CMD_ERROR;
return SendAllVehiclesToDepot(flags, (p1 & DEPOT_SERVICE) != 0, vli);
}

View File

@@ -1638,7 +1638,7 @@ public:
break;
case WID_VL_MANAGE_VEHICLES_DROPDOWN: {
DropDownList *list = this->BuildActionDropdownList(VehicleListIdentifier(this->window_number).type == VL_STANDARD, false);
DropDownList *list = this->BuildActionDropdownList(VehicleListIdentifier::UnPack(this->window_number).type == VL_STANDARD, false);
ShowDropDownList(this, list, 0, WID_VL_MANAGE_VEHICLES_DROPDOWN);
break;
}
@@ -2100,9 +2100,7 @@ struct VehicleDetailsWindow : Window {
case WID_VD_MIDDLE_DETAILS: {
/* For other vehicles, at the place of the matrix. */
bool rtl = _current_text_dir == TD_RTL;
uint sprite_width = UnScaleGUI(
max<uint>(GetSprite(v->GetImage(rtl ? DIR_E : DIR_W, EIT_IN_DETAILS), ST_NORMAL)->width, 70U)) +
WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
uint sprite_width = GetSingleVehicleWidth(v, EIT_IN_DETAILS) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
uint text_left = r.left + (rtl ? 0 : sprite_width);
uint text_right = r.right - (rtl ? sprite_width : 0);
@@ -2372,8 +2370,8 @@ static const uint32 _vehicle_command_translation_table[][4] = {
};
/**
* This is the Callback method after the cloning attempt of a vehicle
* @param result the result of the cloning command
* This is the Callback method after attempting to start/stop a vehicle
* @param result the result of the start/stop command
* @param tile unused
* @param p1 vehicle ID
* @param p2 unused
@@ -2844,9 +2842,11 @@ int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
default:
bool rtl = _current_text_dir == TD_RTL;
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
return UnScaleGUI(real_sprite->width);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
Rect rec;
seq.GetBounds(&rec);
return UnScaleGUI(rec.right - rec.left + 1);
}
}
@@ -2880,16 +2880,24 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
_cursor.sprite_count = 0;
int total_width = 0;
for (; v != NULL; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : NULL) {
if (_cursor.sprite_count == lengthof(_cursor.sprite_seq)) break;
if (total_width >= 2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH) break;
_cursor.sprite_seq[_cursor.sprite_count].sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
_cursor.sprite_seq[_cursor.sprite_count].pal = GetVehiclePalette(v);
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
VehicleSpriteSeq seq;
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
for (uint i = 0; i < seq.count; ++i) {
PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
_cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite;
_cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width;
_cursor.sprite_pos[_cursor.sprite_count].y = 0;
_cursor.sprite_count++;
}
total_width += GetSingleVehicleWidth(v, image_type);
_cursor.sprite_count++;
}
int offs = ((int)VEHICLEINFO_FULL_VEHICLE_WIDTH - total_width) / 2;

View File

@@ -38,7 +38,7 @@ struct BaseVehicleListWindow : public Window {
static const StringID vehicle_sorter_names[];
static GUIVehicleList::SortFunction * const vehicle_sorter_funcs[];
BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno) : Window(desc), vli(wno)
BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno) : Window(desc), vli(VehicleListIdentifier::UnPack(wno))
{
this->vehicles.SetSortFuncs(this->vehicle_sorter_funcs);
}

View File

@@ -37,7 +37,7 @@ uint32 VehicleListIdentifier::Pack() const
* @param data The data to unpack.
* @return true iff the data was valid (enough).
*/
bool VehicleListIdentifier::Unpack(uint32 data)
bool VehicleListIdentifier::UnpackIfValid(uint32 data)
{
byte c = GB(data, 28, 4);
this->company = c == 0xF ? OWNER_NONE : (CompanyID)c;
@@ -52,10 +52,12 @@ bool VehicleListIdentifier::Unpack(uint32 data)
* Decode a packed vehicle list identifier into a new one.
* @param data The data to unpack.
*/
VehicleListIdentifier::VehicleListIdentifier(uint32 data)
/* static */ VehicleListIdentifier VehicleListIdentifier::UnPack(uint32 data)
{
bool ret = this->Unpack(data);
VehicleListIdentifier result;
bool ret = result.UnpackIfValid(data);
assert(ret);
return result;
}
/**

View File

@@ -35,7 +35,8 @@ struct VehicleListIdentifier {
uint32 index; ///< A vehicle list type specific index.
uint32 Pack() const;
bool Unpack(uint32 data);
bool UnpackIfValid(uint32 data);
static VehicleListIdentifier UnPack(uint32 data);
/**
* Create a simple vehicle list.
@@ -47,7 +48,7 @@ struct VehicleListIdentifier {
VehicleListIdentifier(VehicleListType type, VehicleType vtype, CompanyID company, uint index = 0) :
type(type), vtype(vtype), company(company), index(index) {}
VehicleListIdentifier(uint32 data = 0);
VehicleListIdentifier() : type(), vtype(), company(), index() {}
};
/** A list of vehicles. */

View File

@@ -110,14 +110,22 @@ static CGColorSpaceRef QZ_GetCorrectColorSpace()
static CGColorSpaceRef colorSpace = NULL;
if (colorSpace == NULL) {
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (MacOSVersionIsAtLeast(10, 5, 0)) {
colorSpace = CGDisplayCopyColorSpace(CGMainDisplayID());
} else
#endif
{
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !defined(HAVE_OSX_1011_SDK)
CMProfileRef sysProfile;
if (CMGetSystemProfile(&sysProfile) == noErr) {
colorSpace = CGColorSpaceCreateWithPlatformColorSpace(sysProfile);
CMCloseProfile(sysProfile);
} else {
colorSpace = CGColorSpaceCreateDeviceRGB();
}
#endif
}
if (colorSpace == NULL) colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL) error("Could not get system colour space. You might need to recalibrate your monitor.");
}

View File

@@ -84,6 +84,7 @@ static void DedicatedSignalHandler(int sig)
# endif
# include <time.h>
# include <tchar.h>
# include "../os/windows/win32.h"
static HANDLE _hInputReady, _hWaitForInputHandling;
static HANDLE _hThread; // Thread to close
static char _win_console_thread_buffer[200];
@@ -95,6 +96,8 @@ static void WINAPI CheckForConsoleInput()
/* WinCE doesn't support console stuff */
return;
#else
SetWin32ThreadName(-1, "ottd:win-console");
DWORD nb;
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
for (;;) {

View File

@@ -687,7 +687,7 @@ void VideoDriver_SDL::MainLoop()
_draw_mutex->BeginCritical();
_draw_continue = true;
_draw_threaded = ThreadObject::New(&DrawSurfaceToScreenThread, NULL, &_draw_thread);
_draw_threaded = ThreadObject::New(&DrawSurfaceToScreenThread, NULL, &_draw_thread, "ottd:draw-sdl");
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {

View File

@@ -1199,7 +1199,7 @@ void VideoDriver_Win32::MainLoop()
_draw_threaded = false;
} else {
_draw_continue = true;
_draw_threaded = ThreadObject::New(&PaintWindowThread, NULL, &_draw_thread);
_draw_threaded = ThreadObject::New(&PaintWindowThread, NULL, &_draw_thread, "ottd:draw-win32");
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {

View File

@@ -36,7 +36,8 @@ enum ToolbarNormalWidgets {
WID_TN_AIRCRAFTS, ///< Aircraft menu.
WID_TN_ZOOM_IN, ///< Zoom in the main viewport.
WID_TN_ZOOM_OUT, ///< Zoom out the main viewport.
WID_TN_RAILS, ///< Rail building menu.
WID_TN_BUILDING_TOOLS_START, ///< Helper for the offset of the building tools
WID_TN_RAILS = WID_TN_BUILDING_TOOLS_START, ///< Rail building menu.
WID_TN_ROADS, ///< Road building menu.
WID_TN_WATER, ///< Water building toolbar.
WID_TN_AIR, ///< Airport building toolbar.