OpenTTD Source 20250331-master-g3c15e0c889
newgrf_act0_objects.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_object.h"
13#include "newgrf_bytereader.h"
14#include "newgrf_internal.h"
16
17#include "../safeguards.h"
18
26{
28
29 switch (prop) {
30 case 0x0B:
31 case 0x0C:
32 case 0x0D:
33 case 0x12:
34 case 0x14:
35 case 0x16:
36 case 0x17:
37 case 0x18:
38 buf.ReadByte();
39 break;
40
41 case 0x09:
42 case 0x0A:
43 case 0x10:
44 case 0x11:
45 case 0x13:
46 case 0x15:
47 buf.ReadWord();
48 break;
49
50 case 0x08:
51 case 0x0E:
52 case 0x0F:
53 buf.ReadDWord();
54 break;
55
56 case 0x19: // Badge list
57 SkipBadgeList(buf);
58 break;
59
60 default:
61 ret = CIR_UNKNOWN;
62 break;
63 }
64
65 return ret;
66}
67
76static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
77{
79
80 if (last > NUM_OBJECTS_PER_GRF) {
81 GrfMsg(1, "ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.", last, NUM_OBJECTS_PER_GRF);
82 return CIR_INVALID_ID;
83 }
84
85 /* Allocate object specs if they haven't been allocated already. */
86 if (_cur.grffile->objectspec.size() < last) _cur.grffile->objectspec.resize(last);
87
88 for (uint id = first; id < last; ++id) {
89 auto &spec = _cur.grffile->objectspec[id];
90
91 if (prop != 0x08 && spec == nullptr) {
92 /* If the object property 08 is not yet set, ignore this property */
94 if (cir > ret) ret = cir;
95 continue;
96 }
97
98 switch (prop) {
99 case 0x08: { // Class ID
100 /* Allocate space for this object. */
101 if (spec == nullptr) {
102 spec = std::make_unique<ObjectSpec>();
103 spec->views = 1; // Default for NewGRFs that don't set it.
104 spec->size = OBJECT_SIZE_1X1; // Default for NewGRFs that manage to not set it (1x1)
105 }
106
107 /* Swap classid because we read it in BE. */
108 uint32_t classid = buf.ReadDWord();
109 spec->class_index = ObjectClass::Allocate(std::byteswap(classid));
110 break;
111 }
112
113 case 0x09: { // Class name
114 AddStringForMapping(GRFStringID{buf.ReadWord()}, [spec = spec.get()](StringID str) { ObjectClass::Get(spec->class_index)->name = str; });
115 break;
116 }
117
118 case 0x0A: // Object name
119 AddStringForMapping(GRFStringID{buf.ReadWord()}, &spec->name);
120 break;
121
122 case 0x0B: // Climate mask
123 spec->climate = LandscapeTypes{buf.ReadByte()};
124 break;
125
126 case 0x0C: // Size
127 spec->size = buf.ReadByte();
128 if (GB(spec->size, 0, 4) == 0 || GB(spec->size, 4, 4) == 0) {
129 GrfMsg(0, "ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size, id);
130 spec->size = OBJECT_SIZE_1X1;
131 }
132 break;
133
134 case 0x0D: // Build cost multiplier
135 spec->build_cost_multiplier = buf.ReadByte();
136 spec->clear_cost_multiplier = spec->build_cost_multiplier;
137 break;
138
139 case 0x0E: // Introduction date
140 spec->introduction_date = TimerGameCalendar::Date(buf.ReadDWord());
141 break;
142
143 case 0x0F: // End of life
144 spec->end_of_life_date = TimerGameCalendar::Date(buf.ReadDWord());
145 break;
146
147 case 0x10: // Flags
148 spec->flags = (ObjectFlags)buf.ReadWord();
150 break;
151
152 case 0x11: // Animation info
153 spec->animation.frames = buf.ReadByte();
154 spec->animation.status = buf.ReadByte();
155 break;
156
157 case 0x12: // Animation speed
158 spec->animation.speed = buf.ReadByte();
159 break;
160
161 case 0x13: // Animation triggers
162 spec->animation.triggers = buf.ReadWord();
163 break;
164
165 case 0x14: // Removal cost multiplier
166 spec->clear_cost_multiplier = buf.ReadByte();
167 break;
168
169 case 0x15: // Callback mask
170 spec->callback_mask = static_cast<ObjectCallbackMasks>(buf.ReadWord());
171 break;
172
173 case 0x16: // Building height
174 spec->height = buf.ReadByte();
175 break;
176
177 case 0x17: // Views
178 spec->views = buf.ReadByte();
179 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
180 GrfMsg(2, "ObjectChangeInfo: Invalid number of views ({}) for object id {}. Ignoring.", spec->views, id);
181 spec->views = 1;
182 }
183 break;
184
185 case 0x18: // Amount placed on 256^2 map on map creation
186 spec->generate_amount = buf.ReadByte();
187 break;
188
189 case 0x19: // Badge list
190 spec->badges = ReadBadgeList(buf, GSF_OBJECTS);
191 break;
192
193 default:
194 ret = CIR_UNKNOWN;
195 break;
196 }
197 }
198
199 return ret;
200}
201
203template <> ChangeInfoResult GrfChangeInfoHandler<GSF_OBJECTS>::Activation(uint first, uint last, int prop, ByteReader &buf) { return ObjectChangeInfo(first, last, prop, buf); }
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
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).
uint8_t ReadByte()
Read a single byte (8 bits).
StringID name
Name of this class.
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
static Tindex Allocate(uint32_t global_id)
Allocate a class with a given global class ID.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:72
std::vector< BadgeID > ReadBadgeList(ByteReader &buf, GrfSpecFeature feature)
Read a list of badges.
void SkipBadgeList(ByteReader &buf)
Skip a list of badges.
static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for objects.
static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader &buf)
Ignore properties for objects.
NewGRF buffer reader definition.
NewGRF internal processing state.
ChangeInfoResult
Possible return values for the GrfChangeInfoHandler functions.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
@ CIR_UNKNOWN
Variable is unknown.
@ CIR_UNHANDLED
Variable was parsed but unread.
@ CIR_SUCCESS
Variable was parsed and read.
static const uint8_t OBJECT_SIZE_1X1
The value of a NewGRF's size property when the object is 1x1 tiles: low nibble for X,...
@ Uses2CC
Object wants 2CC colour mapping.
void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
NewGRF string mapping definition.
static const ObjectType NUM_OBJECTS_PER_GRF
Number of supported objects per NewGRF.
Definition object_type.h:26
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
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.