summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/newgrf.cpp188
-rw-r--r--src/newgrf.h1
-rw-r--r--src/newgrf_commons.cpp1
3 files changed, 189 insertions, 1 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index 293bc33a7..b9be188af 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2886,6 +2886,152 @@ static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, B
return ret;
}
+static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader *buf)
+{
+ ChangeInfoResult ret = CIR_SUCCESS;
+
+ switch (prop) {
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x16:
+ buf->ReadByte();
+
+ case 0x09:
+ case 0x0A:
+ case 0x10:
+ case 0x11:
+ case 0x15:
+ buf->ReadWord();
+ break;
+
+ case 0x08:
+ case 0x0E:
+ case 0x0F:
+ buf->ReadDWord();
+ break;
+
+ default:
+ ret = CIR_UNKNOWN;
+ break;
+ }
+
+ return ret;
+}
+
+static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
+{
+ ChangeInfoResult ret = CIR_SUCCESS;
+
+ if (id + numinfo > NUM_OBJECTS) {
+ grfmsg(1, "ObjectChangeInfo: Too many objects loaded (%u), max (%u). Ignoring.", id + numinfo, NUM_OBJECTS);
+ return CIR_INVALID_ID;
+ }
+
+ /* Allocate object specs if they haven't been allocated already. */
+ if (_cur_grffile->objectspec == NULL) {
+ _cur_grffile->objectspec = CallocT<ObjectSpec*>(NUM_OBJECTS);
+ }
+
+ for (int i = 0; i < numinfo; i++) {
+ ObjectSpec *spec = _cur_grffile->objectspec[id + i];
+
+ if (prop != 0x08 && spec == NULL) {
+ /* If the object property 08 is not yet set, ignore this property */
+ ChangeInfoResult cir = IgnoreObjectProperty(prop, buf);
+ if (cir > ret) ret = cir;
+ continue;
+ }
+
+ switch (prop) {
+ case 0x08: { // Class ID
+ ObjectSpec **ospec = &_cur_grffile->objectspec[id + i];
+
+ /* Allocate space for this object. */
+ if (*ospec == NULL) *ospec = CallocT<ObjectSpec>(1);
+
+ /* Swap classid because we read it in BE. */
+ uint32 classid = buf->ReadDWord();
+ (*ospec)->cls_id = ObjectClass::Allocate(BSWAP32(classid));
+ (*ospec)->enabled = true;
+ break;
+ }
+
+ case 0x09: { // Class name
+ StringID class_name = buf->ReadWord();
+ ObjectClass::SetName(spec->cls_id, class_name);
+ _string_to_grf_mapping[&ObjectClass::classes[spec->cls_id].name] = _cur_grffile->grfid;
+ break;
+ }
+
+ case 0x0A: // Object name
+ spec->name = buf->ReadWord();
+ _string_to_grf_mapping[&spec->name] = _cur_grffile->grfid;
+ break;
+
+ case 0x0B: // Climate mask
+ spec->climate = buf->ReadByte();
+ break;
+
+ case 0x0C: // Size
+ spec->size = buf->ReadByte();
+ break;
+
+ case 0x0D: // Build cost multipler
+ spec->build_cost_multiplier = buf->ReadByte();
+ spec->clear_cost_multiplier = spec->build_cost_multiplier;
+ break;
+
+ case 0x0E: // Introduction date
+ spec->introduction_date = buf->ReadDWord();
+ break;
+
+ case 0x0F: // End of life
+ spec->end_of_life_date = buf->ReadDWord();
+ break;
+
+ case 0x10: // Flags
+ spec->flags = (ObjectFlags)buf->ReadWord();
+ _loaded_newgrf_features.has_2CC |= (spec->flags & OBJECT_FLAG_2CC_COLOUR) != 0;
+ break;
+
+ case 0x11: // Animation info
+ spec->animation.frames = buf->ReadByte();
+ spec->animation.status = buf->ReadByte();
+ break;
+
+ case 0x12: // Animation speed
+ spec->animation.speed = buf->ReadByte();
+ break;
+
+ case 0x13: // Animation triggers
+ spec->animation.triggers = buf->ReadWord();
+ break;
+
+ case 0x14: // Removal cost multiplier
+ spec->clear_cost_multiplier = buf->ReadByte();
+ break;
+
+ case 0x15: // Callback mask
+ spec->callback_mask = buf->ReadWord();
+ break;
+
+ case 0x16: // Building height
+ spec->height = buf->ReadByte();
+ break;
+
+ default:
+ ret = CIR_UNKNOWN;
+ break;
+ }
+ }
+
+ return ret;
+}
+
static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
{
ChangeInfoResult ret = CIR_SUCCESS;
@@ -3197,7 +3343,7 @@ static void FeatureChangeInfo(ByteReader *buf)
/* GSF_SOUNDFX */ SoundEffectChangeInfo,
/* GSF_AIRPORTS */ AirportChangeInfo,
/* GSF_SIGNALS */ NULL,
- /* GSF_OBJECTS */ NULL,
+ /* GSF_OBJECTS */ ObjectChangeInfo,
/* GSF_RAILTYPES */ RailTypeChangeInfo,
/* GSF_AIRPORTTILES */ AirportTilesChangeInfo,
};
@@ -6722,6 +6868,22 @@ static void ResetCustomIndustries()
}
}
+static void ResetCustomObjects()
+{
+ const GRFFile * const *end = _grf_files.End();
+ for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
+ ObjectSpec **&objectspec = (*file)->objectspec;
+ if (objectspec == NULL) continue;
+ for (uint i = 0; i < NUM_OBJECTS; i++) {
+ free(objectspec[i]);
+ }
+
+ free(objectspec);
+ objectspec = NULL;
+ }
+}
+
+
static void ResetNewGRF()
{
const GRFFile * const *end = _grf_files.End();
@@ -6797,6 +6959,7 @@ static void ResetNewGRFData()
/* Reset the objects. */
ObjectClass::Reset();
+ ResetCustomObjects();
ResetObjects();
/* Reset station classes */
@@ -7191,6 +7354,26 @@ static void FinaliseIndustriesArray()
}
/**
+ * Add all new objects to the object array. Object properties can be set at any
+ * time in the GRF file, so we can only add an object spec to the object array
+ * after the file has finished loading.
+ */
+static void FinaliseObjectsArray()
+{
+ const GRFFile * const *end = _grf_files.End();
+ for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
+ ObjectSpec **&objectspec = (*file)->objectspec;
+ if (objectspec != NULL) {
+ for (int i = 0; i < NUM_OBJECTS; i++) {
+ if (objectspec[i] != NULL && objectspec[i]->enabled) {
+ _object_mngr.SetEntitySpec(objectspec[i]);
+ }
+ }
+ }
+ }
+}
+
+/**
* Add all new airports to the airport array. Airport properties can be set at any
* time in the GRF file, so we can only add a airport spec to the airport array
* after the file has finished loading.
@@ -7586,6 +7769,9 @@ static void AfterLoadGRFs()
/* Add all new industries to the industry array. */
FinaliseIndustriesArray();
+ /* Add all new objects to the object array. */
+ FinaliseObjectsArray();
+
InitializeSortedCargoSpecs();
/* Sort the list of industry types. */
diff --git a/src/newgrf.h b/src/newgrf.h
index 64bfe58df..58202ed25 100644
--- a/src/newgrf.h
+++ b/src/newgrf.h
@@ -106,6 +106,7 @@ struct GRFFile {
struct HouseSpec **housespec;
struct IndustrySpec **industryspec;
struct IndustryTileSpec **indtspec;
+ struct ObjectSpec **objectspec;
struct AirportSpec **airportspec;
struct AirportTileSpec **airtspec;
diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp
index 91a449987..6521a39f7 100644
--- a/src/newgrf_commons.cpp
+++ b/src/newgrf_commons.cpp
@@ -317,6 +317,7 @@ void ObjectOverrideManager::SetEntitySpec(ObjectSpec *spec)
/* Now that we know we can use the given id, copy the spec to its final destination. */
memcpy(&_object_specs[type], spec, sizeof(*spec));
+ ObjectClass::Assign(&_object_specs[type]);
}
/**