Fix old map array tunnel head conversion
[openttd/fttd.git] / src / industry_cmd.cpp
bloba670b0a6d89c16d0baf80db58d598061fe34303c
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());
559 * Move produced cargo from industry to nearby stations.
560 * @param tile Industry tile
561 * @return true if any cargo was moved.
563 static bool TransportIndustryGoods(TileIndex tile)
565 Industry *i = Industry::GetByTile(tile);
566 const IndustrySpec *indspec = GetIndustrySpec(i->type);
567 bool moved_cargo = false;
569 StationFinder stations(i->location);
571 for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
572 uint cw = min(i->produced_cargo_waiting[j], 255);
573 if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
574 i->produced_cargo_waiting[j] -= cw;
576 /* fluctuating economy? */
577 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
579 i->this_month_production[j] += cw;
581 uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
582 i->this_month_transported[j] += am;
584 moved_cargo |= (am != 0);
588 return moved_cargo;
592 static void AnimateTile_Industry(TileIndex tile)
594 IndustryGfx gfx = GetIndustryGfx(tile);
596 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
597 AnimateNewIndustryTile(tile);
598 return;
601 switch (gfx) {
602 case GFX_SUGAR_MINE_SIEVE:
603 if ((_tick_counter & 1) == 0) {
604 byte m = GetAnimationFrame(tile) + 1;
606 if (_settings_client.sound.ambient) {
607 switch (m & 7) {
608 case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
609 case 6: SndPlayTileFx(SND_29_RIP, tile); break;
613 if (m >= 96) {
614 m = 0;
615 DeleteAnimatedTile(tile);
617 SetAnimationFrame(tile, m);
619 MarkTileDirtyByTile(tile);
621 break;
623 case GFX_TOFFEE_QUARY:
624 if ((_tick_counter & 3) == 0) {
625 byte m = GetAnimationFrame(tile);
627 if ((m % 14) == 0 && _settings_client.sound.ambient) {
628 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
631 if (++m >= 70) {
632 m = 0;
633 DeleteAnimatedTile(tile);
635 SetAnimationFrame(tile, m);
637 MarkTileDirtyByTile(tile);
639 break;
641 case GFX_BUBBLE_CATCHER:
642 if ((_tick_counter & 1) == 0) {
643 byte m = GetAnimationFrame(tile);
645 if (++m >= 40) {
646 m = 0;
647 DeleteAnimatedTile(tile);
649 SetAnimationFrame(tile, m);
651 MarkTileDirtyByTile(tile);
653 break;
655 /* Sparks on a coal plant */
656 case GFX_POWERPLANT_SPARKS:
657 if ((_tick_counter & 3) == 0) {
658 byte m = GetAnimationFrame(tile);
659 if (m == 6) {
660 SetAnimationFrame(tile, 0);
661 DeleteAnimatedTile(tile);
662 } else {
663 SetAnimationFrame(tile, m + 1);
664 MarkTileDirtyByTile(tile);
667 break;
669 case GFX_TOY_FACTORY:
670 if ((_tick_counter & 1) == 0) {
671 byte m = GetAnimationFrame(tile) + 1;
673 switch (m) {
674 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
675 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
676 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
677 default:
678 if (m >= 50) {
679 int n = GetIndustryAnimationLoop(tile) + 1;
680 m = 0;
681 if (n >= 8) {
682 n = 0;
683 DeleteAnimatedTile(tile);
685 SetIndustryAnimationLoop(tile, n);
689 SetAnimationFrame(tile, m);
690 MarkTileDirtyByTile(tile);
692 break;
694 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
695 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
696 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
697 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
698 if ((_tick_counter & 3) == 0) {
699 IndustryGfx gfx = GetIndustryGfx(tile);
701 gfx = (gfx < 155) ? gfx + 1 : 148;
702 SetIndustryGfx(tile, gfx);
703 MarkTileDirtyByTile(tile);
705 break;
707 case GFX_OILWELL_ANIMATED_1:
708 case GFX_OILWELL_ANIMATED_2:
709 case GFX_OILWELL_ANIMATED_3:
710 if ((_tick_counter & 7) == 0) {
711 bool b = Chance16(1, 7);
712 IndustryGfx gfx = GetIndustryGfx(tile);
714 byte m = GetAnimationFrame(tile) + 1;
715 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
716 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
717 SetIndustryConstructionStage(tile, 3);
718 DeleteAnimatedTile(tile);
719 } else {
720 SetAnimationFrame(tile, m);
721 SetIndustryGfx(tile, gfx);
722 MarkTileDirtyByTile(tile);
725 break;
727 case GFX_COAL_MINE_TOWER_ANIMATED:
728 case GFX_COPPER_MINE_TOWER_ANIMATED:
729 case GFX_GOLD_MINE_TOWER_ANIMATED: {
730 int state = _tick_counter & 0x7FF;
732 if ((state -= 0x400) < 0) return;
734 if (state < 0x1A0) {
735 if (state < 0x20 || state >= 0x180) {
736 byte m = GetAnimationFrame(tile);
737 if (!(m & 0x40)) {
738 SetAnimationFrame(tile, m | 0x40);
739 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
741 if (state & 7) return;
742 } else {
743 if (state & 3) return;
745 byte m = (GetAnimationFrame(tile) + 1) | 0x40;
746 if (m > 0xC2) m = 0xC0;
747 SetAnimationFrame(tile, m);
748 MarkTileDirtyByTile(tile);
749 } else if (state >= 0x200 && state < 0x3A0) {
750 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
751 if (state & i) return;
753 byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
754 if (m < 0x80) m = 0x82;
755 SetAnimationFrame(tile, m);
756 MarkTileDirtyByTile(tile);
758 break;
763 static void CreateChimneySmoke(TileIndex tile)
765 uint x = TileX(tile) * TILE_SIZE;
766 uint y = TileY(tile) * TILE_SIZE;
767 int z = GetTileMaxPixelZ(tile);
769 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
772 static void MakeIndustryTileBigger(TileIndex tile)
774 byte cnt = GetIndustryConstructionCounter(tile) + 1;
775 if (cnt != 4) {
776 SetIndustryConstructionCounter(tile, cnt);
777 return;
780 byte stage = GetIndustryConstructionStage(tile) + 1;
781 SetIndustryConstructionCounter(tile, 0);
782 SetIndustryConstructionStage(tile, stage);
783 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
784 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
786 MarkTileDirtyByTile(tile);
788 if (!IsIndustryCompleted(tile)) return;
790 IndustryGfx gfx = GetIndustryGfx(tile);
791 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
792 /* New industries are already animated on construction. */
793 return;
796 switch (gfx) {
797 case GFX_POWERPLANT_CHIMNEY:
798 CreateChimneySmoke(tile);
799 break;
801 case GFX_OILRIG_1: {
802 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
803 * tiles (like the default oil rig). Do a proper check to ensure the
804 * tiles belong to the same industry and based on that build the oil rig's
805 * station. */
806 TileIndex other = tile + TileDiffXY(0, 1);
808 if (IsIndustryTile(other) &&
809 GetIndustryGfx(other) == GFX_OILRIG_1 &&
810 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
811 BuildOilRig(tile);
813 break;
816 case GFX_TOY_FACTORY:
817 case GFX_BUBBLE_CATCHER:
818 case GFX_TOFFEE_QUARY:
819 SetAnimationFrame(tile, 0);
820 SetIndustryAnimationLoop(tile, 0);
821 break;
823 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
824 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
825 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
826 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
827 AddAnimatedTile(tile);
828 break;
832 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
834 static const int8 _bubble_spawn_location[3][4] = {
835 { 11, 0, -4, -14 },
836 { -4, -10, -4, 1 },
837 { 49, 59, 60, 65 },
840 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
842 int dir = Random() & 3;
844 EffectVehicle *v = CreateEffectVehicleAbove(
845 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
846 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
847 _bubble_spawn_location[2][dir],
848 EV_BUBBLE
851 if (v != NULL) v->animation_substate = dir;
854 static void TileLoop_Industry(TileIndex tile)
856 if (IsTileOnWater(tile)) TileLoop_Water(tile);
858 /* Normally this doesn't happen, but if an industry NewGRF is removed
859 * an industry that was previously build on water can now be flooded.
860 * If this happens the tile is no longer an industry tile after
861 * returning from TileLoop_Water. */
862 if (!IsIndustryTile(tile)) return;
864 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
866 if (!IsIndustryCompleted(tile)) {
867 MakeIndustryTileBigger(tile);
868 return;
871 if (_game_mode == GM_EDITOR) return;
873 if (TransportIndustryGoods(tile) && !StartStopIndustryTileAnimation(Industry::GetByTile(tile), IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
874 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
876 if (newgfx != INDUSTRYTILE_NOANIM) {
877 ResetIndustryConstructionStage(tile);
878 SetIndustryCompleted(tile);
879 SetIndustryGfx(tile, newgfx);
880 MarkTileDirtyByTile(tile);
881 return;
885 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
887 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
888 if (newgfx != INDUSTRYTILE_NOANIM) {
889 ResetIndustryConstructionStage(tile);
890 SetIndustryGfx(tile, newgfx);
891 MarkTileDirtyByTile(tile);
892 return;
895 IndustryGfx gfx = GetIndustryGfx(tile);
896 switch (gfx) {
897 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
898 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
899 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
900 if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
901 switch (gfx) {
902 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
903 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
904 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
906 SetIndustryGfx(tile, gfx);
907 SetAnimationFrame(tile, 0x80);
908 AddAnimatedTile(tile);
910 break;
912 case GFX_OILWELL_NOT_ANIMATED:
913 if (Chance16(1, 6)) {
914 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
915 SetAnimationFrame(tile, 0);
916 AddAnimatedTile(tile);
918 break;
920 case GFX_COAL_MINE_TOWER_ANIMATED:
921 case GFX_COPPER_MINE_TOWER_ANIMATED:
922 case GFX_GOLD_MINE_TOWER_ANIMATED:
923 if (!(_tick_counter & 0x400)) {
924 switch (gfx) {
925 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
926 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
927 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
929 SetIndustryGfx(tile, gfx);
930 SetIndustryCompleted(tile);
931 SetIndustryConstructionStage(tile, 3);
932 DeleteAnimatedTile(tile);
934 break;
936 case GFX_POWERPLANT_SPARKS:
937 if (Chance16(1, 3)) {
938 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
939 AddAnimatedTile(tile);
941 break;
943 case GFX_COPPER_MINE_CHIMNEY:
944 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
945 break;
948 case GFX_TOY_FACTORY: {
949 Industry *i = Industry::GetByTile(tile);
950 if (i->was_cargo_delivered) {
951 i->was_cargo_delivered = false;
952 SetIndustryAnimationLoop(tile, 0);
953 AddAnimatedTile(tile);
956 break;
958 case GFX_BUBBLE_GENERATOR:
959 TileLoopIndustry_BubbleGenerator(tile);
960 break;
962 case GFX_TOFFEE_QUARY:
963 AddAnimatedTile(tile);
964 break;
966 case GFX_SUGAR_MINE_SIEVE:
967 if (Chance16(1, 3)) AddAnimatedTile(tile);
968 break;
972 static bool ClickTile_Industry(TileIndex tile)
974 ShowIndustryViewWindow(GetIndustryIndex(tile));
975 return true;
978 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
980 /* If the founder merges, the industry was created by the merged company */
981 Industry *i = Industry::GetByTile(tile);
982 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
986 * Check whether the tile is a forest.
987 * @param tile the tile to investigate.
988 * @return true if and only if the tile is a forest
990 bool IsTileForestIndustry(TileIndex tile)
992 /* Check for industry tile */
993 if (!IsIndustryTile(tile)) return false;
995 const Industry *ind = Industry::GetByTile(tile);
997 /* Check for organic industry (i.e. not processing or extractive) */
998 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
1000 /* Check for wood production */
1001 for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
1002 /* The industry produces wood. */
1003 if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
1006 return false;
1009 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
1011 static bool IsValidFarmFieldTile(TileIndex tile, bool allow_fields)
1013 if (!IsGroundTile(tile)) return false;
1015 return IsFieldsTile(tile) ? allow_fields :
1016 !IsSnowTile(tile) && !IsClearGround(tile, GROUND_DESERT) && !IsClearGround(tile, GROUND_SHORE);
1019 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
1021 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1023 do {
1024 tile = TILE_MASK(tile);
1026 if (IsFieldsTile(tile)) {
1027 byte or_ = type;
1029 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
1031 SetFence(tile, side, or_);
1034 tile += diff;
1035 } while (--size);
1038 static void PlantFarmField(TileIndex tile, IndustryID industry)
1040 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1041 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1044 /* determine field size */
1045 uint32 r = (Random() & 0x303) + 0x404;
1046 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1047 uint size_x = GB(r, 0, 8);
1048 uint size_y = GB(r, 8, 8);
1050 TileArea ta (tile);
1051 ta.expand (size_x / 2, size_y / 2, size_x - (size_x / 2), size_y - (size_y / 2));
1053 if (ta.w == 0 || ta.h == 0) return;
1055 /* check the amount of bad tiles */
1056 int count = 0;
1057 TILE_AREA_LOOP(cur_tile, ta) {
1058 assert(cur_tile < MapSize());
1059 count += IsValidFarmFieldTile(cur_tile, false);
1061 if (count * 2 < ta.w * ta.h) return;
1063 /* determine type of field */
1064 r = Random();
1065 uint counter = GB(r, 5, 3);
1066 uint field_type = GB(r, 8, 8) * 9 >> 8;
1068 /* make field */
1069 TILE_AREA_LOOP(cur_tile, ta) {
1070 assert(cur_tile < MapSize());
1071 if (IsValidFarmFieldTile(cur_tile, true)) {
1072 MakeField(cur_tile, field_type, industry);
1073 SetClearCounter(cur_tile, counter);
1074 MarkTileDirtyByTile(cur_tile);
1078 int type = 3;
1079 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1080 type = _plantfarmfield_type[Random() & 0xF];
1083 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1084 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1085 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1086 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1089 void PlantRandomFarmField(const Industry *i)
1091 int x = i->location.w / 2 + Random() % 31 - 16;
1092 int y = i->location.h / 2 + Random() % 31 - 16;
1094 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1096 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1100 * Perform a circular search around the Lumber Mill in order to find trees to cut
1101 * @param i industry
1103 static void ChopLumberMillTrees(Industry *i)
1105 /* We only want to cut trees if all tiles are completed. */
1106 TILE_AREA_LOOP(tile_cur, i->location) {
1107 if (i->TileBelongsToIndustry(tile_cur)) {
1108 if (!IsIndustryCompleted(tile_cur)) return;
1112 TileIndex tile = i->location.tile;
1113 CircularTileIterator iter (tile, 40); // 40x40 tiles to search
1114 for (tile = iter; tile != INVALID_TILE; tile = ++iter) {
1115 if (IsTreeTile(tile) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1116 /* found a tree */
1118 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1120 _industry_sound_ctr = 1;
1121 _industry_sound_tile = tile;
1122 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1124 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1126 cur_company.Restore();
1127 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1128 break;
1133 static void ProduceIndustryGoods(Industry *i)
1135 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1137 /* play a sound? */
1138 if ((i->counter & 0x3F) == 0) {
1139 uint32 r;
1140 uint num;
1141 if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
1142 SndPlayTileFx(
1143 (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
1144 i->location.tile);
1148 i->counter--;
1150 /* produce some cargo */
1151 if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1152 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
1154 IndustryBehaviour indbehav = indsp->behaviour;
1155 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
1156 i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
1158 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1159 uint16 cb_res = CALLBACK_FAILED;
1160 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1161 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1164 bool plant;
1165 if (cb_res != CALLBACK_FAILED) {
1166 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1167 } else {
1168 plant = Chance16(1, 8);
1171 if (plant) PlantRandomFarmField(i);
1173 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1174 uint16 cb_res = CALLBACK_FAILED;
1175 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1176 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1179 bool cut;
1180 if (cb_res != CALLBACK_FAILED) {
1181 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1182 } else {
1183 cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1186 if (cut) ChopLumberMillTrees(i);
1189 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1190 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1194 void OnTick_Industry()
1196 if (_industry_sound_ctr != 0) {
1197 _industry_sound_ctr++;
1199 if (_industry_sound_ctr == 75) {
1200 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1201 } else if (_industry_sound_ctr == 160) {
1202 _industry_sound_ctr = 0;
1203 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1207 if (_game_mode == GM_EDITOR) return;
1209 Industry *i;
1210 FOR_ALL_INDUSTRIES(i) {
1211 ProduceIndustryGoods(i);
1216 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1217 * @param tile %Tile to perform the checking.
1218 * @return Succeeded or failed command.
1220 static CommandCost CheckNewIndustry_NULL(TileIndex tile)
1222 return CommandCost();
1226 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1227 * @param tile %Tile to perform the checking.
1228 * @return Succeeded or failed command.
1230 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1232 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1233 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1234 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1237 return CommandCost();
1241 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1242 * @param tile %Tile to perform the checking.
1243 * @return Succeeded or failed command.
1245 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1247 if (_game_mode == GM_EDITOR) return CommandCost();
1248 if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1250 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1253 extern bool _ignore_restrictions;
1256 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1257 * @param tile %Tile to perform the checking.
1258 * @return Succeeded or failed command.
1260 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1262 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1263 if (TileHeight(tile) == 0 &&
1264 DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1266 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1270 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1271 * @param tile %Tile to perform the checking.
1272 * @return Succeeded or failed command.
1274 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1276 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1277 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1278 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1281 return CommandCost();
1285 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1286 * @param tile %Tile to perform the checking.
1287 * @return Succeeded or failed command.
1289 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1291 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1292 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1294 return CommandCost();
1298 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1299 * @param tile %Tile to perform the checking.
1300 * @return Succeeded or failed command.
1302 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1304 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1305 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1307 return CommandCost();
1311 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1312 * @param tile %Tile to perform the checking.
1313 * @return Succeeded or failed command.
1315 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1317 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1318 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1320 return CommandCost();
1324 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1325 * @param tile %Tile to perform the checking.
1326 * @return Succeeded or failed command.
1328 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1330 if (GetTileZ(tile) > 4) {
1331 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1333 return CommandCost();
1337 * Industrytype check function signature.
1338 * @param tile %Tile to check.
1339 * @return Succeeded or failed command.
1341 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1343 /** Check functions for different types of industry. */
1344 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1345 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1346 CheckNewIndustry_Forest, ///< CHECK_FOREST
1347 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1348 CheckNewIndustry_Farm, ///< CHECK_FARM
1349 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1350 CheckNewIndustry_Water, ///< CHECK_WATER
1351 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1352 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1353 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1357 * Find a town for the industry, while checking for multiple industries in the same town.
1358 * @param tile Position of the industry to build.
1359 * @param type Industry type.
1360 * @param [out] town Pointer to return town for the new industry, \c NULL is written if no good town can be found.
1361 * @return Succeeded or failed command.
1363 * @pre \c *t != NULL
1364 * @post \c *t points to a town on success, and \c NULL on failure.
1366 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1368 *t = ClosestTownFromTile(tile);
1370 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1372 const Industry *i;
1373 FOR_ALL_INDUSTRIES(i) {
1374 if (i->type == (byte)type && i->town == *t) {
1375 *t = NULL;
1376 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1380 return CommandCost();
1383 bool IsSlopeRefused(Slope current, Slope refused)
1385 if (IsSteepSlope(current)) return true;
1386 if (current != SLOPE_FLAT) {
1387 if (IsSteepSlope(refused)) return true;
1389 Slope t = ComplementSlope(current);
1391 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1392 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1393 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1394 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1397 return false;
1401 * Are the tiles of the industry free?
1402 * @param tile Position to check.
1403 * @param it Industry tiles table.
1404 * @param itspec_index The index of the itsepc to build/fund
1405 * @param type Type of the industry.
1406 * @param initial_random_bits The random bits the industry is going to have after construction.
1407 * @param founder Industry founder
1408 * @param creation_type The circumstances the industry is created under.
1409 * @param [out] custom_shape_check Perform custom check for the site.
1410 * @return Failed or succeeded command.
1412 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)
1414 bool refused_slope = false;
1415 bool custom_shape = false;
1417 do {
1418 IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1419 TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1421 if (!IsValidTile(cur_tile)) {
1422 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1425 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1426 if (!IsPlainWaterTile(cur_tile) ||
1427 !IsTileFlat(cur_tile)) {
1428 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1430 } else {
1431 StringID str = CheckVehicleOnGround (cur_tile);
1432 if (str != STR_NULL) return_cmd_error(str);
1434 if (HasBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1436 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1438 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1440 /* Perform land/water check if not disabled */
1441 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1443 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1444 custom_shape = true;
1445 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
1446 if (ret.Failed()) return ret;
1447 } else {
1448 Slope tileh = GetTileSlope(cur_tile);
1449 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1452 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1453 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsHouseTile(cur_tile))) { // Tile is allowed to be a house (and it is a house)
1454 if (!IsHouseTile(cur_tile)) {
1455 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1458 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1459 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1460 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1461 cur_company.Restore();
1463 if (ret.Failed()) return ret;
1464 } else {
1465 /* Clear the tiles, but do not affect town ratings */
1466 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1468 if (ret.Failed()) return ret;
1471 } while ((++it)->ti.x != -0x80);
1473 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1475 /* It is almost impossible to have a fully flat land in TG, so what we
1476 * do is that we check if we can make the land flat later on. See
1477 * CheckIfCanLevelIndustryPlatform(). */
1478 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1479 return CommandCost();
1481 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1485 * Is the industry allowed to be built at this place for the town?
1486 * @param tile Tile to construct the industry.
1487 * @param type Type of the industry.
1488 * @param t Town authority that the industry belongs to.
1489 * @return Succeeded or failed command.
1491 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1493 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1494 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1497 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1498 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1501 return CommandCost();
1504 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1506 /* Check if we don't leave the map */
1507 if (TileX(tile) == 0 || TileY(tile) == 0 || IsVoidTile(tile)) return false;
1509 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1510 TILE_AREA_LOOP(tile_walk, ta) {
1511 uint curh = TileHeight(tile_walk);
1512 /* Is the tile clear? */
1513 if (!IsGroundTile(tile_walk)) return false;
1515 /* Don't allow too big of a change if this is the sub-tile check */
1516 if (internal != 0 && Delta(curh, height) > 1) return false;
1518 /* Different height, so the surrounding tiles of this tile
1519 * has to be correct too (in level, or almost in level)
1520 * else you get a chain-reaction of terraforming. */
1521 if (internal == 0 && curh != height) {
1522 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1523 return false;
1528 return true;
1532 * This function tries to flatten out the land below an industry, without
1533 * damaging the surroundings too much.
1535 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
1537 const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1538 int max_x = 0;
1539 int max_y = 0;
1541 /* Finds dimensions of largest variant of this industry */
1542 do {
1543 if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1544 if (it->ti.x > max_x) max_x = it->ti.x;
1545 if (it->ti.y > max_y) max_y = it->ti.y;
1546 } while ((++it)->ti.x != MKEND);
1548 /* Remember level height */
1549 uint h = TileHeight(tile);
1551 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1552 /* Check that all tiles in area and surrounding are clear
1553 * this determines that there are no obstructing items */
1555 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1556 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1558 if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1560 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1561 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1562 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1564 TILE_AREA_LOOP(tile_walk, ta) {
1565 uint curh = TileHeight(tile_walk);
1566 if (curh != h) {
1567 /* This tile needs terraforming. Check if we can do that without
1568 * damaging the surroundings too much. */
1569 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1570 cur_company.Restore();
1571 return false;
1573 /* This is not 100% correct check, but the best we can do without modifying the map.
1574 * What is missing, is if the difference in height is more than 1.. */
1575 if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1576 cur_company.Restore();
1577 return false;
1582 if (flags & DC_EXEC) {
1583 /* Terraform the land under the industry */
1584 TILE_AREA_LOOP(tile_walk, ta) {
1585 uint curh = TileHeight(tile_walk);
1586 while (curh != h) {
1587 /* We give the terraforming for free here, because we can't calculate
1588 * exact cost in the test-round, and as we all know, that will cause
1589 * a nice assert if they don't match ;) */
1590 DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1591 curh += (curh > h) ? -1 : 1;
1596 cur_company.Restore();
1597 return true;
1602 * Check that the new industry is far enough from conflicting industries.
1603 * @param tile Tile to construct the industry.
1604 * @param type Type of the new industry.
1605 * @return Succeeded or failed command.
1607 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1609 const IndustrySpec *indspec = GetIndustrySpec(type);
1611 for (Industry::TileSet::Iterator iter (&Industry::set, tile, 14); iter.get_item() != NULL; iter.next()) {
1612 const Industry *i = iter.get_item();
1614 /* Within 14 tiles from another industry is considered close */
1615 if (DistanceMax(tile, i->location.tile) > 14) continue;
1617 /* check if there are any conflicting industry types around */
1618 if (i->type == indspec->conflicting[0] ||
1619 i->type == indspec->conflicting[1] ||
1620 i->type == indspec->conflicting[2]) {
1621 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1624 return CommandCost();
1628 * Advertise about a new industry opening.
1629 * @param ind Industry being opened.
1631 static void AdvertiseIndustryOpening(const Industry *ind)
1633 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1634 AddNewsItem<IndustryNewsItem> (ind_spc->new_industry_text,
1635 NT_INDUSTRY_OPEN, ind->index,
1636 ind_spc->name,
1637 ind_spc->new_industry_text > STR_LAST_STRINGID ?
1638 STR_TOWN_NAME : ind->town->index,
1639 ind->town->index);
1640 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1641 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1645 * Put an industry on the map.
1646 * @param i Just allocated poolitem, mostly empty.
1647 * @param tile North tile of the industry.
1648 * @param type Type of the industry.
1649 * @param it Industrylayout to build.
1650 * @param layout Number of the layout.
1651 * @param t Nearest town.
1652 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1653 * @param initial_random_bits Random bits for the industry.
1655 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1657 const IndustrySpec *indspec = GetIndustrySpec(type);
1659 i->location = TileArea(tile, 1, 1);
1660 i->type = type;
1661 Industry::IncIndustryTypeCount(type);
1663 i->produced_cargo[0] = indspec->produced_cargo[0];
1664 i->produced_cargo[1] = indspec->produced_cargo[1];
1665 i->accepts_cargo[0] = indspec->accepts_cargo[0];
1666 i->accepts_cargo[1] = indspec->accepts_cargo[1];
1667 i->accepts_cargo[2] = indspec->accepts_cargo[2];
1668 i->production_rate[0] = indspec->production_rate[0];
1669 i->production_rate[1] = indspec->production_rate[1];
1671 /* don't use smooth economy for industries using production related callbacks */
1672 if (indspec->UsesSmoothEconomy()) {
1673 i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8, 255);
1674 i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8, 255);
1677 i->town = t;
1678 i->owner = OWNER_NONE;
1680 uint16 r = Random();
1681 i->random_colour = GB(r, 0, 4);
1682 i->counter = GB(r, 4, 12);
1683 i->random = initial_random_bits;
1684 i->produced_cargo_waiting[0] = 0;
1685 i->produced_cargo_waiting[1] = 0;
1686 i->incoming_cargo_waiting[0] = 0;
1687 i->incoming_cargo_waiting[1] = 0;
1688 i->incoming_cargo_waiting[2] = 0;
1689 i->this_month_production[0] = 0;
1690 i->this_month_production[1] = 0;
1691 i->this_month_transported[0] = 0;
1692 i->this_month_transported[1] = 0;
1693 i->last_month_pct_transported[0] = 0;
1694 i->last_month_pct_transported[1] = 0;
1695 i->last_month_transported[0] = 0;
1696 i->last_month_transported[1] = 0;
1697 i->was_cargo_delivered = false;
1698 i->last_prod_year = _cur_year;
1699 i->founder = founder;
1701 i->construction_date = _date;
1702 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1703 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1705 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1706 * 0 = created prior of newindustries
1707 * else, chosen layout + 1 */
1708 i->selected_layout = layout + 1;
1710 i->prod_level = PRODLEVEL_DEFAULT;
1712 /* Call callbacks after the regular fields got initialised. */
1714 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1715 uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1716 if (res != CALLBACK_FAILED) {
1717 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1718 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1719 } else {
1720 i->prod_level = res;
1721 i->RecomputeProductionMultipliers();
1726 if (_generating_world) {
1727 i->last_month_production[0] = i->production_rate[0] * 8;
1728 i->last_month_production[1] = i->production_rate[1] * 8;
1729 } else {
1730 i->last_month_production[0] = i->last_month_production[1] = 0;
1733 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1734 uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1735 if (res != CALLBACK_FAILED) {
1736 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1737 i->random_colour = GB(res, 0, 4);
1741 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1742 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1743 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) {
1744 uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1745 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1746 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1747 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1748 break;
1750 i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1754 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1755 for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1756 for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
1757 uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1758 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1759 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1760 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1761 break;
1763 i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1767 /* Plant the tiles */
1769 do {
1770 TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1772 if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1773 i->location.Add(cur_tile);
1775 WaterClass wc = (IsPlainWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1777 DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1779 MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1781 if (_generating_world) {
1782 SetIndustryConstructionCounter(cur_tile, 3);
1783 SetIndustryConstructionStage(cur_tile, 2);
1786 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1787 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
1788 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1789 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1791 } while ((++it)->ti.x != -0x80);
1793 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1794 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1796 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
1798 Station::RecomputeIndustriesNearForAll();
1802 * Helper function for Build/Fund an industry
1803 * @param tile tile where industry is built
1804 * @param type of industry to build
1805 * @param flags of operations to conduct
1806 * @param indspec pointer to industry specifications
1807 * @param itspec_index the index of the itsepc to build/fund
1808 * @param seed random seed (possibly) used by industries
1809 * @param initial_random_bits The random bits the industry is going to have after construction.
1810 * @param founder Founder of the industry
1811 * @param creation_type The circumstances the industry is created under.
1812 * @param [out] ip Pointer to store newly created industry.
1813 * @return Succeeded or failed command.
1815 * @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.
1817 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)
1819 assert(itspec_index < indspec->num_table);
1820 const IndustryTileTable *it = indspec->table[itspec_index];
1821 bool custom_shape_check = false;
1823 *ip = NULL;
1825 SmallVector<ClearedObjectArea, 1> object_areas(_cleared_object_areas);
1826 CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1827 _cleared_object_areas = object_areas;
1828 if (ret.Failed()) return ret;
1830 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1831 ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
1832 } else {
1833 ret = _check_new_industry_procs[indspec->check_proc](tile);
1835 if (ret.Failed()) return ret;
1837 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
1838 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1839 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1842 ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1843 if (ret.Failed()) return ret;
1845 Town *t = NULL;
1846 ret = FindTownForIndustry(tile, type, &t);
1847 if (ret.Failed()) return ret;
1848 assert(t != NULL);
1850 ret = CheckIfIndustryIsAllowed(tile, type, t);
1851 if (ret.Failed()) return ret;
1853 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1855 if (flags & DC_EXEC) {
1856 *ip = new Industry(tile);
1857 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
1858 DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
1861 return CommandCost();
1865 * Build/Fund an industry
1866 * @param tile tile where industry is built
1867 * @param flags of operations to conduct
1868 * @param p1 various bitstuffed elements
1869 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1870 * - p1 = (bit 8 - 15) - first layout to try
1871 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1872 * @param p2 seed to use for desyncfree randomisations
1873 * @param text unused
1874 * @return the cost of this operation or an error
1876 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1878 IndustryType it = GB(p1, 0, 8);
1879 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1881 const IndustrySpec *indspec = GetIndustrySpec(it);
1883 /* Check if the to-be built/founded industry is available for this climate. */
1884 if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
1886 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1887 * Raw material industries are industries that do not accept cargo (at least for now) */
1888 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1889 return CMD_ERROR;
1892 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1893 return CMD_ERROR;
1896 Randomizer randomizer;
1897 randomizer.SetSeed(p2);
1898 uint16 random_initial_bits = GB(p2, 0, 16);
1899 uint32 random_var8f = randomizer.Next();
1900 int num_layouts = indspec->num_table;
1901 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
1902 const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
1904 Industry *ind = NULL;
1905 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
1906 if (flags & DC_EXEC) {
1907 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1908 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1909 /* Prospecting has a chance to fail, however we cannot guarantee that something can
1910 * be built on the map, so the chance gets lower when the map is fuller, but there
1911 * is nothing we can really do about that. */
1912 if (deity_prospect || Random() <= indspec->prospecting_chance) {
1913 for (int i = 0; i < 5000; i++) {
1914 /* We should not have more than one Random() in a function call
1915 * because parameter evaluation order is not guaranteed in the c++ standard
1917 tile = RandomTile();
1918 /* Start with a random layout */
1919 int layout = RandomRange(num_layouts);
1920 /* Check now each layout, starting with the random one */
1921 for (int j = 0; j < num_layouts; j++) {
1922 layout = (layout + 1) % num_layouts;
1923 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
1924 if (ret.Succeeded()) break;
1926 if (ret.Succeeded()) break;
1929 cur_company.Restore();
1931 } else {
1932 int layout = GB(p1, 8, 8);
1933 if (layout >= num_layouts) return CMD_ERROR;
1935 /* Check subsequently each layout, starting with the given layout in p1 */
1936 for (int i = 0; i < num_layouts; i++) {
1937 layout = (layout + 1) % num_layouts;
1938 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
1939 if (ret.Succeeded()) break;
1942 /* If it still failed, there's no suitable layout to build here, return the error */
1943 if (ret.Failed()) return ret;
1946 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1947 AdvertiseIndustryOpening(ind);
1950 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1955 * Create a new industry of random layout.
1956 * @param tile The location to build the industry.
1957 * @param type The industry type to build.
1958 * @param creation_type The circumstances the industry is created under.
1959 * @return the created industry or NULL if it failed.
1961 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1963 const IndustrySpec *indspec = GetIndustrySpec(type);
1965 uint32 seed = Random();
1966 uint32 seed2 = Random();
1967 Industry *i = NULL;
1968 CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
1969 assert(i != NULL || ret.Failed());
1970 return i;
1974 * Compute the appearance probability for an industry during map creation.
1975 * @param it Industry type to compute.
1976 * @param [out] force_at_least_one Returns whether at least one instance should be forced on map creation.
1977 * @return Relative probability for the industry to appear.
1979 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
1981 const IndustrySpec *ind_spc = GetIndustrySpec(it);
1982 uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
1983 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1984 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
1985 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
1986 *force_at_least_one = false;
1987 return 0;
1988 } else {
1989 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1990 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1991 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapPerimeter(chance) : ScaleByMapSize(chance);
1993 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
1994 return chance;
1999 * Compute the probability for constructing a new industry during game play.
2000 * @param it Industry type to compute.
2001 * @param [out] min_number Minimal number of industries that should exist at the map.
2002 * @return Relative probability for the industry to appear.
2004 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
2006 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2007 *min_number = 0;
2008 return 0;
2011 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2012 byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2013 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
2014 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
2015 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
2016 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2017 *min_number = 0;
2018 return 0;
2020 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2021 return chance;
2025 * Get wanted number of industries on the map.
2026 * @return Wanted number of industries at the map.
2028 static uint GetNumberOfIndustries()
2030 /* Number of industries on a 256x256 map. */
2031 static const uint16 numof_industry_table[] = {
2032 0, // none
2033 0, // minimal
2034 10, // very low
2035 25, // low
2036 55, // normal
2037 80, // high
2040 assert(lengthof(numof_industry_table) == ID_END);
2041 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2042 return min(Industry::Pool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2046 * Try to place the industry in the game.
2047 * Since there is no feedback why placement fails, there is no other option
2048 * than to try a few times before concluding it does not work.
2049 * @param type Industry type of the desired industry.
2050 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2051 * @return Pointer to created industry, or \c NULL if creation failed.
2053 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2055 uint tries = try_hard ? 10000u : 2000u;
2056 for (; tries > 0; tries--) {
2057 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2058 if (ind != NULL) return ind;
2060 return NULL;
2064 * Try to build a industry on the map.
2065 * @param type IndustryType of the desired industry
2066 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2068 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2070 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2072 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2073 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2075 cur_company.Restore();
2079 * Get total number of industries existing in the game.
2080 * @return Number of industries currently in the game.
2082 static uint GetCurrentTotalNumberOfIndustries()
2084 int total = 0;
2085 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2086 return total;
2090 /** Reset the entry. */
2091 void IndustryTypeBuildData::Reset()
2093 this->probability = 0;
2094 this->min_number = 0;
2095 this->target_count = 0;
2096 this->max_wait = 1;
2097 this->wait_count = 0;
2100 /** Completely reset the industry build data. */
2101 void IndustryBuildData::Reset()
2103 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2105 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2106 this->builddata[it].Reset();
2110 /** Monthly update of industry build data. */
2111 void IndustryBuildData::MonthlyLoop()
2113 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.
2114 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2116 /* To prevent running out of unused industries for the player to connect,
2117 * add a fraction of new industries each month, but only if the manager can keep up. */
2118 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).
2119 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2120 this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2125 * This function will create random industries during game creation.
2126 * It will scale the amount of industries by mapsize and difficulty level.
2128 void GenerateIndustries()
2130 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2132 uint32 industry_probs[NUM_INDUSTRYTYPES];
2133 bool force_at_least_one[NUM_INDUSTRYTYPES];
2134 uint32 total_prob = 0;
2135 uint num_forced = 0;
2137 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2138 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2139 total_prob += industry_probs[it];
2140 if (force_at_least_one[it]) num_forced++;
2143 uint total_amount = GetNumberOfIndustries();
2144 if (total_prob == 0 || total_amount < num_forced) {
2145 /* Only place the forced ones */
2146 total_amount = num_forced;
2149 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2151 /* Try to build one industry per type independent of any probabilities */
2152 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2153 if (force_at_least_one[it]) {
2154 assert(total_amount > 0);
2155 total_amount--;
2156 PlaceInitialIndustry(it, true);
2160 /* Add the remaining industries according to their probabilities */
2161 for (uint i = 0; i < total_amount; i++) {
2162 uint32 r = RandomRange(total_prob);
2163 IndustryType it = 0;
2164 while (r >= industry_probs[it]) {
2165 r -= industry_probs[it];
2166 it++;
2167 assert(it < NUM_INDUSTRYTYPES);
2169 assert(industry_probs[it] > 0);
2170 PlaceInitialIndustry(it, false);
2172 _industry_builder.Reset();
2176 * Monthly update of industry statistics.
2177 * @param i Industry to update.
2179 static void UpdateIndustryStatistics(Industry *i)
2181 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2182 if (i->produced_cargo[j] != CT_INVALID) {
2183 byte pct = 0;
2184 if (i->this_month_production[j] != 0) {
2185 i->last_prod_year = _cur_year;
2186 pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2188 i->last_month_pct_transported[j] = pct;
2190 i->last_month_production[j] = i->this_month_production[j];
2191 i->this_month_production[j] = 0;
2193 i->last_month_transported[j] = i->this_month_transported[j];
2194 i->this_month_transported[j] = 0;
2200 * Recompute #production_rate for current #prod_level.
2201 * This function is only valid when not using smooth economy.
2203 void Industry::RecomputeProductionMultipliers()
2205 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2206 assert(!indspec->UsesSmoothEconomy());
2208 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2209 this->production_rate[0] = min(CeilDiv(indspec->production_rate[0] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2210 this->production_rate[1] = min(CeilDiv(indspec->production_rate[1] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2215 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2216 * @param it Industry type.
2217 * @return At least one of the fields has changed value.
2219 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2221 byte min_number;
2222 uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2223 bool changed = min_number != this->min_number || probability != this->probability;
2224 this->min_number = min_number;
2225 this->probability = probability;
2226 return changed;
2229 /** Decide how many industries of each type are needed. */
2230 void IndustryBuildData::SetupTargetCount()
2232 bool changed = false;
2233 uint num_planned = 0; // Number of industries planned in the industry build data.
2234 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2235 changed |= this->builddata[it].GetIndustryTypeData(it);
2236 num_planned += this->builddata[it].target_count;
2238 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2239 changed |= num_planned != total_amount;
2240 if (!changed) return; // All industries are still the same, no need to re-randomize.
2242 /* Initialize the target counts. */
2243 uint force_build = 0; // Number of industries that should always be available.
2244 uint32 total_prob = 0; // Sum of probabilities.
2245 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2246 IndustryTypeBuildData *ibd = this->builddata + it;
2247 force_build += ibd->min_number;
2248 ibd->target_count = ibd->min_number;
2249 total_prob += ibd->probability;
2252 if (total_prob == 0) return; // No buildable industries.
2254 /* Subtract forced industries from the number of industries available for construction. */
2255 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2257 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2258 while (total_amount > 0) {
2259 uint32 r = RandomRange(total_prob);
2260 IndustryType it = 0;
2261 while (r >= this->builddata[it].probability) {
2262 r -= this->builddata[it].probability;
2263 it++;
2264 assert(it < NUM_INDUSTRYTYPES);
2266 assert(this->builddata[it].probability > 0);
2267 this->builddata[it].target_count++;
2268 total_amount--;
2273 * Try to create a random industry, during gameplay
2275 void IndustryBuildData::TryBuildNewIndustry()
2277 this->SetupTargetCount();
2279 int missing = 0; // Number of industries that need to be build.
2280 uint count = 0; // Number of industry types eligible for build.
2281 uint32 total_prob = 0; // Sum of probabilities.
2282 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2283 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2284 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2285 missing += difference;
2286 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2287 if (difference > 0) {
2288 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2289 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2290 if (forced_build == NUM_INDUSTRYTYPES ||
2291 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2292 forced_build = it;
2295 total_prob += difference;
2296 count++;
2300 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2302 if (count >= 1) {
2303 /* If not forced, pick a weighted random industry to build.
2304 * For the case that count == 1, there is no need to draw a random number. */
2305 IndustryType it;
2306 if (forced_build != NUM_INDUSTRYTYPES) {
2307 it = forced_build;
2308 } else {
2309 /* Non-forced, select an industry type to build (weighted random). */
2310 uint32 r = 0; // Initialized to silence the compiler.
2311 if (count > 1) r = RandomRange(total_prob);
2312 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2313 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2314 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2315 if (difference <= 0) continue; // Too many of this kind.
2316 if (count == 1) break;
2317 if (r < (uint)difference) break;
2318 r -= difference;
2320 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2323 /* Try to create the industry. */
2324 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2325 if (ind == NULL) {
2326 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2327 this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2328 } else {
2329 AdvertiseIndustryOpening(ind);
2330 this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2334 /* Decrement wait counters. */
2335 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2336 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2341 * Protects an industry from closure if the appropriate flags and conditions are met
2342 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2343 * count of industries of this type must one (or lower) in order to be protected
2344 * against closure.
2345 * @param type IndustryType been queried
2346 * @result true if protection is on, false otherwise (except for oil wells)
2348 static bool CheckIndustryCloseDownProtection(IndustryType type)
2350 const IndustrySpec *indspec = GetIndustrySpec(type);
2352 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2353 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2354 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2358 * Can given cargo type be accepted or produced by the industry?
2359 * @param cargo: Cargo type
2360 * @param ind: Industry
2361 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2362 * @param *c_produces: Pointer to boolean for production of cargo
2363 * @return: \c *c_accepts is set when industry accepts the cargo type,
2364 * \c *c_produces is set when the industry produces the cargo type
2366 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2368 if (cargo == CT_INVALID) return;
2370 /* Check for acceptance of cargo */
2371 for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2372 if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2373 *c_accepts = true;
2374 break;
2378 /* Check for produced cargo */
2379 for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2380 if (cargo == ind->produced_cargo[j]) {
2381 *c_produces = true;
2382 break;
2388 * Compute who can service the industry.
2390 * Here, 'can service' means that he/she has trains and stations close enough
2391 * to the industry with the right cargo type and the right orders (ie has the
2392 * technical means).
2394 * @param ind: Industry being investigated.
2396 * @return The NewsType to use for a production change in this industry.
2398 static NewsType IndustryServiceNewsType (Industry *ind)
2400 /* Find all stations within reach of the industry */
2401 StationList stations;
2402 FindStationsAroundTiles(ind->location, &stations);
2404 if (stations.Length() == 0) return NT_INDUSTRY_NOBODY; // No stations found at all
2406 const Vehicle *v;
2407 int result = 0;
2408 FOR_ALL_VEHICLES(v) {
2409 /* Is it worthwhile to try this vehicle? */
2410 if (v->owner != _local_company && result != 0) continue;
2412 /* Check whether it accepts the right kind of cargo */
2413 bool c_accepts = false;
2414 bool c_produces = false;
2415 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2416 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2417 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2419 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2420 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2421 } else {
2422 continue;
2424 if (!c_accepts && !c_produces) continue; // Wrong cargo
2426 /* Check orders of the vehicle.
2427 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2428 * may have a different cargo type.
2430 const Order *o;
2431 FOR_VEHICLE_ORDERS(v, o) {
2432 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2433 /* Vehicle visits a station to load or unload */
2434 Station *st = Station::Get(o->GetDestination());
2435 assert(st != NULL);
2437 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2438 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2440 if (stations.Contains(st)) {
2441 if (v->owner == _local_company) return NT_INDUSTRY_COMPANY; // Company services industry
2442 result = 1; // Competitor services industry
2447 return result ? NT_INDUSTRY_OTHER : NT_INDUSTRY_NOBODY;
2450 static const uint PERCENT_TRANSPORTED_60 = 153;
2451 static const uint PERCENT_TRANSPORTED_80 = 204;
2454 * Change industry production smoothly for standard industries.
2455 * @param i Industry for which changes are performed.
2456 * @param only_decrease Whether production can only decrease (temperate oil wells).
2457 * @param on_water Whether the industry is built on water (oil rigs).
2458 * @return Whether the industry should be closed.
2460 static bool ChangeIndustryProductionSmooth (Industry *i,
2461 bool only_decrease, bool on_water)
2463 bool close = true;
2465 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2466 if (i->produced_cargo[j] == CT_INVALID) continue;
2468 uint32 r = Random();
2470 assert_compile (PERCENT_TRANSPORTED_80 > PERCENT_TRANSPORTED_60);
2472 int mult;
2473 if (only_decrease) {
2474 /* For industries with only_decrease flags (temperate
2475 * terrain Oil Wells), the multiplier will always be
2476 * -1 so they will only decrease. */
2477 mult = -1;
2478 } else if (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) {
2479 /* Bonus for very high station ratings:
2480 * 16% chance for decrease. */
2481 mult = Chance16I (1, 6, r) ? -1 : 1;
2482 } else {
2483 /* For normal industries, if over 60% is transported,
2484 * 33% chance for decrease, else 67% chance for decrease. */
2485 mult = ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) == Chance16I (1, 3, r)) ? -1 : 1;
2488 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2489 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2490 int old_prod, new_prod;
2491 new_prod = old_prod = i->production_rate[j];
2492 if (Chance16I (1, 22, r >> 16)) {
2493 new_prod += mult * max (((RandomRange(50) + 10) * old_prod) >> 8, 1U);
2496 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2497 new_prod = Clamp (new_prod, 1, 255);
2499 if (on_water && j == 1) {
2500 new_prod = Clamp(new_prod, 0, 16);
2503 /* Do not stop closing the industry when it has the lowest possible production rate */
2504 if (new_prod == old_prod && old_prod > 1) {
2505 close = false;
2506 continue;
2509 int percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2510 i->production_rate[j] = new_prod;
2512 /* Close the industry when it has the lowest possible production rate */
2513 if (new_prod > 1) close = false;
2515 int percent_abs = abs (percent);
2516 if (percent_abs >= 10) {
2517 AddNewsItem<IndustryNewsItem> (percent >= 0 ?
2518 STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH :
2519 STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2520 IndustryServiceNewsType (i), i->index,
2521 CargoSpec::Get(i->produced_cargo[j])->name,
2522 i->index, percent_abs);
2526 return close;
2530 * Change industry production or do closure
2531 * @param i Industry for which changes are performed
2532 * @param monthly true if it's the monthly call, false if it's the random call
2534 static void ChangeIndustryProduction(Industry *i, bool monthly)
2536 StringID str = STR_NULL;
2537 bool closeit = false;
2538 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2539 bool standard = false;
2540 bool suppress_message = false;
2541 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2542 /* don't use smooth economy for industries using production related callbacks */
2543 bool smooth_economy = indspec->UsesSmoothEconomy();
2544 byte div = 0;
2545 byte mul = 0;
2546 int8 increment = 0;
2548 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2549 if (callback_enabled) {
2550 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2551 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2552 suppress_message = HasBit(res, 7);
2553 /* Get the custom message if any */
2554 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2555 res = GB(res, 0, 4);
2556 switch (res) {
2557 default: NOT_REACHED();
2558 case 0x0: break; // Do nothing, but show the custom message if any
2559 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2560 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2561 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2562 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2563 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2564 case 0x8: div = res - 0x3; break; // Divide production by 32
2565 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2566 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2567 case 0xD: // decrement production
2568 case 0xE: // increment production
2569 increment = res == 0x0D ? -1 : 1;
2570 break;
2571 case 0xF: // Set production to third byte of register 0x100
2572 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2573 recalculate_multipliers = true;
2574 break;
2577 } else {
2578 if (monthly != smooth_economy) return;
2579 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2582 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2583 /* decrease or increase */
2584 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2586 if (smooth_economy) {
2587 closeit = ChangeIndustryProductionSmooth (i, only_decrease,
2588 (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0);
2589 } else {
2590 if (only_decrease || Chance16(1, 3)) {
2591 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2592 if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2593 mul = 1; // Increase production
2594 } else {
2595 div = 1; // Decrease production
2601 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2602 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2603 closeit = true;
2607 /* Increase if needed */
2608 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2609 i->prod_level = min(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2610 recalculate_multipliers = true;
2611 if (str == STR_NULL) str = indspec->production_up_text;
2614 /* Decrease if needed */
2615 while (div-- != 0 && !closeit) {
2616 if (i->prod_level == PRODLEVEL_MINIMUM) {
2617 closeit = true;
2618 } else {
2619 i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2620 recalculate_multipliers = true;
2621 if (str == STR_NULL) str = indspec->production_down_text;
2625 /* Increase or Decreasing the production level if needed */
2626 if (increment != 0) {
2627 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2628 closeit = true;
2629 } else {
2630 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2631 recalculate_multipliers = true;
2635 /* Recalculate production_rate
2636 * For non-smooth economy these should always be synchronized with prod_level */
2637 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2639 /* Close if needed and allowed */
2640 if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2641 i->prod_level = PRODLEVEL_CLOSURE;
2642 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2643 str = indspec->closure_text;
2646 if (!suppress_message && str != STR_NULL) {
2647 NewsType nt;
2648 /* Compute news category */
2649 if (closeit) {
2650 nt = NT_INDUSTRY_CLOSE;
2651 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2652 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2653 } else {
2654 nt = IndustryServiceNewsType (i);
2656 /* Report the news to the user. */
2657 uint p0 = (str > STR_LAST_STRINGID) ? STR_TOWN_NAME :
2658 closeit ? STR_FORMAT_INDUSTRY_NAME : i->index;
2659 if (closeit) {
2660 AddNewsItem<TileNewsItem> (str, nt,
2661 i->location.tile + TileDiffXY(1, 1),
2662 p0, i->town->index, indspec->name);
2663 } else {
2664 AddNewsItem<IndustryNewsItem> (str, nt, i->index,
2665 p0, i->town->index, indspec->name);
2671 * Daily handler for the industry changes
2672 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2673 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2674 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2675 * it would be way more. The daily loop handles those changes.
2677 void IndustryDailyLoop()
2679 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
2681 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2682 * the lower 16 bit are a fractional part that might accumulate over several days until it
2683 * is sufficient for an industry. */
2684 uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2686 /* Reset the active part of the counter, just keeping the "fractional part" */
2687 _economy.industry_daily_change_counter &= 0xFFFF;
2689 if (change_loop == 0) {
2690 return; // Nothing to do? get out
2693 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2695 /* perform the required industry changes for the day */
2697 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2698 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
2699 perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2701 for (uint16 j = 0; j < change_loop; j++) {
2702 if (Chance16(perc, 100)) {
2703 _industry_builder.TryBuildNewIndustry();
2704 } else {
2705 Industry *i = Industry::GetRandom();
2706 if (i != NULL) {
2707 ChangeIndustryProduction(i, false);
2708 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2713 cur_company.Restore();
2715 /* production-change */
2716 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2719 void IndustryMonthlyLoop()
2721 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2723 _industry_builder.MonthlyLoop();
2725 Industry *i;
2726 FOR_ALL_INDUSTRIES(i) {
2727 UpdateIndustryStatistics(i);
2728 if (i->prod_level == PRODLEVEL_CLOSURE) {
2729 delete i;
2730 } else {
2731 ChangeIndustryProduction(i, true);
2732 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2736 cur_company.Restore();
2738 /* production-change */
2739 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2743 void InitializeIndustries()
2745 Industry::ResetIndustryCounts();
2746 _industry_sound_tile = 0;
2748 _industry_builder.Reset();
2751 /** Verify whether the generated industries are complete, and warn the user if not. */
2752 void CheckIndustries()
2754 int count = 0;
2755 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2756 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2758 bool force_at_least_one;
2759 uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2760 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2762 const IndustrySpec *is = GetIndustrySpec(it);
2763 SetDParam(0, is->name);
2764 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2766 count++;
2767 if (count >= 3) break; // Don't swamp the user with errors.
2772 * Is an industry with the spec a raw industry?
2773 * @return true if it should be handled as a raw industry
2775 bool IndustrySpec::IsRawIndustry() const
2777 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2781 * Is an industry with the spec a processing industry?
2782 * @return true if it should be handled as a processing industry
2784 bool IndustrySpec::IsProcessingIndustry() const
2786 /* Lumber mills are neither raw nor processing */
2787 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2788 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2792 * Get the cost for constructing this industry
2793 * @return the cost (inflation corrected etc)
2795 Money IndustrySpec::GetConstructionCost() const
2797 /* Building raw industries like secondary uses different price base */
2798 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2799 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2803 * Get the cost for removing this industry
2804 * Take note that the cost will always be zero for non-grf industries.
2805 * Only if the grf author did specified a cost will it be applicable.
2806 * @return the cost (inflation corrected etc)
2808 Money IndustrySpec::GetRemovalCost() const
2810 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2814 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2815 * @return true if smooth economy is used.
2817 bool IndustrySpec::UsesSmoothEconomy() const
2819 return _settings_game.economy.smooth_economy &&
2820 !(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
2821 !(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
2824 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2826 if (AutoslopeEnabled()) {
2827 /* We imitate here TTDP's behaviour:
2828 * - Both new and old slope must not be steep.
2829 * - TileMaxZ must not be changed.
2830 * - Allow autoslope by default.
2831 * - Disallow autoslope if callback succeeds and returns non-zero.
2833 Slope tileh_old = GetTileSlope(tile);
2834 /* TileMaxZ must not be changed. Slopes must not be steep. */
2835 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2836 const IndustryGfx gfx = GetIndustryGfx(tile);
2837 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2839 /* Call callback 3C 'disable autosloping for industry tiles'. */
2840 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2841 /* If the callback fails, allow autoslope. */
2842 uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2843 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2844 } else {
2845 /* allow autoslope */
2846 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2850 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2853 extern const TileTypeProcs _tile_type_industry_procs = {
2854 DrawTile_Industry, // draw_tile_proc
2855 GetSlopePixelZ_Industry, // get_slope_z_proc
2856 ClearTile_Industry, // clear_tile_proc
2857 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2858 GetTileDesc_Industry, // get_tile_desc_proc
2859 NULL, // get_tile_railway_status_proc
2860 NULL, // get_tile_road_status_proc
2861 NULL, // get_tile_waterway_status_proc
2862 ClickTile_Industry, // click_tile_proc
2863 AnimateTile_Industry, // animate_tile_proc
2864 TileLoop_Industry, // tile_loop_proc
2865 ChangeTileOwner_Industry, // change_tile_owner_proc
2866 NULL, // add_produced_cargo_proc
2867 GetFoundation_Industry, // get_foundation_proc
2868 TerraformTile_Industry, // terraform_tile_proc