00001
00002
00003
00004
00005
00006
00007
00008
00009
00012
00013
00014 #include "animated_tile_func.h"
00015 #include "core/random_func.hpp"
00016 #include "date_func.h"
00017 #include "viewport_func.h"
00018 #include "newgrf_animation_type.h"
00019 #include "newgrf_callbacks.h"
00020
00029 template <typename Tbase, typename Tspec, typename Tobj, typename Textra, uint16 (*GetCallback)(CallbackID callback, uint32 param1, uint32 param2, const Tspec *statspec, Tobj *st, TileIndex tile, Textra extra_data)>
00030 struct AnimationBase {
00040 static void AnimateTile(const Tspec *spec, Tobj *obj, TileIndex tile, bool random_animation, Textra extra_data = 0)
00041 {
00042 assert(spec != NULL);
00043
00044
00045 uint8 animation_speed = spec->animation.speed;
00046 if (HasBit(spec->callback_mask, Tbase::cbm_animation_speed)) {
00047 uint16 callback = GetCallback(Tbase::cb_animation_speed, 0, 0, spec, obj, tile, extra_data);
00048 if (callback != CALLBACK_FAILED) {
00049 if (callback >= 0x100 && spec->grf_prop.grffile->grf_version >= 8) ErrorUnknownCallbackResult(spec->grf_prop.grffile->grfid, Tbase::cb_animation_speed, callback);
00050 animation_speed = Clamp(callback & 0xFF, 0, 16);
00051 }
00052 }
00053
00054
00055
00056
00057
00058 if (_tick_counter % (1 << animation_speed) != 0) return;
00059
00060 uint8 frame = GetAnimationFrame(tile);
00061 uint8 num_frames = spec->animation.frames;
00062
00063 bool frame_set_by_callback = false;
00064
00065 if (HasBit(spec->callback_mask, Tbase::cbm_animation_next_frame)) {
00066 uint16 callback = GetCallback(Tbase::cb_animation_next_frame, random_animation ? Random() : 0, 0, spec, obj, tile, extra_data);
00067
00068 if (callback != CALLBACK_FAILED) {
00069 frame_set_by_callback = true;
00070
00071 switch (callback & 0xFF) {
00072 case 0xFF:
00073 DeleteAnimatedTile(tile);
00074 break;
00075
00076 case 0xFE:
00077 frame_set_by_callback = false;
00078 break;
00079
00080 default:
00081 frame = callback & 0xFF;
00082 break;
00083 }
00084
00085
00086
00087 if (GB(callback, 8, 7) != 0) PlayTileSound(spec->grf_prop.grffile, GB(callback, 8, 7), tile);
00088 }
00089 }
00090
00091 if (!frame_set_by_callback) {
00092 if (frame < num_frames) {
00093 frame++;
00094 } else if (frame == num_frames && spec->animation.status == ANIM_STATUS_LOOPING) {
00095
00096 frame = 0;
00097 } else {
00098
00099 DeleteAnimatedTile(tile);
00100 }
00101 }
00102
00103 SetAnimationFrame(tile, frame);
00104 MarkTileDirtyByTile(tile);
00105 }
00106
00119 static void ChangeAnimationFrame(CallbackID cb, const Tspec *spec, Tobj *obj, TileIndex tile, uint32 random_bits, uint32 trigger, Textra extra_data = 0)
00120 {
00121 uint16 callback = GetCallback(cb, random_bits, trigger, spec, obj, tile, extra_data);
00122 if (callback == CALLBACK_FAILED) return;
00123
00124 switch (callback & 0xFF) {
00125 case 0xFD: break;
00126 case 0xFE: AddAnimatedTile(tile); break;
00127 case 0xFF: DeleteAnimatedTile(tile); break;
00128 default:
00129 SetAnimationFrame(tile, callback);
00130 AddAnimatedTile(tile);
00131 break;
00132 }
00133
00134
00135
00136 if (GB(callback, 8, 7) != 0) PlayTileSound(spec->grf_prop.grffile, GB(callback, 8, 7), tile);
00137 }
00138 };