diff options
Diffstat (limited to 'src/newgrf_industrytiles.cpp')
-rw-r--r-- | src/newgrf_industrytiles.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp index 77993eafa..f87e4a6d7 100644 --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -15,6 +15,7 @@ #include "newgrf_spritegroup.h" #include "newgrf_callbacks.h" #include "newgrf_industries.h" +#include "newgrf_industrytiles.h" #include "newgrf_text.h" #include "industry_map.h" #include "clear_map.h" @@ -249,3 +250,104 @@ bool PerformIndustryTileSlopeCheck(TileIndex tile, const IndustryTileSpec *its, default: _error_message = GetGRFStringID(its->grf_prop.grffile->grfid, 0xD000 + callback_res); return false; } } + +void AnimateNewIndustryTile(TileIndex tile) +{ + Industry *ind = GetIndustryByTile(tile); + IndustryGfx gfx = GetIndustryGfx(tile); + const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); + byte animation_speed = itspec->animation_speed; + + if (HASBIT(itspec->callback_flags, CBM_INDT_ANIM_SPEED)) { + uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIMATION_SPEED, 0, 0, gfx, ind, 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; + byte frame = GetIndustryAnimationState(tile); + uint16 num_frames = GB(itspec->animation_info, 0, 8) + 1; + + if (HASBIT(itspec->callback_flags, CBM_INDT_ANIM_NEXT_FRAME)) { + uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIM_NEXT_FRAME, HASBIT(itspec->animation_special_flags, 0) ? Random() : 0, 0, gfx, ind, 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 (!frame_set_by_callback) { + if (frame < num_frames) { + frame++; + } else if (frame == num_frames && GB(itspec->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); + } + } + + SetIndustryAnimationState(tile, frame); + MarkTileDirtyByTile(tile); +} + +static void ChangeIndustryTileAnimationFrame(TileIndex tile, IndustryAnimationTrigger iat, uint32 random_bits, IndustryGfx gfx, Industry *ind) +{ + uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIM_START_STOP, random_bits, iat, gfx, ind, 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: + SetIndustryAnimationState(tile, callback_res & 0xFF); + AddAnimatedTile(tile); + break; + } +} + +bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random) +{ + IndustryGfx gfx = GetIndustryGfx(tile); + const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); + + if (!HASBIT(itspec->animation_triggers, iat)) return false; + + Industry *ind = GetIndustryByTile(tile); + ChangeIndustryTileAnimationFrame(tile, iat, random, gfx, ind); + return true; +} + +bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigger iat) +{ + bool ret = true; + uint32 random = Random(); + BEGIN_TILE_LOOP(tile, ind->width, ind->height, ind->xy) + if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) { + ret &= StartStopIndustryTileAnimation(tile, iat, random); + SB(random, 0, 16, Random()); + } + END_TILE_LOOP(tile, ind->width, ind->height, ind->xy) + + return ret; +} |