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