diff -r 5a8b295aa345 -r 4cc327ad39d5 src/industry_cmd.cpp --- a/src/industry_cmd.cpp Tue Mar 27 23:27:27 2007 +0000 +++ b/src/industry_cmd.cpp Sat Jun 02 19:59:29 2007 +0000 @@ -37,6 +37,28 @@ static byte _industry_sound_ctr; static TileIndex _industry_sound_tile; +IndustrySpec _industry_specs[NUM_INDUSTRYTYPES]; +IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES]; + +/** This function initialize the spec arrays of both + * industry and industry tiles. + * It adjusts the enabling of the industry too, based on climate availability. + * This will allow for clearer testings */ +void ResetIndustries() +{ + memset(&_industry_specs, 0, sizeof(_industry_specs)); + memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs)); + + /* once performed, enable only the current climate industries */ + for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) { + _industry_specs[i].enabled = HASBIT(_origin_industry_specs[i].climate_availability, _opt.landscape); + } + + + memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs)); + memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs)); +} + /** * Called if a new block is added to the industry-pool */ @@ -55,26 +77,16 @@ * Retrieve the type for this industry. Although it is accessed by a tile, * it will return the general type of industry, and not the sprite index * as would do GetIndustryGfx. - * The same information can be accessed by looking at Industry->type * @param tile that is queried * @pre IsTileType(tile, MP_INDUSTRY) * @return general type for this industry, as defined in industry.h **/ IndustryType GetIndustryType(TileIndex tile) { - IndustryGfx this_type = GetIndustryGfx(tile); - IndustryType iloop; - assert(IsTileType(tile, MP_INDUSTRY)); - for (iloop = IT_COAL_MINE; iloop < IT_END; iloop += 1) { - if (IS_BYTE_INSIDE(this_type, industry_gfx_Solver[iloop].MinGfx, - industry_gfx_Solver[iloop].MaxGfx+1)) { - return iloop; - } - } - - return IT_INVALID; //we have not found equivalent, whatever the reason + const Industry *ind = GetIndustryByTile(tile); + return IsValidIndustry(ind) ? ind->type : (IndustryType)IT_INVALID; } /** @@ -82,12 +94,12 @@ * This will ensure at once : proper access and * not allowing modifications of it. * @param thistype of industry (which is the index in _industry_specs) - * @pre thistype < IT_END + * @pre thistype < NUM_INDUSTRYTYPES * @return a pointer to the corresponding industry spec **/ const IndustrySpec *GetIndustrySpec(IndustryType thistype) { - assert(thistype < IT_END); + assert(thistype < NUM_INDUSTRYTYPES); return &_industry_specs[thistype]; } @@ -96,12 +108,12 @@ * This will ensure at once : proper access and * not allowing modifications of it. * @param gfx of industrytile (which is the index in _industry_specs) - * @pre gfx < NUM_INDUSTRY_GFXES + * @pre gfx < INVALID_INDUSTRYTILE * @return a pointer to the corresponding industrytile spec **/ const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx) { - assert(gfx < NUM_INDUSTRY_GFXES); + assert(gfx < INVALID_INDUSTRYTILE); return &_industry_tile_specs[gfx]; } @@ -117,7 +129,7 @@ } END_TILE_LOOP(tile_cur, i->width, i->height, i->xy); - if (i->type == IT_FARM || i->type == IT_FARM_2) { + if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) { /* Remove the farmland and convert it to regular tiles over time. */ BEGIN_TILE_LOOP(tile_cur, 42, 42, i->xy - TileDiffXY(21, 21)) { tile_cur = TILE_MASK(tile_cur); @@ -137,8 +149,7 @@ static void IndustryDrawSugarMine(const TileInfo *ti) { - const DrawIndustrySpec1Struct *d; - uint32 image; + const DrawIndustryAnimationStruct *d; if (!IsIndustryCompleted(ti->tile)) return; @@ -146,23 +157,23 @@ AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0); - image = d->image_2; - if (image != 0) AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + image - 1, PAL_NONE, 8, 41); + if (d->image_2 != 0) { + AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41); + } - image = d->image_3; - if (image != 0) { - AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + image - 1, PAL_NONE, - _drawtile_proc1_x[image - 1], _drawtile_proc1_y[image - 1]); + if (d->image_3 != 0) { + AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE, + _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y); } } static void IndustryDrawToffeeQuarry(const TileInfo *ti) { - int x = 0; + uint8 x = 0; if (IsIndustryCompleted(ti->tile)) { - x = _industry_anim_offs[GetIndustryAnimationState(ti->tile)]; - if ( (byte)x == 0xFF) + x = _industry_anim_offs_toffee[GetIndustryAnimationState(ti->tile)]; + if (x == 0xFF) x = 0; } @@ -173,7 +184,7 @@ static void IndustryDrawBubbleGenerator( const TileInfo *ti) { if (IsIndustryCompleted(ti->tile)) { - AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_2[GetIndustryAnimationState(ti->tile)]); + AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetIndustryAnimationState(ti->tile)]); } else { AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67); } @@ -181,12 +192,12 @@ static void IndustryDrawToyFactory(const TileInfo *ti) { - const DrawIndustrySpec4Struct *d; + const DrawIndustryAnimationStruct *d; - d = &_industry_anim_offs_3[GetIndustryAnimationState(ti->tile)]; + d = &_industry_anim_offs_toys[GetIndustryAnimationState(ti->tile)]; if (d->image_1 != 0xFF) { - AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, 50 - d->image_1 * 2, 96 + d->image_1); + AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1); } if (d->image_2 != 0xFF) { @@ -200,13 +211,13 @@ static void IndustryDrawCoalPlantSparks(const TileInfo *ti) { if (IsIndustryCompleted(ti->tile)) { - uint image = GetIndustryAnimationState(ti->tile); + uint8 image = GetIndustryAnimationState(ti->tile); if (image != 0 && image < 7) { AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS, PAL_NONE, - _coal_plant_sparks_x[image - 1], - _coal_plant_sparks_y[image - 1] + _coal_plant_sparks[image - 1].x, + _coal_plant_sparks[image - 1].y ); } } @@ -259,7 +270,7 @@ /* Add industry on top of the ground? */ image = dits->building.sprite; if (image != 0) { - if (_display_opt & DO_TRANS_BUILDINGS) { + if (HASBIT(_transparent_opt, TO_INDUSTRIES)) { SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); pal = PALETTE_TO_TRANSPARENT; } else { @@ -274,7 +285,7 @@ dits->dz, z); - if (_display_opt & DO_TRANS_BUILDINGS) return; + if (HASBIT(_transparent_opt, TO_INDUSTRIES)) return; } { @@ -298,14 +309,10 @@ const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile)); CargoID a; - a = itspec->accepts_cargo[0]; - if (a != CT_INVALID) ac[a] = (a == CT_PASSENGERS) ? 1 : 8; - - a = itspec->accepts_cargo[1]; - if (a != CT_INVALID) ac[a] = 8; - - a = itspec->accepts_cargo[2]; - if (a != CT_INVALID) ac[a] = 8; + for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) { + a = itspec->accepts_cargo[i]; + if (a != CT_INVALID) ac[a] = itspec->acceptance[i]; + } } static void GetTileDesc_Industry(TileIndex tile, TileDesc *td) @@ -323,6 +330,7 @@ static int32 ClearTile_Industry(TileIndex tile, byte flags) { Industry *i = GetIndustryByTile(tile); + const IndustrySpec *indspec = GetIndustrySpec(i->type); /* water can destroy industries * in editor you can bulldoze industries @@ -331,8 +339,8 @@ */ if ((_current_player != OWNER_WATER && _game_mode != GM_EDITOR && !_cheats.magic_bulldozer.value) || - (_current_player == OWNER_WATER && i->type == IT_OIL_RIG)) { - SetDParam(0, GetIndustrySpec(i->type)->name); + (_current_player == OWNER_WATER && (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER))) { + SetDParam(0, indspec->name); return_cmd_error(STR_4800_IN_THE_WAY); } @@ -355,12 +363,12 @@ i->last_mo_production[0] += cw; - am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[0], cw); + am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw); i->last_mo_transported[0] += am; if (am != 0) { uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production; - if (newgfx != INDUTILE_NOANIM) { + if (newgfx != INDUSTRYTILE_NOANIM) { ResetIndustryConstructionStage(tile); SetIndustryCompleted(tile, true); SetIndustryGfx(tile, newgfx); @@ -377,7 +385,7 @@ i->last_mo_production[1] += cw; - am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[1], cw); + am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[1], cw); i->last_mo_transported[1] += am; } } @@ -411,7 +419,7 @@ if ((_tick_counter & 3) == 0) { m = GetIndustryAnimationState(tile); - if (_industry_anim_offs[m] == 0xFF) { + if (_industry_anim_offs_toffee[m] == 0xFF) { SndPlayTileFx(SND_30_CARTOON_SOUND, tile); } @@ -457,23 +465,22 @@ if ((_tick_counter & 1) == 0) { m = GetIndustryAnimationState(tile) + 1; - if (m == 1) { - SndPlayTileFx(SND_2C_MACHINERY, tile); - } else if (m == 23) { - SndPlayTileFx(SND_2B_COMEDY_HIT, tile); - } else if (m == 28) { - SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); + switch (m) { + case 1: SndPlayTileFx(SND_2C_MACHINERY, tile); break; + case 23: SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break; + case 28: SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break; + default: + if (m >= 50) { + int n = GetIndustryAnimationLoop(tile) + 1; + m = 0; + if (n >= 8) { + n = 0; + DeleteAnimatedTile(tile); + } + SetIndustryAnimationLoop(tile, n); + } } - if (m >= 50) { - int n = GetIndustryAnimationLoop(tile) + 1; - m = 0; - if (n >= 8) { - n = 0; - DeleteAnimatedTile(tile); - } - SetIndustryAnimationLoop(tile, n); - } SetIndustryAnimationState(tile, m); MarkTileDirtyByTile(tile); } @@ -496,7 +503,7 @@ case GFX_OILWELL_ANIMATED_2: case GFX_OILWELL_ANIMATED_3: if ((_tick_counter & 7) == 0) { - bool b = CHANCE16(1,7); + bool b = CHANCE16(1, 7); IndustryGfx gfx = GetIndustryGfx(tile); m = GetIndustryAnimationState(tile) + 1; @@ -647,7 +654,7 @@ TransportIndustryGoods(tile); newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next; - if (newgfx != INDUTILE_NOANIM) { + if (newgfx != INDUSTRYTILE_NOANIM) { ResetIndustryConstructionStage(tile); SetIndustryGfx(tile, newgfx); MarkTileDirtyByTile(tile); @@ -705,7 +712,7 @@ break; case GFX_POWERPLANT_SPARKS: - if (CHANCE16(1,3)) { + if (CHANCE16(1, 3)) { SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile); AddAnimatedTile(tile); } @@ -746,14 +753,14 @@ ShowIndustryViewWindow(GetIndustryIndex(tile)); } -static uint32 GetTileTrackStatus_Industry(TileIndex tile, TransportType mode) +static uint32 GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode) { return 0; } static void GetProducedCargo_Industry(TileIndex tile, CargoID *b) { - const Industry *i = GetIndustryByTile(tile); + const IndustrySpec *i = GetIndustrySpec(GetIndustryByTile(tile)->type); b[0] = i->produced_cargo[0]; b[1] = i->produced_cargo[1]; @@ -916,57 +923,17 @@ i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + 45); ///< Found a tree, add according value to waiting cargo } -static const byte _industry_sounds[37][2] = { - {0}, - {0}, - {1, SND_28_SAWMILL}, - {0}, - {0}, - {0}, - {1, SND_03_FACTORY_WHISTLE}, - {1, SND_03_FACTORY_WHISTLE}, - {0}, - {3, SND_24_SHEEP}, - {0}, - {0}, - {0}, - {0}, - {1, SND_28_SAWMILL}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {1, SND_03_FACTORY_WHISTLE}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {0}, - {1, SND_33_PLASTIC_MINE}, - {0}, - {0}, - {0}, - {0}, -}; - - static void ProduceIndustryGoods(Industry *i) { uint32 r; uint num; + const IndustrySpec *indsp = GetIndustrySpec(i->type); /* play a sound? */ if ((i->counter & 0x3F) == 0) { - if (CHANCE16R(1,14,r) && (num=_industry_sounds[i->type][0]) != 0) { + if (CHANCE16R(1, 14, r) && (num = indsp->number_of_sounds) != 0) { SndPlayTileFx( - (SoundFx)(_industry_sounds[i->type][1] + (((r >> 16) * num) >> 16)), + (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]), i->xy); } } @@ -975,12 +942,13 @@ /* produce some cargo */ if ((i->counter & 0xFF) == 0) { + IndustyBehaviour indbehav = indsp->behaviour; i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + i->production_rate[0]); i->cargo_waiting[1] = min(0xffff, i->cargo_waiting[1] + i->production_rate[1]); - if (i->type == IT_FARM || i->type == IT_FARM_2) { + if (indbehav & INDUSTRYBEH_PLANT_FIELDS) { MaybePlantFarmField(i); - } else if (i->type == IT_LUMBER_MILL && (i->counter & 0x1FF) == 0) { + } else if ((indbehav & INDUSTRYBEH_CUT_TREES) && (i->counter & 0x1FF) == 0) { ChopLumberMillTrees(i); } } @@ -1156,8 +1124,12 @@ } } else { if (!EnsureNoVehicle(cur_tile)) return false; + IndustyBehaviour ind_behav = GetIndustrySpec(type)->behaviour; - if (type == IT_OIL_RIG) { + if (ind_behav & INDUSTRYBEH_BUILT_ONWATER) { + /* As soon as the tile is not water, bail out. + * But that does not mean the search is over. You have + * to make sure every tile of the industry will be only water*/ if (!IsClearWaterTile(cur_tile)) return false; } else { Slope tileh; @@ -1186,27 +1158,19 @@ } } - if (type == IT_BANK_TEMP) { + if (ind_behav & INDUSTRYBEH_ONLY_INTOWN) { if (!IsTileType(cur_tile, MP_HOUSE)) { _error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS; return false; } - } else if (type == IT_BANK_TROPIC_ARCTIC) { - if (!IsTileType(cur_tile, MP_HOUSE)) { - _error_message = STR_030D_CAN_ONLY_BE_BUILT_IN_TOWNS; - return false; + } else { + if (ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) { + if (!IsTileType(cur_tile, MP_HOUSE)) goto do_clear; + } else { +do_clear: + if (CmdFailed(DoCommand(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) + return false; } - } else if (type == IT_TOY_SHOP) { - if (!IsTileType(cur_tile, MP_HOUSE)) goto do_clear; - } else if (type == IT_WATER_TOWER) { - if (!IsTileType(cur_tile, MP_HOUSE)) { - _error_message = STR_0316_CAN_ONLY_BE_BUILT_IN_TOWNS; - return false; - } - } else { -do_clear: - if (CmdFailed(DoCommand(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) - return false; } } } @@ -1217,12 +1181,12 @@ static bool CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t) { - if (type == IT_BANK_TEMP && t->population < 1200) { + if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->population < 1200) { _error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS; return false; } - if (type == IT_TOY_SHOP && DistanceMax(t->xy, tile) > 9) { + if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) { _error_message = STR_0239_SITE_UNSUITABLE; return false; } @@ -1337,7 +1301,7 @@ /* check if an industry that accepts the same goods is nearby */ if (DistanceMax(tile, i->xy) <= 14 && indspec->accepts_cargo[0] != CT_INVALID && - indspec->accepts_cargo[0] == i->accepts_cargo[0] && ( + indspec->accepts_cargo[0] == indspec->accepts_cargo[0] && ( _game_mode != GM_EDITOR || !_patches.same_industry_close || !_patches.multiple_industry_per_town @@ -1388,11 +1352,6 @@ i->width = i->height = 0; i->type = type; - i->produced_cargo[0] = indspec->produced_cargo[0]; - i->produced_cargo[1] = indspec->produced_cargo[1]; - i->accepts_cargo[0] = indspec->accepts_cargo[0]; - i->accepts_cargo[1] = indspec->accepts_cargo[1]; - i->accepts_cargo[2] = indspec->accepts_cargo[2]; i->production_rate[0] = indspec->production_rate[0]; i->production_rate[1] = indspec->production_rate[1]; @@ -1450,7 +1409,7 @@ i->width++; i->height++; - if (i->type == IT_FARM || i->type == IT_FARM_2) { + if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) { for (j = 0; j != 50; j++) PlantRandomFarmField(i); } _industry_sort_dirty = true; @@ -1511,7 +1470,9 @@ indspec = GetIndustrySpec(p1); /* Check if the to-be built/founded industry is available for this climate. */ - if (!HASBIT(indspec->climate_availability, _opt_ptr->landscape)) return CMD_ERROR; + if (!indspec->enabled) { + return CMD_ERROR; + } /* If the patch for raw-material industries is not on, you cannot build raw-material industries. * Raw material industries are industries that do not accept cargo (at least for now) @@ -1520,7 +1481,7 @@ indspec->accepts_cargo[0] == CT_INVALID && indspec->accepts_cargo[1] == CT_INVALID && indspec->accepts_cargo[2] == CT_INVALID && - p1 != IT_LUMBER_MILL) { + !(indspec->behaviour & INDUSTRYBEH_CUT_TREES)) { return CMD_ERROR; } @@ -1545,24 +1506,26 @@ return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, it); } -static const byte _numof_industry_table[4][12] = { +static const byte _numof_industry_table[5][12] = { /* difficulty settings for number of industries */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //none + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //very low {0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5}, //low {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, //normal {0, 2, 3, 4, 6, 7, 8, 9, 10, 10, 10}, //high }; +/** This function is the one who really do the creation work + * of random industries during game creation + * @param type IndustryType of the desired industry + * @param amount of industries that need to be built */ static void PlaceInitialIndustry(IndustryType type, int amount) { int num = _numof_industry_table[_opt.diff.number_industries][amount]; + const IndustrySpec *ind_spc = GetIndustrySpec(type); - if (type == IT_OIL_REFINERY || type == IT_OIL_RIG) { - /* These are always placed next to the coastline, so we scale by the perimeter instead. */ - num = ScaleByMapSize1D(num); - } else { - num = ScaleByMapSize(num); - } + /* These are always placed next to the coastline, so we scale by the perimeter instead. */ + num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); if (_opt.diff.number_industries != 0) { PlayerID old_player = _current_player; @@ -1583,31 +1546,48 @@ } } +/** This function will create ramdon industries during game creation. + * It will scale the amount of industries by map size as well as difficulty level */ void GenerateIndustries() { - const byte *b; uint i = 0; + uint8 chance; + IndustryType it; + const IndustrySpec *ind_spc; /* Find the total amount of industries */ - b = _industry_create_table[_opt.landscape]; - do { - int num = _numof_industry_table[_opt.diff.number_industries][b[0]]; + for (it = IT_COAL_MINE; it < NUM_INDUSTRYTYPES; it++) { - if (b[1] == IT_OIL_REFINERY || b[1] == IT_OIL_RIG) { - /* These are always placed next to the coastline, so we scale by the perimeter instead. */ - num = ScaleByMapSize1D(num); - } else { - num = ScaleByMapSize(num); + ind_spc = GetIndustrySpec(it); + if (ind_spc->enabled) { + chance = ind_spc->appear_creation[_opt.landscape]; + if (chance > 0) { + /* once the chance of appearance is determind, it have to be scaled by + * the difficulty level. The "chance" in question is more an index into + * the _numof_industry_table,in fact */ + int num = _numof_industry_table[_opt.diff.number_industries][chance]; + + /* These are always placed next to the coastline, so we scale by the perimeter instead. */ + num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); + i += num; + } } + } - i += num; - } while ( (b+=2)[0] != 0); SetGeneratingWorldProgress(GWP_INDUSTRY, i); - b = _industry_create_table[_opt.landscape]; - do { - PlaceInitialIndustry(b[1], b[0]); - } while ( (b+=2)[0] != 0); + for (it = IT_COAL_MINE; it < NUM_INDUSTRYTYPES; it++) { + /* Once the number of industries has been determined, let's really create them. + * The test for chance allows us to try create industries that are available only + * for this landscape. + * @todo : Do we really have to pass chance as un-scaled value, since we've already + * processed that scaling above? No, don't think so. Will find a way. */ + ind_spc = GetIndustrySpec(it); + if (ind_spc->enabled) { + chance = ind_spc->appear_creation[_opt.landscape]; + if (chance > 0) PlaceInitialIndustry(it, chance); + } + }; } /* Change industry production or do closure */ @@ -1627,7 +1607,7 @@ break; default: /* INDUSTRY_PRODUCTION */ - for (j = 0; j < 2 && i->produced_cargo[j] != CT_INVALID; j++){ + for (j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){ uint32 r = Random(); int old_prod, new_prod, percent; int mag; @@ -1653,11 +1633,11 @@ mag = abs(percent); if (mag >= 10) { SetDParam(2, mag); - SetDParam(0, GetCargo(i->produced_cargo[j])->name); + SetDParam(0, GetCargo(indspec->produced_cargo[j])->name); SetDParam(1, i->index); AddNewsItem( percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN, - NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_ECONOMY, 0), + NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_ECONOMY, 0), i->xy + TileDiffXY(1, 1), 0 ); } @@ -1671,7 +1651,7 @@ SetDParam(0, i->index); AddNewsItem( indspec->closure_text, - NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_OPENCLOSE, 0), + NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), i->xy + TileDiffXY(1, 1), 0 ); } @@ -1681,39 +1661,28 @@ static void UpdateIndustryStatistics(Industry *i) { byte pct; + bool refresh = false; + const IndustrySpec *indsp = GetIndustrySpec(i->type); - if (i->produced_cargo[0] != CT_INVALID) { - pct = 0; - if (i->last_mo_production[0] != 0) { - i->last_prod_year = _cur_year; - pct = min(i->last_mo_transported[0] * 256 / i->last_mo_production[0],255); + for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) { + if (indsp->produced_cargo[j] != CT_INVALID) { + pct = 0; + if (i->last_mo_production[j] != 0) { + i->last_prod_year = _cur_year; + pct = min(i->last_mo_transported[j] * 256 / i->last_mo_production[j], 255); + } + i->pct_transported[j] = pct; + + i->total_production[j] = i->last_mo_production[j]; + i->last_mo_production[j] = 0; + + i->total_transported[j] = i->last_mo_transported[j]; + i->last_mo_transported[j] = 0; + refresh = true; } - i->pct_transported[0] = pct; - - i->total_production[0] = i->last_mo_production[0]; - i->last_mo_production[0] = 0; - - i->total_transported[0] = i->last_mo_transported[0]; - i->last_mo_transported[0] = 0; } - if (i->produced_cargo[1] != CT_INVALID) { - pct = 0; - if (i->last_mo_production[1] != 0) { - i->last_prod_year = _cur_year; - pct = min(i->last_mo_transported[1] * 256 / i->last_mo_production[1],255); - } - i->pct_transported[1] = pct; - - i->total_production[1] = i->last_mo_production[1]; - i->last_mo_production[1] = 0; - - i->total_transported[1] = i->last_mo_transported[1]; - i->last_mo_transported[1] = 0; - } - - - if (i->produced_cargo[0] != CT_INVALID || i->produced_cargo[1] != CT_INVALID) + if (refresh) InvalidateWindow(WC_INDUSTRY_VIEW, i->index); if (i->prod_level == 0) { @@ -1723,34 +1692,61 @@ } } -static const byte _new_industry_rand[4][32] = { - {12, 12, 12, 12, 12, 12, 12, 0, 0, 6, 6, 9, 9, 3, 3, 3, 18, 18, 4, 4, 2, 2, 5, 5, 5, 5, 5, 5, 1, 1, 8, 8}, - {16, 16, 16, 0, 0, 0, 9, 9, 9, 9, 13, 13, 3, 3, 3, 3, 15, 15, 15, 4, 4, 11, 11, 11, 11, 11, 14, 14, 1, 1, 7, 7}, - {21, 21, 21, 24, 22, 22, 22, 22, 23, 23, 16, 16, 16, 4, 4, 19, 19, 19, 13, 13, 20, 20, 20, 11, 11, 11, 17, 17, 17, 10, 10, 10}, - {30, 30, 30, 36, 36, 31, 31, 31, 27, 27, 27, 28, 28, 28, 26, 26, 26, 34, 34, 34, 35, 35, 35, 29, 29, 29, 32, 32, 32, 33, 33, 33}, +/** Simple helper that will collect data for the generation of industries */ +struct ProbabilityHelper { + uint16 prob; ///< probability + IndustryType ind; ///< industry id correcponding }; -static void MaybeNewIndustry(uint32 r) +/** + * Try to create a random industry, during gameplay + */ +static void MaybeNewIndustry(void) { - int type =_new_industry_rand[_opt.landscape][GB(r, 16, 5)]; - int j; - Industry *i; - const IndustrySpec *ind_spc = GetIndustrySpec(type);; + Industry *ind; //will receive the industry's creation pointer + IndustryType rndtype, j; // Loop controlers + const IndustrySpec *ind_spc; + uint num = 0; + ProbabilityHelper cumulative_probs[NUM_INDUSTRYTYPES]; // probability collector + uint16 probability_max = 0; - if (type == IT_OIL_WELL && _cur_year > 1950) return; - if (type == IT_OIL_RIG && _cur_year < 1960) return; + /* Generate a list of all possible industries that can be built. */ + for (j = 0; j < NUM_INDUSTRYTYPES; j++) { + byte chance = GetIndustrySpec(j)->appear_ingame[_opt.landscape]; - j = 2000; + /* if appearing chance for this landscape is above 0, this industry can be chosen */ + if (chance != 0) { + probability_max += chance; + /* adds the result for this industry */ + cumulative_probs[num].ind = j; + cumulative_probs[num++].prob = probability_max; + } + } + + /* Find a random type, with maximum being what has been evaluate above*/ + rndtype = RandomRange(probability_max); + for (j = 0; j < NUM_INDUSTRYTYPES; j++) { + /* and choose the index of the industry that matches as close as possible this random type */ + if (cumulative_probs[j].prob >= rndtype) break; + } + + ind_spc = GetIndustrySpec(cumulative_probs[j].ind); + /* Check if it is allowed */ + if ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) return; + if ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) return; + + /* try to create 2000 times this industry */ + num = 2000; for (;;) { - i = CreateNewIndustry(RandomTile(), type); - if (i != NULL) break; - if (--j == 0) return; + ind = CreateNewIndustry(RandomTile(), cumulative_probs[j].ind); + if (ind != NULL) break; + if (--num == 0) return; } SetDParam(0, ind_spc->name); - SetDParam(1, i->town->index); + SetDParam(1, ind->town->index); AddNewsItem(ind_spc->new_industry_text, - NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, NT_OPENCLOSE, 0), i->xy, 0); + NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0); } static void ChangeIndustryProduction(Industry *i) @@ -1766,12 +1762,12 @@ case INDUSTRYLIFE_PRODUCTION: /* decrease or increase */ - if (type == IT_OIL_WELL && _opt.landscape == LT_TEMPERATE) + if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE) only_decrease = true; - if (only_decrease || CHANCE16(1,3)) { + if (only_decrease || CHANCE16(1, 3)) { /* If you transport > 60%, 66% chance we increase, else 33% chance we increase */ - if (!only_decrease && (i->pct_transported[0] > 153) != CHANCE16(1,3)) { + if (!only_decrease && (i->pct_transported[0] > 153) != CHANCE16(1, 3)) { /* Increase production */ if (i->prod_level != 0x80) { byte b; @@ -1808,7 +1804,7 @@ case INDUSTRYLIFE_CLOSABLE: /* maybe close */ - if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1,2)) { + if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, 2)) { i->prod_level = 0; str = indspec->closure_text; } @@ -1817,7 +1813,7 @@ if (str != STR_NULL) { SetDParam(0, i->index); - AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_TILE, str == indspec->closure_text ? NT_OPENCLOSE : NT_ECONOMY, 0), i->xy + TileDiffXY(1, 1), 0); + AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, str == indspec->closure_text ? NT_OPENCLOSE : NT_ECONOMY, 0), i->xy + TileDiffXY(1, 1), 0); } } @@ -1833,7 +1829,7 @@ /* 3% chance that we start a new industry */ if (CHANCE16(3, 100)) { - MaybeNewIndustry(Random()); + MaybeNewIndustry(); } else if (!_patches.smooth_economy) { i = GetRandomIndustry(); if (i != NULL) ChangeIndustryProduction(i); @@ -1879,10 +1875,10 @@ SLE_VAR(Industry, width, SLE_UINT8), SLE_VAR(Industry, height, SLE_UINT8), SLE_REF(Industry, town, REF_TOWN), - SLE_ARR(Industry, produced_cargo, SLE_UINT8, 2), + SLE_CONDNULL( 2, 2, 60), ///< used to be industry's produced_cargo SLE_ARR(Industry, cargo_waiting, SLE_UINT16, 2), SLE_ARR(Industry, production_rate, SLE_UINT8, 2), - SLE_ARR(Industry, accepts_cargo, SLE_UINT8, 3), + SLE_CONDNULL( 3, 2, 60), ///< used to be industry's accepts_cargo SLE_VAR(Industry, prod_level, SLE_UINT8), SLE_ARR(Industry, last_mo_production, SLE_UINT16, 2), SLE_ARR(Industry, last_mo_transported, SLE_UINT16, 2),