mirror of https://github.com/OpenTTD/OpenTTD
(svn r10508) -Codechange: allow customizable animation schemes for industries.
parent
8d4b7ac33b
commit
79d04412b0
|
@ -36,6 +36,7 @@
|
||||||
#include "newgrf_sound.h"
|
#include "newgrf_sound.h"
|
||||||
#include "newgrf_callbacks.h"
|
#include "newgrf_callbacks.h"
|
||||||
#include "newgrf_industries.h"
|
#include "newgrf_industries.h"
|
||||||
|
#include "newgrf_industrytiles.h"
|
||||||
#include "unmovable.h"
|
#include "unmovable.h"
|
||||||
#include "date.h"
|
#include "date.h"
|
||||||
#include "cargotype.h"
|
#include "cargotype.h"
|
||||||
|
@ -1251,6 +1252,8 @@ static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pie
|
||||||
best->produced_cargo_waiting[0] = min(best->produced_cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF);
|
best->produced_cargo_waiting[0] = min(best->produced_cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF);
|
||||||
best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF);
|
best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StartStopIndustryTileAnimation(best, IAT_INDUSTRY_RECEIVED_CARGO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,10 @@ struct IndustryTileSpec {
|
||||||
///< state instead of the construction state
|
///< state instead of the construction state
|
||||||
/* Newgrf data */
|
/* Newgrf data */
|
||||||
uint8 callback_flags; ///< Flags telling which grf callback is set
|
uint8 callback_flags; ///< Flags telling which grf callback is set
|
||||||
|
uint16 animation_info; ///< Information about the animation (is it looping, how many loops etc)
|
||||||
|
uint8 animation_speed; ///< The speed of the animation
|
||||||
|
uint8 animation_triggers; ///< When to start the animation
|
||||||
|
uint8 animation_special_flags; ///< Extra flags to influence the animation
|
||||||
bool enabled; ///< entity still avaible (by default true).newgrf can disable it, though
|
bool enabled; ///< entity still avaible (by default true).newgrf can disable it, though
|
||||||
struct GRFFileProps grf_prop;
|
struct GRFFileProps grf_prop;
|
||||||
};
|
};
|
||||||
|
|
|
@ -413,7 +413,7 @@ static void TransportIndustryGoods(TileIndex tile)
|
||||||
|
|
||||||
am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw);
|
am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw);
|
||||||
i->this_month_transported[0] += am;
|
i->this_month_transported[0] += am;
|
||||||
if (am != 0) {
|
if (am != 0 && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
|
||||||
uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
|
uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
|
||||||
|
|
||||||
if (newgfx != INDUSTRYTILE_NOANIM) {
|
if (newgfx != INDUSTRYTILE_NOANIM) {
|
||||||
|
@ -442,8 +442,14 @@ static void TransportIndustryGoods(TileIndex tile)
|
||||||
static void AnimateTile_Industry(TileIndex tile)
|
static void AnimateTile_Industry(TileIndex tile)
|
||||||
{
|
{
|
||||||
byte m;
|
byte m;
|
||||||
|
IndustryGfx gfx = GetIndustryGfx(tile);
|
||||||
|
|
||||||
switch (GetIndustryGfx(tile)) {
|
if (GetIndustryTileSpec(gfx)->animation_info != 0xFFFF) {
|
||||||
|
AnimateNewIndustryTile(tile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (gfx) {
|
||||||
case GFX_SUGAR_MINE_SIEVE:
|
case GFX_SUGAR_MINE_SIEVE:
|
||||||
if ((_tick_counter & 1) == 0) {
|
if ((_tick_counter & 1) == 0) {
|
||||||
m = GetIndustryAnimationState(tile) + 1;
|
m = GetIndustryAnimationState(tile) + 1;
|
||||||
|
@ -629,6 +635,7 @@ static void MakeIndustryTileBigger(TileIndex tile)
|
||||||
stage = GetIndustryConstructionStage(tile) + 1;
|
stage = GetIndustryConstructionStage(tile) + 1;
|
||||||
SetIndustryConstructionCounter(tile, 0);
|
SetIndustryConstructionCounter(tile, 0);
|
||||||
SetIndustryConstructionStage(tile, stage);
|
SetIndustryConstructionStage(tile, stage);
|
||||||
|
StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
|
||||||
if (stage == 3) {
|
if (stage == 3) {
|
||||||
SetIndustryCompleted(tile, true);
|
SetIndustryCompleted(tile, true);
|
||||||
}
|
}
|
||||||
|
@ -637,7 +644,15 @@ static void MakeIndustryTileBigger(TileIndex tile)
|
||||||
|
|
||||||
if (!IsIndustryCompleted(tile)) return;
|
if (!IsIndustryCompleted(tile)) return;
|
||||||
|
|
||||||
switch (GetIndustryGfx(tile)) {
|
IndustryGfx gfx = GetIndustryGfx(tile);
|
||||||
|
if (gfx >= NEW_INDUSTRYTILEOFFSET) {
|
||||||
|
/* New industry */
|
||||||
|
const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
|
||||||
|
if (its->animation_info != 0xFFFF) AddAnimatedTile(tile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (gfx) {
|
||||||
case GFX_POWERPLANT_CHIMNEY:
|
case GFX_POWERPLANT_CHIMNEY:
|
||||||
CreateIndustryEffectSmoke(tile);
|
CreateIndustryEffectSmoke(tile);
|
||||||
break;
|
break;
|
||||||
|
@ -701,6 +716,8 @@ static void TileLoop_Industry(TileIndex tile)
|
||||||
|
|
||||||
TransportIndustryGoods(tile);
|
TransportIndustryGoods(tile);
|
||||||
|
|
||||||
|
if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
|
||||||
|
|
||||||
newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
|
newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
|
||||||
if (newgfx != INDUSTRYTILE_NOANIM) {
|
if (newgfx != INDUSTRYTILE_NOANIM) {
|
||||||
ResetIndustryConstructionStage(tile);
|
ResetIndustryConstructionStage(tile);
|
||||||
|
@ -1032,6 +1049,7 @@ void OnTick_Industry()
|
||||||
if (_game_mode == GM_EDITOR) return;
|
if (_game_mode == GM_EDITOR) return;
|
||||||
|
|
||||||
FOR_ALL_INDUSTRIES(i) {
|
FOR_ALL_INDUSTRIES(i) {
|
||||||
|
StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
|
||||||
ProduceIndustryGoods(i);
|
ProduceIndustryGoods(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1765,19 +1765,19 @@ static bool IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, byte **b
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0F: // Animation information
|
case 0x0F: // Animation information
|
||||||
grf_load_word(&buf); // TODO
|
tsp->animation_info = grf_load_word(&buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10: // Animation speed
|
case 0x10: // Animation speed
|
||||||
grf_load_byte(&buf); // TODO
|
tsp->animation_speed = grf_load_byte(&buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x11: // Triggers for callback 25
|
case 0x11: // Triggers for callback 25
|
||||||
grf_load_byte(&buf); // TODO
|
tsp->animation_triggers = grf_load_byte(&buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12: // Special flags
|
case 0x12: // Special flags
|
||||||
grf_load_byte(&buf); // TODO
|
tsp->animation_special_flags = grf_load_byte(&buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -85,13 +85,13 @@ enum CallbackID {
|
||||||
CBID_STATION_TILE_LAYOUT = 0x24,
|
CBID_STATION_TILE_LAYOUT = 0x24,
|
||||||
|
|
||||||
/** Called for periodically starting or stopping the animation. */
|
/** Called for periodically starting or stopping the animation. */
|
||||||
CBID_INDTILE_ANIM_START_STOP = 0x25, // not implemented
|
CBID_INDTILE_ANIM_START_STOP = 0x25,
|
||||||
|
|
||||||
/** Called to determine industry tile next animation frame. */
|
/** Called to determine industry tile next animation frame. */
|
||||||
CBID_INDTILE_ANIM_NEXT_FRAME = 0x26, // not implemented
|
CBID_INDTILE_ANIM_NEXT_FRAME = 0x26,
|
||||||
|
|
||||||
/** Called to indicate how long the current animation frame should last. */
|
/** Called to indicate how long the current animation frame should last. */
|
||||||
CBID_INDTILE_ANIMATION_SPEED = 0x27, // not implemented
|
CBID_INDTILE_ANIMATION_SPEED = 0x27,
|
||||||
|
|
||||||
/** Called to determine if the given industry can be built on specific area. */
|
/** Called to determine if the given industry can be built on specific area. */
|
||||||
CBID_INDUSTRY_LOCATION = 0x28,
|
CBID_INDUSTRY_LOCATION = 0x28,
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "newgrf_spritegroup.h"
|
#include "newgrf_spritegroup.h"
|
||||||
#include "newgrf_callbacks.h"
|
#include "newgrf_callbacks.h"
|
||||||
#include "newgrf_industries.h"
|
#include "newgrf_industries.h"
|
||||||
|
#include "newgrf_industrytiles.h"
|
||||||
#include "newgrf_text.h"
|
#include "newgrf_text.h"
|
||||||
#include "industry_map.h"
|
#include "industry_map.h"
|
||||||
#include "clear_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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -5,8 +5,20 @@
|
||||||
#ifndef NEWGRF_INDUSTRYTILES_H
|
#ifndef NEWGRF_INDUSTRYTILES_H
|
||||||
#define NEWGRF_INDUSTRYTILES_H
|
#define NEWGRF_INDUSTRYTILES_H
|
||||||
|
|
||||||
|
enum IndustryAnimationTrigger {
|
||||||
|
IAT_CONSTRUCTION_STATE_CHANGE,
|
||||||
|
IAT_TILELOOP,
|
||||||
|
IAT_INDUSTRY_TICK,
|
||||||
|
IAT_INDUSTRY_RECEIVED_CARGO,
|
||||||
|
IAT_INDUSTRY_DISTRIBUTES_CARGO,
|
||||||
|
};
|
||||||
|
|
||||||
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds);
|
bool DrawNewIndustryTile(TileInfo *ti, Industry *i, IndustryGfx gfx, const IndustryTileSpec *inds);
|
||||||
uint16 GetIndustryTileCallback(uint16 callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile);
|
uint16 GetIndustryTileCallback(uint16 callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile);
|
||||||
bool PerformIndustryTileSlopeCheck(TileIndex tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx);
|
bool PerformIndustryTileSlopeCheck(TileIndex tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx);
|
||||||
|
|
||||||
|
void AnimateNewIndustryTile(TileIndex tile);
|
||||||
|
bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random = Random());
|
||||||
|
bool StartStopIndustryTileAnimation(const Industry *ind, IndustryAnimationTrigger iat);
|
||||||
|
|
||||||
#endif /* NEWGRF_INDUSTRYTILES_H */
|
#endif /* NEWGRF_INDUSTRYTILES_H */
|
||||||
|
|
|
@ -1532,7 +1532,7 @@ static const IndustrySpec _origin_industry_specs[NEW_INDUSTRYOFFSET] = {
|
||||||
* @param a2 next frame of animation
|
* @param a2 next frame of animation
|
||||||
* @param a3 chooses between animation or construction state
|
* @param a3 chooses between animation or construction state
|
||||||
*/
|
*/
|
||||||
#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) {{c1, c2, c3}, {ca1, ca2, ca3}, sl, a1, a2, a3, 0, true, {0, 0, NULL, NULL, 0}}
|
#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) {{c1, c2, c3}, {ca1, ca2, ca3}, sl, a1, a2, a3, 0, 0xFFFF, 2, 0, 0, true, {0, 0, NULL, NULL, 0}}
|
||||||
static const IndustryTileSpec _origin_industry_tile_specs[NEW_INDUSTRYTILEOFFSET] = {
|
static const IndustryTileSpec _origin_industry_tile_specs[NEW_INDUSTRYTILEOFFSET] = {
|
||||||
/* Coal Mine */
|
/* Coal Mine */
|
||||||
MT(0, CT_INVALID, 0, CT_INVALID, 0, CT_INVALID, SLOPE_STEEP, INDUSTRYTILE_NOANIM, INDUSTRYTILE_NOANIM, false),
|
MT(0, CT_INVALID, 0, CT_INVALID, 0, CT_INVALID, SLOPE_STEEP, INDUSTRYTILE_NOANIM, INDUSTRYTILE_NOANIM, false),
|
||||||
|
|
Loading…
Reference in New Issue