mirror of https://github.com/OpenTTD/OpenTTD.git
Compare commits
8 Commits
c458d3e163
...
c319246715
Author | SHA1 | Date |
---|---|---|
Peter Nelson | c319246715 | |
Peter Nelson | bf8de188ec | |
Peter Nelson | 72c55128d2 | |
Peter Nelson | a6d401debf | |
Peter Nelson | 6b8db74afd | |
Peter Nelson | 879f06540f | |
Peter Nelson | 52ad5d86f7 | |
Peter Nelson | 6e98c5c26a |
|
@ -2043,11 +2043,11 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
|||
const uint8_t *layout = buf->ReadBytes(length * number);
|
||||
statspec->layouts[length - 1][number - 1].assign(layout, layout + length * number);
|
||||
|
||||
/* Validate tile values are only the permitted 00, 02, 04 and 06. */
|
||||
/* Ensure the first bit, axis, is zero. The rest of the value is validated during rendering, as we don't know the range yet. */
|
||||
for (auto &tile : statspec->layouts[length - 1][number - 1]) {
|
||||
if ((tile & 6) != tile) {
|
||||
if ((tile & ~1U) != tile) {
|
||||
GrfMsg(1, "StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
|
||||
tile &= 6;
|
||||
tile &= ~1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2070,9 +2070,18 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
|||
statspec->cargo_threshold = buf->ReadWord();
|
||||
break;
|
||||
|
||||
case 0x11: // Pylon placement
|
||||
statspec->pylons = buf->ReadByte();
|
||||
case 0x11: { // Pylon placement
|
||||
uint8_t pylons = buf->ReadByte();
|
||||
if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
if (HasBit(pylons, j)) {
|
||||
statspec->tileflags[j] |= StationSpec::TileFlags::Pylons;
|
||||
} else {
|
||||
statspec->tileflags[j] &= ~StationSpec::TileFlags::Pylons;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x12: // Cargo types for random triggers
|
||||
if (_cur.grffile->grf_version >= 7) {
|
||||
|
@ -2086,13 +2095,31 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
|||
statspec->flags = buf->ReadByte();
|
||||
break;
|
||||
|
||||
case 0x14: // Overhead wire placement
|
||||
statspec->wires = buf->ReadByte();
|
||||
case 0x14: { // Overhead wire placement
|
||||
uint8_t wires = buf->ReadByte();
|
||||
if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
if (HasBit(wires, j)) {
|
||||
statspec->tileflags[j] |= StationSpec::TileFlags::NoWires;
|
||||
} else {
|
||||
statspec->tileflags[j] &= ~StationSpec::TileFlags::NoWires;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x15: // Blocked tiles
|
||||
statspec->blocked = buf->ReadByte();
|
||||
case 0x15: { // Blocked tiles
|
||||
uint8_t blocked = buf->ReadByte();
|
||||
if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
if (HasBit(blocked, j)) {
|
||||
statspec->tileflags[j] |= StationSpec::TileFlags::Blocked;
|
||||
} else {
|
||||
statspec->tileflags[j] &= ~StationSpec::TileFlags::Blocked;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x16: // Animation info
|
||||
statspec->animation.frames = buf->ReadByte();
|
||||
|
@ -2144,6 +2171,13 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
|||
AddStringForMapping(buf->ReadWord(), [statspec](StringID str) { StationClass::Get(statspec->cls_id)->name = str; });
|
||||
break;
|
||||
|
||||
case 0x1E: { // Extended tile flags (replaces prop 11, 14 and 15)
|
||||
uint16_t tiles = buf->ReadExtendedByte();
|
||||
auto flags = reinterpret_cast<const StationSpec::TileFlags *>(buf->ReadBytes(tiles));
|
||||
statspec->tileflags.assign(flags, flags + tiles);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = CIR_UNKNOWN;
|
||||
break;
|
||||
|
@ -4846,7 +4880,6 @@ static ChangeInfoResult RoadStopChangeInfo(uint id, int numinfo, int prop, ByteR
|
|||
|
||||
uint32_t classid = buf->ReadDWord();
|
||||
rs->cls_id = RoadStopClass::Allocate(BSWAP32(classid));
|
||||
rs->spec_id = id + i;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ enum CallbackID {
|
|||
/** Determine whether a newstation should be made available to build. */
|
||||
CBID_STATION_AVAILABILITY = 0x13, // 8 bit callback
|
||||
|
||||
/** Choose a sprite layout to draw, instead of the standard 0-7 range. */
|
||||
CBID_STATION_SPRITE_LAYOUT = 0x14,
|
||||
/** Choose a tile layout to draw, instead of the standard range. */
|
||||
CBID_STATION_DRAW_TILE_LAYOUT = 0x14,
|
||||
|
||||
/**
|
||||
* Refit capacity, the passed vehicle needs to have its ->cargo_type set to
|
||||
|
@ -93,7 +93,7 @@ enum CallbackID {
|
|||
CBID_VEHICLE_ADDITIONAL_TEXT = 0x23,
|
||||
|
||||
/** Called when building a station to customize the tile layout */
|
||||
CBID_STATION_TILE_LAYOUT = 0x24, // 15 bit callback
|
||||
CBID_STATION_BUILD_TILE_LAYOUT = 0x24, // 15 bit callback
|
||||
|
||||
/** Called for periodically starting or stopping the animation. */
|
||||
CBID_INDTILE_ANIM_START_STOP = 0x25, // 15 bit callback
|
||||
|
@ -308,7 +308,7 @@ enum VehicleCallbackMask {
|
|||
*/
|
||||
enum StationCallbackMask {
|
||||
CBM_STATION_AVAIL = 0, ///< Availability of station in construction window
|
||||
CBM_STATION_SPRITE_LAYOUT = 1, ///< Use callback to select a sprite layout to use
|
||||
CBM_STATION_DRAW_TILE_LAYOUT = 1, ///< Use callback to select a tile layout to use when drawing.
|
||||
CBM_STATION_ANIMATION_NEXT_FRAME = 2, ///< Use a custom next frame callback
|
||||
CBM_STATION_ANIMATION_SPEED = 3, ///< Customize the animation speed of the station
|
||||
CBM_STATION_SLOPE_CHECK = 4, ///< Check slope of new station tiles
|
||||
|
|
|
@ -308,25 +308,15 @@ bool Convert8bitBooleanCallback(const struct GRFFile *grffile, uint16_t cbid, ui
|
|||
*/
|
||||
template <size_t Tcnt>
|
||||
struct GRFFilePropsBase {
|
||||
GRFFilePropsBase() : local_id(0), grffile(nullptr)
|
||||
{
|
||||
/* The lack of some compilers to provide default constructors complying to the specs
|
||||
* requires us to zero the stuff ourself. */
|
||||
memset(spritegroup, 0, sizeof(spritegroup));
|
||||
}
|
||||
|
||||
uint16_t local_id; ///< id defined by the grf file for this entity
|
||||
const struct GRFFile *grffile; ///< grf file that introduced this entity
|
||||
const struct SpriteGroup *spritegroup[Tcnt]; ///< pointer to the different sprites of the entity
|
||||
uint16_t local_id = 0; ///< id defined by the grf file for this entity
|
||||
const struct GRFFile *grffile = nullptr; ///< grf file that introduced this entity
|
||||
std::array<const struct SpriteGroup *, Tcnt> spritegroup{}; ///< pointers to the different sprites of the entity
|
||||
};
|
||||
|
||||
/** Data related to the handling of grf files. */
|
||||
struct GRFFileProps : GRFFilePropsBase<1> {
|
||||
/** Set all default data constructor for the props. */
|
||||
GRFFileProps(uint16_t subst_id = 0) :
|
||||
GRFFilePropsBase<1>(), subst_id(subst_id), override(subst_id)
|
||||
{
|
||||
}
|
||||
constexpr GRFFileProps(uint16_t subst_id = 0) : subst_id(subst_id), override(subst_id) {}
|
||||
|
||||
uint16_t subst_id;
|
||||
uint16_t override; ///< id of the entity been replaced by
|
||||
|
|
|
@ -53,7 +53,7 @@ const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, Eng
|
|||
void SetCustomEngineSprites(EngineID engine, uint8_t cargo, const SpriteGroup *group)
|
||||
{
|
||||
Engine *e = Engine::Get(engine);
|
||||
assert(cargo < lengthof(e->grf_prop.spritegroup));
|
||||
assert(cargo < std::size(e->grf_prop.spritegroup));
|
||||
|
||||
if (e->grf_prop.spritegroup[cargo] != nullptr) {
|
||||
GrfMsg(6, "SetCustomEngineSprites: engine {} cargo {} already has group -- replacing", engine, cargo);
|
||||
|
@ -1062,7 +1062,7 @@ VehicleResolverObject::VehicleResolverObject(EngineID engine_type, const Vehicle
|
|||
if (this->root_spritegroup == nullptr) {
|
||||
const Engine *e = Engine::Get(engine_type);
|
||||
CargoID cargo = v != nullptr ? v->cargo_type : SpriteGroupCargo::SG_PURCHASE;
|
||||
assert(cargo < lengthof(e->grf_prop.spritegroup));
|
||||
assert(cargo < std::size(e->grf_prop.spritegroup));
|
||||
this->root_spritegroup = e->grf_prop.spritegroup[cargo] != nullptr ? e->grf_prop.spritegroup[cargo] : e->grf_prop.spritegroup[SpriteGroupCargo::SG_DEFAULT];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,6 @@ struct RoadStopSpec {
|
|||
*/
|
||||
GRFFilePropsBase<NUM_CARGO + 3> grf_prop;
|
||||
RoadStopClassID cls_id; ///< The class to which this spec belongs.
|
||||
int spec_id; ///< The ID of this spec inside the class.
|
||||
StringID name; ///< Name of this stop
|
||||
|
||||
RoadStopAvailabilityType stop_type = ROADSTOPTYPE_ALL;
|
||||
|
|
|
@ -504,7 +504,7 @@ uint32_t Waypoint::GetNewGRFVariable(const ResolverObject &, uint8_t variable, [
|
|||
|
||||
/* virtual */ const SpriteGroup *StationResolverObject::ResolveReal(const RealSpriteGroup *group) const
|
||||
{
|
||||
if (this->station_scope.st == nullptr || this->station_scope.statspec->cls_id == STAT_CLASS_WAYP) {
|
||||
if (this->station_scope.st == nullptr || !Station::IsExpected(this->station_scope.st)) {
|
||||
return group->loading[0];
|
||||
}
|
||||
|
||||
|
@ -782,8 +782,8 @@ bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID
|
|||
const StationSpec *statspec = StationClass::Get(sclass)->GetSpec(station);
|
||||
if (statspec == nullptr) return false;
|
||||
|
||||
if (HasBit(statspec->callback_mask, CBM_STATION_SPRITE_LAYOUT)) {
|
||||
uint16_t callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, nullptr, INVALID_TILE);
|
||||
if (HasBit(statspec->callback_mask, CBM_STATION_DRAW_TILE_LAYOUT)) {
|
||||
uint16_t callback = GetStationCallback(CBID_STATION_DRAW_TILE_LAYOUT, 0, 0, statspec, nullptr, INVALID_TILE);
|
||||
if (callback != CALLBACK_FAILED) tile = callback & ~1;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef NEWGRF_STATION_H
|
||||
#define NEWGRF_STATION_H
|
||||
|
||||
#include "core/enum_type.hpp"
|
||||
#include "newgrf_animation_type.h"
|
||||
#include "newgrf_callbacks.h"
|
||||
#include "newgrf_class.h"
|
||||
|
@ -112,7 +113,7 @@ struct StationSpec {
|
|||
StationSpec() : cls_id(STAT_CLASS_DFLT), name(0),
|
||||
disallowed_platforms(0), disallowed_lengths(0),
|
||||
cargo_threshold(0), cargo_triggers(0),
|
||||
callback_mask(0), flags(0), pylons(0), wires(0), blocked(0),
|
||||
callback_mask(0), flags(0),
|
||||
animation({0, 0, 0, 0}) {}
|
||||
/**
|
||||
* Properties related the the grf file.
|
||||
|
@ -157,9 +158,13 @@ struct StationSpec {
|
|||
|
||||
uint8_t flags; ///< Bitmask of flags, bit 0: use different sprite set; bit 1: divide cargo about by station size
|
||||
|
||||
uint8_t pylons; ///< Bitmask of base tiles (0 - 7) which should contain elrail pylons
|
||||
uint8_t wires; ///< Bitmask of base tiles (0 - 7) which should contain elrail wires
|
||||
uint8_t blocked; ///< Bitmask of base tiles (0 - 7) which are blocked to trains
|
||||
enum class TileFlags : uint8_t {
|
||||
None = 0,
|
||||
Pylons = 1U << 0, ///< Tile should contain catenary pylons.
|
||||
NoWires = 1U << 1, ///< Tile should NOT contain catenary wires.
|
||||
Blocked = 1U << 2, ///< Tile is blocked to vehicles.
|
||||
};
|
||||
std::vector<TileFlags> tileflags; ///< List of tile flags.
|
||||
|
||||
AnimationInfo animation;
|
||||
|
||||
|
@ -173,6 +178,7 @@ struct StationSpec {
|
|||
*/
|
||||
std::vector<std::vector<std::vector<uint8_t>>> layouts;
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(StationSpec::TileFlags);
|
||||
|
||||
/** Class containing information relating to station classes. */
|
||||
using StationClass = NewGRFClass<StationSpec, StationClassID, STAT_CLASS_MAX>;
|
||||
|
|
|
@ -1294,6 +1294,14 @@ static CommandCost CalculateRailStationCost(TileArea tile_area, DoCommandFlag fl
|
|||
return cost;
|
||||
}
|
||||
|
||||
StationSpec::TileFlags GetStationTileFlags(TileIndex tile, const StationSpec *statspec)
|
||||
{
|
||||
const StationGfx gfx = GetStationGfx(tile);
|
||||
/* Default stations do not draw pylons under roofs (gfx >= 4) */
|
||||
if (statspec == nullptr || gfx >= statspec->tileflags.size()) return gfx < 4 ? StationSpec::TileFlags::Pylons : StationSpec::TileFlags::None;
|
||||
return statspec->tileflags[gfx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set rail station tile flags for the given tile.
|
||||
* @param tile Tile to set flags on.
|
||||
|
@ -1301,15 +1309,10 @@ static CommandCost CalculateRailStationCost(TileArea tile_area, DoCommandFlag fl
|
|||
*/
|
||||
void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec)
|
||||
{
|
||||
const StationGfx gfx = GetStationGfx(tile);
|
||||
bool blocked = statspec != nullptr && HasBit(statspec->blocked, gfx);
|
||||
/* Default stations do not draw pylons under roofs (gfx >= 4) */
|
||||
bool pylons = statspec != nullptr ? HasBit(statspec->pylons, gfx) : gfx < 4;
|
||||
bool wires = statspec == nullptr || !HasBit(statspec->wires, gfx);
|
||||
|
||||
SetStationTileBlocked(tile, blocked);
|
||||
SetStationTileHavePylons(tile, pylons);
|
||||
SetStationTileHaveWires(tile, wires);
|
||||
auto flags = GetStationTileFlags(tile, statspec);
|
||||
SetStationTileBlocked(tile, (flags & StationSpec::TileFlags::Blocked) == StationSpec::TileFlags::Blocked);
|
||||
SetStationTileHavePylons(tile, (flags & StationSpec::TileFlags::Pylons) == StationSpec::TileFlags::Pylons);
|
||||
SetStationTileHaveWires(tile, (flags & StationSpec::TileFlags::NoWires) != StationSpec::TileFlags::NoWires);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1461,12 +1464,12 @@ CommandCost CmdBuildRailStation(DoCommandFlag flags, TileIndex tile_org, RailTyp
|
|||
uint32_t platinfo = GetPlatformInfo(AXIS_X, GetStationGfx(tile), plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
|
||||
|
||||
/* As the station is not yet completely finished, the station does not yet exist. */
|
||||
uint16_t callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, nullptr, tile);
|
||||
uint16_t callback = GetStationCallback(CBID_STATION_BUILD_TILE_LAYOUT, platinfo, 0, statspec, nullptr, tile);
|
||||
if (callback != CALLBACK_FAILED) {
|
||||
if (callback < 8) {
|
||||
if (callback <= UINT8_MAX) {
|
||||
SetStationGfx(tile, (callback & ~1) + axis);
|
||||
} else {
|
||||
ErrorUnknownCallbackResult(statspec->grf_prop.grffile->grfid, CBID_STATION_TILE_LAYOUT, callback);
|
||||
ErrorUnknownCallbackResult(statspec->grf_prop.grffile->grfid, CBID_STATION_BUILD_TILE_LAYOUT, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2885,7 +2888,9 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
|
|||
|
||||
const DrawTileSprites *GetStationTileLayout(StationType st, uint8_t gfx)
|
||||
{
|
||||
return &_station_display_datas[st][gfx];
|
||||
const auto layouts = _station_display_datas[st];
|
||||
if (gfx < layouts.size()) return layouts.data() + gfx;
|
||||
return layouts.data();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2978,8 +2983,8 @@ static void DrawTile_Station(TileInfo *ti)
|
|||
if (statspec != nullptr) {
|
||||
tile_layout = GetStationGfx(ti->tile);
|
||||
|
||||
if (HasBit(statspec->callback_mask, CBM_STATION_SPRITE_LAYOUT)) {
|
||||
uint16_t callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
|
||||
if (HasBit(statspec->callback_mask, CBM_STATION_DRAW_TILE_LAYOUT)) {
|
||||
uint16_t callback = GetStationCallback(CBID_STATION_DRAW_TILE_LAYOUT, 0, 0, statspec, st, ti->tile);
|
||||
if (callback != CALLBACK_FAILED) tile_layout = (callback & ~1) + GetRailStationAxis(ti->tile);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ static const StationID INVALID_STATION = 0xFFFF;
|
|||
typedef SmallStack<StationID, StationID, INVALID_STATION, 8, 0xFFFD> StationIDStack;
|
||||
|
||||
/** Station types */
|
||||
enum StationType {
|
||||
enum StationType : uint8_t {
|
||||
STATION_RAIL,
|
||||
STATION_AIRPORT,
|
||||
STATION_TRUCK,
|
||||
|
@ -37,6 +37,7 @@ enum StationType {
|
|||
STATION_DOCK,
|
||||
STATION_BUOY,
|
||||
STATION_WAYPOINT,
|
||||
STATION_END,
|
||||
};
|
||||
|
||||
/** Types of RoadStops */
|
||||
|
|
|
@ -99,8 +99,8 @@ static const NIFeature _nif_vehicle = {
|
|||
#define NICS(cb_id, bit) NIC(cb_id, StationSpec, callback_mask, bit)
|
||||
static const NICallback _nic_stations[] = {
|
||||
NICS(CBID_STATION_AVAILABILITY, CBM_STATION_AVAIL),
|
||||
NICS(CBID_STATION_SPRITE_LAYOUT, CBM_STATION_SPRITE_LAYOUT),
|
||||
NICS(CBID_STATION_TILE_LAYOUT, CBM_NO_BIT),
|
||||
NICS(CBID_STATION_DRAW_TILE_LAYOUT, CBM_STATION_DRAW_TILE_LAYOUT),
|
||||
NICS(CBID_STATION_BUILD_TILE_LAYOUT,CBM_NO_BIT),
|
||||
NICS(CBID_STATION_ANIM_START_STOP, CBM_NO_BIT),
|
||||
NICS(CBID_STATION_ANIM_NEXT_FRAME, CBM_STATION_ANIMATION_NEXT_FRAME),
|
||||
NICS(CBID_STATION_ANIMATION_SPEED, CBM_STATION_ANIMATION_SPEED),
|
||||
|
|
|
@ -990,7 +990,7 @@ static const DrawTileSprites _station_display_datas_waypoint[] = {
|
|||
* As these are drawn/build like stations, they may use the same number of layouts. */
|
||||
static_assert(lengthof(_station_display_datas_rail) == lengthof(_station_display_datas_waypoint));
|
||||
|
||||
static const DrawTileSprites * const _station_display_datas[] = {
|
||||
static const std::array<std::span<const DrawTileSprites>, STATION_END> _station_display_datas = {{
|
||||
_station_display_datas_rail,
|
||||
_station_display_datas_airport,
|
||||
_station_display_datas_truck,
|
||||
|
@ -999,4 +999,4 @@ static const DrawTileSprites * const _station_display_datas[] = {
|
|||
_station_display_datas_dock,
|
||||
_station_display_datas_buoy,
|
||||
_station_display_datas_waypoint,
|
||||
};
|
||||
}};
|
||||
|
|
Loading…
Reference in New Issue