OpenTTD Source 20250328-master-gc3457cd4c0
newgrf_act0_ships.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../stdafx.h"
11#include "../debug.h"
12#include "../newgrf_cargo.h"
13#include "../newgrf_engine.h"
14#include "../newgrf_sound.h"
15#include "../vehicle_base.h"
16#include "newgrf_bytereader.h"
18#include "newgrf_internal.h"
20
21#include "../safeguards.h"
22
31static ChangeInfoResult ShipVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
32{
34
35 for (uint id = first; id < last; ++id) {
36 Engine *e = GetNewEngine(_cur.grffile, VEH_SHIP, id);
37 if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles
38
39 EngineInfo *ei = &e->info;
40 ShipVehicleInfo *svi = &e->u.ship;
41
42 switch (prop) {
43 case 0x08: { // Sprite ID
44 uint8_t spriteid = buf.ReadByte();
45 uint8_t orig_spriteid = spriteid;
46
47 /* ships have different custom id in the GRF file */
48 if (spriteid == 0xFF) spriteid = 0xFD;
49
50 if (spriteid < 0xFD) spriteid >>= 1;
51
52 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
53 svi->image_index = spriteid;
54 } else {
55 GrfMsg(1, "ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
56 svi->image_index = 0;
57 }
58 break;
59 }
60
61 case 0x09: // Refittable
62 svi->old_refittable = (buf.ReadByte() != 0);
63 break;
64
65 case PROP_SHIP_COST_FACTOR: // 0x0A Cost factor
66 svi->cost_factor = buf.ReadByte();
67 break;
68
69 case PROP_SHIP_SPEED: // 0x0B Speed (1 unit is 0.5 km-ish/h). Use 0x23 to achieve higher speeds.
70 svi->max_speed = buf.ReadByte();
71 break;
72
73 case 0x0C: { // Cargo type
74 _gted[e->index].defaultcargo_grf = _cur.grffile;
75 uint8_t ctype = buf.ReadByte();
76
77 if (ctype == 0xFF) {
78 /* 0xFF is specified as 'use first refittable' */
79 ei->cargo_type = INVALID_CARGO;
80 } else {
81 /* Use translated cargo. Might result in INVALID_CARGO (first refittable), if cargo is not defined. */
82 ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
83 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2, "ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
84 }
85 ei->cargo_label = CT_INVALID;
86 break;
87 }
88
89 case PROP_SHIP_CARGO_CAPACITY: // 0x0D Cargo capacity
90 svi->capacity = buf.ReadWord();
91 break;
92
93 case PROP_SHIP_RUNNING_COST_FACTOR: // 0x0F Running cost factor
94 svi->running_cost = buf.ReadByte();
95 break;
96
97 case 0x10: // SFX
98 svi->sfx = GetNewGRFSoundID(_cur.grffile, buf.ReadByte());
99 break;
100
101 case 0x11: { // Cargoes available for refitting
102 uint32_t mask = buf.ReadDWord();
103 _gted[e->index].UpdateRefittability(mask != 0);
104 ei->refit_mask = TranslateRefitMask(mask);
105 _gted[e->index].defaultcargo_grf = _cur.grffile;
106 break;
107 }
108
109 case 0x12: { // Callback mask
110 auto mask = ei->callback_mask.base();
111 SB(mask, 0, 8, buf.ReadByte());
113 break;
114 }
115
116 case 0x13: // Refit cost
117 ei->refit_cost = buf.ReadByte();
118 break;
119
120 case 0x14: // Ocean speed fraction
121 svi->ocean_speed_frac = buf.ReadByte();
122 break;
123
124 case 0x15: // Canal speed fraction
125 svi->canal_speed_frac = buf.ReadByte();
126 break;
127
128 case 0x16: // Retire vehicle early
129 ei->retire_early = buf.ReadByte();
130 break;
131
132 case 0x17: // Miscellaneous flags
133 ei->misc_flags = static_cast<EngineMiscFlags>(buf.ReadByte());
135 break;
136
137 case 0x18: // Cargo classes allowed
138 _gted[e->index].cargo_allowed = CargoClasses{buf.ReadWord()};
139 _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed.Any());
140 _gted[e->index].defaultcargo_grf = _cur.grffile;
141 break;
142
143 case 0x19: // Cargo classes disallowed
144 _gted[e->index].cargo_disallowed = CargoClasses{buf.ReadWord()};
145 _gted[e->index].UpdateRefittability(false);
146 break;
147
148 case 0x1A: // Long format introduction date (days since year 0)
149 ei->base_intro = TimerGameCalendar::Date(buf.ReadDWord());
150 break;
151
152 case 0x1B: // Alter purchase list sort order
154 break;
155
156 case 0x1C: // Visual effect
157 svi->visual_effect = buf.ReadByte();
158 /* Avoid accidentally setting visual_effect to the default value
159 * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
160 if (svi->visual_effect == VE_DEFAULT) {
163 }
164 break;
165
166 case PROP_SHIP_CARGO_AGE_PERIOD: // 0x1D Cargo aging period
167 ei->cargo_age_period = buf.ReadWord();
168 break;
169
170 case 0x1E: // CTT refit include list
171 case 0x1F: { // CTT refit exclude list
172 uint8_t count = buf.ReadByte();
173 _gted[e->index].UpdateRefittability(prop == 0x1E && count != 0);
174 if (prop == 0x1E) _gted[e->index].defaultcargo_grf = _cur.grffile;
175 CargoTypes &ctt = prop == 0x1E ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
176 ctt = 0;
177 while (count--) {
178 CargoType ctype = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
179 if (IsValidCargoType(ctype)) SetBit(ctt, ctype);
180 }
181 break;
182 }
183
184 case 0x20: // Engine variant
185 ei->variant_id = static_cast<EngineID>(buf.ReadWord());
186 break;
187
188 case 0x21: // Extra miscellaneous flags
189 ei->extra_flags = static_cast<ExtraEngineFlags>(buf.ReadDWord());
190 break;
191
192 case 0x22: { // Callback additional mask
193 auto mask = ei->callback_mask.base();
194 SB(mask, 8, 8, buf.ReadByte());
196 break;
197 }
198
199 case 0x23: // Speed (1 unit is 0.5 km-ish/h)
200 svi->max_speed = buf.ReadWord();
201 break;
202
203 case 0x24: // Acceleration (1 unit is 0.5 km-ish/h per tick)
204 svi->acceleration = std::max<uint8_t>(1, buf.ReadByte());
205 break;
206
207 case 0x25: // Cargo classes required for a refit.
208 _gted[e->index].cargo_allowed_required = CargoClasses{buf.ReadWord()};
209 break;
210
211 case 0x26: // Badge list
212 e->badges = ReadBadgeList(buf, GSF_SHIPS);
213 break;
214
215 default:
216 ret = CommonVehicleChangeInfo(ei, prop, buf);
217 break;
218 }
219 }
220
221 return ret;
222}
223
225template <> ChangeInfoResult GrfChangeInfoHandler<GSF_SHIPS>::Activation(uint first, uint last, int prop, ByteReader &buf) { return ShipVehicleChangeInfo(first, last, prop, buf); }
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
Definition cargo_type.h:72
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:23
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:106
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
Class to read from a NewGRF file.
uint32_t ReadDWord()
Read a single DWord (32 bits).
uint16_t ReadWord()
Read a single Word (16 bits).
uint16_t ReadExtendedByte()
Read a single Extended Byte (8 or 16 bits).
uint8_t ReadByte()
Read a single byte (8 bits).
@ Uses2CC
Vehicle uses two company colours.
Engine * GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access)
Returns the engine associated to a certain internal_id, resp.
Definition newgrf.cpp:207
ReferenceThroughBaseContainer< std::vector< GRFTempEngineData > > _gted
Temporary engine data used during NewGRF loading.
Definition newgrf.cpp:76
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:72
CargoTypes TranslateRefitMask(uint32_t refit_mask)
Translate the refit mask.
Definition newgrf.cpp:307
ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, ByteReader &buf)
Define properties common to all vehicles.
std::vector< BadgeID > ReadBadgeList(ByteReader &buf, GrfSpecFeature feature)
Read a list of badges.
static ChangeInfoResult ShipVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for ships.
NewGRF buffer reader definition.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
void AlterVehicleListOrder(EngineID engine, uint16_t target)
Record a vehicle ListOrderChange.
NewGRF internal processing state.
ChangeInfoResult
Possible return values for the GrfChangeInfoHandler functions.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
@ CIR_UNHANDLED
Variable was parsed but unread.
@ CIR_SUCCESS
Variable was parsed and read.
NewGRF internal processing state for vehicles.
@ PROP_SHIP_CARGO_CAPACITY
Capacity.
@ PROP_SHIP_COST_FACTOR
Purchase cost.
@ PROP_SHIP_SPEED
Max. speed: 1 unit = 1/3.2 mph = 0.5 km-ish/h.
@ PROP_SHIP_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_SHIP_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
SoundID GetNewGRFSoundID(const GRFFile *file, SoundID sound_id)
Resolve NewGRF sound ID.
NewGRF string mapping definition.
Information about a vehicle.
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
EngineMiscFlags misc_flags
Miscellaneous flags.
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
VehicleCallbackMasks callback_mask
Bitmask of vehicle callbacks that have to be called.
TimerGameCalendar::Date base_intro
Basic date of engine introduction (without random parts).
int8_t retire_early
Number of years early to retire vehicle.
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition newgrf.h:184
GRF feature handler.
GRFFile * grffile
Currently processed GRF file.
Tindex index
Index of this pool item.
Information about a ship vehicle.
Definition engine_type.h:71
bool old_refittable
Is ship refittable; only used during initialisation. Later use EngineInfo::refit_mask.
Definition engine_type.h:79
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
Definition engine_type.h:81
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition engine_type.h:80
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
Definition engine_type.h:76
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
Definition engine_type.h:75
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
Definition engine_type.h:82
@ VE_TYPE_COUNT
Number of bits used for the effect type.
@ VE_TYPE_START
First bit used for the type of effect.
@ VE_DISABLE_EFFECT
Flag to disable visual effect.
@ VE_DEFAULT
Default value to indicate that visual effect should be based on engine class.
@ VEH_SHIP
Ship vehicle type.