Translations update
[openttd/fttd.git] / src / industry_cmd.cpp
blob1cec2135b6b073d360264d3ce4b9df821cfeb1a5
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file industry_cmd.cpp Handling of industry tiles. */
12 #include "stdafx.h"
13 #include "map/ground.h"
14 #include "map/bridge.h"
15 #include "industry.h"
16 #include "station_base.h"
17 #include "landscape.h"
18 #include "viewport_func.h"
19 #include "command_func.h"
20 #include "town.h"
21 #include "news_func.h"
22 #include "cheat_type.h"
23 #include "genworld.h"
24 #include "newgrf_cargo.h"
25 #include "newgrf_debug.h"
26 #include "newgrf_industrytiles.h"
27 #include "autoslope.h"
28 #include "water.h"
29 #include "strings_func.h"
30 #include "window_func.h"
31 #include "date_func.h"
32 #include "vehicle_func.h"
33 #include "sound_func.h"
34 #include "animated_tile_func.h"
35 #include "effectvehicle_func.h"
36 #include "effectvehicle_base.h"
37 #include "ai/ai.hpp"
38 #include "core/pool_func.hpp"
39 #include "subsidy_func.h"
40 #include "core/backup_type.hpp"
41 #include "object_base.h"
42 #include "game/game.hpp"
43 #include "station_func.h"
44 #include "error.h"
46 #include "table/strings.h"
47 #include "table/industry_land.h"
48 #include "table/build_industry.h"
50 template<> Industry::Pool Industry::PoolItem::pool ("Industry");
51 INSTANTIATE_POOL_METHODS(Industry)
53 void ShowIndustryViewWindow(int industry);
54 void BuildOilRig(TileIndex tile);
56 static byte _industry_sound_ctr;
57 static TileIndex _industry_sound_tile;
59 uint16 Industry::counts[NUM_INDUSTRYTYPES];
61 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
62 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
63 IndustryBuildData _industry_builder; ///< In-game manager of industries.
65 /**
66 * This function initialize the spec arrays of both
67 * industry and industry tiles.
68 * It adjusts the enabling of the industry too, based on climate availability.
69 * This will allow for clearer testings
71 void ResetIndustries()
73 memset(&_industry_specs, 0, sizeof(_industry_specs));
74 memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
76 /* once performed, enable only the current climate industries */
77 for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
78 _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
79 HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
82 memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
83 memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
85 /* Reset any overrides that have been set. */
86 _industile_mngr.ResetOverride();
87 _industry_mngr.ResetOverride();
90 /**
91 * Retrieve the type for this industry. Although it is accessed by a tile,
92 * it will return the general type of industry, and not the sprite index
93 * as would do GetIndustryGfx.
94 * @param tile that is queried
95 * @pre IsIndustryTile(tile)
96 * @return general type for this industry, as defined in industry.h
98 IndustryType GetIndustryType(TileIndex tile)
100 assert(IsIndustryTile(tile));
102 const Industry *ind = Industry::GetByTile(tile);
103 assert(ind != NULL);
104 return ind->type;
108 * Accessor for array _industry_specs.
109 * This will ensure at once : proper access and
110 * not allowing modifications of it.
111 * @param thistype of industry (which is the index in _industry_specs)
112 * @pre thistype < NUM_INDUSTRYTYPES
113 * @return a pointer to the corresponding industry spec
115 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
117 assert(thistype < NUM_INDUSTRYTYPES);
118 return &_industry_specs[thistype];
122 * Accessor for array _industry_tile_specs.
123 * This will ensure at once : proper access and
124 * not allowing modifications of it.
125 * @param gfx of industrytile (which is the index in _industry_tile_specs)
126 * @pre gfx < INVALID_INDUSTRYTILE
127 * @return a pointer to the corresponding industrytile spec
129 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
131 assert(gfx < INVALID_INDUSTRYTILE);
132 return &_industry_tile_specs[gfx];
135 Industry::~Industry()
137 if (CleaningPool()) return;
139 /* Industry can also be destroyed when not fully initialized.
140 * This means that we do not have to clear tiles either.
141 * Also we must not decrement industry counts in that case. */
142 if (this->location.w == 0) return;
144 remove_from_tileset();
146 TILE_AREA_LOOP(tile_cur, this->location) {
147 if (IsIndustryTile(tile_cur)) {
148 if (GetIndustryIndex(tile_cur) == this->index) {
149 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur);
151 /* MakeWaterKeepingClass() can also handle 'land' */
152 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
154 } else if (IsStationTile(tile_cur) && IsOilRig(tile_cur)) {
155 DeleteOilRig(tile_cur);
159 if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
160 TileArea ta (this->location.tile);
161 ta.expand (21);
163 /* Remove the farmland and convert it to regular tiles over time. */
164 TILE_AREA_LOOP(tile_cur, ta) {
165 if (IsFieldsTile(tile_cur) &&
166 GetIndustryIndexOfField(tile_cur) == this->index) {
167 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
172 /* don't let any disaster vehicle target invalid industry */
173 ReleaseDisastersTargetingIndustry(this->index);
175 /* Clear the persistent storage. */
176 delete this->psa;
178 DecIndustryTypeCount(this->type);
180 DeleteIndustryNews(this->index);
181 DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
182 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
184 DeleteSubsidyWith(ST_INDUSTRY, this->index);
185 CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
189 * Invalidating some stuff after removing item from the pool.
190 * @param index index of deleted item
192 void Industry::PostDestructor(size_t index)
194 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
195 Station::RecomputeIndustriesNearForAll();
200 * Return a random valid industry.
201 * @return random industry, NULL if there are no industries
203 /* static */ Industry *Industry::GetRandom()
205 if (Industry::GetNumItems() == 0) return NULL;
206 int num = RandomRange((uint16)Industry::GetNumItems());
207 size_t index = MAX_UVALUE(size_t);
209 while (num >= 0) {
210 num--;
211 index++;
213 /* Make sure we have a valid industry */
214 while (!Industry::IsValidID(index)) {
215 index++;
216 assert(index < Industry::GetPoolSize());
220 return Industry::Get(index);
224 static void IndustryDrawSugarMine(const TileInfo *ti)
226 static const byte anim[96][4] = {
227 { 4, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
228 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 1 },
229 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 1, 1 },
230 { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 2 },
231 { 1, 2 }, { 1, 2 }, { 1, 2 }, { 1, 2 }, { 1, 2 }, { 1, 2 },
232 { 1, 2 }, { 1, 2 }, { 2, 2 }, { 2, 2 }, { 2, 3 }, { 2, 3 },
233 { 2, 3 }, { 2, 3 }, { 2, 3 }, { 2, 3 }, { 2, 3 }, { 2, 3 },
234 { 2, 3 }, { 2, 3 }, { 2, 3 }, { 2, 4 }, { 2, 4 }, { 2, 4 },
235 { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 },
236 { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 },
237 { 3, 4 }, { 3, 4 }, { 3, 4 }, { 3, 4 }, { 4, 4 }, { 4, 4 },
238 { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 },
239 { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 },
240 { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 },
241 { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 },
242 { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 }, { 4, 4 },
245 static const byte sieve_x[8] = { 8, 6, 4, 6, 8, 10, 12, 10 };
247 static const byte pile_offsets[5][2] = {
248 { 22, 73 }, { 17, 70 }, { 14, 69 }, { 10, 66 }, { 8, 41 },
251 if (!IsIndustryCompleted(ti->tile)) return;
253 byte m = GetAnimationFrame (ti->tile);
254 const byte *d = anim[m];
256 AddChildSpriteScreen (ti->vd, SPR_IT_SUGAR_MINE_SIEVE + d[0],
257 PAL_NONE, sieve_x[m % 8], 0);
259 if ((uint)(m - 1) < 66) {
260 AddChildSpriteScreen (ti->vd,
261 SPR_IT_SUGAR_MINE_CLOUDS + ((m - 1) % 6),
262 PAL_NONE, 8, 41);
265 if (d[1] != 0) {
266 AddChildSpriteScreen (ti->vd, SPR_IT_SUGAR_MINE_PILE + d[1] - 1, PAL_NONE,
267 pile_offsets[d[1] - 1][0], pile_offsets[d[1] - 1][1]);
271 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
273 static const byte anim[] = {
274 0, 0, 0, 0, 2, 4, 6, 8, 10, 9, 7, 5, 3, 1,
277 uint8 x = 0;
279 if (IsIndustryCompleted(ti->tile)) {
280 x = anim[GetAnimationFrame(ti->tile) % 14];
283 AddChildSpriteScreen (ti->vd, SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
284 AddChildSpriteScreen (ti->vd, SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
287 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
289 static const byte bubbles[] = {
290 68, 69, 71, 74, 77, 80, 83, 85, 86, 86,
291 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
292 86, 86, 85, 84, 83, 82, 81, 80, 79, 78,
293 77, 76, 75, 74, 73, 72, 71, 70, 69, 68,
296 if (IsIndustryCompleted(ti->tile)) {
297 AddChildSpriteScreen (ti->vd, SPR_IT_BUBBLE_GENERATOR_BUBBLE,
298 PAL_NONE, 5, bubbles[GetAnimationFrame(ti->tile)]);
300 AddChildSpriteScreen (ti->vd, SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
303 static void IndustryDrawToyFactory(const TileInfo *ti)
305 static const byte anim[][2] = {
306 { 255, 0 }, { 25, 0 }, { 24, 0 }, { 23, 0 }, { 22, 0 },
307 { 21, 0 }, { 20, 0 }, { 19, 0 }, { 18, 0 }, { 17, 0 },
308 { 16, 0 }, { 15, 0 }, { 14, 0 }, { 13, 0 }, { 12, 0 },
309 { 11, 0 }, { 10, 0 }, { 9, 0 }, { 8, 0 }, { 7, 0 },
310 { 7, 1 }, { 7, 2 }, { 7, 4 }, { 7, 6 }, { 7, 8 },
311 { 7, 11 }, { 7, 14 }, { 7, 17 }, { 7, 20 }, { 7, 24 },
312 { 100, 29 }, { 100, 24 }, { 100, 20 }, { 100, 17 }, { 100, 14 },
313 { 100, 11 }, { 100, 8 }, { 100, 6 }, { 100, 4 }, { 100, 2 },
314 { 100, 1 }, { 101, 0 }, { 102, 0 }, { 103, 0 }, { 104, 0 },
315 { 105, 0 }, { 106, 0 }, { 107, 0 }, { 108, 0 }, { 255, 0 },
318 const byte *b = anim[GetAnimationFrame(ti->tile)];
320 byte i = b[0];
321 int x, y;
322 SpriteID s;
323 if (i < 100) {
324 x = 2 * i;
325 y = 121 - i;
326 s = SPR_IT_TOY_FACTORY_CLAY;
327 } else if (i < 255) {
328 x = 216 - 2 * i;
329 y = i;
330 s = SPR_IT_TOY_FACTORY_ROBOT;
331 } else {
332 s = 0;
335 if (s != 0) AddChildSpriteScreen (ti->vd, s, PAL_NONE, x, y);
337 AddChildSpriteScreen (ti->vd, SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, b[1]);
338 AddChildSpriteScreen (ti->vd, SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
341 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
343 /* Spark positions. */
344 static const byte sparks[][2] = {
345 {11, 23}, {11, 11}, {14, 6}, {13, 3}, {18, 1}, {15, 0},
348 if (IsIndustryCompleted(ti->tile)) {
349 uint8 image = GetAnimationFrame(ti->tile);
351 if (image != 0 && image < 7) {
352 AddChildSpriteScreen (ti->vd, image + SPR_IT_POWER_PLANT_TRANSFORMERS,
353 PAL_NONE,
354 sparks[image - 1][0],
355 sparks[image - 1][1]
361 typedef void IndustryDrawTileProc(const TileInfo *ti);
362 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
363 IndustryDrawSugarMine,
364 IndustryDrawToffeeQuarry,
365 IndustryDrawBubbleGenerator,
366 IndustryDrawToyFactory,
367 IndustryDrawCoalPlantSparks,
370 static void DrawTile_Industry(TileInfo *ti)
372 IndustryGfx gfx = GetIndustryGfx(ti->tile);
373 Industry *ind = Industry::GetByTile(ti->tile);
374 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
376 /* Retrieve pointer to the draw industry tile struct */
377 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
378 /* Draw the tile using the specialized method of newgrf industrytile.
379 * DrawNewIndustry will return false if ever the resolver could not
380 * find any sprite to display. So in this case, we will jump on the
381 * substitute gfx instead. */
382 if (indts->grf_prop.spritegroup != NULL && DrawNewIndustryTile (ti, ind, gfx, indts)) {
383 return;
384 } else {
385 /* No sprite group (or no valid one) found, meaning no graphics associated.
386 * Use the substitute one instead */
387 if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
388 gfx = indts->grf_prop.subst_id;
389 /* And point the industrytile spec accordingly */
390 indts = GetIndustryTileSpec(gfx);
395 const uint64 dits = industry_draw_tile_data[gfx][(indts->anim_state ?
396 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
397 GetIndustryConstructionStage(ti->tile))];
399 SpriteID image = dits & (0xffff | (1 << PALETTE_MODIFIER_COLOUR));
401 /* DrawFoundation() modifies ti->z and ti->tileh */
402 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
404 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
405 * Do not do this if the tile's WaterClass is 'land'. */
406 if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
407 DrawWaterClassGround(ti);
408 } else {
409 DrawGroundSprite (ti, image, GroundSpritePaletteTransform (image, PAL_NONE, GENERAL_SPRITE_COLOUR(ind->random_colour)));
412 /* If industries are transparent and invisible, do not draw the upper part */
413 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
415 /* Add industry on top of the ground? */
416 image = (dits >> 32) & (0xffff | (1 << PALETTE_MODIFIER_COLOUR));
417 if (image != 0) {
418 PaletteID pal = HasBit(image, PALETTE_MODIFIER_COLOUR) ?
419 GENERAL_SPRITE_COLOUR(ind->random_colour) :
420 PAL_NONE;
421 AddSortableSpriteToDraw (ti->vd, image, pal,
422 ti->x + GB(dits, 16, 3), ti->y + GB(dits, 19, 3),
423 GB(dits, 48, 5), GB(dits, 53, 5), GB(dits, 22, 7),
424 ti->z,
425 IsTransparencySet(TO_INDUSTRIES));
427 if (!IsTransparencySet(TO_INDUSTRIES)) {
428 uint proc = GB(dits, 58, 3);
429 if (proc > 0) _industry_draw_tile_procs[proc - 1](ti);
434 static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
436 return GetTileMaxPixelZ(tile);
439 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
441 IndustryGfx gfx = GetIndustryGfx(tile);
443 /* For NewGRF industry tiles we might not be drawing a foundation. We need to
444 * account for this, as other structures should
445 * draw the wall of the foundation in this case.
447 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
448 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
449 if (indts->grf_prop.spritegroup != NULL && HasBit(indts->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
450 uint32 callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, Industry::GetByTile(tile), tile);
451 if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(indts->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
454 return FlatteningFoundation(tileh);
457 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted)
459 IndustryGfx gfx = GetIndustryGfx(tile);
460 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
462 /* When we have to use a callback, we put our data in the next two variables */
463 CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)];
464 uint8 raw_cargo_acceptance[lengthof(itspec->acceptance)];
466 /* And then these will always point to a same sized array with the required data */
467 const CargoID *accepts_cargo = itspec->accepts_cargo;
468 const uint8 *cargo_acceptance = itspec->acceptance;
470 if (HasBit(itspec->callback_mask, CBM_INDT_ACCEPT_CARGO)) {
471 uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
472 if (res != CALLBACK_FAILED) {
473 accepts_cargo = raw_accepts_cargo;
474 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
478 if (HasBit(itspec->callback_mask, CBM_INDT_CARGO_ACCEPTANCE)) {
479 uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
480 if (res != CALLBACK_FAILED) {
481 cargo_acceptance = raw_cargo_acceptance;
482 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_cargo_acceptance[i] = GB(res, i * 4, 4);
486 const Industry *ind = Industry::GetByTile(tile);
487 for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
488 CargoID a = accepts_cargo[i];
489 if (a == CT_INVALID || cargo_acceptance[i] == 0) continue; // work only with valid cargoes
491 /* Add accepted cargo */
492 acceptance[a] += cargo_acceptance[i];
494 /* Maybe set 'always accepted' bit (if it's not set already) */
495 if (HasBit(*always_accepted, a)) continue;
497 bool accepts = false;
498 for (uint cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
499 /* Test whether the industry itself accepts the cargo type */
500 if (ind->accepts_cargo[cargo_index] == a) {
501 accepts = true;
502 break;
506 if (accepts) continue;
508 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
509 SetBit(*always_accepted, a);
513 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
515 const Industry *i = Industry::GetByTile(tile);
516 const IndustrySpec *is = GetIndustrySpec(i->type);
518 td->owner[0] = i->owner;
519 td->str = is->name;
520 if (!IsIndustryCompleted(tile)) {
521 td->dparam = td->str;
522 td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
525 if (is->grf_prop.grffile != NULL) {
526 td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
530 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
532 Industry *i = Industry::GetByTile(tile);
533 const IndustrySpec *indspec = GetIndustrySpec(i->type);
535 /* water can destroy industries
536 * in editor you can bulldoze industries
537 * with magic_bulldozer cheat you can destroy industries
538 * (area around OILRIG is water, so water shouldn't flood it
540 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
541 !_cheats.magic_bulldozer.value) ||
542 ((flags & DC_AUTO) != 0) ||
543 (_current_company == OWNER_WATER &&
544 ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
545 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
546 SetDParam(1, indspec->name);
547 return_cmd_error(flags & DC_AUTO ? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY : INVALID_STRING_ID);
550 if (flags & DC_EXEC) {
551 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
552 Game::NewEvent(new ScriptEventIndustryClose(i->index));
553 delete i;
555 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
558 static void TransportIndustryGoods(TileIndex tile)
560 Industry *i = Industry::GetByTile(tile);
561 const IndustrySpec *indspec = GetIndustrySpec(i->type);
562 bool moved_cargo = false;
564 StationFinder stations(i->location);
566 for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
567 uint cw = min(i->produced_cargo_waiting[j], 255);
568 if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
569 i->produced_cargo_waiting[j] -= cw;
571 /* fluctuating economy? */
572 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
574 i->this_month_production[j] += cw;
576 uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
577 i->this_month_transported[j] += am;
579 moved_cargo |= (am != 0);
583 if (moved_cargo && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
584 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
586 if (newgfx != INDUSTRYTILE_NOANIM) {
587 ResetIndustryConstructionStage(tile);
588 SetIndustryCompleted(tile);
589 SetIndustryGfx(tile, newgfx);
590 MarkTileDirtyByTile(tile);
596 static void AnimateTile_Industry(TileIndex tile)
598 IndustryGfx gfx = GetIndustryGfx(tile);
600 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
601 AnimateNewIndustryTile(tile);
602 return;
605 switch (gfx) {
606 case GFX_SUGAR_MINE_SIEVE:
607 if ((_tick_counter & 1) == 0) {
608 byte m = GetAnimationFrame(tile) + 1;
610 if (_settings_client.sound.ambient) {
611 switch (m & 7) {
612 case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
613 case 6: SndPlayTileFx(SND_29_RIP, tile); break;
617 if (m >= 96) {
618 m = 0;
619 DeleteAnimatedTile(tile);
621 SetAnimationFrame(tile, m);
623 MarkTileDirtyByTile(tile);
625 break;
627 case GFX_TOFFEE_QUARY:
628 if ((_tick_counter & 3) == 0) {
629 byte m = GetAnimationFrame(tile);
631 if ((m % 14) == 0 && _settings_client.sound.ambient) {
632 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
635 if (++m >= 70) {
636 m = 0;
637 DeleteAnimatedTile(tile);
639 SetAnimationFrame(tile, m);
641 MarkTileDirtyByTile(tile);
643 break;
645 case GFX_BUBBLE_CATCHER:
646 if ((_tick_counter & 1) == 0) {
647 byte m = GetAnimationFrame(tile);
649 if (++m >= 40) {
650 m = 0;
651 DeleteAnimatedTile(tile);
653 SetAnimationFrame(tile, m);
655 MarkTileDirtyByTile(tile);
657 break;
659 /* Sparks on a coal plant */
660 case GFX_POWERPLANT_SPARKS:
661 if ((_tick_counter & 3) == 0) {
662 byte m = GetAnimationFrame(tile);
663 if (m == 6) {
664 SetAnimationFrame(tile, 0);
665 DeleteAnimatedTile(tile);
666 } else {
667 SetAnimationFrame(tile, m + 1);
668 MarkTileDirtyByTile(tile);
671 break;
673 case GFX_TOY_FACTORY:
674 if ((_tick_counter & 1) == 0) {
675 byte m = GetAnimationFrame(tile) + 1;
677 switch (m) {
678 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
679 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
680 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
681 default:
682 if (m >= 50) {
683 int n = GetIndustryAnimationLoop(tile) + 1;
684 m = 0;
685 if (n >= 8) {
686 n = 0;
687 DeleteAnimatedTile(tile);
689 SetIndustryAnimationLoop(tile, n);
693 SetAnimationFrame(tile, m);
694 MarkTileDirtyByTile(tile);
696 break;
698 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
699 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
700 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
701 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
702 if ((_tick_counter & 3) == 0) {
703 IndustryGfx gfx = GetIndustryGfx(tile);
705 gfx = (gfx < 155) ? gfx + 1 : 148;
706 SetIndustryGfx(tile, gfx);
707 MarkTileDirtyByTile(tile);
709 break;
711 case GFX_OILWELL_ANIMATED_1:
712 case GFX_OILWELL_ANIMATED_2:
713 case GFX_OILWELL_ANIMATED_3:
714 if ((_tick_counter & 7) == 0) {
715 bool b = Chance16(1, 7);
716 IndustryGfx gfx = GetIndustryGfx(tile);
718 byte m = GetAnimationFrame(tile) + 1;
719 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
720 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
721 SetIndustryConstructionStage(tile, 3);
722 DeleteAnimatedTile(tile);
723 } else {
724 SetAnimationFrame(tile, m);
725 SetIndustryGfx(tile, gfx);
726 MarkTileDirtyByTile(tile);
729 break;
731 case GFX_COAL_MINE_TOWER_ANIMATED:
732 case GFX_COPPER_MINE_TOWER_ANIMATED:
733 case GFX_GOLD_MINE_TOWER_ANIMATED: {
734 int state = _tick_counter & 0x7FF;
736 if ((state -= 0x400) < 0) return;
738 if (state < 0x1A0) {
739 if (state < 0x20 || state >= 0x180) {
740 byte m = GetAnimationFrame(tile);
741 if (!(m & 0x40)) {
742 SetAnimationFrame(tile, m | 0x40);
743 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
745 if (state & 7) return;
746 } else {
747 if (state & 3) return;
749 byte m = (GetAnimationFrame(tile) + 1) | 0x40;
750 if (m > 0xC2) m = 0xC0;
751 SetAnimationFrame(tile, m);
752 MarkTileDirtyByTile(tile);
753 } else if (state >= 0x200 && state < 0x3A0) {
754 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
755 if (state & i) return;
757 byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
758 if (m < 0x80) m = 0x82;
759 SetAnimationFrame(tile, m);
760 MarkTileDirtyByTile(tile);
762 break;
767 static void CreateChimneySmoke(TileIndex tile)
769 uint x = TileX(tile) * TILE_SIZE;
770 uint y = TileY(tile) * TILE_SIZE;
771 int z = GetTileMaxPixelZ(tile);
773 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
776 static void MakeIndustryTileBigger(TileIndex tile)
778 byte cnt = GetIndustryConstructionCounter(tile) + 1;
779 if (cnt != 4) {
780 SetIndustryConstructionCounter(tile, cnt);
781 return;
784 byte stage = GetIndustryConstructionStage(tile) + 1;
785 SetIndustryConstructionCounter(tile, 0);
786 SetIndustryConstructionStage(tile, stage);
787 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
788 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
790 MarkTileDirtyByTile(tile);
792 if (!IsIndustryCompleted(tile)) return;
794 IndustryGfx gfx = GetIndustryGfx(tile);
795 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
796 /* New industries are already animated on construction. */
797 return;
800 switch (gfx) {
801 case GFX_POWERPLANT_CHIMNEY:
802 CreateChimneySmoke(tile);
803 break;
805 case GFX_OILRIG_1: {
806 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
807 * tiles (like the default oil rig). Do a proper check to ensure the
808 * tiles belong to the same industry and based on that build the oil rig's
809 * station. */
810 TileIndex other = tile + TileDiffXY(0, 1);
812 if (IsIndustryTile(other) &&
813 GetIndustryGfx(other) == GFX_OILRIG_1 &&
814 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
815 BuildOilRig(tile);
817 break;
820 case GFX_TOY_FACTORY:
821 case GFX_BUBBLE_CATCHER:
822 case GFX_TOFFEE_QUARY:
823 SetAnimationFrame(tile, 0);
824 SetIndustryAnimationLoop(tile, 0);
825 break;
827 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
828 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
829 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
830 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
831 AddAnimatedTile(tile);
832 break;
836 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
838 static const int8 _bubble_spawn_location[3][4] = {
839 { 11, 0, -4, -14 },
840 { -4, -10, -4, 1 },
841 { 49, 59, 60, 65 },
844 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
846 int dir = Random() & 3;
848 EffectVehicle *v = CreateEffectVehicleAbove(
849 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
850 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
851 _bubble_spawn_location[2][dir],
852 EV_BUBBLE
855 if (v != NULL) v->animation_substate = dir;
858 static void TileLoop_Industry(TileIndex tile)
860 if (IsTileOnWater(tile)) TileLoop_Water(tile);
862 /* Normally this doesn't happen, but if an industry NewGRF is removed
863 * an industry that was previously build on water can now be flooded.
864 * If this happens the tile is no longer an industry tile after
865 * returning from TileLoop_Water. */
866 if (!IsIndustryTile(tile)) return;
868 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
870 if (!IsIndustryCompleted(tile)) {
871 MakeIndustryTileBigger(tile);
872 return;
875 if (_game_mode == GM_EDITOR) return;
877 TransportIndustryGoods(tile);
879 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
881 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
882 if (newgfx != INDUSTRYTILE_NOANIM) {
883 ResetIndustryConstructionStage(tile);
884 SetIndustryGfx(tile, newgfx);
885 MarkTileDirtyByTile(tile);
886 return;
889 IndustryGfx gfx = GetIndustryGfx(tile);
890 switch (gfx) {
891 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
892 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
893 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
894 if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
895 switch (gfx) {
896 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
897 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
898 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
900 SetIndustryGfx(tile, gfx);
901 SetAnimationFrame(tile, 0x80);
902 AddAnimatedTile(tile);
904 break;
906 case GFX_OILWELL_NOT_ANIMATED:
907 if (Chance16(1, 6)) {
908 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
909 SetAnimationFrame(tile, 0);
910 AddAnimatedTile(tile);
912 break;
914 case GFX_COAL_MINE_TOWER_ANIMATED:
915 case GFX_COPPER_MINE_TOWER_ANIMATED:
916 case GFX_GOLD_MINE_TOWER_ANIMATED:
917 if (!(_tick_counter & 0x400)) {
918 switch (gfx) {
919 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
920 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
921 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
923 SetIndustryGfx(tile, gfx);
924 SetIndustryCompleted(tile);
925 SetIndustryConstructionStage(tile, 3);
926 DeleteAnimatedTile(tile);
928 break;
930 case GFX_POWERPLANT_SPARKS:
931 if (Chance16(1, 3)) {
932 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
933 AddAnimatedTile(tile);
935 break;
937 case GFX_COPPER_MINE_CHIMNEY:
938 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
939 break;
942 case GFX_TOY_FACTORY: {
943 Industry *i = Industry::GetByTile(tile);
944 if (i->was_cargo_delivered) {
945 i->was_cargo_delivered = false;
946 SetIndustryAnimationLoop(tile, 0);
947 AddAnimatedTile(tile);
950 break;
952 case GFX_BUBBLE_GENERATOR:
953 TileLoopIndustry_BubbleGenerator(tile);
954 break;
956 case GFX_TOFFEE_QUARY:
957 AddAnimatedTile(tile);
958 break;
960 case GFX_SUGAR_MINE_SIEVE:
961 if (Chance16(1, 3)) AddAnimatedTile(tile);
962 break;
966 static bool ClickTile_Industry(TileIndex tile)
968 ShowIndustryViewWindow(GetIndustryIndex(tile));
969 return true;
972 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
974 /* If the founder merges, the industry was created by the merged company */
975 Industry *i = Industry::GetByTile(tile);
976 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
980 * Check whether the tile is a forest.
981 * @param tile the tile to investigate.
982 * @return true if and only if the tile is a forest
984 bool IsTileForestIndustry(TileIndex tile)
986 /* Check for industry tile */
987 if (!IsIndustryTile(tile)) return false;
989 const Industry *ind = Industry::GetByTile(tile);
991 /* Check for organic industry (i.e. not processing or extractive) */
992 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
994 /* Check for wood production */
995 for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
996 /* The industry produces wood. */
997 if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
1000 return false;
1003 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
1005 static bool IsValidFarmFieldTile(TileIndex tile, bool allow_fields)
1007 if (!IsGroundTile(tile)) return false;
1009 return IsFieldsTile(tile) ? allow_fields :
1010 !IsSnowTile(tile) && !IsClearGround(tile, GROUND_DESERT) && !IsClearGround(tile, GROUND_SHORE);
1013 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
1015 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1017 do {
1018 tile = TILE_MASK(tile);
1020 if (IsFieldsTile(tile)) {
1021 byte or_ = type;
1023 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
1025 SetFence(tile, side, or_);
1028 tile += diff;
1029 } while (--size);
1032 static void PlantFarmField(TileIndex tile, IndustryID industry)
1034 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1035 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1038 /* determine field size */
1039 uint32 r = (Random() & 0x303) + 0x404;
1040 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1041 uint size_x = GB(r, 0, 8);
1042 uint size_y = GB(r, 8, 8);
1044 TileArea ta (tile);
1045 ta.expand (size_x / 2, size_y / 2, size_x - (size_x / 2), size_y - (size_y / 2));
1047 if (ta.w == 0 || ta.h == 0) return;
1049 /* check the amount of bad tiles */
1050 int count = 0;
1051 TILE_AREA_LOOP(cur_tile, ta) {
1052 assert(cur_tile < MapSize());
1053 count += IsValidFarmFieldTile(cur_tile, false);
1055 if (count * 2 < ta.w * ta.h) return;
1057 /* determine type of field */
1058 r = Random();
1059 uint counter = GB(r, 5, 3);
1060 uint field_type = GB(r, 8, 8) * 9 >> 8;
1062 /* make field */
1063 TILE_AREA_LOOP(cur_tile, ta) {
1064 assert(cur_tile < MapSize());
1065 if (IsValidFarmFieldTile(cur_tile, true)) {
1066 MakeField(cur_tile, field_type, industry);
1067 SetClearCounter(cur_tile, counter);
1068 MarkTileDirtyByTile(cur_tile);
1072 int type = 3;
1073 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1074 type = _plantfarmfield_type[Random() & 0xF];
1077 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1078 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1079 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1080 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1083 void PlantRandomFarmField(const Industry *i)
1085 int x = i->location.w / 2 + Random() % 31 - 16;
1086 int y = i->location.h / 2 + Random() % 31 - 16;
1088 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1090 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1094 * Perform a circular search around the Lumber Mill in order to find trees to cut
1095 * @param i industry
1097 static void ChopLumberMillTrees(Industry *i)
1099 /* We only want to cut trees if all tiles are completed. */
1100 TILE_AREA_LOOP(tile_cur, i->location) {
1101 if (i->TileBelongsToIndustry(tile_cur)) {
1102 if (!IsIndustryCompleted(tile_cur)) return;
1106 TileIndex tile = i->location.tile;
1107 CircularTileIterator iter (tile, 40); // 40x40 tiles to search
1108 for (tile = iter; tile != INVALID_TILE; tile = ++iter) {
1109 if (IsTreeTile(tile) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1110 /* found a tree */
1112 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1114 _industry_sound_ctr = 1;
1115 _industry_sound_tile = tile;
1116 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1118 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1120 cur_company.Restore();
1121 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1122 break;
1127 static void ProduceIndustryGoods(Industry *i)
1129 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1131 /* play a sound? */
1132 if ((i->counter & 0x3F) == 0) {
1133 uint32 r;
1134 uint num;
1135 if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
1136 SndPlayTileFx(
1137 (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
1138 i->location.tile);
1142 i->counter--;
1144 /* produce some cargo */
1145 if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1146 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
1148 IndustryBehaviour indbehav = indsp->behaviour;
1149 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
1150 i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
1152 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1153 uint16 cb_res = CALLBACK_FAILED;
1154 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1155 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1158 bool plant;
1159 if (cb_res != CALLBACK_FAILED) {
1160 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1161 } else {
1162 plant = Chance16(1, 8);
1165 if (plant) PlantRandomFarmField(i);
1167 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1168 uint16 cb_res = CALLBACK_FAILED;
1169 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1170 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1173 bool cut;
1174 if (cb_res != CALLBACK_FAILED) {
1175 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1176 } else {
1177 cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1180 if (cut) ChopLumberMillTrees(i);
1183 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1184 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1188 void OnTick_Industry()
1190 if (_industry_sound_ctr != 0) {
1191 _industry_sound_ctr++;
1193 if (_industry_sound_ctr == 75) {
1194 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1195 } else if (_industry_sound_ctr == 160) {
1196 _industry_sound_ctr = 0;
1197 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1201 if (_game_mode == GM_EDITOR) return;
1203 Industry *i;
1204 FOR_ALL_INDUSTRIES(i) {
1205 ProduceIndustryGoods(i);
1210 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1211 * @param tile %Tile to perform the checking.
1212 * @return Succeeded or failed command.
1214 static CommandCost CheckNewIndustry_NULL(TileIndex tile)
1216 return CommandCost();
1220 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1221 * @param tile %Tile to perform the checking.
1222 * @return Succeeded or failed command.
1224 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1226 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1227 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1228 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1231 return CommandCost();
1235 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1236 * @param tile %Tile to perform the checking.
1237 * @return Succeeded or failed command.
1239 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1241 if (_game_mode == GM_EDITOR) return CommandCost();
1242 if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1244 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1247 extern bool _ignore_restrictions;
1250 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1251 * @param tile %Tile to perform the checking.
1252 * @return Succeeded or failed command.
1254 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1256 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1257 if (TileHeight(tile) == 0 &&
1258 DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1260 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1264 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1265 * @param tile %Tile to perform the checking.
1266 * @return Succeeded or failed command.
1268 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1270 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1271 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1272 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1275 return CommandCost();
1279 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1280 * @param tile %Tile to perform the checking.
1281 * @return Succeeded or failed command.
1283 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1285 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1286 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1288 return CommandCost();
1292 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1293 * @param tile %Tile to perform the checking.
1294 * @return Succeeded or failed command.
1296 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1298 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1299 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1301 return CommandCost();
1305 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1306 * @param tile %Tile to perform the checking.
1307 * @return Succeeded or failed command.
1309 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1311 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1312 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1314 return CommandCost();
1318 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1319 * @param tile %Tile to perform the checking.
1320 * @return Succeeded or failed command.
1322 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1324 if (GetTileZ(tile) > 4) {
1325 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1327 return CommandCost();
1331 * Industrytype check function signature.
1332 * @param tile %Tile to check.
1333 * @return Succeeded or failed command.
1335 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1337 /** Check functions for different types of industry. */
1338 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1339 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1340 CheckNewIndustry_Forest, ///< CHECK_FOREST
1341 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1342 CheckNewIndustry_Farm, ///< CHECK_FARM
1343 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1344 CheckNewIndustry_Water, ///< CHECK_WATER
1345 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1346 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1347 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1351 * Find a town for the industry, while checking for multiple industries in the same town.
1352 * @param tile Position of the industry to build.
1353 * @param type Industry type.
1354 * @param [out] town Pointer to return town for the new industry, \c NULL is written if no good town can be found.
1355 * @return Succeeded or failed command.
1357 * @pre \c *t != NULL
1358 * @post \c *t points to a town on success, and \c NULL on failure.
1360 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1362 *t = ClosestTownFromTile(tile);
1364 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1366 const Industry *i;
1367 FOR_ALL_INDUSTRIES(i) {
1368 if (i->type == (byte)type && i->town == *t) {
1369 *t = NULL;
1370 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1374 return CommandCost();
1377 bool IsSlopeRefused(Slope current, Slope refused)
1379 if (IsSteepSlope(current)) return true;
1380 if (current != SLOPE_FLAT) {
1381 if (IsSteepSlope(refused)) return true;
1383 Slope t = ComplementSlope(current);
1385 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1386 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1387 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1388 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1391 return false;
1395 * Are the tiles of the industry free?
1396 * @param tile Position to check.
1397 * @param it Industry tiles table.
1398 * @param itspec_index The index of the itsepc to build/fund
1399 * @param type Type of the industry.
1400 * @param initial_random_bits The random bits the industry is going to have after construction.
1401 * @param founder Industry founder
1402 * @param creation_type The circumstances the industry is created under.
1403 * @param [out] custom_shape_check Perform custom check for the site.
1404 * @return Failed or succeeded command.
1406 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, uint itspec_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = NULL)
1408 bool refused_slope = false;
1409 bool custom_shape = false;
1411 do {
1412 IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1413 TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1415 if (!IsValidTile(cur_tile)) {
1416 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1419 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1420 if (!IsPlainWaterTile(cur_tile) ||
1421 !IsTileFlat(cur_tile)) {
1422 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1424 } else {
1425 StringID str = CheckVehicleOnGround (cur_tile);
1426 if (str != STR_NULL) return_cmd_error(str);
1428 if (HasBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1430 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1432 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1434 /* Perform land/water check if not disabled */
1435 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1437 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1438 custom_shape = true;
1439 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
1440 if (ret.Failed()) return ret;
1441 } else {
1442 Slope tileh = GetTileSlope(cur_tile);
1443 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1446 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1447 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsHouseTile(cur_tile))) { // Tile is allowed to be a house (and it is a house)
1448 if (!IsHouseTile(cur_tile)) {
1449 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1452 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1453 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1454 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1455 cur_company.Restore();
1457 if (ret.Failed()) return ret;
1458 } else {
1459 /* Clear the tiles, but do not affect town ratings */
1460 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1462 if (ret.Failed()) return ret;
1465 } while ((++it)->ti.x != -0x80);
1467 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1469 /* It is almost impossible to have a fully flat land in TG, so what we
1470 * do is that we check if we can make the land flat later on. See
1471 * CheckIfCanLevelIndustryPlatform(). */
1472 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1473 return CommandCost();
1475 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1479 * Is the industry allowed to be built at this place for the town?
1480 * @param tile Tile to construct the industry.
1481 * @param type Type of the industry.
1482 * @param t Town authority that the industry belongs to.
1483 * @return Succeeded or failed command.
1485 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1487 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1488 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1491 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1492 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1495 return CommandCost();
1498 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1500 /* Check if we don't leave the map */
1501 if (TileX(tile) == 0 || TileY(tile) == 0 || IsVoidTile(tile)) return false;
1503 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1504 TILE_AREA_LOOP(tile_walk, ta) {
1505 uint curh = TileHeight(tile_walk);
1506 /* Is the tile clear? */
1507 if (!IsGroundTile(tile_walk)) return false;
1509 /* Don't allow too big of a change if this is the sub-tile check */
1510 if (internal != 0 && Delta(curh, height) > 1) return false;
1512 /* Different height, so the surrounding tiles of this tile
1513 * has to be correct too (in level, or almost in level)
1514 * else you get a chain-reaction of terraforming. */
1515 if (internal == 0 && curh != height) {
1516 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1517 return false;
1522 return true;
1526 * This function tries to flatten out the land below an industry, without
1527 * damaging the surroundings too much.
1529 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
1531 const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1532 int max_x = 0;
1533 int max_y = 0;
1535 /* Finds dimensions of largest variant of this industry */
1536 do {
1537 if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1538 if (it->ti.x > max_x) max_x = it->ti.x;
1539 if (it->ti.y > max_y) max_y = it->ti.y;
1540 } while ((++it)->ti.x != MKEND);
1542 /* Remember level height */
1543 uint h = TileHeight(tile);
1545 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1546 /* Check that all tiles in area and surrounding are clear
1547 * this determines that there are no obstructing items */
1549 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1550 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1552 if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1554 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1555 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1556 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1558 TILE_AREA_LOOP(tile_walk, ta) {
1559 uint curh = TileHeight(tile_walk);
1560 if (curh != h) {
1561 /* This tile needs terraforming. Check if we can do that without
1562 * damaging the surroundings too much. */
1563 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1564 cur_company.Restore();
1565 return false;
1567 /* This is not 100% correct check, but the best we can do without modifying the map.
1568 * What is missing, is if the difference in height is more than 1.. */
1569 if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1570 cur_company.Restore();
1571 return false;
1576 if (flags & DC_EXEC) {
1577 /* Terraform the land under the industry */
1578 TILE_AREA_LOOP(tile_walk, ta) {
1579 uint curh = TileHeight(tile_walk);
1580 while (curh != h) {
1581 /* We give the terraforming for free here, because we can't calculate
1582 * exact cost in the test-round, and as we all know, that will cause
1583 * a nice assert if they don't match ;) */
1584 DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1585 curh += (curh > h) ? -1 : 1;
1590 cur_company.Restore();
1591 return true;
1596 * Check that the new industry is far enough from conflicting industries.
1597 * @param tile Tile to construct the industry.
1598 * @param type Type of the new industry.
1599 * @return Succeeded or failed command.
1601 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1603 const IndustrySpec *indspec = GetIndustrySpec(type);
1605 for (Industry::TileSet::Iterator iter (&Industry::set, tile, 14); iter.get_item() != NULL; iter.next()) {
1606 const Industry *i = iter.get_item();
1608 /* Within 14 tiles from another industry is considered close */
1609 if (DistanceMax(tile, i->location.tile) > 14) continue;
1611 /* check if there are any conflicting industry types around */
1612 if (i->type == indspec->conflicting[0] ||
1613 i->type == indspec->conflicting[1] ||
1614 i->type == indspec->conflicting[2]) {
1615 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1618 return CommandCost();
1622 * Advertise about a new industry opening.
1623 * @param ind Industry being opened.
1625 static void AdvertiseIndustryOpening(const Industry *ind)
1627 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1628 AddNewsItem<IndustryNewsItem> (ind_spc->new_industry_text,
1629 NT_INDUSTRY_OPEN, ind->index,
1630 ind_spc->name,
1631 ind_spc->new_industry_text > STR_LAST_STRINGID ?
1632 STR_TOWN_NAME : ind->town->index,
1633 ind->town->index);
1634 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1635 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1639 * Put an industry on the map.
1640 * @param i Just allocated poolitem, mostly empty.
1641 * @param tile North tile of the industry.
1642 * @param type Type of the industry.
1643 * @param it Industrylayout to build.
1644 * @param layout Number of the layout.
1645 * @param t Nearest town.
1646 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1647 * @param initial_random_bits Random bits for the industry.
1649 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1651 const IndustrySpec *indspec = GetIndustrySpec(type);
1653 i->location = TileArea(tile, 1, 1);
1654 i->type = type;
1655 Industry::IncIndustryTypeCount(type);
1657 i->produced_cargo[0] = indspec->produced_cargo[0];
1658 i->produced_cargo[1] = indspec->produced_cargo[1];
1659 i->accepts_cargo[0] = indspec->accepts_cargo[0];
1660 i->accepts_cargo[1] = indspec->accepts_cargo[1];
1661 i->accepts_cargo[2] = indspec->accepts_cargo[2];
1662 i->production_rate[0] = indspec->production_rate[0];
1663 i->production_rate[1] = indspec->production_rate[1];
1665 /* don't use smooth economy for industries using production related callbacks */
1666 if (indspec->UsesSmoothEconomy()) {
1667 i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8, 255);
1668 i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8, 255);
1671 i->town = t;
1672 i->owner = OWNER_NONE;
1674 uint16 r = Random();
1675 i->random_colour = GB(r, 0, 4);
1676 i->counter = GB(r, 4, 12);
1677 i->random = initial_random_bits;
1678 i->produced_cargo_waiting[0] = 0;
1679 i->produced_cargo_waiting[1] = 0;
1680 i->incoming_cargo_waiting[0] = 0;
1681 i->incoming_cargo_waiting[1] = 0;
1682 i->incoming_cargo_waiting[2] = 0;
1683 i->this_month_production[0] = 0;
1684 i->this_month_production[1] = 0;
1685 i->this_month_transported[0] = 0;
1686 i->this_month_transported[1] = 0;
1687 i->last_month_pct_transported[0] = 0;
1688 i->last_month_pct_transported[1] = 0;
1689 i->last_month_transported[0] = 0;
1690 i->last_month_transported[1] = 0;
1691 i->was_cargo_delivered = false;
1692 i->last_prod_year = _cur_year;
1693 i->founder = founder;
1695 i->construction_date = _date;
1696 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1697 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1699 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1700 * 0 = created prior of newindustries
1701 * else, chosen layout + 1 */
1702 i->selected_layout = layout + 1;
1704 i->prod_level = PRODLEVEL_DEFAULT;
1706 /* Call callbacks after the regular fields got initialised. */
1708 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1709 uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1710 if (res != CALLBACK_FAILED) {
1711 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1712 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1713 } else {
1714 i->prod_level = res;
1715 i->RecomputeProductionMultipliers();
1720 if (_generating_world) {
1721 i->last_month_production[0] = i->production_rate[0] * 8;
1722 i->last_month_production[1] = i->production_rate[1] * 8;
1723 } else {
1724 i->last_month_production[0] = i->last_month_production[1] = 0;
1727 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1728 uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1729 if (res != CALLBACK_FAILED) {
1730 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1731 i->random_colour = GB(res, 0, 4);
1735 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1736 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1737 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) {
1738 uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1739 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1740 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1741 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1742 break;
1744 i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1748 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1749 for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1750 for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
1751 uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1752 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1753 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1754 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1755 break;
1757 i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1761 /* Plant the tiles */
1763 do {
1764 TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1766 if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1767 i->location.Add(cur_tile);
1769 WaterClass wc = (IsPlainWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1771 DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1773 MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1775 if (_generating_world) {
1776 SetIndustryConstructionCounter(cur_tile, 3);
1777 SetIndustryConstructionStage(cur_tile, 2);
1780 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1781 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
1782 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1783 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1785 } while ((++it)->ti.x != -0x80);
1787 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1788 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1790 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
1792 Station::RecomputeIndustriesNearForAll();
1796 * Helper function for Build/Fund an industry
1797 * @param tile tile where industry is built
1798 * @param type of industry to build
1799 * @param flags of operations to conduct
1800 * @param indspec pointer to industry specifications
1801 * @param itspec_index the index of the itsepc to build/fund
1802 * @param seed random seed (possibly) used by industries
1803 * @param initial_random_bits The random bits the industry is going to have after construction.
1804 * @param founder Founder of the industry
1805 * @param creation_type The circumstances the industry is created under.
1806 * @param [out] ip Pointer to store newly created industry.
1807 * @return Succeeded or failed command.
1809 * @post \c *ip contains the newly created industry if all checks are successful and the \a flags request actual creation, else it contains \c NULL afterwards.
1811 static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, uint itspec_index, uint32 random_var8f, uint16 random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
1813 assert(itspec_index < indspec->num_table);
1814 const IndustryTileTable *it = indspec->table[itspec_index];
1815 bool custom_shape_check = false;
1817 *ip = NULL;
1819 SmallVector<ClearedObjectArea, 1> object_areas(_cleared_object_areas);
1820 CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1821 _cleared_object_areas = object_areas;
1822 if (ret.Failed()) return ret;
1824 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1825 ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
1826 } else {
1827 ret = _check_new_industry_procs[indspec->check_proc](tile);
1829 if (ret.Failed()) return ret;
1831 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
1832 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1833 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1836 ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1837 if (ret.Failed()) return ret;
1839 Town *t = NULL;
1840 ret = FindTownForIndustry(tile, type, &t);
1841 if (ret.Failed()) return ret;
1842 assert(t != NULL);
1844 ret = CheckIfIndustryIsAllowed(tile, type, t);
1845 if (ret.Failed()) return ret;
1847 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1849 if (flags & DC_EXEC) {
1850 *ip = new Industry(tile);
1851 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
1852 DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
1855 return CommandCost();
1859 * Build/Fund an industry
1860 * @param tile tile where industry is built
1861 * @param flags of operations to conduct
1862 * @param p1 various bitstuffed elements
1863 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1864 * - p1 = (bit 8 - 15) - first layout to try
1865 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1866 * @param p2 seed to use for desyncfree randomisations
1867 * @param text unused
1868 * @return the cost of this operation or an error
1870 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1872 IndustryType it = GB(p1, 0, 8);
1873 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1875 const IndustrySpec *indspec = GetIndustrySpec(it);
1877 /* Check if the to-be built/founded industry is available for this climate. */
1878 if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
1880 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1881 * Raw material industries are industries that do not accept cargo (at least for now) */
1882 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1883 return CMD_ERROR;
1886 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1887 return CMD_ERROR;
1890 Randomizer randomizer;
1891 randomizer.SetSeed(p2);
1892 uint16 random_initial_bits = GB(p2, 0, 16);
1893 uint32 random_var8f = randomizer.Next();
1894 int num_layouts = indspec->num_table;
1895 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
1896 const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
1898 Industry *ind = NULL;
1899 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
1900 if (flags & DC_EXEC) {
1901 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1902 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1903 /* Prospecting has a chance to fail, however we cannot guarantee that something can
1904 * be built on the map, so the chance gets lower when the map is fuller, but there
1905 * is nothing we can really do about that. */
1906 if (deity_prospect || Random() <= indspec->prospecting_chance) {
1907 for (int i = 0; i < 5000; i++) {
1908 /* We should not have more than one Random() in a function call
1909 * because parameter evaluation order is not guaranteed in the c++ standard
1911 tile = RandomTile();
1912 /* Start with a random layout */
1913 int layout = RandomRange(num_layouts);
1914 /* Check now each layout, starting with the random one */
1915 for (int j = 0; j < num_layouts; j++) {
1916 layout = (layout + 1) % num_layouts;
1917 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
1918 if (ret.Succeeded()) break;
1920 if (ret.Succeeded()) break;
1923 cur_company.Restore();
1925 } else {
1926 int layout = GB(p1, 8, 8);
1927 if (layout >= num_layouts) return CMD_ERROR;
1929 /* Check subsequently each layout, starting with the given layout in p1 */
1930 for (int i = 0; i < num_layouts; i++) {
1931 layout = (layout + 1) % num_layouts;
1932 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
1933 if (ret.Succeeded()) break;
1936 /* If it still failed, there's no suitable layout to build here, return the error */
1937 if (ret.Failed()) return ret;
1940 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1941 AdvertiseIndustryOpening(ind);
1944 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1949 * Create a new industry of random layout.
1950 * @param tile The location to build the industry.
1951 * @param type The industry type to build.
1952 * @param creation_type The circumstances the industry is created under.
1953 * @return the created industry or NULL if it failed.
1955 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1957 const IndustrySpec *indspec = GetIndustrySpec(type);
1959 uint32 seed = Random();
1960 uint32 seed2 = Random();
1961 Industry *i = NULL;
1962 CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
1963 assert(i != NULL || ret.Failed());
1964 return i;
1968 * Compute the appearance probability for an industry during map creation.
1969 * @param it Industry type to compute.
1970 * @param [out] force_at_least_one Returns whether at least one instance should be forced on map creation.
1971 * @return Relative probability for the industry to appear.
1973 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
1975 const IndustrySpec *ind_spc = GetIndustrySpec(it);
1976 uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
1977 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1978 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
1979 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
1980 *force_at_least_one = false;
1981 return 0;
1982 } else {
1983 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1984 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1985 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapPerimeter(chance) : ScaleByMapSize(chance);
1987 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
1988 return chance;
1993 * Compute the probability for constructing a new industry during game play.
1994 * @param it Industry type to compute.
1995 * @param [out] min_number Minimal number of industries that should exist at the map.
1996 * @return Relative probability for the industry to appear.
1998 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
2000 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2001 *min_number = 0;
2002 return 0;
2005 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2006 byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2007 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
2008 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
2009 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
2010 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2011 *min_number = 0;
2012 return 0;
2014 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2015 return chance;
2019 * Get wanted number of industries on the map.
2020 * @return Wanted number of industries at the map.
2022 static uint GetNumberOfIndustries()
2024 /* Number of industries on a 256x256 map. */
2025 static const uint16 numof_industry_table[] = {
2026 0, // none
2027 0, // minimal
2028 10, // very low
2029 25, // low
2030 55, // normal
2031 80, // high
2034 assert(lengthof(numof_industry_table) == ID_END);
2035 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2036 return min(Industry::Pool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2040 * Try to place the industry in the game.
2041 * Since there is no feedback why placement fails, there is no other option
2042 * than to try a few times before concluding it does not work.
2043 * @param type Industry type of the desired industry.
2044 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2045 * @return Pointer to created industry, or \c NULL if creation failed.
2047 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2049 uint tries = try_hard ? 10000u : 2000u;
2050 for (; tries > 0; tries--) {
2051 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2052 if (ind != NULL) return ind;
2054 return NULL;
2058 * Try to build a industry on the map.
2059 * @param type IndustryType of the desired industry
2060 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2062 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2064 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2066 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2067 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2069 cur_company.Restore();
2073 * Get total number of industries existing in the game.
2074 * @return Number of industries currently in the game.
2076 static uint GetCurrentTotalNumberOfIndustries()
2078 int total = 0;
2079 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2080 return total;
2084 /** Reset the entry. */
2085 void IndustryTypeBuildData::Reset()
2087 this->probability = 0;
2088 this->min_number = 0;
2089 this->target_count = 0;
2090 this->max_wait = 1;
2091 this->wait_count = 0;
2094 /** Completely reset the industry build data. */
2095 void IndustryBuildData::Reset()
2097 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2099 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2100 this->builddata[it].Reset();
2104 /** Monthly update of industry build data. */
2105 void IndustryBuildData::MonthlyLoop()
2107 static const int NEWINDS_PER_MONTH = 0x38000 / (10 * 12); // lower 16 bits is a float fraction, 3.5 industries per decade, divided by 10 * 12 months.
2108 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2110 /* To prevent running out of unused industries for the player to connect,
2111 * add a fraction of new industries each month, but only if the manager can keep up. */
2112 uint max_behind = 1 + min(99u, ScaleByMapSize(3)); // At most 2 industries for small maps, and 100 at the biggest map (about 6 months industry build attempts).
2113 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2114 this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2119 * This function will create random industries during game creation.
2120 * It will scale the amount of industries by mapsize and difficulty level.
2122 void GenerateIndustries()
2124 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2126 uint32 industry_probs[NUM_INDUSTRYTYPES];
2127 bool force_at_least_one[NUM_INDUSTRYTYPES];
2128 uint32 total_prob = 0;
2129 uint num_forced = 0;
2131 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2132 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2133 total_prob += industry_probs[it];
2134 if (force_at_least_one[it]) num_forced++;
2137 uint total_amount = GetNumberOfIndustries();
2138 if (total_prob == 0 || total_amount < num_forced) {
2139 /* Only place the forced ones */
2140 total_amount = num_forced;
2143 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2145 /* Try to build one industry per type independent of any probabilities */
2146 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2147 if (force_at_least_one[it]) {
2148 assert(total_amount > 0);
2149 total_amount--;
2150 PlaceInitialIndustry(it, true);
2154 /* Add the remaining industries according to their probabilities */
2155 for (uint i = 0; i < total_amount; i++) {
2156 uint32 r = RandomRange(total_prob);
2157 IndustryType it = 0;
2158 while (r >= industry_probs[it]) {
2159 r -= industry_probs[it];
2160 it++;
2161 assert(it < NUM_INDUSTRYTYPES);
2163 assert(industry_probs[it] > 0);
2164 PlaceInitialIndustry(it, false);
2166 _industry_builder.Reset();
2170 * Monthly update of industry statistics.
2171 * @param i Industry to update.
2173 static void UpdateIndustryStatistics(Industry *i)
2175 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2176 if (i->produced_cargo[j] != CT_INVALID) {
2177 byte pct = 0;
2178 if (i->this_month_production[j] != 0) {
2179 i->last_prod_year = _cur_year;
2180 pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2182 i->last_month_pct_transported[j] = pct;
2184 i->last_month_production[j] = i->this_month_production[j];
2185 i->this_month_production[j] = 0;
2187 i->last_month_transported[j] = i->this_month_transported[j];
2188 i->this_month_transported[j] = 0;
2194 * Recompute #production_rate for current #prod_level.
2195 * This function is only valid when not using smooth economy.
2197 void Industry::RecomputeProductionMultipliers()
2199 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2200 assert(!indspec->UsesSmoothEconomy());
2202 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2203 this->production_rate[0] = min(CeilDiv(indspec->production_rate[0] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2204 this->production_rate[1] = min(CeilDiv(indspec->production_rate[1] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2209 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2210 * @param it Industry type.
2211 * @return At least one of the fields has changed value.
2213 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2215 byte min_number;
2216 uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2217 bool changed = min_number != this->min_number || probability != this->probability;
2218 this->min_number = min_number;
2219 this->probability = probability;
2220 return changed;
2223 /** Decide how many industries of each type are needed. */
2224 void IndustryBuildData::SetupTargetCount()
2226 bool changed = false;
2227 uint num_planned = 0; // Number of industries planned in the industry build data.
2228 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2229 changed |= this->builddata[it].GetIndustryTypeData(it);
2230 num_planned += this->builddata[it].target_count;
2232 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2233 changed |= num_planned != total_amount;
2234 if (!changed) return; // All industries are still the same, no need to re-randomize.
2236 /* Initialize the target counts. */
2237 uint force_build = 0; // Number of industries that should always be available.
2238 uint32 total_prob = 0; // Sum of probabilities.
2239 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2240 IndustryTypeBuildData *ibd = this->builddata + it;
2241 force_build += ibd->min_number;
2242 ibd->target_count = ibd->min_number;
2243 total_prob += ibd->probability;
2246 if (total_prob == 0) return; // No buildable industries.
2248 /* Subtract forced industries from the number of industries available for construction. */
2249 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2251 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2252 while (total_amount > 0) {
2253 uint32 r = RandomRange(total_prob);
2254 IndustryType it = 0;
2255 while (r >= this->builddata[it].probability) {
2256 r -= this->builddata[it].probability;
2257 it++;
2258 assert(it < NUM_INDUSTRYTYPES);
2260 assert(this->builddata[it].probability > 0);
2261 this->builddata[it].target_count++;
2262 total_amount--;
2267 * Try to create a random industry, during gameplay
2269 void IndustryBuildData::TryBuildNewIndustry()
2271 this->SetupTargetCount();
2273 int missing = 0; // Number of industries that need to be build.
2274 uint count = 0; // Number of industry types eligible for build.
2275 uint32 total_prob = 0; // Sum of probabilities.
2276 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2277 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2278 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2279 missing += difference;
2280 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2281 if (difference > 0) {
2282 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2283 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2284 if (forced_build == NUM_INDUSTRYTYPES ||
2285 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2286 forced_build = it;
2289 total_prob += difference;
2290 count++;
2294 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2296 if (count >= 1) {
2297 /* If not forced, pick a weighted random industry to build.
2298 * For the case that count == 1, there is no need to draw a random number. */
2299 IndustryType it;
2300 if (forced_build != NUM_INDUSTRYTYPES) {
2301 it = forced_build;
2302 } else {
2303 /* Non-forced, select an industry type to build (weighted random). */
2304 uint32 r = 0; // Initialized to silence the compiler.
2305 if (count > 1) r = RandomRange(total_prob);
2306 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2307 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2308 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2309 if (difference <= 0) continue; // Too many of this kind.
2310 if (count == 1) break;
2311 if (r < (uint)difference) break;
2312 r -= difference;
2314 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2317 /* Try to create the industry. */
2318 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2319 if (ind == NULL) {
2320 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2321 this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2322 } else {
2323 AdvertiseIndustryOpening(ind);
2324 this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2328 /* Decrement wait counters. */
2329 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2330 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2335 * Protects an industry from closure if the appropriate flags and conditions are met
2336 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2337 * count of industries of this type must one (or lower) in order to be protected
2338 * against closure.
2339 * @param type IndustryType been queried
2340 * @result true if protection is on, false otherwise (except for oil wells)
2342 static bool CheckIndustryCloseDownProtection(IndustryType type)
2344 const IndustrySpec *indspec = GetIndustrySpec(type);
2346 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2347 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2348 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2352 * Can given cargo type be accepted or produced by the industry?
2353 * @param cargo: Cargo type
2354 * @param ind: Industry
2355 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2356 * @param *c_produces: Pointer to boolean for production of cargo
2357 * @return: \c *c_accepts is set when industry accepts the cargo type,
2358 * \c *c_produces is set when the industry produces the cargo type
2360 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2362 if (cargo == CT_INVALID) return;
2364 /* Check for acceptance of cargo */
2365 for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2366 if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2367 *c_accepts = true;
2368 break;
2372 /* Check for produced cargo */
2373 for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2374 if (cargo == ind->produced_cargo[j]) {
2375 *c_produces = true;
2376 break;
2382 * Compute who can service the industry.
2384 * Here, 'can service' means that he/she has trains and stations close enough
2385 * to the industry with the right cargo type and the right orders (ie has the
2386 * technical means).
2388 * @param ind: Industry being investigated.
2390 * @return The NewsType to use for a production change in this industry.
2392 static NewsType IndustryServiceNewsType (Industry *ind)
2394 /* Find all stations within reach of the industry */
2395 StationList stations;
2396 FindStationsAroundTiles(ind->location, &stations);
2398 if (stations.Length() == 0) return NT_INDUSTRY_NOBODY; // No stations found at all
2400 const Vehicle *v;
2401 int result = 0;
2402 FOR_ALL_VEHICLES(v) {
2403 /* Is it worthwhile to try this vehicle? */
2404 if (v->owner != _local_company && result != 0) continue;
2406 /* Check whether it accepts the right kind of cargo */
2407 bool c_accepts = false;
2408 bool c_produces = false;
2409 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2410 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2411 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2413 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2414 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2415 } else {
2416 continue;
2418 if (!c_accepts && !c_produces) continue; // Wrong cargo
2420 /* Check orders of the vehicle.
2421 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2422 * may have a different cargo type.
2424 const Order *o;
2425 FOR_VEHICLE_ORDERS(v, o) {
2426 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2427 /* Vehicle visits a station to load or unload */
2428 Station *st = Station::Get(o->GetDestination());
2429 assert(st != NULL);
2431 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2432 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2434 if (stations.Contains(st)) {
2435 if (v->owner == _local_company) return NT_INDUSTRY_COMPANY; // Company services industry
2436 result = 1; // Competitor services industry
2441 return result ? NT_INDUSTRY_OTHER : NT_INDUSTRY_NOBODY;
2444 static const uint PERCENT_TRANSPORTED_60 = 153;
2445 static const uint PERCENT_TRANSPORTED_80 = 204;
2448 * Change industry production smoothly for standard industries.
2449 * @param i Industry for which changes are performed.
2450 * @param only_decrease Whether production can only decrease (temperate oil wells).
2451 * @param on_water Whether the industry is built on water (oil rigs).
2452 * @return Whether the industry should be closed.
2454 static bool ChangeIndustryProductionSmooth (Industry *i,
2455 bool only_decrease, bool on_water)
2457 bool close = true;
2459 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2460 if (i->produced_cargo[j] == CT_INVALID) continue;
2462 uint32 r = Random();
2464 assert_compile (PERCENT_TRANSPORTED_80 > PERCENT_TRANSPORTED_60);
2466 int mult;
2467 if (only_decrease) {
2468 /* For industries with only_decrease flags (temperate
2469 * terrain Oil Wells), the multiplier will always be
2470 * -1 so they will only decrease. */
2471 mult = -1;
2472 } else if (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) {
2473 /* Bonus for very high station ratings:
2474 * 16% chance for decrease. */
2475 mult = Chance16I (1, 6, r) ? -1 : 1;
2476 } else {
2477 /* For normal industries, if over 60% is transported,
2478 * 33% chance for decrease, else 67% chance for decrease. */
2479 mult = ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) == Chance16I (1, 3, r)) ? -1 : 1;
2482 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2483 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2484 int old_prod, new_prod;
2485 new_prod = old_prod = i->production_rate[j];
2486 if (Chance16I (1, 22, r >> 16)) {
2487 new_prod += mult * max (((RandomRange(50) + 10) * old_prod) >> 8, 1U);
2490 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2491 new_prod = Clamp (new_prod, 1, 255);
2493 if (on_water && j == 1) {
2494 new_prod = Clamp(new_prod, 0, 16);
2497 /* Do not stop closing the industry when it has the lowest possible production rate */
2498 if (new_prod == old_prod && old_prod > 1) {
2499 close = false;
2500 continue;
2503 int percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2504 i->production_rate[j] = new_prod;
2506 /* Close the industry when it has the lowest possible production rate */
2507 if (new_prod > 1) close = false;
2509 int percent_abs = abs (percent);
2510 if (percent_abs >= 10) {
2511 AddNewsItem<IndustryNewsItem> (percent >= 0 ?
2512 STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH :
2513 STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2514 IndustryServiceNewsType (i), i->index,
2515 CargoSpec::Get(i->produced_cargo[j])->name,
2516 i->index, percent_abs);
2520 return close;
2524 * Change industry production or do closure
2525 * @param i Industry for which changes are performed
2526 * @param monthly true if it's the monthly call, false if it's the random call
2528 static void ChangeIndustryProduction(Industry *i, bool monthly)
2530 StringID str = STR_NULL;
2531 bool closeit = false;
2532 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2533 bool standard = false;
2534 bool suppress_message = false;
2535 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2536 /* don't use smooth economy for industries using production related callbacks */
2537 bool smooth_economy = indspec->UsesSmoothEconomy();
2538 byte div = 0;
2539 byte mul = 0;
2540 int8 increment = 0;
2542 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2543 if (callback_enabled) {
2544 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2545 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2546 suppress_message = HasBit(res, 7);
2547 /* Get the custom message if any */
2548 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2549 res = GB(res, 0, 4);
2550 switch (res) {
2551 default: NOT_REACHED();
2552 case 0x0: break; // Do nothing, but show the custom message if any
2553 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2554 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2555 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2556 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2557 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2558 case 0x8: div = res - 0x3; break; // Divide production by 32
2559 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2560 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2561 case 0xD: // decrement production
2562 case 0xE: // increment production
2563 increment = res == 0x0D ? -1 : 1;
2564 break;
2565 case 0xF: // Set production to third byte of register 0x100
2566 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2567 recalculate_multipliers = true;
2568 break;
2571 } else {
2572 if (monthly != smooth_economy) return;
2573 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2576 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2577 /* decrease or increase */
2578 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2580 if (smooth_economy) {
2581 closeit = ChangeIndustryProductionSmooth (i, only_decrease,
2582 (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0);
2583 } else {
2584 if (only_decrease || Chance16(1, 3)) {
2585 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2586 if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2587 mul = 1; // Increase production
2588 } else {
2589 div = 1; // Decrease production
2595 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2596 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2597 closeit = true;
2601 /* Increase if needed */
2602 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2603 i->prod_level = min(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2604 recalculate_multipliers = true;
2605 if (str == STR_NULL) str = indspec->production_up_text;
2608 /* Decrease if needed */
2609 while (div-- != 0 && !closeit) {
2610 if (i->prod_level == PRODLEVEL_MINIMUM) {
2611 closeit = true;
2612 } else {
2613 i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2614 recalculate_multipliers = true;
2615 if (str == STR_NULL) str = indspec->production_down_text;
2619 /* Increase or Decreasing the production level if needed */
2620 if (increment != 0) {
2621 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2622 closeit = true;
2623 } else {
2624 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2625 recalculate_multipliers = true;
2629 /* Recalculate production_rate
2630 * For non-smooth economy these should always be synchronized with prod_level */
2631 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2633 /* Close if needed and allowed */
2634 if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2635 i->prod_level = PRODLEVEL_CLOSURE;
2636 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2637 str = indspec->closure_text;
2640 if (!suppress_message && str != STR_NULL) {
2641 NewsType nt;
2642 /* Compute news category */
2643 if (closeit) {
2644 nt = NT_INDUSTRY_CLOSE;
2645 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2646 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2647 } else {
2648 nt = IndustryServiceNewsType (i);
2650 /* Report the news to the user. */
2651 uint p0 = (str > STR_LAST_STRINGID) ? STR_TOWN_NAME :
2652 closeit ? STR_FORMAT_INDUSTRY_NAME : i->index;
2653 if (closeit) {
2654 AddNewsItem<TileNewsItem> (str, nt,
2655 i->location.tile + TileDiffXY(1, 1),
2656 p0, i->town->index, indspec->name);
2657 } else {
2658 AddNewsItem<IndustryNewsItem> (str, nt, i->index,
2659 p0, i->town->index, indspec->name);
2665 * Daily handler for the industry changes
2666 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2667 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2668 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2669 * it would be way more. The daily loop handles those changes.
2671 void IndustryDailyLoop()
2673 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
2675 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2676 * the lower 16 bit are a fractional part that might accumulate over several days until it
2677 * is sufficient for an industry. */
2678 uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2680 /* Reset the active part of the counter, just keeping the "fractional part" */
2681 _economy.industry_daily_change_counter &= 0xFFFF;
2683 if (change_loop == 0) {
2684 return; // Nothing to do? get out
2687 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2689 /* perform the required industry changes for the day */
2691 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2692 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
2693 perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2695 for (uint16 j = 0; j < change_loop; j++) {
2696 if (Chance16(perc, 100)) {
2697 _industry_builder.TryBuildNewIndustry();
2698 } else {
2699 Industry *i = Industry::GetRandom();
2700 if (i != NULL) {
2701 ChangeIndustryProduction(i, false);
2702 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2707 cur_company.Restore();
2709 /* production-change */
2710 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2713 void IndustryMonthlyLoop()
2715 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2717 _industry_builder.MonthlyLoop();
2719 Industry *i;
2720 FOR_ALL_INDUSTRIES(i) {
2721 UpdateIndustryStatistics(i);
2722 if (i->prod_level == PRODLEVEL_CLOSURE) {
2723 delete i;
2724 } else {
2725 ChangeIndustryProduction(i, true);
2726 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2730 cur_company.Restore();
2732 /* production-change */
2733 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2737 void InitializeIndustries()
2739 Industry::ResetIndustryCounts();
2740 _industry_sound_tile = 0;
2742 _industry_builder.Reset();
2745 /** Verify whether the generated industries are complete, and warn the user if not. */
2746 void CheckIndustries()
2748 int count = 0;
2749 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2750 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2752 bool force_at_least_one;
2753 uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2754 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2756 const IndustrySpec *is = GetIndustrySpec(it);
2757 SetDParam(0, is->name);
2758 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2760 count++;
2761 if (count >= 3) break; // Don't swamp the user with errors.
2766 * Is an industry with the spec a raw industry?
2767 * @return true if it should be handled as a raw industry
2769 bool IndustrySpec::IsRawIndustry() const
2771 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2775 * Is an industry with the spec a processing industry?
2776 * @return true if it should be handled as a processing industry
2778 bool IndustrySpec::IsProcessingIndustry() const
2780 /* Lumber mills are neither raw nor processing */
2781 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2782 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2786 * Get the cost for constructing this industry
2787 * @return the cost (inflation corrected etc)
2789 Money IndustrySpec::GetConstructionCost() const
2791 /* Building raw industries like secondary uses different price base */
2792 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2793 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2797 * Get the cost for removing this industry
2798 * Take note that the cost will always be zero for non-grf industries.
2799 * Only if the grf author did specified a cost will it be applicable.
2800 * @return the cost (inflation corrected etc)
2802 Money IndustrySpec::GetRemovalCost() const
2804 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2808 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2809 * @return true if smooth economy is used.
2811 bool IndustrySpec::UsesSmoothEconomy() const
2813 return _settings_game.economy.smooth_economy &&
2814 !(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
2815 !(HasBit(this->callback_mask, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CHANGE) || HasBit(this->callback_mask, CBM_IND_PROD_CHANGE_BUILD)); // production change callbacks
2818 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2820 if (AutoslopeEnabled()) {
2821 /* We imitate here TTDP's behaviour:
2822 * - Both new and old slope must not be steep.
2823 * - TileMaxZ must not be changed.
2824 * - Allow autoslope by default.
2825 * - Disallow autoslope if callback succeeds and returns non-zero.
2827 Slope tileh_old = GetTileSlope(tile);
2828 /* TileMaxZ must not be changed. Slopes must not be steep. */
2829 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2830 const IndustryGfx gfx = GetIndustryGfx(tile);
2831 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2833 /* Call callback 3C 'disable autosloping for industry tiles'. */
2834 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2835 /* If the callback fails, allow autoslope. */
2836 uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2837 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2838 } else {
2839 /* allow autoslope */
2840 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2844 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2847 extern const TileTypeProcs _tile_type_industry_procs = {
2848 DrawTile_Industry, // draw_tile_proc
2849 GetSlopePixelZ_Industry, // get_slope_z_proc
2850 ClearTile_Industry, // clear_tile_proc
2851 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2852 GetTileDesc_Industry, // get_tile_desc_proc
2853 NULL, // get_tile_railway_status_proc
2854 NULL, // get_tile_road_status_proc
2855 NULL, // get_tile_waterway_status_proc
2856 ClickTile_Industry, // click_tile_proc
2857 AnimateTile_Industry, // animate_tile_proc
2858 TileLoop_Industry, // tile_loop_proc
2859 ChangeTileOwner_Industry, // change_tile_owner_proc
2860 NULL, // add_produced_cargo_proc
2861 GetFoundation_Industry, // get_foundation_proc
2862 TerraformTile_Industry, // terraform_tile_proc