OpenTTD Source: src/newgrf/newgrf_act0_objects.cpp Source File

OpenTTD Source 15.3

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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
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"
15#include "newgrf_stringmapping.h"
16
17#include "../safeguards.h"
18
25 static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader &buf)
26{
27 ChangeInfoResult ret = CIR_SUCCESS;
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
76 static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
77{
78 ChangeInfoResult ret = CIR_SUCCESS;
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_gps.grffile->objectspec.size() < last) _cur_gps.grffile->objectspec.resize(last);
87
88 for (uint id = first; id < last; ++id) {
89 auto &spec = _cur_gps.grffile->objectspec[id];
90
91 if (prop != 0x08 && spec == nullptr) {
92 /* If the object property 08 is not yet set, ignore this property */
93 ChangeInfoResult cir = IgnoreObjectProperty(prop, buf);
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();
149 _loaded_newgrf_features.has_2CC |= spec->flags.Test(ObjectFlag::Uses2CC);
150 break;
151
152 case 0x11: // Animation info
153 spec->animation.frames = buf.ReadByte();
154 spec->animation.status = static_cast<AnimationStatus>(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 = static_cast<ObjectAnimationTriggers>(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
202template <> ChangeInfoResult GrfChangeInfoHandler<GSF_OBJECTS>::Reserve(uint, uint, int, ByteReader &) { return CIR_UNHANDLED; }
203template <> ChangeInfoResult GrfChangeInfoHandler<GSF_OBJECTS>::Activation(uint first, uint last, int prop, ByteReader &buf) { return ObjectChangeInfo(first, last, prop, buf); }
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
ByteReader
Class to read from a NewGRF file.
Definition newgrf_bytereader.h:18
ByteReader::ReadDWord
uint32_t ReadDWord()
Read a single DWord (32 bits).
Definition newgrf_bytereader.h:66
ByteReader::ReadWord
uint16_t ReadWord()
Read a single Word (16 bits).
Definition newgrf_bytereader.h:45
ByteReader::ReadByte
uint8_t ReadByte()
Read a single byte (8 bits).
Definition newgrf_bytereader.h:34
EnumBitSet< LandscapeType, uint8_t >
NewGRFClass::name
StringID name
Name of this class.
Definition newgrf_class.h:49
NewGRFClass::Get
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
Definition newgrf_class_func.h:82
NewGRFClass::Allocate
static Tindex Allocate(uint32_t global_id)
Allocate a class with a given global class ID.
Definition newgrf_class_func.h:32
_loaded_newgrf_features
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:74
ReadBadgeList
std::vector< BadgeID > ReadBadgeList(ByteReader &buf, GrfSpecFeature feature)
Read a list of badges.
Definition newgrf_act0.cpp:86
SkipBadgeList
void SkipBadgeList(ByteReader &buf)
Skip a list of badges.
Definition newgrf_act0.cpp:72
ObjectChangeInfo
static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for objects.
Definition newgrf_act0_objects.cpp:76
IgnoreObjectProperty
static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader &buf)
Ignore properties for objects.
Definition newgrf_act0_objects.cpp:25
AnimationStatus
AnimationStatus
Definition newgrf_animation_type.h:13
newgrf_bytereader.h
NewGRF buffer reader definition.
newgrf_internal.h
NewGRF internal processing state.
ChangeInfoResult
ChangeInfoResult
Possible return values for the GrfChangeInfoHandler functions.
Definition newgrf_internal.h:20
CIR_INVALID_ID
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
Definition newgrf_internal.h:25
CIR_UNKNOWN
@ CIR_UNKNOWN
Variable is unknown.
Definition newgrf_internal.h:24
CIR_UNHANDLED
@ CIR_UNHANDLED
Variable was parsed but unread.
Definition newgrf_internal.h:23
CIR_SUCCESS
@ CIR_SUCCESS
Variable was parsed and read.
Definition newgrf_internal.h:21
OBJECT_SIZE_1X1
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,...
Definition newgrf_object.h:43
ObjectFlag::Uses2CC
@ Uses2CC
Object wants 2CC colour mapping.
AddStringForMapping
void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
Definition newgrf_stringmapping.cpp:42
newgrf_stringmapping.h
NewGRF string mapping definition.
NUM_OBJECTS_PER_GRF
static const ObjectType NUM_OBJECTS_PER_GRF
Number of supported objects per NewGRF.
Definition object_type.h:26
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
GRFLoadedFeatures::has_2CC
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition newgrf.h:189
GrfChangeInfoHandler
GRF feature handler.
Definition newgrf_internal.h:30
GrfProcessingState::grffile
GRFFile * grffile
Currently processed GRF file.
Definition newgrf_internal.h:67
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer >