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 "functions.h"
00018 #include "newgrf_animation_type.h"
00019 #include "newgrf_callbacks.h"
00020
00028 template <typename Tbase, typename Tspec, typename Tobj, uint16 (*GetCallback)(CallbackID callback, uint32 param1, uint32 param2, const Tspec *statspec, const Tobj *st, TileIndex tile)>
00029 struct AnimationBase {
00038 static void AnimateTile(const Tspec *spec, const Tobj *obj, TileIndex tile, bool random_animation)
00039 {
00040 assert(spec != NULL);
00041
00042
00043 uint8 animation_speed = spec->animation.speed;
00044 if (HasBit(spec->callback_mask, Tbase::cbm_animation_speed)) {
00045 uint16 callback = GetCallback(Tbase::cb_animation_speed, 0, 0, spec, obj, tile);
00046 if (callback != CALLBACK_FAILED) animation_speed = Clamp(callback & 0xFF, 0, 16);
00047 }
00048
00049
00050
00051
00052
00053 if (_tick_counter % (1 << animation_speed) != 0) return;
00054
00055 uint8 frame = GetAnimationFrame(tile);
00056 uint8 num_frames = spec->animation.frames;
00057
00058 bool frame_set_by_callback = false;
00059
00060 if (HasBit(spec->callback_mask, Tbase::cbm_animation_next_frame)) {
00061 uint16 callback = GetCallback(Tbase::cb_animation_next_frame, random_animation ? Random() : 0, 0, spec, obj, tile);
00062
00063 if (callback != CALLBACK_FAILED) {
00064 frame_set_by_callback = true;
00065
00066 switch (callback & 0xFF) {
00067 case 0xFF:
00068 DeleteAnimatedTile(tile);
00069 break;
00070
00071 case 0xFE:
00072 frame_set_by_callback = false;
00073 break;
00074
00075 default:
00076 frame = callback & 0xFF;
00077 break;
00078 }
00079
00080
00081
00082 if (GB(callback, 8, 7) != 0) PlayTileSound(spec->grf_prop.grffile, GB(callback, 8, 7), tile);
00083 }
00084 }
00085
00086 if (!frame_set_by_callback) {
00087 if (frame < num_frames) {
00088 frame++;
00089 } else if (frame == num_frames && spec->animation.status == ANIM_STATUS_LOOPING) {
00090
00091 frame = 0;
00092 } else {
00093
00094 DeleteAnimatedTile(tile);
00095 }
00096 }
00097
00098 SetAnimationFrame(tile, frame);
00099 MarkTileDirtyByTile(tile);
00100 }
00101
00113 static void ChangeAnimationFrame(CallbackID cb, const Tspec *spec, const Tobj *obj, TileIndex tile, uint32 random_bits, uint32 trigger)
00114 {
00115 uint16 callback = GetCallback(cb, random_bits, trigger, spec, obj, tile);
00116 if (callback == CALLBACK_FAILED) return;
00117
00118 switch (callback & 0xFF) {
00119 case 0xFD: break;
00120 case 0xFE: AddAnimatedTile(tile); break;
00121 case 0xFF: DeleteAnimatedTile(tile); break;
00122 default:
00123 SetAnimationFrame(tile, callback);
00124 AddAnimatedTile(tile);
00125 break;
00126 }
00127
00128
00129
00130 if (GB(callback, 8, 7) != 0) PlayTileSound(spec->grf_prop.grffile, GB(callback, 8, 7), tile);
00131 }
00132 };