# HG changeset patch # User yexo # Date 2010-02-22 14:16:57 # Node ID ca137edec6feac84647316a89034dce91e098fcd # Parent 952e574afdf237f23b9ae628c0eaa4390e8feeec (svn r19197) -Codechange: introduce animation callbacks for airport tiles diff --git a/src/economy.cpp b/src/economy.cpp --- a/src/economy.cpp +++ b/src/economy.cpp @@ -27,6 +27,7 @@ #include "newgrf_industries.h" #include "newgrf_industrytiles.h" #include "newgrf_station.h" +#include "newgrf_airporttiles.h" #include "unmovable.h" #include "group.h" #include "strings_func.h" @@ -1288,6 +1289,7 @@ static void LoadUnloadVehicle(Vehicle *v st->last_vehicle_type = v->type; StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type); + AirportAnimationTrigger(st, AAT_STATION_CARGO_TAKEN, v->cargo_type); unloading_time += cap; diff --git a/src/newgrf_airporttiles.cpp b/src/newgrf_airporttiles.cpp --- a/src/newgrf_airporttiles.cpp +++ b/src/newgrf_airporttiles.cpp @@ -15,12 +15,17 @@ #include "newgrf.h" #include "newgrf_airporttiles.h" #include "newgrf_spritegroup.h" +#include "newgrf_sound.h" +#include "animated_tile_func.h" #include "station_base.h" #include "water.h" #include "viewport_func.h" #include "landscape.h" #include "company_base.h" #include "town.h" +#include "variables.h" +#include "functions.h" +#include "core/random_func.hpp" #include "table/airporttiles.h" @@ -124,9 +129,7 @@ static uint32 GetAirportTileIDAtOffset(T return 0xFFFF; } - /* Don't use GetAirportGfx here as we want the original (not overriden) - * graphics id. */ - StationGfx gfx = GetStationGfx(tile); + StationGfx gfx = GetAirportGfx(tile); const AirportTileSpec *ats = AirportTileSpec::Get(gfx); if (gfx < NEW_AIRPORTTILE_OFFSET) { // Does it belongs to an old type? @@ -291,4 +294,110 @@ bool DrawNewAirportTile(TileInfo *ti, St return true; } +void AnimateAirportTile(TileIndex tile) +{ + Station *st = Station::GetByTile(tile); + StationGfx gfx = GetAirportGfx(tile); + const AirportTileSpec *ats = AirportTileSpec::Get(gfx); + uint8 animation_speed = ats->animation_speed; + if (HasBit(ats->callback_flags, CBM_AIRT_ANIM_SPEED)) { + uint16 callback_res = GetAirportTileCallback(CBID_AIRPTILE_ANIMATION_SPEED, 0, 0, gfx, st, tile); + if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 0, 16); + } + + /* An animation speed of 2 means the animation frame changes 4 ticks, and + * increasing this value by one doubles the wait. 0 is the minimum value + * allowed for animation_speed, which corresponds to 30ms, and 16 is the + * maximum, corresponding to around 33 minutes. */ + if ((_tick_counter % (1 << animation_speed)) != 0) return; + + bool frame_set_by_callback = false; + uint8 frame = GetStationAnimationFrame(tile); + uint16 num_frames = GB(ats->animation_info, 0, 8); + + if (HasBit(ats->callback_flags, CBM_AIRT_ANIM_NEXT_FRAME)) { + uint16 callback_res = GetAirportTileCallback(CBID_AIRPTILE_ANIM_NEXT_FRAME, HasBit(ats->animation_special_flags, 0) ? Random() : 0, 0, gfx, st, tile); + + if (callback_res != CALLBACK_FAILED) { + frame_set_by_callback = true; + + switch (callback_res & 0xFF) { + case 0xFF: + DeleteAnimatedTile(tile); + break; + case 0xFE: + /* Carry on as normal. */ + frame_set_by_callback = false; + break; + default: + frame = callback_res & 0xFF; + break; + } + + /* If the lower 7 bits of the upper byte of the callback + * result are not empty, it is a sound effect. */ + if (GB(callback_res, 8, 7) != 0) PlayTileSound(ats->grf_prop.grffile, GB(callback_res, 8, 7), tile); + } + } + + if (!frame_set_by_callback) { + if (frame < num_frames) { + frame++; + } else if (frame == num_frames && GB(ats->animation_info, 8, 8) == 1) { + /* This animation loops, so start again from the beginning */ + frame = 0; + } else { + /* This animation doesn't loop, so stay here */ + DeleteAnimatedTile(tile); + } + } + + SetStationAnimationFrame(tile, frame); + MarkTileDirtyByTile(tile); +} + +static void ChangeAirportTileAnimationFrame(const AirportTileSpec *ats, TileIndex tile, AirpAnimationTrigger trigger, StationGfx gfx, Station *st) +{ + uint16 callback_res = GetAirportTileCallback(CBID_AIRPTILE_ANIM_START_STOP, Random(), trigger, gfx, st, tile); + if (callback_res == CALLBACK_FAILED) return; + + switch (callback_res & 0xFF) { + case 0xFD: /* Do nothing. */ break; + case 0xFE: AddAnimatedTile(tile); break; + case 0xFF: DeleteAnimatedTile(tile); break; + default: + SetStationAnimationFrame(tile, callback_res & 0xFF); + AddAnimatedTile(tile); + break; + } + + /* If the lower 7 bits of the upper byte of the callback + * result are not empty, it is a sound effect. */ + if (GB(callback_res, 8, 7) != 0) PlayTileSound(ats->grf_prop.grffile, GB(callback_res, 8, 7), tile); +} + +void AirportTileAnimationTrigger(Station *st, TileIndex tile, AirpAnimationTrigger trigger, CargoID cargo_type) +{ + StationGfx gfx = GetAirportGfx(tile); + const AirportTileSpec *ats = AirportTileSpec::Get(gfx); + + if (!HasBit(ats->animation_triggers, trigger)) return; + + ChangeAirportTileAnimationFrame(ats, tile, trigger, gfx, st); + return; +} + +void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID cargo_type) +{ + if (st->airport_tile == INVALID_TILE) return; + + const AirportSpec *as = st->GetAirportSpec(); + int w = as->size_x; + int h = as->size_y; + + TILE_LOOP(tile, w, h, st->airport_tile) { + if (st->TileBelongsToAirport(tile)) AirportTileAnimationTrigger(st, tile, trigger, cargo_type); + } +} + diff --git a/src/newgrf_airporttiles.h b/src/newgrf_airporttiles.h --- a/src/newgrf_airporttiles.h +++ b/src/newgrf_airporttiles.h @@ -17,6 +17,15 @@ #include "newgrf_commons.h" #include "airport.h" +/** Animation triggers for airport tiles */ +enum AirpAnimationTrigger { + AAT_BUILT, ///< Triggered when the airport it build (for all tiles at the same time) + AAT_TILELOOP, ///< Triggered in the periodic tile loop + AAT_STATION_NEW_CARGO, ///< Triggered when new cargo arrives at the station (for all tiles at the same time) + AAT_STATION_CARGO_TAKEN, ///< Triggered when a cargo type is completely removed from the station (for all tiles at the same time) + AAT_STATION_250_ticks, ///< Triggered every 250 ticks (for all tiles at the same time) +}; + /** * Defines the data structure of each indivudual tile of an airport. */ @@ -40,6 +49,10 @@ private: friend void AirportTileOverrideManager::SetEntitySpec(const AirportTileSpec *airpts); }; +StationGfx GetTranslatedAirportTileID(StationGfx gfx); +void AnimateAirportTile(TileIndex tile); +void AirportTileAnimationTrigger(Station *st, TileIndex tile, AirpAnimationTrigger trigger, CargoID cargo_type = CT_INVALID); +void AirportAnimationTrigger(Station *st, AirpAnimationTrigger trigger, CargoID cargo_type = CT_INVALID); bool DrawNewAirportTile(TileInfo *ti, Station *st, StationGfx gfx, const AirportTileSpec *airts); #endif /* NEWGRF_AIRPORTTILES_H */ diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h --- a/src/newgrf_callbacks.h +++ b/src/newgrf_callbacks.h @@ -223,6 +223,15 @@ enum CallbackID { /** Called to determine the type (if any) of foundation to draw for an airport tile. */ CBID_AIRPTILE_DRAW_FOUNDATIONS = 0x150, // 15 bit callback + + /** Called for periodically starting or stopping the animation. */ + CBID_AIRPTILE_ANIM_START_STOP = 0x152, // 15 bit callback + + /** Called to determine airport tile next animation frame. */ + CBID_AIRPTILE_ANIM_NEXT_FRAME = 0x153, // 15 bit callback + + /** Called to indicate how long the current animation frame should last. */ + CBID_AIRPTILE_ANIMATION_SPEED = 0x154, // 8 bit callback }; /** diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2079,6 +2079,15 @@ CommandCost CmdBuildAirport(TileIndex ti do { TileIndex cur_tile = tile + ToTileIndexDiff(it->ti); MakeAirport(cur_tile, st->owner, st->index, it->gfx); + + if (AirportTileSpec::Get(GetTranslatedAirportTileID(it->gfx))->animation_info != 0xFFFF) AddAnimatedTile(cur_tile); + } while ((++it)->ti.x != -0x80); + + /* Only call the animation trigger after all tiles have been built */ + it = as->table[0]; + do { + TileIndex cur_tile = tile + ToTileIndexDiff(it->ti); + AirportTileAnimationTrigger(st, cur_tile, AAT_BUILT); } while ((++it)->ti.x != -0x80); st->UpdateVirtCoord(); @@ -2703,9 +2712,7 @@ static void TileLoop_Station(TileIndex t * hardcoded.....not good */ switch (GetStationType(tile)) { case STATION_AIRPORT: - if (AirportTileSpec::Get(GetStationGfx(tile))->animation_info != 0xFFFF) { - AddAnimatedTile(tile); - } + AirportTileAnimationTrigger(Station::GetByTile(tile), tile, AAT_TILELOOP); break; case STATION_DOCK: @@ -2982,6 +2989,7 @@ void OnTick_Station() /* Stop processing this station if it was deleted */ if (!StationHandleBigTick(st)) continue; StationAnimationTrigger(st, st->xy, STAT_ANIM_250_TICKS); + if (Station::IsExpected(st)) AirportAnimationTrigger(Station::From(st), AAT_STATION_250_ticks); } } } @@ -3016,6 +3024,7 @@ static void UpdateStationWaiting(Station SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP); StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type); + AirportAnimationTrigger(st, AAT_STATION_NEW_CARGO, type); SetWindowDirty(WC_STATION_VIEW, st->index); st->MarkTilesDirty(true);