# HG changeset patch # User rubidium # Date 2007-07-05 05:41:56 # Node ID 156fd244b919e2cf2faf0ccfa0b9db4e2765cfe2 # Parent 05d674bf4070770611bf53c323eaaa1cca31885c (svn r10442) -Codechange: implement the industry production callback. diff --git a/src/economy.cpp b/src/economy.cpp --- a/src/economy.cpp +++ b/src/economy.cpp @@ -35,6 +35,7 @@ #include "newgrf_engine.h" #include "newgrf_sound.h" #include "newgrf_callbacks.h" +#include "newgrf_industries.h" #include "unmovable.h" #include "date.h" #include "cargotype.h" @@ -1239,7 +1240,7 @@ static void DeliverGoodsToIndustry(TileI if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(callback, CBM_IND_PRODUCTION_256_TICKS)) { best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF); - if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {} ///< @todo Perform some magic + if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) IndustryProductionCallback(ind, 0); } else { 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); diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -30,6 +30,7 @@ #include "water_map.h" #include "tree_map.h" #include "cargotype.h" +#include "newgrf_industries.h" #include "newgrf_industrytiles.h" #include "newgrf_callbacks.h" @@ -965,6 +966,8 @@ static void ProduceIndustryGoods(Industr /* produce some cargo */ if ((i->counter & 0xFF) == 0) { + if (HASBIT(indsp->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1); + IndustyBehaviour indbehav = indsp->behaviour; i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]); i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]); diff --git a/src/newgrf.cpp b/src/newgrf.cpp --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2287,6 +2287,35 @@ static void NewSpriteGroup(byte *buf, in break; } + case GSF_INDUSTRIES: { + if (type > 1) { + grfmsg(1, "NewSpriteGroup: Unsupported industry production version %d, skipping", type); + break; + } + + group = AllocateSpriteGroup(); + group->type = SGT_INDUSTRY_PRODUCTION; + group->g.indprod.version = type; + if (type == 0) { + for (uint i = 0; i < 3; i++) { + group->g.indprod.substract_input[i] = grf_load_word(&buf); + } + for (uint i = 0; i < 2; i++) { + group->g.indprod.add_output[i] = grf_load_word(&buf); + } + group->g.indprod.again = grf_load_byte(&buf); + } else { + for (uint i = 0; i < 3; i++) { + group->g.indprod.substract_input[i] = grf_load_byte(&buf); + } + for (uint i = 0; i < 2; i++) { + group->g.indprod.add_output[i] = grf_load_byte(&buf); + } + group->g.indprod.again = grf_load_byte(&buf); + } + break; + } + /* Loading of Tile Layout and Production Callback groups would happen here */ default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature); } diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -124,7 +124,7 @@ uint32 IndustryGetVariable(const Resolve case 0x42: { // waiting cargo, but only if those two callback flags are set uint16 callback = indspec->callback_flags; if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(callback, CBM_IND_PRODUCTION_256_TICKS)) { - return max(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0x7FFF); + return max(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0xFFFF); } else { return 0; } @@ -263,3 +263,40 @@ uint16 GetIndustryCallback(uint16 callba return group->g.callback.result; } + +static int32 DerefIndProd(uint field, bool use_register) +{ + return use_register ? (int32)GetRegister(field) : field; +} + +/** + * Get the industry production callback and apply it to the industry. + * @param ind the industry this callback has to be called for + * @param reason the reason it is called (0 = incoming cargo, 1 = periodic tick callback) + */ +void IndustryProductionCallback(Industry *ind, int reason) +{ + ResolverObject object; + NewIndustryResolver(&object, INVALID_TILE, ind); + object.callback_param2 = reason; + + for (uint loop = 0;; loop++) { + SB(object.callback_param2, 8, 16, loop); + const SpriteGroup *group = Resolve(GetIndustrySpec(ind->type)->grf_prop.spritegroup, &object); + if (group == NULL || group->type != SGT_INDUSTRY_PRODUCTION) break; + + bool deref = (group->g.indprod.version == 1); + + for (uint i = 0; i < 3; i++) { + ind->incoming_cargo_waiting[i] = clamp(ind->incoming_cargo_waiting[i] - DerefIndProd(group->g.indprod.substract_input[i], deref), 0, 0xFFFF); + } + for (uint i = 0; i < 2; i++) { + ind->produced_cargo_waiting[i] = clamp(ind->produced_cargo_waiting[i] + DerefIndProd(group->g.indprod.add_output[i], deref), 0, 0xFFFF); + } + + int32 again = DerefIndProd(group->g.indprod.again, deref); + if (again == 0) break; + + SB(object.callback_param2, 24, 8, again); + } +} diff --git a/src/newgrf_industries.h b/src/newgrf_industries.h --- a/src/newgrf_industries.h +++ b/src/newgrf_industries.h @@ -12,6 +12,7 @@ uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available); uint16 GetIndustryCallback(uint16 callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile); uint32 GetIndustryIDAtOffset(TileIndex new_tile, TileIndex old_tile, const Industry *i); +void IndustryProductionCallback(Industry *ind, int reason); /* in newgrf_industrytiles.cpp*/ uint32 IndustryTileGetRandomBits(const ResolverObject *object); diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -76,7 +76,7 @@ void InitializeSpriteGroupPool() _spritegroup_count = 0; } -static uint32 _temp_store[0x110]; +uint32 _temp_store[0x110]; static inline uint32 GetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -8,6 +8,19 @@ #include "town.h" #include "industry.h" +/** + * Gets the value of a so-called newgrf "register". + * @param i index of the register + * @pre i < 0x110 + * @return the value of the register + */ +static inline uint32 GetRegister(uint i) +{ + assert(i < 0x110); + extern uint32 _temp_store[0x110]; + return _temp_store[i]; +} + struct SpriteGroup; @@ -135,6 +148,13 @@ struct TileLayoutSpriteGroup { struct DrawTileSprites *dts; }; +struct IndustryProductionSpriteGroup { + uint8 version; + uint16 substract_input[3]; + uint16 add_output[2]; + uint8 again; +}; + /* List of different sprite group types */ enum SpriteGroupType { SGT_INVALID, @@ -144,6 +164,7 @@ enum SpriteGroupType { SGT_CALLBACK, SGT_RESULT, SGT_TILELAYOUT, + SGT_INDUSTRY_PRODUCTION, }; /* Common wrapper for all the different sprite group types */ @@ -157,6 +178,7 @@ struct SpriteGroup { CallbackResultSpriteGroup callback; ResultSpriteGroup result; TileLayoutSpriteGroup layout; + IndustryProductionSpriteGroup indprod; } g; };