industry_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: industry_cmd.cpp 14562 2008-11-03 20:23:51Z frosch $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "clear_map.h"
00008 #include "industry_map.h"
00009 #include "station_map.h"
00010 #include "train.h"
00011 #include "landscape.h"
00012 #include "viewport_func.h"
00013 #include "command_func.h"
00014 #include "industry.h"
00015 #include "town.h"
00016 #include "news_func.h"
00017 #include "saveload.h"
00018 #include "variables.h"
00019 #include "cheat_func.h"
00020 #include "genworld.h"
00021 #include "water_map.h"
00022 #include "tree_map.h"
00023 #include "cargotype.h"
00024 #include "newgrf.h"
00025 #include "newgrf_commons.h"
00026 #include "newgrf_industries.h"
00027 #include "newgrf_industrytiles.h"
00028 #include "newgrf_callbacks.h"
00029 #include "autoslope.h"
00030 #include "transparency.h"
00031 #include "water.h"
00032 #include "strings_func.h"
00033 #include "tile_cmd.h"
00034 #include "functions.h"
00035 #include "window_func.h"
00036 #include "date_func.h"
00037 #include "vehicle_func.h"
00038 #include "sound_func.h"
00039 #include "station_base.h"
00040 #include "oldpool_func.h"
00041 #include "animated_tile_func.h"
00042 #include "effectvehicle_func.h"
00043 
00044 #include "table/strings.h"
00045 #include "table/sprites.h"
00046 #include "table/industry_land.h"
00047 #include "table/build_industry.h"
00048 
00049 void ShowIndustryViewWindow(int industry);
00050 void BuildOilRig(TileIndex tile);
00051 
00052 static byte _industry_sound_ctr;
00053 static TileIndex _industry_sound_tile;
00054 
00055 int _total_industries;                      //general counter
00056 uint16 _industry_counts[NUM_INDUSTRYTYPES]; // Number of industries per type ingame
00057 
00058 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
00059 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
00060 
00065 void ResetIndustries()
00066 {
00067   memset(&_industry_specs, 0, sizeof(_industry_specs));
00068   memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
00069 
00070   /* once performed, enable only the current climate industries */
00071   for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
00072     _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
00073         HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
00074   }
00075 
00076   memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
00077   memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
00078 
00079   /* Reset any overrides that have been set. */
00080   _industile_mngr.ResetOverride();
00081   _industry_mngr.ResetOverride();
00082 }
00083 
00084 void ResetIndustryCreationProbility(IndustryType type)
00085 {
00086   assert(type < INVALID_INDUSTRYTYPE);
00087   _industry_specs[type].appear_creation[_settings_game.game_creation.landscape] = 0;
00088 }
00089 
00090 DEFINE_OLD_POOL_GENERIC(Industry, Industry)
00091 
00092 
00100 IndustryType GetIndustryType(TileIndex tile)
00101 {
00102   assert(IsTileType(tile, MP_INDUSTRY));
00103 
00104   const Industry *ind = GetIndustryByTile(tile);
00105   return ind->IsValid() ? ind->type : (IndustryType)IT_INVALID;
00106 }
00107 
00116 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
00117 {
00118   assert(thistype < NUM_INDUSTRYTYPES);
00119   return &_industry_specs[thistype];
00120 }
00121 
00130 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
00131 {
00132   assert(gfx < INVALID_INDUSTRYTILE);
00133   return &_industry_tile_specs[gfx];
00134 }
00135 
00136 Industry::~Industry()
00137 {
00138   if (CleaningPool()) return;
00139 
00140   /* Industry can also be destroyed when not fully initialized.
00141    * This means that we do not have to clear tiles either. */
00142   if (this->width == 0) {
00143     this->xy = 0;
00144     return;
00145   }
00146 
00147   BEGIN_TILE_LOOP(tile_cur, this->width, this->height, this->xy);
00148     if (IsTileType(tile_cur, MP_INDUSTRY)) {
00149       if (GetIndustryIndex(tile_cur) == this->index) {
00150         /* MakeWaterKeepingClass() can also handle 'land' */
00151         MakeWaterKeepingClass(tile_cur, OWNER_NONE);
00152       }
00153     } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
00154       DeleteOilRig(tile_cur);
00155     }
00156   END_TILE_LOOP(tile_cur, this->width, this->height, this->xy);
00157 
00158   if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
00159     /* Remove the farmland and convert it to regular tiles over time. */
00160     BEGIN_TILE_LOOP(tile_cur, 42, 42, this->xy - TileDiffXY(21, 21)) {
00161       tile_cur = TILE_MASK(tile_cur);
00162       if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
00163           GetIndustryIndexOfField(tile_cur) == this->index) {
00164         SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
00165       }
00166     } END_TILE_LOOP(tile_cur, 42, 42, this->xy - TileDiff(21, 21))
00167   }
00168 
00169   DecIndustryTypeCount(this->type);
00170 
00171   DeleteSubsidyWithIndustry(this->index);
00172   DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
00173   InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
00174   this->xy = 0;
00175 }
00176 
00177 static void IndustryDrawSugarMine(const TileInfo *ti)
00178 {
00179   const DrawIndustryAnimationStruct *d;
00180 
00181   if (!IsIndustryCompleted(ti->tile)) return;
00182 
00183   d = &_draw_industry_spec1[GetIndustryAnimationState(ti->tile)];
00184 
00185   AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
00186 
00187   if (d->image_2 != 0) {
00188     AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
00189   }
00190 
00191   if (d->image_3 != 0) {
00192     AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
00193       _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
00194   }
00195 }
00196 
00197 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
00198 {
00199   uint8 x = 0;
00200 
00201   if (IsIndustryCompleted(ti->tile)) {
00202     x = _industry_anim_offs_toffee[GetIndustryAnimationState(ti->tile)];
00203     if (x == 0xFF)
00204       x = 0;
00205   }
00206 
00207   AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
00208   AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
00209 }
00210 
00211 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
00212 {
00213   if (IsIndustryCompleted(ti->tile)) {
00214     AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetIndustryAnimationState(ti->tile)]);
00215   } else {
00216     AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
00217   }
00218 }
00219 
00220 static void IndustryDrawToyFactory(const TileInfo *ti)
00221 {
00222   const DrawIndustryAnimationStruct *d;
00223 
00224   d = &_industry_anim_offs_toys[GetIndustryAnimationState(ti->tile)];
00225 
00226   if (d->image_1 != 0xFF) {
00227     AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
00228   }
00229 
00230   if (d->image_2 != 0xFF) {
00231     AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
00232   }
00233 
00234   AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
00235   AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
00236 }
00237 
00238 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
00239 {
00240   if (IsIndustryCompleted(ti->tile)) {
00241     uint8 image = GetIndustryAnimationState(ti->tile);
00242 
00243     if (image != 0 && image < 7) {
00244       AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
00245         PAL_NONE,
00246         _coal_plant_sparks[image - 1].x,
00247         _coal_plant_sparks[image - 1].y
00248       );
00249     }
00250   }
00251 }
00252 
00253 typedef void IndustryDrawTileProc(const TileInfo *ti);
00254 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
00255   IndustryDrawSugarMine,
00256   IndustryDrawToffeeQuarry,
00257   IndustryDrawBubbleGenerator,
00258   IndustryDrawToyFactory,
00259   IndustryDrawCoalPlantSparks,
00260 };
00261 
00262 static void DrawTile_Industry(TileInfo *ti)
00263 {
00264   IndustryGfx gfx = GetIndustryGfx(ti->tile);
00265   Industry *ind = GetIndustryByTile(ti->tile);
00266   const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
00267   const DrawBuildingsTileStruct *dits;
00268   SpriteID image;
00269   SpriteID pal;
00270 
00271   /* Retrieve pointer to the draw industry tile struct */
00272   if (gfx >= NEW_INDUSTRYTILEOFFSET) {
00273     /* Draw the tile using the specialized method of newgrf industrytile.
00274      * DrawNewIndustry will return false if ever the resolver could not
00275      * find any sprite to display.  So in this case, we will jump on the
00276      * substitute gfx instead. */
00277     if (indts->grf_prop.spritegroup != NULL && DrawNewIndustryTile(ti, ind, gfx, indts)) {
00278       return;
00279     } else {
00280       /* No sprite group (or no valid one) found, meaning no graphics associated.
00281        * Use the substitute one instead */
00282       if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
00283         gfx = indts->grf_prop.subst_id;
00284         /* And point the industrytile spec accordingly */
00285         indts = GetIndustryTileSpec(gfx);
00286       }
00287     }
00288   }
00289 
00290   dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
00291       GetIndustryAnimationState(ti->tile) & INDUSTRY_COMPLETED :
00292       GetIndustryConstructionStage(ti->tile))];
00293 
00294   image = dits->ground.sprite;
00295   if (HasBit(image, PALETTE_MODIFIER_COLOR) && dits->ground.pal == PAL_NONE) {
00296     pal = GENERAL_SPRITE_COLOR(ind->random_color);
00297   } else {
00298     pal = dits->ground.pal;
00299   }
00300 
00301   /* DrawFoundation() modifes ti->z and ti->tileh */
00302   if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
00303 
00304   /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
00305    * Do not do this if the tile's WaterClass is 'land'. */
00306   if (image == SPR_FLAT_WATER_TILE && IsIndustryTileOnWater(ti->tile)) {
00307     DrawWaterClassGround(ti);
00308   } else {
00309     DrawGroundSprite(image, pal);
00310   }
00311 
00312   /* If industries are transparent and invisible, do not draw the upper part */
00313   if (IsInvisibilitySet(TO_INDUSTRIES)) return;
00314 
00315   /* Add industry on top of the ground? */
00316   image = dits->building.sprite;
00317   if (image != 0) {
00318     AddSortableSpriteToDraw(image,
00319       (HasBit(image, PALETTE_MODIFIER_COLOR) && dits->building.pal == PAL_NONE) ? GENERAL_SPRITE_COLOR(ind->random_color) : dits->building.pal,
00320       ti->x + dits->subtile_x,
00321       ti->y + dits->subtile_y,
00322       dits->width,
00323       dits->height,
00324       dits->dz,
00325       ti->z,
00326       IsTransparencySet(TO_INDUSTRIES));
00327 
00328     if (IsTransparencySet(TO_INDUSTRIES)) return;
00329   }
00330 
00331   {
00332     int proc = dits->draw_proc - 1;
00333     if (proc >= 0) _industry_draw_tile_procs[proc](ti);
00334   }
00335 }
00336 
00337 static uint GetSlopeZ_Industry(TileIndex tile, uint x, uint y)
00338 {
00339   return GetTileMaxZ(tile);
00340 }
00341 
00342 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
00343 {
00344   IndustryGfx gfx = GetIndustryGfx(tile);
00345 
00346   /* For NewGRF industry tiles we might not be drawing a foundation. We need to
00347    * account for this, as other structures should
00348    * draw the wall of the foundation in this case.
00349    */
00350   if (gfx >= NEW_INDUSTRYTILEOFFSET) {
00351     const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
00352     if (indts->grf_prop.spritegroup != NULL && HasBit(indts->callback_flags, CBM_INDT_DRAW_FOUNDATIONS)) {
00353       uint32 callback_res = GetIndustryTileCallback(CBID_INDUSTRY_DRAW_FOUNDATIONS, 0, 0, gfx, GetIndustryByTile(tile), tile);
00354       if (callback_res == 0) return FOUNDATION_NONE;
00355     }
00356   }
00357   return FlatteningFoundation(tileh);
00358 }
00359 
00360 static void GetAcceptedCargo_Industry(TileIndex tile, AcceptedCargo ac)
00361 {
00362   IndustryGfx gfx = GetIndustryGfx(tile);
00363   const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
00364 
00365   /* When we have to use a callback, we put our data in the next two variables */
00366   CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)];
00367   uint8 raw_acceptance[lengthof(itspec->acceptance)];
00368 
00369   /* And then these will always point to a same sized array with the required data */
00370   const CargoID *accepts_cargo = itspec->accepts_cargo;
00371   const uint8 *acceptance = itspec->acceptance;
00372 
00373   if (HasBit(itspec->callback_flags, CBM_INDT_ACCEPT_CARGO)) {
00374     uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, GetIndustryByTile(tile), tile);
00375     if (res != CALLBACK_FAILED) {
00376       accepts_cargo = raw_accepts_cargo;
00377       for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
00378     }
00379   }
00380 
00381   if (HasBit(itspec->callback_flags, CBM_INDT_CARGO_ACCEPTANCE)) {
00382     uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, GetIndustryByTile(tile), tile);
00383     if (res != CALLBACK_FAILED) {
00384       acceptance = raw_acceptance;
00385       for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_acceptance[i] = GB(res, i * 4, 4);
00386     }
00387   }
00388 
00389   for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
00390     CargoID a = accepts_cargo[i];
00391     /* Only set the value once. */
00392     if (a != CT_INVALID && ac[a] == 0) ac[a] = acceptance[i];
00393   }
00394 }
00395 
00396 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
00397 {
00398   const Industry *i = GetIndustryByTile(tile);
00399   const IndustrySpec *is = GetIndustrySpec(i->type);
00400 
00401   td->owner[0] = i->owner;
00402   td->str = is->name;
00403   if (!IsIndustryCompleted(tile)) {
00404     SetDParamX(td->dparam, 0, td->str);
00405     td->str = STR_2058_UNDER_CONSTRUCTION;
00406   }
00407 
00408   if (is->grf_prop.grffile != NULL) {
00409     td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->name;
00410   }
00411 }
00412 
00413 static CommandCost ClearTile_Industry(TileIndex tile, byte flags)
00414 {
00415   Industry *i = GetIndustryByTile(tile);
00416   const IndustrySpec *indspec = GetIndustrySpec(i->type);
00417 
00418   /* water can destroy industries
00419    * in editor you can bulldoze industries
00420    * with magic_bulldozer cheat you can destroy industries
00421    * (area around OILRIG is water, so water shouldn't flood it
00422    */
00423   if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
00424       !_cheats.magic_bulldozer.value) ||
00425       ((flags & DC_AUTO) != 0) ||
00426       (_current_company == OWNER_WATER &&
00427         ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
00428         HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
00429     SetDParam(0, indspec->name);
00430     return_cmd_error(STR_4800_IN_THE_WAY);
00431   }
00432 
00433   if (flags & DC_EXEC) delete i;
00434   return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
00435 }
00436 
00437 static void TransportIndustryGoods(TileIndex tile)
00438 {
00439   Industry *i = GetIndustryByTile(tile);
00440   const IndustrySpec *indspec = GetIndustrySpec(i->type);
00441   bool moved_cargo = false;
00442 
00443   for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
00444     uint cw = min(i->produced_cargo_waiting[j], 255);
00445     if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
00446       i->produced_cargo_waiting[j] -= cw;
00447 
00448       /* fluctuating economy? */
00449       if (_economy.fluct <= 0) cw = (cw + 1) / 2;
00450 
00451       i->this_month_production[j] += cw;
00452 
00453       uint am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[j], cw);
00454       i->this_month_transported[j] += am;
00455 
00456       moved_cargo |= (am != 0);
00457     }
00458   }
00459 
00460   if (moved_cargo && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
00461     uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
00462 
00463     if (newgfx != INDUSTRYTILE_NOANIM) {
00464       ResetIndustryConstructionStage(tile);
00465       SetIndustryCompleted(tile, true);
00466       SetIndustryGfx(tile, newgfx);
00467       MarkTileDirtyByTile(tile);
00468     }
00469   }
00470 }
00471 
00472 
00473 static void AnimateTile_Industry(TileIndex tile)
00474 {
00475   byte m;
00476   IndustryGfx gfx = GetIndustryGfx(tile);
00477 
00478   if (GetIndustryTileSpec(gfx)->animation_info != 0xFFFF) {
00479     AnimateNewIndustryTile(tile);
00480     return;
00481   }
00482 
00483   switch (gfx) {
00484   case GFX_SUGAR_MINE_SIEVE:
00485     if ((_tick_counter & 1) == 0) {
00486       m = GetIndustryAnimationState(tile) + 1;
00487 
00488       switch (m & 7) {
00489       case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
00490       case 6: SndPlayTileFx(SND_29_RIP, tile); break;
00491       }
00492 
00493       if (m >= 96) {
00494         m = 0;
00495         DeleteAnimatedTile(tile);
00496       }
00497       SetIndustryAnimationState(tile, m);
00498 
00499       MarkTileDirtyByTile(tile);
00500     }
00501     break;
00502 
00503   case GFX_TOFFEE_QUARY:
00504     if ((_tick_counter & 3) == 0) {
00505       m = GetIndustryAnimationState(tile);
00506 
00507       if (_industry_anim_offs_toffee[m] == 0xFF) {
00508         SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
00509       }
00510 
00511       if (++m >= 70) {
00512         m = 0;
00513         DeleteAnimatedTile(tile);
00514       }
00515       SetIndustryAnimationState(tile, m);
00516 
00517       MarkTileDirtyByTile(tile);
00518     }
00519     break;
00520 
00521   case GFX_BUBBLE_CATCHER:
00522     if ((_tick_counter & 1) == 0) {
00523       m = GetIndustryAnimationState(tile);
00524 
00525       if (++m >= 40) {
00526         m = 0;
00527         DeleteAnimatedTile(tile);
00528       }
00529       SetIndustryAnimationState(tile, m);
00530 
00531       MarkTileDirtyByTile(tile);
00532     }
00533     break;
00534 
00535   /* Sparks on a coal plant */
00536   case GFX_POWERPLANT_SPARKS:
00537     if ((_tick_counter & 3) == 0) {
00538       m = GetIndustryAnimationState(tile);
00539       if (m == 6) {
00540         SetIndustryAnimationState(tile, 0);
00541         DeleteAnimatedTile(tile);
00542       } else {
00543         SetIndustryAnimationState(tile, m + 1);
00544         MarkTileDirtyByTile(tile);
00545       }
00546     }
00547     break;
00548 
00549   case GFX_TOY_FACTORY:
00550     if ((_tick_counter & 1) == 0) {
00551       m = GetIndustryAnimationState(tile) + 1;
00552 
00553       switch (m) {
00554         case  1: SndPlayTileFx(SND_2C_MACHINERY, tile); break;
00555         case 23: SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
00556         case 28: SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
00557         default:
00558           if (m >= 50) {
00559             int n = GetIndustryAnimationLoop(tile) + 1;
00560             m = 0;
00561             if (n >= 8) {
00562               n = 0;
00563               DeleteAnimatedTile(tile);
00564             }
00565             SetIndustryAnimationLoop(tile, n);
00566           }
00567       }
00568 
00569       SetIndustryAnimationState(tile, m);
00570       MarkTileDirtyByTile(tile);
00571     }
00572     break;
00573 
00574   case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
00575   case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
00576   case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
00577   case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
00578     if ((_tick_counter & 3) == 0) {
00579       IndustryGfx gfx = GetIndustryGfx(tile);
00580 
00581       gfx = (gfx < 155) ? gfx + 1 : 148;
00582       SetIndustryGfx(tile, gfx);
00583       MarkTileDirtyByTile(tile);
00584     }
00585     break;
00586 
00587   case GFX_OILWELL_ANIMATED_1:
00588   case GFX_OILWELL_ANIMATED_2:
00589   case GFX_OILWELL_ANIMATED_3:
00590     if ((_tick_counter & 7) == 0) {
00591       bool b = Chance16(1, 7);
00592       IndustryGfx gfx = GetIndustryGfx(tile);
00593 
00594       m = GetIndustryAnimationState(tile) + 1;
00595       if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
00596         SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
00597         SetIndustryConstructionStage(tile, 3);
00598         DeleteAnimatedTile(tile);
00599       } else {
00600         SetIndustryAnimationState(tile, m);
00601         SetIndustryGfx(tile, gfx);
00602         MarkTileDirtyByTile(tile);
00603       }
00604     }
00605     break;
00606 
00607   case GFX_COAL_MINE_TOWER_ANIMATED:
00608   case GFX_COPPER_MINE_TOWER_ANIMATED:
00609   case GFX_GOLD_MINE_TOWER_ANIMATED: {
00610       int state = _tick_counter & 0x7FF;
00611 
00612       if ((state -= 0x400) < 0)
00613         return;
00614 
00615       if (state < 0x1A0) {
00616         if (state < 0x20 || state >= 0x180) {
00617           m = GetIndustryAnimationState(tile);
00618           if (!(m & 0x40)) {
00619             SetIndustryAnimationState(tile, m | 0x40);
00620             SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
00621           }
00622           if (state & 7)
00623             return;
00624         } else {
00625           if (state & 3)
00626             return;
00627         }
00628         m = (GetIndustryAnimationState(tile) + 1) | 0x40;
00629         if (m > 0xC2) m = 0xC0;
00630         SetIndustryAnimationState(tile, m);
00631         MarkTileDirtyByTile(tile);
00632       } else if (state >= 0x200 && state < 0x3A0) {
00633         int i;
00634         i = (state < 0x220 || state >= 0x380) ? 7 : 3;
00635         if (state & i)
00636           return;
00637 
00638         m = (GetIndustryAnimationState(tile) & 0xBF) - 1;
00639         if (m < 0x80) m = 0x82;
00640         SetIndustryAnimationState(tile, m);
00641         MarkTileDirtyByTile(tile);
00642       }
00643     } break;
00644   }
00645 }
00646 
00647 static void CreateChimneySmoke(TileIndex tile)
00648 {
00649   uint x = TileX(tile) * TILE_SIZE;
00650   uint y = TileY(tile) * TILE_SIZE;
00651   uint z = GetTileMaxZ(tile);
00652 
00653   CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
00654 }
00655 
00656 static void MakeIndustryTileBigger(TileIndex tile)
00657 {
00658   byte cnt = GetIndustryConstructionCounter(tile) + 1;
00659   byte stage;
00660 
00661   if (cnt != 4) {
00662     SetIndustryConstructionCounter(tile, cnt);
00663     return;
00664   }
00665 
00666   stage = GetIndustryConstructionStage(tile) + 1;
00667   SetIndustryConstructionCounter(tile, 0);
00668   SetIndustryConstructionStage(tile, stage);
00669   StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
00670   if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile, true);
00671 
00672   MarkTileDirtyByTile(tile);
00673 
00674   if (!IsIndustryCompleted(tile)) return;
00675 
00676   IndustryGfx gfx = GetIndustryGfx(tile);
00677   if (gfx >= NEW_INDUSTRYTILEOFFSET) {
00678     /* New industries are already animated on construction. */
00679     return;
00680   }
00681 
00682   switch (gfx) {
00683   case GFX_POWERPLANT_CHIMNEY:
00684     CreateChimneySmoke(tile);
00685     break;
00686 
00687   case GFX_OILRIG_1:
00688     if (GetIndustryGfx(tile + TileDiffXY(0, 1)) == GFX_OILRIG_1) BuildOilRig(tile);
00689     break;
00690 
00691   case GFX_TOY_FACTORY:
00692   case GFX_BUBBLE_CATCHER:
00693   case GFX_TOFFEE_QUARY:
00694     SetIndustryAnimationState(tile, 0);
00695     SetIndustryAnimationLoop(tile, 0);
00696     break;
00697 
00698   case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
00699   case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
00700   case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
00701   case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
00702     AddAnimatedTile(tile);
00703     break;
00704   }
00705 }
00706 
00707 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
00708 {
00709   int dir;
00710   Vehicle *v;
00711   static const int8 _bubble_spawn_location[3][4] = {
00712     { 11,   0, -4, -14 },
00713     { -4, -10, -4,   1 },
00714     { 49,  59, 60,  65 },
00715   };
00716 
00717   SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
00718 
00719   dir = Random() & 3;
00720 
00721   v = CreateEffectVehicleAbove(
00722     TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
00723     TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
00724     _bubble_spawn_location[2][dir],
00725     EV_BUBBLE
00726   );
00727 
00728   if (v != NULL) v->u.effect.animation_substate = dir;
00729 }
00730 
00731 static void TileLoop_Industry(TileIndex tile)
00732 {
00733   IndustryGfx newgfx;
00734   IndustryGfx gfx;
00735 
00736   if (IsIndustryTileOnWater(tile)) TileLoop_Water(tile);
00737 
00738   TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
00739 
00740   if (!IsIndustryCompleted(tile)) {
00741     MakeIndustryTileBigger(tile);
00742     return;
00743   }
00744 
00745   if (_game_mode == GM_EDITOR) return;
00746 
00747   TransportIndustryGoods(tile);
00748 
00749   if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
00750 
00751   newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
00752   if (newgfx != INDUSTRYTILE_NOANIM) {
00753     ResetIndustryConstructionStage(tile);
00754     SetIndustryGfx(tile, newgfx);
00755     MarkTileDirtyByTile(tile);
00756     return;
00757   }
00758 
00759   gfx = GetIndustryGfx(tile);
00760 
00761   switch (gfx) {
00762   case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
00763   case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
00764   case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
00765     if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
00766       switch (gfx) {
00767         case GFX_COAL_MINE_TOWER_NOT_ANIMATED:   gfx = GFX_COAL_MINE_TOWER_ANIMATED;   break;
00768         case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
00769         case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:   gfx = GFX_GOLD_MINE_TOWER_ANIMATED;   break;
00770       }
00771       SetIndustryGfx(tile, gfx);
00772       SetIndustryAnimationState(tile, 0x80);
00773       AddAnimatedTile(tile);
00774     }
00775     break;
00776 
00777   case GFX_OILWELL_NOT_ANIMATED:
00778     if (Chance16(1, 6)) {
00779       SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
00780       SetIndustryAnimationState(tile, 0);
00781       AddAnimatedTile(tile);
00782     }
00783     break;
00784 
00785   case GFX_COAL_MINE_TOWER_ANIMATED:
00786   case GFX_COPPER_MINE_TOWER_ANIMATED:
00787   case GFX_GOLD_MINE_TOWER_ANIMATED:
00788     if (!(_tick_counter & 0x400)) {
00789       switch (gfx) {
00790         case GFX_COAL_MINE_TOWER_ANIMATED:   gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED;   break;
00791         case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
00792         case GFX_GOLD_MINE_TOWER_ANIMATED:   gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED;   break;
00793       }
00794       SetIndustryGfx(tile, gfx);
00795       SetIndustryCompleted(tile, true);
00796       SetIndustryConstructionStage(tile, 3);
00797       DeleteAnimatedTile(tile);
00798     }
00799     break;
00800 
00801   case GFX_POWERPLANT_SPARKS:
00802     if (Chance16(1, 3)) {
00803       SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
00804       AddAnimatedTile(tile);
00805     }
00806     break;
00807 
00808   case GFX_COPPER_MINE_CHIMNEY:
00809     CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_SMOKE);
00810     break;
00811 
00812 
00813   case GFX_TOY_FACTORY: {
00814       Industry *i = GetIndustryByTile(tile);
00815       if (i->was_cargo_delivered) {
00816         i->was_cargo_delivered = false;
00817         SetIndustryAnimationLoop(tile, 0);
00818         AddAnimatedTile(tile);
00819       }
00820     }
00821     break;
00822 
00823   case GFX_BUBBLE_GENERATOR:
00824     TileLoopIndustry_BubbleGenerator(tile);
00825     break;
00826 
00827   case GFX_TOFFEE_QUARY:
00828     AddAnimatedTile(tile);
00829     break;
00830 
00831   case GFX_SUGAR_MINE_SIEVE:
00832     if (Chance16(1, 3)) AddAnimatedTile(tile);
00833     break;
00834   }
00835 }
00836 
00837 static void ClickTile_Industry(TileIndex tile)
00838 {
00839   ShowIndustryViewWindow(GetIndustryIndex(tile));
00840 }
00841 
00842 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00843 {
00844   return 0;
00845 }
00846 
00847 static void GetProducedCargo_Industry(TileIndex tile, CargoID *b)
00848 {
00849   const Industry *i = GetIndustryByTile(tile);
00850 
00851   b[0] = i->produced_cargo[0];
00852   b[1] = i->produced_cargo[1];
00853 }
00854 
00855 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
00856 {
00857   /* If the founder merges, the industry was created by the merged company */
00858   Industry *i = GetIndustryByTile(tile);
00859   if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
00860 }
00861 
00862 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
00863 
00864 static bool IsBadFarmFieldTile(TileIndex tile)
00865 {
00866   switch (GetTileType(tile)) {
00867     case MP_CLEAR: return IsClearGround(tile, CLEAR_FIELDS) || IsClearGround(tile, CLEAR_SNOW) || IsClearGround(tile, CLEAR_DESERT);
00868     case MP_TREES: return (GetTreeGround(tile) == TREE_GROUND_SHORE);
00869     default:       return true;
00870   }
00871 }
00872 
00873 static bool IsBadFarmFieldTile2(TileIndex tile)
00874 {
00875   switch (GetTileType(tile)) {
00876     case MP_CLEAR: return IsClearGround(tile, CLEAR_SNOW) || IsClearGround(tile, CLEAR_DESERT);
00877     case MP_TREES: return (GetTreeGround(tile) == TREE_GROUND_SHORE);
00878     default:       return true;
00879   }
00880 }
00881 
00882 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction)
00883 {
00884   do {
00885     tile = TILE_MASK(tile);
00886 
00887     if (IsTileType(tile, MP_CLEAR) || IsTileType(tile,