From bc156f754aa5785a09cf5aa195361e4b9ccecab3 Mon Sep 17 00:00:00 2001 From: yexo Date: Mon, 22 Feb 2010 14:16:19 +0000 Subject: [PATCH] (svn r19194) -Feature: action 0/1/2/3 support for newgrf airporttiles --- src/newgrf.cpp | 163 ++++++++++++++++++++++++++++++++++++++ src/newgrf.h | 2 + src/newgrf_airporttiles.h | 4 + src/table/airporttiles.h | 2 +- 4 files changed, 170 insertions(+), 1 deletion(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 54372575f6..f856310ae9 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2649,6 +2649,93 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte return ret; } +static ChangeInfoResult AirportTilesChangeInfo(uint airtid, int numinfo, int prop, ByteReader *buf) +{ + ChangeInfoResult ret = CIR_SUCCESS; + + if (airtid + numinfo > NUM_AIRPORTTILES) { + grfmsg(1, "AirportTileChangeInfo: Too many airport tiles loaded (%u), max (%u). Ignoring.", airtid + numinfo, NUM_AIRPORTTILES); + return CIR_INVALID_ID; + } + + /* Allocate airport tile specs if they haven't been allocated already. */ + if (_cur_grffile->airtspec == NULL) { + _cur_grffile->airtspec = CallocT(NUM_AIRPORTTILES); + } + + for (int i = 0; i < numinfo; i++) { + AirportTileSpec *tsp = _cur_grffile->airtspec[airtid + i]; + + if (prop != 0x08 && tsp == NULL) { + grfmsg(2, "AirportTileChangeInfo: Attempt to modify undefined airport tile %u. Ignoring.", airtid + i); + return CIR_INVALID_ID; + } + + switch (prop) { + case 0x08: { // Substitute airport tile type + AirportTileSpec **tilespec = &_cur_grffile->airtspec[airtid + i]; + byte subs_id = buf->ReadByte(); + + if (subs_id >= NEW_AIRPORTTILE_OFFSET) { + /* The substitute id must be one of the original airport tiles. */ + grfmsg(2, "AirportTileChangeInfo: Attempt to use new airport tile %u as substitute airport tile for %u. Ignoring.", subs_id, airtid + i); + continue; + } + + /* Allocate space for this airport tile. */ + if (*tilespec == NULL) { + *tilespec = CallocT(1); + tsp = *tilespec; + + memcpy(tsp, AirportTileSpec::Get(subs_id), sizeof(AirportTileSpec)); + tsp->enabled = true; + + tsp->animation_info = 0xFFFF; + + tsp->grf_prop.local_id = airtid + i; + tsp->grf_prop.subst_id = subs_id; + tsp->grf_prop.grffile = _cur_grffile; + _airporttile_mngr.AddEntityID(airtid + i, _cur_grffile->grfid, subs_id); // pre-reserve the tile slot + } + } break; + + case 0x09: { // Airport tile override + byte override = buf->ReadByte(); + + /* The airport tile being overridden must be an original airport tile. */ + if (override >= NEW_AIRPORTTILE_OFFSET) { + grfmsg(2, "AirportTileChangeInfo: Attempt to override new airport tile %u with airport tile id %u. Ignoring.", override, airtid + i); + continue; + } + + _airporttile_mngr.Add(airtid + i, _cur_grffile->grfid, override); + } break; + + case 0x0E: // Callback flags + tsp->callback_flags = buf->ReadByte(); + break; + + case 0x0F: // Animation information + tsp->animation_info = buf->ReadWord(); + break; + + case 0x10: // Animation speed + tsp->animation_speed = buf->ReadByte(); + break; + + case 0x11: // Animation triggers + tsp->animation_triggers = buf->ReadByte(); + break; + + default: + ret = CIR_UNKNOWN; + break; + } + } + + return ret; +} + static bool HandleChangeInfoResult(const char *caller, ChangeInfoResult cir, uint8 feature, uint8 property) { switch (cir) { @@ -2708,6 +2795,7 @@ static void FeatureChangeInfo(ByteReader *buf) /* GSF_SIGNALS */ NULL, /* GSF_OBJECTS */ NULL, /* GSF_RAILTYPES */ RailTypeChangeInfo, + /* GSF_AIRPORTTILES */ AirportTilesChangeInfo, }; uint8 feature = buf->ReadByte(); @@ -3077,6 +3165,7 @@ static void NewSpriteGroup(ByteReader *buf) } case GSF_TOWNHOUSE: + case GSF_AIRPORTTILES: case GSF_INDUSTRYTILES: { byte num_spriteset_ents = _cur_grffile->spriteset_numents; byte num_spritesets = _cur_grffile->spriteset_numsets; @@ -3551,6 +3640,37 @@ static void RailTypeMapSpriteGroup(ByteReader *buf, uint8 idcount) buf->ReadWord(); } +static void AirportTileMapSpriteGroup(ByteReader *buf, uint8 idcount) +{ + uint8 *airptiles = AllocaM(uint8, idcount); + for (uint i = 0; i < idcount; i++) { + airptiles[i] = buf->ReadByte(); + } + + /* Skip the cargo type section, we only care about the default group */ + uint8 cidcount = buf->ReadByte(); + buf->Skip(cidcount * 3); + + uint16 groupid = buf->ReadWord(); + if (!IsValidGroupID(groupid, "AirportTileMapSpriteGroup")) return; + + if (_cur_grffile->airtspec == NULL) { + grfmsg(1, "AirportTileMapSpriteGroup: No airport tiles defined, skipping"); + return; + } + + for (uint i = 0; i < idcount; i++) { + AirportTileSpec *airtsp = _cur_grffile->airtspec[airptiles[i]]; + + if (airtsp == NULL) { + grfmsg(1, "AirportTileMapSpriteGroup: Airport tile %d undefined, skipping", airptiles[i]); + continue; + } + + airtsp->grf_prop.spritegroup = _cur_grffile->spritegroups[groupid]; + } +} + /* Action 0x03 */ static void FeatureMapSpriteGroup(ByteReader *buf) @@ -3630,6 +3750,10 @@ static void FeatureMapSpriteGroup(ByteReader *buf) RailTypeMapSpriteGroup(buf, idcount); break; + case GSF_AIRPORTTILES: + AirportTileMapSpriteGroup(buf, idcount); + return; + default: grfmsg(1, "FeatureMapSpriteGroup: Unsupported feature %d, skipping", feature); return; @@ -5649,6 +5773,21 @@ static void ResetCustomHouses() } } +static void ResetCustomAirports() +{ + const GRFFile * const *end = _grf_files.End(); + for (GRFFile **file = _grf_files.Begin(); file != end; file++) { + AirportTileSpec **&airporttilespec = (*file)->airtspec; + if (airporttilespec != NULL) { + for (uint i = 0; i < NUM_AIRPORTTILES; i++) { + free(airporttilespec[i]); + } + free(airporttilespec); + airporttilespec = NULL; + } + } +} + static void ResetCustomIndustries() { const GRFFile * const *end = _grf_files.End(); @@ -5770,6 +5909,7 @@ static void ResetNewGRFData() ResetCustomStations(); /* Reset airport-related structures */ + ResetCustomAirports(); AirportTileSpec::ResetAirportTiles(); /* Reset canal sprite groups and flags */ @@ -6109,6 +6249,26 @@ static void FinaliseIndustriesArray() } } +/** + * 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. + */ +static void FinaliseAirportsArray() +{ + const GRFFile * const *end = _grf_files.End(); + for (GRFFile **file = _grf_files.Begin(); file != end; file++) { + AirportTileSpec **&airporttilespec = (*file)->airtspec; + if (airporttilespec != NULL) { + for (int i = 0; i < NUM_AIRPORTTILES; i++) { + if (airporttilespec[i] != NULL && airporttilespec[i]->enabled) { + _airporttile_mngr.SetEntitySpec(airporttilespec[i]); + } + } + } + } +} + /* Here we perform initial decoding of some special sprites (as are they * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very * partial implementation yet). @@ -6476,6 +6636,9 @@ static void AfterLoadGRFs() /* Create dynamic list of industry legends for smallmap_gui.cpp */ BuildIndustriesLegend(); + /* Add all new airports to the airports array. */ + FinaliseAirportsArray(); + /* Update the townname generators list */ InitGRFTownGeneratorNames(); diff --git a/src/newgrf.h b/src/newgrf.h index 6f4dd758e1..9220c50143 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -58,6 +58,7 @@ enum GrfSpecFeature { GSF_SIGNALS, GSF_OBJECTS, GSF_RAILTYPES, + GSF_AIRPORTTILES, GSF_END, }; @@ -103,6 +104,7 @@ struct GRFFile { HouseSpec **housespec; IndustrySpec **industryspec; IndustryTileSpec **indtspec; + struct AirportTileSpec **airtspec; uint32 param[0x80]; uint param_end; ///< one more than the highest set parameter diff --git a/src/newgrf_airporttiles.h b/src/newgrf_airporttiles.h index 0cf1483572..0a77f4e162 100644 --- a/src/newgrf_airporttiles.h +++ b/src/newgrf_airporttiles.h @@ -12,6 +12,7 @@ #ifndef NEWGRF_AIRPORTTILES_H #define NEWGRF_AIRPORTTILES_H +#include "airport.h" #include "station_map.h" #include "newgrf_commons.h" #include "airport.h" @@ -23,6 +24,9 @@ struct AirportTileSpec { uint16 animation_info; ///< Information about the animation (is it looping, how many loops etc) uint8 animation_speed; ///< The speed of the animation + uint8 callback_flags; ///< Flags telling which grf callback is set + uint8 animation_triggers; ///< When to start the animation + uint8 animation_special_flags; ///< Extra flags to influence the animation bool enabled; ///< entity still available (by default true). newgrf can disable it, though GRFFileProps grf_prop; ///< properties related the the grf file diff --git a/src/table/airporttiles.h b/src/table/airporttiles.h index 5d7c61c18b..19843f7314 100644 --- a/src/table/airporttiles.h +++ b/src/table/airporttiles.h @@ -13,7 +13,7 @@ #define AIRPORTTILES_H /** Writes all airport tile properties in the AirportTile struct */ -#define AT(num_frames, anim_speed) {(1 << 8) | num_frames, anim_speed, true, {INVALID_AIRPORTTILE, 0, NULL, NULL, INVALID_AIRPORTTILE}} +#define AT(num_frames, anim_speed) {(1 << 8) | num_frames, anim_speed, 0, 0, 0, true, {INVALID_AIRPORTTILE, 0, NULL, NULL, INVALID_AIRPORTTILE}} /** Writes an airport tile without animation in the AirportTile struct */ #define AT_NOANIM {0xFFFF, 2}