Cache animated tile speed, use btree map for animated tiles

This commit is contained in:
Jonathan G Rennison
2020-11-24 19:02:38 +00:00
parent 72a7ae25e8
commit 2ad446369d
23 changed files with 267 additions and 56 deletions

View File

@@ -38,6 +38,7 @@ add_files(
airport.h airport.h
airport_gui.cpp airport_gui.cpp
animated_tile.cpp animated_tile.cpp
animated_tile.h
animated_tile_func.h animated_tile_func.h
articulated_vehicles.cpp articulated_vehicles.cpp
articulated_vehicles.h articulated_vehicles.h

View File

@@ -8,16 +8,19 @@
/** @file animated_tile.cpp Everything related to animated tiles. */ /** @file animated_tile.cpp Everything related to animated tiles. */
#include "stdafx.h" #include "stdafx.h"
#include "animated_tile.h"
#include "core/alloc_func.hpp" #include "core/alloc_func.hpp"
#include "core/smallvec_type.hpp" #include "core/smallvec_type.hpp"
#include "tile_cmd.h" #include "tile_cmd.h"
#include "viewport_func.h" #include "viewport_func.h"
#include "framerate_type.h" #include "framerate_type.h"
#include "date_func.h"
#include "3rdparty/cpp-btree/btree_map.h"
#include "safeguards.h" #include "safeguards.h"
/** The table/list with animated tiles. */ /** The table/list with animated tiles. */
std::vector<TileIndex> _animated_tiles; btree::btree_map<TileIndex, AnimatedTileInfo> _animated_tiles;
/** /**
* Removes the given tile from the animated tile table. * Removes the given tile from the animated tile table.
@@ -25,14 +28,43 @@ std::vector<TileIndex> _animated_tiles;
*/ */
void DeleteAnimatedTile(TileIndex tile) void DeleteAnimatedTile(TileIndex tile)
{ {
auto to_remove = std::find(_animated_tiles.begin(), _animated_tiles.end(), tile); auto to_remove = _animated_tiles.find(tile);
if (to_remove != _animated_tiles.end()) { if (to_remove != _animated_tiles.end() && !to_remove->second.pending_deletion) {
/* The order of the remaining elements must stay the same, otherwise the animation loop may miss a tile. */ to_remove->second.pending_deletion = true;
_animated_tiles.erase(to_remove);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
} }
} }
static void UpdateAnimatedTileSpeed(TileIndex tile, AnimatedTileInfo &info)
{
extern uint8 GetAnimatedTileSpeed_Town(TileIndex tile);
extern uint8 GetAnimatedTileSpeed_Station(TileIndex tile);
extern uint8 GetAnimatedTileSpeed_Industry(TileIndex tile);
extern uint8 GetNewObjectTileAnimationSpeed(TileIndex tile);
switch (GetTileType(tile)) {
case MP_HOUSE:
info.speed = GetAnimatedTileSpeed_Town(tile);
break;
case MP_STATION:
info.speed = GetAnimatedTileSpeed_Station(tile);
break;
case MP_INDUSTRY:
info.speed = GetAnimatedTileSpeed_Industry(tile);
break;
case MP_OBJECT:
info.speed = GetNewObjectTileAnimationSpeed(tile);
break;
default:
info.speed = 0;
break;
}
}
/** /**
* Add the given tile to the animated tile table (if it does not exist * Add the given tile to the animated tile table (if it does not exist
* on that table yet). Also increases the size of the table if necessary. * on that table yet). Also increases the size of the table if necessary.
@@ -41,7 +73,18 @@ void DeleteAnimatedTile(TileIndex tile)
void AddAnimatedTile(TileIndex tile) void AddAnimatedTile(TileIndex tile)
{ {
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
include(_animated_tiles, tile); AnimatedTileInfo &info = _animated_tiles[tile];
UpdateAnimatedTileSpeed(tile, info);
info.pending_deletion = false;
}
int GetAnimatedTileSpeed(TileIndex tile)
{
const auto iter = _animated_tiles.find(tile);
if (iter != _animated_tiles.end() && !iter->second.pending_deletion) {
return iter->second.speed;
}
return -1;
} }
/** /**
@@ -56,9 +99,18 @@ void AnimateAnimatedTiles()
PerformanceAccumulator framerate(PFE_GL_LANDSCAPE); PerformanceAccumulator framerate(PFE_GL_LANDSCAPE);
const TileIndex *ti = _animated_tiles.data(); const uint32 ticks = (uint) _scaled_tick_counter;
while (ti < _animated_tiles.data() + _animated_tiles.size()) { const uint8 max_speed = (ticks == 0) ? 32 : FindFirstBit(ticks);
const TileIndex curr = *ti;
auto iter = _animated_tiles.begin();
while (iter != _animated_tiles.end()) {
if (iter->second.pending_deletion) {
iter = _animated_tiles.erase(iter);
continue;
}
if (iter->second.speed <= max_speed) {
const TileIndex curr = iter->first;
switch (GetTileType(curr)) { switch (GetTileType(curr)) {
case MP_HOUSE: case MP_HOUSE:
AnimateTile_Town(curr); AnimateTile_Town(curr);
@@ -79,17 +131,21 @@ void AnimateAnimatedTiles()
default: default:
NOT_REACHED(); NOT_REACHED();
} }
}
++iter;
}
}
/* During the AnimateTile call, DeleteAnimatedTile could have been called, void UpdateAllAnimatedTileSpeeds()
* deleting an element we've already processed and pushing the rest one {
* slot to the left. We can detect this by checking whether the index auto iter = _animated_tiles.begin();
* in the current slot has changed - if it has, an element has been deleted, while (iter != _animated_tiles.end()) {
* and we should process the current slot again instead of going forward. if (iter->second.pending_deletion) {
* NOTE: this will still break if more than one animated tile is being iter = _animated_tiles.erase(iter);
* deleted during the same AnimateTile call, but no code seems to continue;
* be doing this anyway. }
*/ UpdateAnimatedTileSpeed(iter->first, iter->second);
if (*ti == curr) ++ti; ++iter;
} }
} }

23
src/animated_tile.h Normal file
View File

@@ -0,0 +1,23 @@
/*
* This file is part of OpenTTD.
* 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.
* 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.
* 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/>.
*/
/** @file animated_tile.h %Tile animation! */
#ifndef ANIMATED_TILE_H
#define ANIMATED_TILE_H
#include "tile_type.h"
#include "3rdparty/cpp-btree/btree_map.h"
struct AnimatedTileInfo {
uint8 speed = 0;
bool pending_deletion = false;
};
extern btree::btree_map<TileIndex, AnimatedTileInfo> _animated_tiles;
#endif /* ANIMATED_TILE_H */

View File

@@ -15,6 +15,7 @@
void AddAnimatedTile(TileIndex tile); void AddAnimatedTile(TileIndex tile);
void DeleteAnimatedTile(TileIndex tile); void DeleteAnimatedTile(TileIndex tile);
void AnimateAnimatedTiles(); void AnimateAnimatedTiles();
void UpdateAllAnimatedTileSpeeds();
void InitializeAnimatedTiles(); void InitializeAnimatedTiles();
#endif /* ANIMATED_TILE_FUNC_H */ #endif /* ANIMATED_TILE_FUNC_H */

View File

@@ -724,6 +724,47 @@ void AnimateTile_Industry(TileIndex tile)
} }
} }
uint8 GetAnimatedTileSpeed_Industry(TileIndex tile)
{
IndustryGfx gfx = GetIndustryGfx(tile);
if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
return GetNewIndustryTileAnimationSpeed(tile);
}
switch (gfx) {
case GFX_SUGAR_MINE_SIEVE:
return 1;
case GFX_TOFFEE_QUARY:
return 2;
case GFX_BUBBLE_CATCHER:
return 1;
case GFX_POWERPLANT_SPARKS:
return 2;
case GFX_TOY_FACTORY:
return 1;
case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
return 2;
case GFX_OILWELL_ANIMATED_1:
case GFX_OILWELL_ANIMATED_2:
case GFX_OILWELL_ANIMATED_3:
return 3;
default:
return 0;
}
}
static void CreateChimneySmoke(TileIndex tile) static void CreateChimneySmoke(TileIndex tile)
{ {
uint x = TileX(tile) * TILE_SIZE; uint x = TileX(tile) * TILE_SIZE;

View File

@@ -312,3 +312,10 @@ void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID
} }
} }
uint8 GetAirportTileAnimationSpeed(TileIndex tile)
{
const AirportTileSpec *ats = AirportTileSpec::GetByTile(tile);
if (ats == nullptr) return 0;
return AirportTileAnimationBase::GetAnimationSpeed(ats);
}

View File

@@ -86,6 +86,7 @@ StationGfx GetTranslatedAirportTileID(StationGfx gfx);
void AnimateAirportTile(TileIndex tile); void AnimateAirportTile(TileIndex tile);
void AirportTileAnimationTrigger(Station *st, TileIndex tile, AirpAnimationTrigger trigger, CargoID cargo_type = CT_INVALID); void AirportTileAnimationTrigger(Station *st, TileIndex tile, AirpAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID cargo_type = CT_INVALID); void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
uint8 GetAirportTileAnimationSpeed(TileIndex tile);
bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const AirportTileSpec *airts); bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const AirportTileSpec *airts);
#endif /* NEWGRF_AIRPORTTILES_H */ #endif /* NEWGRF_AIRPORTTILES_H */

View File

@@ -133,4 +133,10 @@ struct AnimationBase {
* result are not empty, it is a sound effect. */ * result are not empty, it is a sound effect. */
if (GB(callback, 8, 7) != 0 && _settings_client.sound.ambient) PlayTileSound(spec->grf_prop.grffile, GB(callback, 8, 7), tile); if (GB(callback, 8, 7) != 0 && _settings_client.sound.ambient) PlayTileSound(spec->grf_prop.grffile, GB(callback, 8, 7), tile);
} }
static uint8 GetAnimationSpeed(const Tspec *spec)
{
if (HasBit(spec->callback_mask, Tbase::cbm_animation_speed)) return 0;
return spec->animation.speed;
}
}; };

View File

@@ -662,6 +662,14 @@ void AnimateNewHouseConstruction(TileIndex tile)
} }
} }
uint8 GetNewHouseTileAnimationSpeed(TileIndex tile)
{
const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
if (hs == nullptr) return 0;
return HouseAnimationBase::GetAnimationSpeed(hs);
}
/** /**
* Check if GRF allows a given house to be constructed (callback 17) * Check if GRF allows a given house to be constructed (callback 17)
* @param house_id house type * @param house_id house type

View File

@@ -144,6 +144,7 @@ void DrawNewHouseTile(TileInfo *ti, HouseID house_id);
void DrawNewHouseTileInGUI(int x, int y, HouseID house_id, bool ground); void DrawNewHouseTileInGUI(int x, int y, HouseID house_id, bool ground);
void AnimateNewHouseTile(TileIndex tile); void AnimateNewHouseTile(TileIndex tile);
void AnimateNewHouseConstruction(TileIndex tile); void AnimateNewHouseConstruction(TileIndex tile);
uint8 GetNewHouseTileAnimationSpeed(TileIndex tile);
uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town = nullptr, TileIndex tile = INVALID_TILE, uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town = nullptr, TileIndex tile = INVALID_TILE,
bool not_yet_constructed = false, uint8 initial_random_bits = 0, CargoTypes watched_cargo_triggers = 0); bool not_yet_constructed = false, uint8 initial_random_bits = 0, CargoTypes watched_cargo_triggers = 0);

View File

@@ -300,6 +300,14 @@ bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigge
return ret; return ret;
} }
uint8 GetNewIndustryTileAnimationSpeed(TileIndex tile)
{
const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile));
if (itspec == nullptr) return 0;
return IndustryAnimationBase::GetAnimationSpeed(itspec);
}
/** /**
* Trigger random triggers for an industry tile and reseed its random bits. * Trigger random triggers for an industry tile and reseed its random bits.
* @param tile Industry tile to trigger. * @param tile Industry tile to trigger.

View File

@@ -64,6 +64,7 @@ CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind
void AnimateNewIndustryTile(TileIndex tile); void AnimateNewIndustryTile(TileIndex tile);
bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random = Random()); bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random = Random());
bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigger iat); bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigger iat);
uint8 GetNewIndustryTileAnimationSpeed(TileIndex tile);
/** Available industry tile triggers. */ /** Available industry tile triggers. */

View File

@@ -530,6 +530,14 @@ void AnimateNewObjectTile(TileIndex tile)
ObjectAnimationBase::AnimateTile(spec, Object::GetByTile(tile), tile, (spec->flags & OBJECT_FLAG_ANIM_RANDOM_BITS) != 0); ObjectAnimationBase::AnimateTile(spec, Object::GetByTile(tile), tile, (spec->flags & OBJECT_FLAG_ANIM_RANDOM_BITS) != 0);
} }
uint8 GetNewObjectTileAnimationSpeed(TileIndex tile)
{
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
if (spec == nullptr || !(spec->flags & OBJECT_FLAG_ANIMATION)) return 0;
return ObjectAnimationBase::GetAnimationSpeed(spec);
}
/** /**
* Trigger the update of animation on a single tile. * Trigger the update of animation on a single tile.
* @param o The object that got triggered. * @param o The object that got triggered.

View File

@@ -163,6 +163,7 @@ uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, cons
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec); void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec);
void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view); void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view);
void AnimateNewObjectTile(TileIndex tile); void AnimateNewObjectTile(TileIndex tile);
uint8 GetNewObjectTileAnimationSpeed(TileIndex tile);
void TriggerObjectTileAnimation(Object *o, TileIndex tile, ObjectAnimationTrigger trigger, const ObjectSpec *spec); void TriggerObjectTileAnimation(Object *o, TileIndex tile, ObjectAnimationTrigger trigger, const ObjectSpec *spec);
void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const ObjectSpec *spec); void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const ObjectSpec *spec);

View File

@@ -924,6 +924,14 @@ void AnimateStationTile(TileIndex tile)
StationAnimationBase::AnimateTile(ss, BaseStation::GetByTile(tile), tile, HasBit(ss->flags, SSF_CB141_RANDOM_BITS)); StationAnimationBase::AnimateTile(ss, BaseStation::GetByTile(tile), tile, HasBit(ss->flags, SSF_CB141_RANDOM_BITS));
} }
uint8 GetStationTileAnimationSpeed(TileIndex tile)
{
const StationSpec *ss = GetStationSpec(tile);
if (ss == nullptr) return 0;
return StationAnimationBase::GetAnimationSpeed(ss);
}
void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type) void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type)
{ {
/* List of coverage areas for each animation trigger */ /* List of coverage areas for each animation trigger */

View File

@@ -204,6 +204,7 @@ void DeallocateSpecFromStation(BaseStation *st, byte specindex);
bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station); bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station);
void AnimateStationTile(TileIndex tile); void AnimateStationTile(TileIndex tile);
uint8 GetStationTileAnimationSpeed(TileIndex tile);
void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID); void TriggerStationAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type = CT_INVALID); void TriggerStationRandomisation(Station *st, TileIndex tile, StationRandomTrigger trigger, CargoID cargo_type = CT_INVALID);
void StationUpdateCachedTriggers(BaseStation *st); void StationUpdateCachedTriggers(BaseStation *st);

View File

@@ -63,6 +63,7 @@
#include "../bridge_signal_map.h" #include "../bridge_signal_map.h"
#include "../water.h" #include "../water.h"
#include "../settings_func.h" #include "../settings_func.h"
#include "../animated_tile.h"
#include "saveload_internal.h" #include "saveload_internal.h"
@@ -2461,16 +2462,9 @@ bool AfterLoadGame()
/* Animated tiles would sometimes not be actually animated or /* Animated tiles would sometimes not be actually animated or
* in case of old savegames duplicate. */ * in case of old savegames duplicate. */
extern std::vector<TileIndex> _animated_tiles; for (auto tile = _animated_tiles.begin(); tile != _animated_tiles.end(); /* Nothing */) {
for (auto tile = _animated_tiles.begin(); tile < _animated_tiles.end(); /* Nothing */) {
/* Remove if tile is not animated */ /* Remove if tile is not animated */
bool remove = _tile_type_procs[GetTileType(*tile)]->animate_tile_proc == nullptr; bool remove = _tile_type_procs[GetTileType(tile->first)]->animate_tile_proc == nullptr;
/* and remove if duplicate */
for (auto j = _animated_tiles.begin(); !remove && j < tile; j++) {
remove = *tile == *j;
}
if (remove) { if (remove) {
tile = _animated_tiles.erase(tile); tile = _animated_tiles.erase(tile);
@@ -3806,6 +3800,10 @@ bool AfterLoadGame()
RecalculateRoadCachedOneWayStates(); RecalculateRoadCachedOneWayStates();
} }
if (SlXvIsFeatureMissing(XSLFI_ANIMATED_TILE_EXTRA)) {
UpdateAllAnimatedTileSpeeds();
}
InitializeRoadGUI(); InitializeRoadGUI();
/* This needs to be done after conversion. */ /* This needs to be done after conversion. */
@@ -3928,4 +3926,5 @@ void ReloadNewGRFData()
CheckTrainsLengths(); CheckTrainsLengths();
AfterLoadTemplateVehiclesUpdateImage(); AfterLoadTemplateVehiclesUpdateImage();
AfterLoadTemplateVehiclesUpdateProperties(); AfterLoadTemplateVehiclesUpdateProperties();
UpdateAllAnimatedTileSpeeds();
} }

View File

@@ -8,6 +8,7 @@
/** @file animated_tile_sl.cpp Code handling saving and loading of animated tiles */ /** @file animated_tile_sl.cpp Code handling saving and loading of animated tiles */
#include "../stdafx.h" #include "../stdafx.h"
#include "../animated_tile.h"
#include "../tile_type.h" #include "../tile_type.h"
#include "../core/alloc_func.hpp" #include "../core/alloc_func.hpp"
#include "../core/smallvec_type.hpp" #include "../core/smallvec_type.hpp"
@@ -16,15 +17,21 @@
#include "../safeguards.h" #include "../safeguards.h"
extern std::vector<TileIndex> _animated_tiles;
/** /**
* Save the ANIT chunk. * Save the ANIT chunk.
*/ */
static void Save_ANIT() static void Save_ANIT()
{ {
SlSetLength(_animated_tiles.size() * sizeof(_animated_tiles.front())); uint count = 0;
SlArray(_animated_tiles.data(), _animated_tiles.size(), SLE_UINT32); for (const auto &it : _animated_tiles) {
if (!it.second.pending_deletion) count++;
}
SlSetLength(count * 5);
for (const auto &it : _animated_tiles) {
if (it.second.pending_deletion) continue;
SlWriteUint32(it.first);
SlWriteByte(it.second.speed);
}
} }
/** /**
@@ -40,15 +47,26 @@ static void Load_ANIT()
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
if (anim_list[i] == 0) break; if (anim_list[i] == 0) break;
_animated_tiles.push_back(anim_list[i]); _animated_tiles[anim_list[i]] = {};
} }
return; return;
} }
uint count = (uint)SlGetFieldLength() / sizeof(_animated_tiles.front());
_animated_tiles.clear(); _animated_tiles.clear();
_animated_tiles.resize(_animated_tiles.size() + count); if (SlXvIsFeaturePresent(XSLFI_ANIMATED_TILE_EXTRA)) {
SlArray(_animated_tiles.data(), count, SLE_UINT32); uint count = (uint)SlGetFieldLength() / 5;
for (uint i = 0; i < count; i++) {
TileIndex tile = SlReadUint32();
AnimatedTileInfo info = {};
info.speed = SlReadByte();
_animated_tiles[tile] = info;
}
} else {
uint count = (uint)SlGetFieldLength() / 4;
for (uint i = 0; i < count; i++) {
_animated_tiles[SlReadUint32()] = {};
}
}
} }
/** /**

View File

@@ -139,6 +139,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_ONE_WAY_DT_ROAD_STOP, XSCF_NULL, 1, 1, "one_way_dt_road_stop", nullptr, nullptr, nullptr }, { XSLFI_ONE_WAY_DT_ROAD_STOP, XSCF_NULL, 1, 1, "one_way_dt_road_stop", nullptr, nullptr, nullptr },
{ XSLFI_ONE_WAY_ROAD_STATE, XSCF_NULL, 1, 1, "one_way_road_state", nullptr, nullptr, nullptr }, { XSLFI_ONE_WAY_ROAD_STATE, XSCF_NULL, 1, 1, "one_way_road_state", nullptr, nullptr, nullptr },
{ XSLFI_VENC_CHUNK, XSCF_IGNORABLE_ALL, 1, 1, "venc_chunk", nullptr, nullptr, "VENC" }, { XSLFI_VENC_CHUNK, XSCF_IGNORABLE_ALL, 1, 1, "venc_chunk", nullptr, nullptr, "VENC" },
{ XSLFI_ANIMATED_TILE_EXTRA, XSCF_NULL, 1, 1, "animated_tile_extra", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
}; };

View File

@@ -93,6 +93,7 @@ enum SlXvFeatureIndex {
XSLFI_ONE_WAY_DT_ROAD_STOP, ///< One-way drive-through road stops XSLFI_ONE_WAY_DT_ROAD_STOP, ///< One-way drive-through road stops
XSLFI_ONE_WAY_ROAD_STATE, ///< One-way road state cache XSLFI_ONE_WAY_ROAD_STATE, ///< One-way road state cache
XSLFI_VENC_CHUNK, ///< VENC chunk XSLFI_VENC_CHUNK, ///< VENC chunk
XSLFI_ANIMATED_TILE_EXTRA, ///< Animated tile extra info
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk

View File

@@ -26,6 +26,7 @@
#include "../engine_func.h" #include "../engine_func.h"
#include "../company_base.h" #include "../company_base.h"
#include "../disaster_vehicle.h" #include "../disaster_vehicle.h"
#include "../animated_tile.h"
#include "../core/smallvec_type.hpp" #include "../core/smallvec_type.hpp"
#include "saveload_internal.h" #include "saveload_internal.h"
#include "oldloader.h" #include "oldloader.h"
@@ -483,7 +484,6 @@ static inline uint RemapOrderIndex(uint x)
return _savegame_type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2; return _savegame_type == SGT_TTO ? (x - 0x1AC4) / 2 : (x - 0x1C18) / 2;
} }
extern std::vector<TileIndex> _animated_tiles;
extern char *_old_name_array; extern char *_old_name_array;
static uint32 _old_town_index; static uint32 _old_town_index;
@@ -643,7 +643,7 @@ static bool LoadOldAnimTileList(LoadgameState *ls, int num)
/* The first zero in the loaded array indicates the end of the list. */ /* The first zero in the loaded array indicates the end of the list. */
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
if (anim_list[i] == 0) break; if (anim_list[i] == 0) break;
_animated_tiles.push_back(anim_list[i]); _animated_tiles[anim_list[i]] = {};
} }
return true; return true;

View File

@@ -3553,6 +3553,18 @@ void AnimateTile_Station(TileIndex tile)
} }
} }
uint8 GetAnimatedTileSpeed_Station(TileIndex tile)
{
if (HasStationRail(tile)) {
return GetStationTileAnimationSpeed(tile);
}
if (IsAirport(tile)) {
AnimateAirportTile(tile);
}
return 0;
}
static bool ClickTile_Station(TileIndex tile) static bool ClickTile_Station(TileIndex tile)
{ {

View File

@@ -432,6 +432,14 @@ static Foundation GetFoundation_Town(TileIndex tile, Slope tileh)
return FlatteningFoundation(tileh); return FlatteningFoundation(tileh);
} }
uint8 GetAnimatedTileSpeed_Town(TileIndex tile)
{
if (GetHouseType(tile) >= NEW_HOUSE_OFFSET) {
return GetNewHouseTileAnimationSpeed(tile);
}
return 2;
}
/** /**
* Animate a tile for a town * Animate a tile for a town
* Only certain houses can be animated * Only certain houses can be animated