Change: Only resort town directory window on population change if necessary
[openttd-github.git] / src / industry_cmd.cpp
blob628e33557074eac75ace36badaaef895d3da1574
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
8 /** @file industry_cmd.cpp Handling of industry tiles. */
10 #include "stdafx.h"
11 #include "clear_map.h"
12 #include "industry.h"
13 #include "station_base.h"
14 #include "landscape.h"
15 #include "viewport_func.h"
16 #include "command_func.h"
17 #include "town.h"
18 #include "news_func.h"
19 #include "cheat_type.h"
20 #include "genworld.h"
21 #include "tree_map.h"
22 #include "newgrf_cargo.h"
23 #include "newgrf_debug.h"
24 #include "newgrf_industrytiles.h"
25 #include "autoslope.h"
26 #include "water.h"
27 #include "strings_func.h"
28 #include "window_func.h"
29 #include "date_func.h"
30 #include "vehicle_func.h"
31 #include "sound_func.h"
32 #include "animated_tile_func.h"
33 #include "effectvehicle_func.h"
34 #include "effectvehicle_base.h"
35 #include "ai/ai.hpp"
36 #include "core/pool_func.hpp"
37 #include "subsidy_func.h"
38 #include "core/backup_type.hpp"
39 #include "object_base.h"
40 #include "game/game.hpp"
41 #include "error.h"
43 #include "table/strings.h"
44 #include "table/industry_land.h"
45 #include "table/build_industry.h"
47 #include "safeguards.h"
49 IndustryPool _industry_pool("Industry");
50 INSTANTIATE_POOL_METHODS(Industry)
52 void ShowIndustryViewWindow(int industry);
53 void BuildOilRig(TileIndex tile);
55 static byte _industry_sound_ctr;
56 static TileIndex _industry_sound_tile;
58 uint16 Industry::counts[NUM_INDUSTRYTYPES];
60 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
61 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
62 IndustryBuildData _industry_builder; ///< In-game manager of industries.
64 /**
65 * This function initialize the spec arrays of both
66 * industry and industry tiles.
67 * It adjusts the enabling of the industry too, based on climate availability.
68 * This will allow for clearer testings
70 void ResetIndustries()
72 for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
73 /* Reset the spec to default */
74 if (i < lengthof(_origin_industry_specs)) {
75 _industry_specs[i] = _origin_industry_specs[i];
76 } else {
77 _industry_specs[i] = IndustrySpec{};
80 /* Enable only the current climate industries */
81 _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
82 HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
85 memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
86 memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
88 /* Reset any overrides that have been set. */
89 _industile_mngr.ResetOverride();
90 _industry_mngr.ResetOverride();
93 /**
94 * Retrieve the type for this industry. Although it is accessed by a tile,
95 * it will return the general type of industry, and not the sprite index
96 * as would do GetIndustryGfx.
97 * @param tile that is queried
98 * @pre IsTileType(tile, MP_INDUSTRY)
99 * @return general type for this industry, as defined in industry.h
101 IndustryType GetIndustryType(TileIndex tile)
103 assert(IsTileType(tile, MP_INDUSTRY));
105 const Industry *ind = Industry::GetByTile(tile);
106 assert(ind != nullptr);
107 return ind->type;
111 * Accessor for array _industry_specs.
112 * This will ensure at once : proper access and
113 * not allowing modifications of it.
114 * @param thistype of industry (which is the index in _industry_specs)
115 * @pre thistype < NUM_INDUSTRYTYPES
116 * @return a pointer to the corresponding industry spec
118 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
120 assert(thistype < NUM_INDUSTRYTYPES);
121 return &_industry_specs[thistype];
125 * Accessor for array _industry_tile_specs.
126 * This will ensure at once : proper access and
127 * not allowing modifications of it.
128 * @param gfx of industrytile (which is the index in _industry_tile_specs)
129 * @pre gfx < INVALID_INDUSTRYTILE
130 * @return a pointer to the corresponding industrytile spec
132 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
134 assert(gfx < INVALID_INDUSTRYTILE);
135 return &_industry_tile_specs[gfx];
138 Industry::~Industry()
140 if (CleaningPool()) return;
142 /* Industry can also be destroyed when not fully initialized.
143 * This means that we do not have to clear tiles either.
144 * Also we must not decrement industry counts in that case. */
145 if (this->location.w == 0) return;
147 const bool has_neutral_station = this->neutral_station != nullptr;
149 TILE_AREA_LOOP(tile_cur, this->location) {
150 if (IsTileType(tile_cur, MP_INDUSTRY)) {
151 if (GetIndustryIndex(tile_cur) == this->index) {
152 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur);
154 /* MakeWaterKeepingClass() can also handle 'land' */
155 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
157 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
158 DeleteOilRig(tile_cur);
162 if (has_neutral_station) {
163 /* Remove possible docking tiles */
164 TILE_AREA_LOOP(tile_cur, this->location) {
165 ClearDockingTilesCheckingNeighbours(tile_cur);
169 if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
170 TileArea ta = TileArea(this->location.tile, 0, 0).Expand(21);
172 /* Remove the farmland and convert it to regular tiles over time. */
173 TILE_AREA_LOOP(tile_cur, ta) {
174 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
175 GetIndustryIndexOfField(tile_cur) == this->index) {
176 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
181 /* don't let any disaster vehicle target invalid industry */
182 ReleaseDisastersTargetingIndustry(this->index);
184 /* Clear the persistent storage. */
185 delete this->psa;
187 DecIndustryTypeCount(this->type);
189 DeleteIndustryNews(this->index);
190 DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
191 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
193 DeleteSubsidyWith(ST_INDUSTRY, this->index);
194 CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
196 for (Station *st : this->stations_near) {
197 st->industries_near.erase(this);
202 * Invalidating some stuff after removing item from the pool.
203 * @param index index of deleted item
205 void Industry::PostDestructor(size_t index)
207 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
212 * Return a random valid industry.
213 * @return random industry, nullptr if there are no industries
215 /* static */ Industry *Industry::GetRandom()
217 if (Industry::GetNumItems() == 0) return nullptr;
218 int num = RandomRange((uint16)Industry::GetNumItems());
219 size_t index = MAX_UVALUE(size_t);
221 while (num >= 0) {
222 num--;
223 index++;
225 /* Make sure we have a valid industry */
226 while (!Industry::IsValidID(index)) {
227 index++;
228 assert(index < Industry::GetPoolSize());
232 return Industry::Get(index);
236 static void IndustryDrawSugarMine(const TileInfo *ti)
238 if (!IsIndustryCompleted(ti->tile)) return;
240 const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
242 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
244 if (d->image_2 != 0) {
245 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
248 if (d->image_3 != 0) {
249 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
250 _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
254 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
256 uint8 x = 0;
258 if (IsIndustryCompleted(ti->tile)) {
259 x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
260 if (x == 0xFF) {
261 x = 0;
265 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
266 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
269 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
271 if (IsIndustryCompleted(ti->tile)) {
272 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
274 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
277 static void IndustryDrawToyFactory(const TileInfo *ti)
279 const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
281 if (d->image_1 != 0xFF) {
282 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
285 if (d->image_2 != 0xFF) {
286 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
289 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
290 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
293 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
295 if (IsIndustryCompleted(ti->tile)) {
296 uint8 image = GetAnimationFrame(ti->tile);
298 if (image != 0 && image < 7) {
299 AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
300 PAL_NONE,
301 _coal_plant_sparks[image - 1].x,
302 _coal_plant_sparks[image - 1].y
308 typedef void IndustryDrawTileProc(const TileInfo *ti);
309 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
310 IndustryDrawSugarMine,
311 IndustryDrawToffeeQuarry,
312 IndustryDrawBubbleGenerator,
313 IndustryDrawToyFactory,
314 IndustryDrawCoalPlantSparks,
317 static void DrawTile_Industry(TileInfo *ti)
319 IndustryGfx gfx = GetIndustryGfx(ti->tile);
320 Industry *ind = Industry::GetByTile(ti->tile);
321 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
323 /* Retrieve pointer to the draw industry tile struct */
324 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
325 /* Draw the tile using the specialized method of newgrf industrytile.
326 * DrawNewIndustry will return false if ever the resolver could not
327 * find any sprite to display. So in this case, we will jump on the
328 * substitute gfx instead. */
329 if (indts->grf_prop.spritegroup[0] != nullptr && DrawNewIndustryTile(ti, ind, gfx, indts)) {
330 return;
331 } else {
332 /* No sprite group (or no valid one) found, meaning no graphics associated.
333 * Use the substitute one instead */
334 if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
335 gfx = indts->grf_prop.subst_id;
336 /* And point the industrytile spec accordingly */
337 indts = GetIndustryTileSpec(gfx);
342 const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
343 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
344 GetIndustryConstructionStage(ti->tile))];
346 SpriteID image = dits->ground.sprite;
348 /* DrawFoundation() modifies ti->z and ti->tileh */
349 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
351 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
352 * Do not do this if the tile's WaterClass is 'land'. */
353 if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
354 DrawWaterClassGround(ti);
355 } else {
356 DrawGroundSprite(image, GroundSpritePaletteTransform(image, dits->ground.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)));
359 /* If industries are transparent and invisible, do not draw the upper part */
360 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
362 /* Add industry on top of the ground? */
363 image = dits->building.sprite;
364 if (image != 0) {
365 AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)),
366 ti->x + dits->subtile_x,
367 ti->y + dits->subtile_y,
368 dits->width,
369 dits->height,
370 dits->dz,
371 ti->z,
372 IsTransparencySet(TO_INDUSTRIES));
374 if (IsTransparencySet(TO_INDUSTRIES)) return;
378 int proc = dits->draw_proc - 1;
379 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
383 static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
385 return GetTileMaxPixelZ(tile);
388 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
390 IndustryGfx gfx = GetIndustryGfx(tile);
392 /* For NewGRF industry tiles we might not be drawing a foundation. We need to
393 * account for this, as other structures should
394 * draw the wall of the foundation in this case.
396 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
397 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
398 if (indts->grf_prop.spritegroup[0] != nullptr && HasBit(indts->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
399 uint32 callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, Industry::GetByTile(tile), tile);
400 if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(indts->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
403 return FlatteningFoundation(tileh);
406 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, CargoTypes *always_accepted)
408 IndustryGfx gfx = GetIndustryGfx(tile);
409 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
410 const Industry *ind = Industry::GetByTile(tile);
412 /* Starting point for acceptance */
413 CargoID accepts_cargo[lengthof(itspec->accepts_cargo)];
414 int8 cargo_acceptance[lengthof(itspec->acceptance)];
415 MemCpyT(accepts_cargo, itspec->accepts_cargo, lengthof(accepts_cargo));
416 MemCpyT(cargo_acceptance, itspec->acceptance, lengthof(cargo_acceptance));
418 if (itspec->special_flags & INDTILE_SPECIAL_ACCEPTS_ALL_CARGO) {
419 /* Copy all accepted cargoes from industry itself */
420 for (uint i = 0; i < lengthof(ind->accepts_cargo); i++) {
421 CargoID *pos = std::find(accepts_cargo, endof(accepts_cargo), ind->accepts_cargo[i]);
422 if (pos == endof(accepts_cargo)) {
423 /* Not found, insert */
424 pos = std::find(accepts_cargo, endof(accepts_cargo), CT_INVALID);
425 if (pos == endof(accepts_cargo)) continue; // nowhere to place, give up on this one
426 *pos = ind->accepts_cargo[i];
428 cargo_acceptance[pos - accepts_cargo] += 8;
432 if (HasBit(itspec->callback_mask, CBM_INDT_ACCEPT_CARGO)) {
433 /* Try callback for accepts list, if success override all existing accepts */
434 uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
435 if (res != CALLBACK_FAILED) {
436 MemSetT(accepts_cargo, CT_INVALID, lengthof(accepts_cargo));
437 for (uint i = 0; i < 3; i++) accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
441 if (HasBit(itspec->callback_mask, CBM_INDT_CARGO_ACCEPTANCE)) {
442 /* Try callback for acceptance list, if success override all existing acceptance */
443 uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
444 if (res != CALLBACK_FAILED) {
445 MemSetT(cargo_acceptance, 0, lengthof(cargo_acceptance));
446 for (uint i = 0; i < 3; i++) cargo_acceptance[i] = GB(res, i * 4, 4);
450 for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
451 CargoID a = accepts_cargo[i];
452 if (a == CT_INVALID || cargo_acceptance[i] <= 0) continue; // work only with valid cargoes
454 /* Add accepted cargo */
455 acceptance[a] += cargo_acceptance[i];
457 /* Maybe set 'always accepted' bit (if it's not set already) */
458 if (HasBit(*always_accepted, a)) continue;
460 bool accepts = false;
461 for (uint cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
462 /* Test whether the industry itself accepts the cargo type */
463 if (ind->accepts_cargo[cargo_index] == a) {
464 accepts = true;
465 break;
469 if (accepts) continue;
471 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
472 SetBit(*always_accepted, a);
476 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
478 const Industry *i = Industry::GetByTile(tile);
479 const IndustrySpec *is = GetIndustrySpec(i->type);
481 td->owner[0] = i->owner;
482 td->str = is->name;
483 if (!IsIndustryCompleted(tile)) {
484 SetDParamX(td->dparam, 0, td->str);
485 td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
488 if (is->grf_prop.grffile != nullptr) {
489 td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
493 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
495 Industry *i = Industry::GetByTile(tile);
496 const IndustrySpec *indspec = GetIndustrySpec(i->type);
498 /* water can destroy industries
499 * in editor you can bulldoze industries
500 * with magic_bulldozer cheat you can destroy industries
501 * (area around OILRIG is water, so water shouldn't flood it
503 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
504 !_cheats.magic_bulldozer.value) ||
505 ((flags & DC_AUTO) != 0) ||
506 (_current_company == OWNER_WATER &&
507 ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
508 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
509 SetDParam(1, indspec->name);
510 return_cmd_error(flags & DC_AUTO ? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY : INVALID_STRING_ID);
513 if (flags & DC_EXEC) {
514 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
515 Game::NewEvent(new ScriptEventIndustryClose(i->index));
516 delete i;
518 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
522 * Move produced cargo from industry to nearby stations.
523 * @param tile Industry tile
524 * @return true if any cargo was moved.
526 static bool TransportIndustryGoods(TileIndex tile)
528 Industry *i = Industry::GetByTile(tile);
529 const IndustrySpec *indspec = GetIndustrySpec(i->type);
530 bool moved_cargo = false;
532 for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
533 uint cw = min(i->produced_cargo_waiting[j], 255);
534 if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
535 i->produced_cargo_waiting[j] -= cw;
537 /* fluctuating economy? */
538 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
540 i->this_month_production[j] += cw;
542 uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, &i->stations_near);
543 i->this_month_transported[j] += am;
545 moved_cargo |= (am != 0);
549 return moved_cargo;
553 static void AnimateTile_Industry(TileIndex tile)
555 IndustryGfx gfx = GetIndustryGfx(tile);
557 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
558 AnimateNewIndustryTile(tile);
559 return;
562 switch (gfx) {
563 case GFX_SUGAR_MINE_SIEVE:
564 if ((_tick_counter & 1) == 0) {
565 byte m = GetAnimationFrame(tile) + 1;
567 if (_settings_client.sound.ambient) {
568 switch (m & 7) {
569 case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
570 case 6: SndPlayTileFx(SND_29_RIP, tile); break;
574 if (m >= 96) {
575 m = 0;
576 DeleteAnimatedTile(tile);
578 SetAnimationFrame(tile, m);
580 MarkTileDirtyByTile(tile);
582 break;
584 case GFX_TOFFEE_QUARY:
585 if ((_tick_counter & 3) == 0) {
586 byte m = GetAnimationFrame(tile);
588 if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
589 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
592 if (++m >= 70) {
593 m = 0;
594 DeleteAnimatedTile(tile);
596 SetAnimationFrame(tile, m);
598 MarkTileDirtyByTile(tile);
600 break;
602 case GFX_BUBBLE_CATCHER:
603 if ((_tick_counter & 1) == 0) {
604 byte m = GetAnimationFrame(tile);
606 if (++m >= 40) {
607 m = 0;
608 DeleteAnimatedTile(tile);
610 SetAnimationFrame(tile, m);
612 MarkTileDirtyByTile(tile);
614 break;
616 /* Sparks on a coal plant */
617 case GFX_POWERPLANT_SPARKS:
618 if ((_tick_counter & 3) == 0) {
619 byte m = GetAnimationFrame(tile);
620 if (m == 6) {
621 SetAnimationFrame(tile, 0);
622 DeleteAnimatedTile(tile);
623 } else {
624 SetAnimationFrame(tile, m + 1);
625 MarkTileDirtyByTile(tile);
628 break;
630 case GFX_TOY_FACTORY:
631 if ((_tick_counter & 1) == 0) {
632 byte m = GetAnimationFrame(tile) + 1;
634 switch (m) {
635 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
636 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
637 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
638 default:
639 if (m >= 50) {
640 int n = GetIndustryAnimationLoop(tile) + 1;
641 m = 0;
642 if (n >= 8) {
643 n = 0;
644 DeleteAnimatedTile(tile);
646 SetIndustryAnimationLoop(tile, n);
650 SetAnimationFrame(tile, m);
651 MarkTileDirtyByTile(tile);
653 break;
655 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
656 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
657 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
658 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
659 if ((_tick_counter & 3) == 0) {
660 IndustryGfx gfx = GetIndustryGfx(tile);
662 gfx = (gfx < 155) ? gfx + 1 : 148;
663 SetIndustryGfx(tile, gfx);
664 MarkTileDirtyByTile(tile);
666 break;
668 case GFX_OILWELL_ANIMATED_1:
669 case GFX_OILWELL_ANIMATED_2:
670 case GFX_OILWELL_ANIMATED_3:
671 if ((_tick_counter & 7) == 0) {
672 bool b = Chance16(1, 7);
673 IndustryGfx gfx = GetIndustryGfx(tile);
675 byte m = GetAnimationFrame(tile) + 1;
676 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
677 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
678 SetIndustryConstructionStage(tile, 3);
679 DeleteAnimatedTile(tile);
680 } else {
681 SetAnimationFrame(tile, m);
682 SetIndustryGfx(tile, gfx);
683 MarkTileDirtyByTile(tile);
686 break;
688 case GFX_COAL_MINE_TOWER_ANIMATED:
689 case GFX_COPPER_MINE_TOWER_ANIMATED:
690 case GFX_GOLD_MINE_TOWER_ANIMATED: {
691 int state = _tick_counter & 0x7FF;
693 if ((state -= 0x400) < 0) return;
695 if (state < 0x1A0) {
696 if (state < 0x20 || state >= 0x180) {
697 byte m = GetAnimationFrame(tile);
698 if (!(m & 0x40)) {
699 SetAnimationFrame(tile, m | 0x40);
700 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
702 if (state & 7) return;
703 } else {
704 if (state & 3) return;
706 byte m = (GetAnimationFrame(tile) + 1) | 0x40;
707 if (m > 0xC2) m = 0xC0;
708 SetAnimationFrame(tile, m);
709 MarkTileDirtyByTile(tile);
710 } else if (state >= 0x200 && state < 0x3A0) {
711 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
712 if (state & i) return;
714 byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
715 if (m < 0x80) m = 0x82;
716 SetAnimationFrame(tile, m);
717 MarkTileDirtyByTile(tile);
719 break;
724 static void CreateChimneySmoke(TileIndex tile)
726 uint x = TileX(tile) * TILE_SIZE;
727 uint y = TileY(tile) * TILE_SIZE;
728 int z = GetTileMaxPixelZ(tile);
730 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
733 static void MakeIndustryTileBigger(TileIndex tile)
735 byte cnt = GetIndustryConstructionCounter(tile) + 1;
736 if (cnt != 4) {
737 SetIndustryConstructionCounter(tile, cnt);
738 return;
741 byte stage = GetIndustryConstructionStage(tile) + 1;
742 SetIndustryConstructionCounter(tile, 0);
743 SetIndustryConstructionStage(tile, stage);
744 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
745 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
747 MarkTileDirtyByTile(tile);
749 if (!IsIndustryCompleted(tile)) return;
751 IndustryGfx gfx = GetIndustryGfx(tile);
752 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
753 /* New industries are already animated on construction. */
754 return;
757 switch (gfx) {
758 case GFX_POWERPLANT_CHIMNEY:
759 CreateChimneySmoke(tile);
760 break;
762 case GFX_OILRIG_1: {
763 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
764 * tiles (like the default oil rig). Do a proper check to ensure the
765 * tiles belong to the same industry and based on that build the oil rig's
766 * station. */
767 TileIndex other = tile + TileDiffXY(0, 1);
769 if (IsTileType(other, MP_INDUSTRY) &&
770 GetIndustryGfx(other) == GFX_OILRIG_1 &&
771 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
772 BuildOilRig(tile);
774 break;
777 case GFX_TOY_FACTORY:
778 case GFX_BUBBLE_CATCHER:
779 case GFX_TOFFEE_QUARY:
780 SetAnimationFrame(tile, 0);
781 SetIndustryAnimationLoop(tile, 0);
782 break;
784 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
785 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
786 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
787 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
788 AddAnimatedTile(tile);
789 break;
793 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
795 static const int8 _bubble_spawn_location[3][4] = {
796 { 11, 0, -4, -14 },
797 { -4, -10, -4, 1 },
798 { 49, 59, 60, 65 },
801 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
803 int dir = Random() & 3;
805 EffectVehicle *v = CreateEffectVehicleAbove(
806 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
807 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
808 _bubble_spawn_location[2][dir],
809 EV_BUBBLE
812 if (v != nullptr) v->animation_substate = dir;
815 static void TileLoop_Industry(TileIndex tile)
817 if (IsTileOnWater(tile)) TileLoop_Water(tile);
819 /* Normally this doesn't happen, but if an industry NewGRF is removed
820 * an industry that was previously build on water can now be flooded.
821 * If this happens the tile is no longer an industry tile after
822 * returning from TileLoop_Water. */
823 if (!IsTileType(tile, MP_INDUSTRY)) return;
825 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
827 if (!IsIndustryCompleted(tile)) {
828 MakeIndustryTileBigger(tile);
829 return;
832 if (_game_mode == GM_EDITOR) return;
834 if (TransportIndustryGoods(tile) && !StartStopIndustryTileAnimation(Industry::GetByTile(tile), IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
835 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
837 if (newgfx != INDUSTRYTILE_NOANIM) {
838 ResetIndustryConstructionStage(tile);
839 SetIndustryCompleted(tile);
840 SetIndustryGfx(tile, newgfx);
841 MarkTileDirtyByTile(tile);
842 return;
846 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
848 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
849 if (newgfx != INDUSTRYTILE_NOANIM) {
850 ResetIndustryConstructionStage(tile);
851 SetIndustryGfx(tile, newgfx);
852 MarkTileDirtyByTile(tile);
853 return;
856 IndustryGfx gfx = GetIndustryGfx(tile);
857 switch (gfx) {
858 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
859 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
860 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
861 if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
862 switch (gfx) {
863 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
864 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
865 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
867 SetIndustryGfx(tile, gfx);
868 SetAnimationFrame(tile, 0x80);
869 AddAnimatedTile(tile);
871 break;
873 case GFX_OILWELL_NOT_ANIMATED:
874 if (Chance16(1, 6)) {
875 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
876 SetAnimationFrame(tile, 0);
877 AddAnimatedTile(tile);
879 break;
881 case GFX_COAL_MINE_TOWER_ANIMATED:
882 case GFX_COPPER_MINE_TOWER_ANIMATED:
883 case GFX_GOLD_MINE_TOWER_ANIMATED:
884 if (!(_tick_counter & 0x400)) {
885 switch (gfx) {
886 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
887 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
888 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
890 SetIndustryGfx(tile, gfx);
891 SetIndustryCompleted(tile);
892 SetIndustryConstructionStage(tile, 3);
893 DeleteAnimatedTile(tile);
895 break;
897 case GFX_POWERPLANT_SPARKS:
898 if (Chance16(1, 3)) {
899 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
900 AddAnimatedTile(tile);
902 break;
904 case GFX_COPPER_MINE_CHIMNEY:
905 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
906 break;
909 case GFX_TOY_FACTORY: {
910 Industry *i = Industry::GetByTile(tile);
911 if (i->was_cargo_delivered) {
912 i->was_cargo_delivered = false;
913 SetIndustryAnimationLoop(tile, 0);
914 AddAnimatedTile(tile);
917 break;
919 case GFX_BUBBLE_GENERATOR:
920 TileLoopIndustry_BubbleGenerator(tile);
921 break;
923 case GFX_TOFFEE_QUARY:
924 AddAnimatedTile(tile);
925 break;
927 case GFX_SUGAR_MINE_SIEVE:
928 if (Chance16(1, 3)) AddAnimatedTile(tile);
929 break;
933 static bool ClickTile_Industry(TileIndex tile)
935 ShowIndustryViewWindow(GetIndustryIndex(tile));
936 return true;
939 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
941 return 0;
944 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
946 /* If the founder merges, the industry was created by the merged company */
947 Industry *i = Industry::GetByTile(tile);
948 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
952 * Check whether the tile is a forest.
953 * @param tile the tile to investigate.
954 * @return true if and only if the tile is a forest
956 bool IsTileForestIndustry(TileIndex tile)
958 /* Check for industry tile */
959 if (!IsTileType(tile, MP_INDUSTRY)) return false;
961 const Industry *ind = Industry::GetByTile(tile);
963 /* Check for organic industry (i.e. not processing or extractive) */
964 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
966 /* Check for wood production */
967 for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
968 /* The industry produces wood. */
969 if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
972 return false;
975 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
978 * Check whether the tile can be replaced by a farm field.
979 * @param tile the tile to investigate.
980 * @param allow_fields if true, the method will return true even if
981 * the tile is a farm tile, otherwise the tile may not be a farm tile
982 * @return true if the tile can become a farm field
984 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
986 switch (GetTileType(tile)) {
987 case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
988 case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
989 default: return false;
994 * Build farm field fence
995 * @param tile the tile to position the fence on
996 * @param size the size of the field being planted in tiles
997 * @param type type of fence to set
998 * @param side the side of the tile to attempt placement
1000 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
1002 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1004 do {
1005 tile = TILE_MASK(tile);
1007 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
1008 byte or_ = type;
1010 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
1012 SetFence(tile, side, or_);
1015 tile += diff;
1016 } while (--size);
1019 static void PlantFarmField(TileIndex tile, IndustryID industry)
1021 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1022 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1025 /* determine field size */
1026 uint32 r = (Random() & 0x303) + 0x404;
1027 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1028 uint size_x = GB(r, 0, 8);
1029 uint size_y = GB(r, 8, 8);
1031 TileArea ta(tile - TileDiffXY(min(TileX(tile), size_x / 2), min(TileY(tile), size_y / 2)), size_x, size_y);
1032 ta.ClampToMap();
1034 if (ta.w == 0 || ta.h == 0) return;
1036 /* check the amount of bad tiles */
1037 int count = 0;
1038 TILE_AREA_LOOP(cur_tile, ta) {
1039 assert(cur_tile < MapSize());
1040 count += IsSuitableForFarmField(cur_tile, false);
1042 if (count * 2 < ta.w * ta.h) return;
1044 /* determine type of field */
1045 r = Random();
1046 uint counter = GB(r, 5, 3);
1047 uint field_type = GB(r, 8, 8) * 9 >> 8;
1049 /* make field */
1050 TILE_AREA_LOOP(cur_tile, ta) {
1051 assert(cur_tile < MapSize());
1052 if (IsSuitableForFarmField(cur_tile, true)) {
1053 MakeField(cur_tile, field_type, industry);
1054 SetClearCounter(cur_tile, counter);
1055 MarkTileDirtyByTile(cur_tile);
1059 int type = 3;
1060 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1061 type = _plantfarmfield_type[Random() & 0xF];
1064 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1065 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1066 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1067 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1070 void PlantRandomFarmField(const Industry *i)
1072 int x = i->location.w / 2 + Random() % 31 - 16;
1073 int y = i->location.h / 2 + Random() % 31 - 16;
1075 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1077 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1081 * Search callback function for ChopLumberMillTrees
1082 * @param tile to test
1083 * @param user_data that is passed by the caller. In this case, nothing
1084 * @return the result of the test
1086 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
1088 if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1089 /* found a tree */
1091 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1093 _industry_sound_ctr = 1;
1094 _industry_sound_tile = tile;
1095 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1097 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1099 cur_company.Restore();
1100 return true;
1102 return false;
1106 * Perform a circular search around the Lumber Mill in order to find trees to cut
1107 * @param i industry
1109 static void ChopLumberMillTrees(Industry *i)
1111 /* We only want to cut trees if all tiles are completed. */
1112 TILE_AREA_LOOP(tile_cur, i->location) {
1113 if (i->TileBelongsToIndustry(tile_cur)) {
1114 if (!IsIndustryCompleted(tile_cur)) return;
1118 TileIndex tile = i->location.tile;
1119 if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, nullptr)) { // 40x40 tiles to search.
1120 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1124 static void ProduceIndustryGoods(Industry *i)
1126 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1128 /* play a sound? */
1129 if ((i->counter & 0x3F) == 0) {
1130 uint32 r;
1131 if (Chance16R(1, 14, r) && indsp->number_of_sounds != 0 && _settings_client.sound.ambient) {
1132 for (size_t j = 0; j < lengthof(i->last_month_production); j++) {
1133 if (i->last_month_production[j] > 0) {
1134 /* Play sound since last month had production */
1135 SndPlayTileFx(
1136 (SoundFx)(indsp->random_sounds[((r >> 16) * indsp->number_of_sounds) >> 16]),
1137 i->location.tile);
1138 break;
1144 i->counter--;
1146 /* produce some cargo */
1147 if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1148 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
1150 IndustryBehaviour indbehav = indsp->behaviour;
1151 for (size_t j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
1152 i->produced_cargo_waiting[j] = min(0xffff, i->produced_cargo_waiting[j] + i->production_rate[j]);
1155 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1156 uint16 cb_res = CALLBACK_FAILED;
1157 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1158 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1161 bool plant;
1162 if (cb_res != CALLBACK_FAILED) {
1163 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1164 } else {
1165 plant = Chance16(1, 8);
1168 if (plant) PlantRandomFarmField(i);
1170 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1171 uint16 cb_res = CALLBACK_FAILED;
1172 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1173 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1176 bool cut;
1177 if (cb_res != CALLBACK_FAILED) {
1178 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1179 } else {
1180 cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1183 if (cut) ChopLumberMillTrees(i);
1186 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1187 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1191 void OnTick_Industry()
1193 if (_industry_sound_ctr != 0) {
1194 _industry_sound_ctr++;
1196 if (_industry_sound_ctr == 75) {
1197 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1198 } else if (_industry_sound_ctr == 160) {
1199 _industry_sound_ctr = 0;
1200 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1204 if (_game_mode == GM_EDITOR) return;
1206 for (Industry *i : Industry::Iterate()) {
1207 ProduceIndustryGoods(i);
1212 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1213 * @param tile %Tile to perform the checking.
1214 * @return Succeeded or failed command.
1216 static CommandCost CheckNewIndustry_NULL(TileIndex tile)
1218 return CommandCost();
1222 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1223 * @param tile %Tile to perform the checking.
1224 * @return Succeeded or failed command.
1226 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1228 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1229 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1230 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1233 return CommandCost();
1237 * Check if a tile is within a distance from map edges, scaled by map dimensions independently.
1238 * Each dimension is checked independently, and dimensions smaller than 256 are not scaled.
1239 * @param tile Which tile to check distance of.
1240 * @param maxdist Normal distance on a 256x256 map.
1241 * @return True if the tile is near the map edge.
1243 static bool CheckScaledDistanceFromEdge(TileIndex tile, uint maxdist)
1245 uint maxdist_x = maxdist;
1246 uint maxdist_y = maxdist;
1248 if (MapSizeX() > 256) maxdist_x *= MapSizeX() / 256;
1249 if (MapSizeY() > 256) maxdist_y *= MapSizeY() / 256;
1251 if (DistanceFromEdgeDir(tile, DIAGDIR_NE) < maxdist_x) return true;
1252 if (DistanceFromEdgeDir(tile, DIAGDIR_NW) < maxdist_y) return true;
1253 if (DistanceFromEdgeDir(tile, DIAGDIR_SW) < maxdist_x) return true;
1254 if (DistanceFromEdgeDir(tile, DIAGDIR_SE) < maxdist_y) return true;
1256 return false;
1260 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1261 * @param tile %Tile to perform the checking.
1262 * @return Succeeded or failed command.
1264 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1266 if (_game_mode == GM_EDITOR) return CommandCost();
1268 if (CheckScaledDistanceFromEdge(TILE_ADDXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1270 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1273 extern bool _ignore_restrictions;
1276 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1277 * @param tile %Tile to perform the checking.
1278 * @return Succeeded or failed command.
1280 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1282 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1284 if (TileHeight(tile) == 0 &&
1285 CheckScaledDistanceFromEdge(TILE_ADDXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1287 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1291 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1292 * @param tile %Tile to perform the checking.
1293 * @return Succeeded or failed command.
1295 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1297 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1298 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1299 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1302 return CommandCost();
1306 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1307 * @param tile %Tile to perform the checking.
1308 * @return Succeeded or failed command.
1310 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1312 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1313 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1315 return CommandCost();
1319 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1320 * @param tile %Tile to perform the checking.
1321 * @return Succeeded or failed command.
1323 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1325 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1326 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1328 return CommandCost();
1332 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1333 * @param tile %Tile to perform the checking.
1334 * @return Succeeded or failed command.
1336 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1338 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1339 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1341 return CommandCost();
1345 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1346 * @param tile %Tile to perform the checking.
1347 * @return Succeeded or failed command.
1349 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1351 if (GetTileZ(tile) > 4) {
1352 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1354 return CommandCost();
1358 * Industrytype check function signature.
1359 * @param tile %Tile to check.
1360 * @return Succeeded or failed command.
1362 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1364 /** Check functions for different types of industry. */
1365 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1366 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1367 CheckNewIndustry_Forest, ///< CHECK_FOREST
1368 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1369 CheckNewIndustry_Farm, ///< CHECK_FARM
1370 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1371 CheckNewIndustry_Water, ///< CHECK_WATER
1372 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1373 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1374 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1378 * Find a town for the industry, while checking for multiple industries in the same town.
1379 * @param tile Position of the industry to build.
1380 * @param type Industry type.
1381 * @param[out] t Pointer to return town for the new industry, \c nullptr is written if no good town can be found.
1382 * @return Succeeded or failed command.
1384 * @pre \c *t != nullptr
1385 * @post \c *t points to a town on success, and \c nullptr on failure.
1387 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1389 *t = ClosestTownFromTile(tile, UINT_MAX);
1391 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1393 for (const Industry *i : Industry::Iterate()) {
1394 if (i->type == (byte)type && i->town == *t) {
1395 *t = nullptr;
1396 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1400 return CommandCost();
1403 bool IsSlopeRefused(Slope current, Slope refused)
1405 if (IsSteepSlope(current)) return true;
1406 if (current != SLOPE_FLAT) {
1407 if (IsSteepSlope(refused)) return true;
1409 Slope t = ComplementSlope(current);
1411 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1412 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1413 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1414 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1417 return false;
1421 * Are the tiles of the industry free?
1422 * @param tile Position to check.
1423 * @param layout Industry tiles table.
1424 * @param layout_index The index of the layout to build/fund
1425 * @param type Type of the industry.
1426 * @param initial_random_bits The random bits the industry is going to have after construction.
1427 * @param founder Industry founder
1428 * @param creation_type The circumstances the industry is created under.
1429 * @param[out] custom_shape_check Perform custom check for the site.
1430 * @return Failed or succeeded command.
1432 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
1434 bool refused_slope = false;
1435 bool custom_shape = false;
1437 for (const IndustryTileLayoutTile &it : layout) {
1438 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1439 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1441 if (!IsValidTile(cur_tile)) {
1442 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1445 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1446 if (!IsWaterTile(cur_tile) ||
1447 !IsTileFlat(cur_tile)) {
1448 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1450 } else {
1451 CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1452 if (ret.Failed()) return ret;
1453 if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1455 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1457 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1459 /* Perform land/water check if not disabled */
1460 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1462 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1463 custom_shape = true;
1464 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
1465 if (ret.Failed()) return ret;
1466 } else {
1467 Slope tileh = GetTileSlope(cur_tile);
1468 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1471 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1472 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1473 if (!IsTileType(cur_tile, MP_HOUSE)) {
1474 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1477 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1478 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1479 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1480 cur_company.Restore();
1482 if (ret.Failed()) return ret;
1483 } else {
1484 /* Clear the tiles, but do not affect town ratings */
1485 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1487 if (ret.Failed()) return ret;
1492 if (custom_shape_check != nullptr) *custom_shape_check = custom_shape;
1494 /* It is almost impossible to have a fully flat land in TG, so what we
1495 * do is that we check if we can make the land flat later on. See
1496 * CheckIfCanLevelIndustryPlatform(). */
1497 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1498 return CommandCost();
1500 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1504 * Is the industry allowed to be built at this place for the town?
1505 * @param tile Tile to construct the industry.
1506 * @param type Type of the industry.
1507 * @param t Town authority that the industry belongs to.
1508 * @return Succeeded or failed command.
1510 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1512 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1513 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1516 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1517 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1520 return CommandCost();
1523 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1525 /* Check if we don't leave the map */
1526 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1528 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1529 TILE_AREA_LOOP(tile_walk, ta) {
1530 uint curh = TileHeight(tile_walk);
1531 /* Is the tile clear? */
1532 if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1534 /* Don't allow too big of a change if this is the sub-tile check */
1535 if (internal != 0 && Delta(curh, height) > 1) return false;
1537 /* Different height, so the surrounding tiles of this tile
1538 * has to be correct too (in level, or almost in level)
1539 * else you get a chain-reaction of terraforming. */
1540 if (internal == 0 && curh != height) {
1541 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1542 return false;
1547 return true;
1551 * This function tries to flatten out the land below an industry, without
1552 * damaging the surroundings too much.
1554 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileLayout &layout, int type)
1556 int max_x = 0;
1557 int max_y = 0;
1559 /* Finds dimensions of largest variant of this industry */
1560 for (const IndustryTileLayoutTile &it : layout) {
1561 if (it.gfx == GFX_WATERTILE_SPECIALCHECK) continue; // watercheck tiles don't count for footprint size
1562 if (it.ti.x > max_x) max_x = it.ti.x;
1563 if (it.ti.y > max_y) max_y = it.ti.y;
1566 /* Remember level height */
1567 uint h = TileHeight(tile);
1569 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1570 /* Check that all tiles in area and surrounding are clear
1571 * this determines that there are no obstructing items */
1573 /* TileArea::Expand is not used here as we need to abort
1574 * instead of clamping if the bounds cannot expanded. */
1575 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1576 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1578 if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1580 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1581 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1582 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1584 TILE_AREA_LOOP(tile_walk, ta) {
1585 uint curh = TileHeight(tile_walk);
1586 if (curh != h) {
1587 /* This tile needs terraforming. Check if we can do that without
1588 * damaging the surroundings too much. */
1589 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1590 cur_company.Restore();
1591 return false;
1593 /* This is not 100% correct check, but the best we can do without modifying the map.
1594 * What is missing, is if the difference in height is more than 1.. */
1595 if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1596 cur_company.Restore();
1597 return false;
1602 if (flags & DC_EXEC) {
1603 /* Terraform the land under the industry */
1604 TILE_AREA_LOOP(tile_walk, ta) {
1605 uint curh = TileHeight(tile_walk);
1606 while (curh != h) {
1607 /* We give the terraforming for free here, because we can't calculate
1608 * exact cost in the test-round, and as we all know, that will cause
1609 * a nice assert if they don't match ;) */
1610 DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1611 curh += (curh > h) ? -1 : 1;
1616 cur_company.Restore();
1617 return true;
1622 * Check that the new industry is far enough from conflicting industries.
1623 * @param tile Tile to construct the industry.
1624 * @param type Type of the new industry.
1625 * @return Succeeded or failed command.
1627 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1629 const IndustrySpec *indspec = GetIndustrySpec(type);
1631 /* On a large map with many industries, it may be faster to check an area. */
1632 static const int dmax = 14;
1633 if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
1634 const Industry* i = nullptr;
1635 TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax);
1636 TILE_AREA_LOOP(atile, tile_area) {
1637 if (GetTileType(atile) == MP_INDUSTRY) {
1638 const Industry *i2 = Industry::GetByTile(atile);
1639 if (i == i2) continue;
1640 i = i2;
1641 if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1642 if (i->type == indspec->conflicting[0] ||
1643 i->type == indspec->conflicting[1] ||
1644 i->type == indspec->conflicting[2]) {
1645 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1649 return CommandCost();
1652 for (const Industry *i : Industry::Iterate()) {
1653 /* Within 14 tiles from another industry is considered close */
1654 if (DistanceMax(tile, i->location.tile) > 14) continue;
1656 /* check if there are any conflicting industry types around */
1657 if (i->type == indspec->conflicting[0] ||
1658 i->type == indspec->conflicting[1] ||
1659 i->type == indspec->conflicting[2]) {
1660 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1663 return CommandCost();
1667 * Advertise about a new industry opening.
1668 * @param ind Industry being opened.
1670 static void AdvertiseIndustryOpening(const Industry *ind)
1672 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1673 SetDParam(0, ind_spc->name);
1674 if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1675 SetDParam(1, STR_TOWN_NAME);
1676 SetDParam(2, ind->town->index);
1677 } else {
1678 SetDParam(1, ind->town->index);
1680 AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1681 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1682 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1686 * Populate an industry's list of nearby stations, and if it accepts any cargo, also
1687 * add the industry to each station's nearby industry list.
1688 * @param ind Industry
1690 static void PopulateStationsNearby(Industry *ind)
1692 if (ind->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) {
1693 /* Industry has a neutral station. Use it and ignore any other nearby stations. */
1694 ind->stations_near.insert(ind->neutral_station);
1695 ind->neutral_station->industries_near.clear();
1696 ind->neutral_station->industries_near.insert(ind);
1697 return;
1700 /* Get our list of nearby stations. */
1701 FindStationsAroundTiles(ind->location, &ind->stations_near, false);
1703 /* Test if industry can accept cargo */
1704 uint cargo_index;
1705 for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
1706 if (ind->accepts_cargo[cargo_index] != CT_INVALID) break;
1708 if (cargo_index >= lengthof(ind->accepts_cargo)) return;
1710 /* Cargo is accepted, add industry to nearby stations nearby industry list. */
1711 for (Station *st : ind->stations_near) {
1712 st->industries_near.insert(ind);
1717 * Put an industry on the map.
1718 * @param i Just allocated poolitem, mostly empty.
1719 * @param tile North tile of the industry.
1720 * @param type Type of the industry.
1721 * @param layout Industrylayout to build.
1722 * @param layout_index Number of the industry layout.
1723 * @param t Nearest town.
1724 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1725 * @param initial_random_bits Random bits for the industry.
1727 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileLayout &layout, size_t layout_index, Town *t, Owner founder, uint16 initial_random_bits)
1729 const IndustrySpec *indspec = GetIndustrySpec(type);
1731 i->location = TileArea(tile, 1, 1);
1732 i->type = type;
1733 Industry::IncIndustryTypeCount(type);
1735 MemCpyT(i->produced_cargo, indspec->produced_cargo, lengthof(i->produced_cargo));
1736 MemCpyT(i->production_rate, indspec->production_rate, lengthof(i->production_rate));
1737 MemCpyT(i->accepts_cargo, indspec->accepts_cargo, lengthof(i->accepts_cargo));
1739 MemSetT(i->produced_cargo_waiting, 0, lengthof(i->produced_cargo_waiting));
1740 MemSetT(i->this_month_production, 0, lengthof(i->this_month_production));
1741 MemSetT(i->this_month_transported, 0, lengthof(i->this_month_transported));
1742 MemSetT(i->last_month_pct_transported, 0, lengthof(i->last_month_pct_transported));
1743 MemSetT(i->last_month_transported, 0, lengthof(i->last_month_transported));
1744 MemSetT(i->incoming_cargo_waiting, 0, lengthof(i->incoming_cargo_waiting));
1745 MemSetT(i->last_cargo_accepted_at, 0, lengthof(i->last_cargo_accepted_at));
1747 /* don't use smooth economy for industries using production related callbacks */
1748 if (indspec->UsesSmoothEconomy()) {
1749 for (size_t ci = 0; ci < lengthof(i->production_rate); ci++) {
1750 i->production_rate[ci] = min((RandomRange(256) + 128) * i->production_rate[ci] >> 8, 255);
1754 i->town = t;
1755 i->owner = OWNER_NONE;
1757 uint16 r = Random();
1758 i->random_colour = GB(r, 0, 4);
1759 i->counter = GB(r, 4, 12);
1760 i->random = initial_random_bits;
1761 i->was_cargo_delivered = false;
1762 i->last_prod_year = _cur_year;
1763 i->founder = founder;
1765 i->construction_date = _date;
1766 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1767 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1769 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1770 * 0 = created prior of newindustries
1771 * else, chosen layout + 1 */
1772 i->selected_layout = (byte)(layout_index + 1);
1774 i->prod_level = PRODLEVEL_DEFAULT;
1776 /* Call callbacks after the regular fields got initialised. */
1778 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1779 uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1780 if (res != CALLBACK_FAILED) {
1781 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1782 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1783 } else {
1784 i->prod_level = res;
1785 i->RecomputeProductionMultipliers();
1790 if (_generating_world) {
1791 if (HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
1792 IndustryProductionCallback(i, 1);
1793 for (size_t ci = 0; ci < lengthof(i->last_month_production); ci++) {
1794 i->last_month_production[ci] = i->produced_cargo_waiting[ci] * 8;
1795 i->produced_cargo_waiting[ci] = 0;
1799 for (size_t ci = 0; ci < lengthof(i->last_month_production); ci++) {
1800 i->last_month_production[ci] += i->production_rate[ci] * 8;
1804 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1805 uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1806 if (res != CALLBACK_FAILED) {
1807 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1808 i->random_colour = GB(res, 0, 4);
1812 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1813 /* Clear all input cargo types */
1814 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1815 /* Query actual types */
1816 uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? lengthof(i->accepts_cargo) : 3;
1817 for (uint j = 0; j < maxcargoes; j++) {
1818 uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1819 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1820 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1821 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1822 break;
1824 CargoID cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1825 /* Industries without "unlimited" cargo types support depend on the specific order/slots of cargo types.
1826 * They need to be able to blank out specific slots without aborting the callback sequence,
1827 * and solve this by returning undefined cargo indexes. Skip these. */
1828 if (cargo == CT_INVALID && !(indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED)) continue;
1829 /* Verify valid cargo */
1830 if (std::find(indspec->accepts_cargo, endof(indspec->accepts_cargo), cargo) == endof(indspec->accepts_cargo)) {
1831 /* Cargo not in spec, error in NewGRF */
1832 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1833 break;
1835 if (std::find(i->accepts_cargo, i->accepts_cargo + j, cargo) != i->accepts_cargo + j) {
1836 /* Duplicate cargo */
1837 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1838 break;
1840 i->accepts_cargo[j] = cargo;
1844 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1845 /* Clear all output cargo types */
1846 for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1847 /* Query actual types */
1848 uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? lengthof(i->produced_cargo) : 2;
1849 for (uint j = 0; j < maxcargoes; j++) {
1850 uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1851 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1852 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1853 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1854 break;
1856 CargoID cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1857 /* Allow older GRFs to skip slots. */
1858 if (cargo == CT_INVALID && !(indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED)) continue;
1859 /* Verify valid cargo */
1860 if (std::find(indspec->produced_cargo, endof(indspec->produced_cargo), cargo) == endof(indspec->produced_cargo)) {
1861 /* Cargo not in spec, error in NewGRF */
1862 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1863 break;
1865 if (std::find(i->produced_cargo, i->produced_cargo + j, cargo) != i->produced_cargo + j) {
1866 /* Duplicate cargo */
1867 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1868 break;
1870 i->produced_cargo[j] = cargo;
1874 /* Plant the tiles */
1876 for (const IndustryTileLayoutTile &it : layout) {
1877 TileIndex cur_tile = tile + ToTileIndexDiff(it.ti);
1879 if (it.gfx != GFX_WATERTILE_SPECIALCHECK) {
1880 i->location.Add(cur_tile);
1882 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1884 DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1886 MakeIndustry(cur_tile, i->index, it.gfx, Random(), wc);
1888 if (_generating_world) {
1889 SetIndustryConstructionCounter(cur_tile, 3);
1890 SetIndustryConstructionStage(cur_tile, 2);
1893 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1894 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it.gfx);
1895 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1896 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1900 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1901 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1903 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
1905 if (!_generating_world) PopulateStationsNearby(i);
1909 * Helper function for Build/Fund an industry
1910 * @param tile tile where industry is built
1911 * @param type of industry to build
1912 * @param flags of operations to conduct
1913 * @param indspec pointer to industry specifications
1914 * @param layout_index the index of the itsepc to build/fund
1915 * @param random_var8f random seed (possibly) used by industries
1916 * @param random_initial_bits The random bits the industry is going to have after construction.
1917 * @param founder Founder of the industry
1918 * @param creation_type The circumstances the industry is created under.
1919 * @param[out] ip Pointer to store newly created industry.
1920 * @return Succeeded or failed command.
1922 * @post \c *ip contains the newly created industry if all checks are successful and the \a flags request actual creation, else it contains \c nullptr afterwards.
1924 static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, size_t layout_index, uint32 random_var8f, uint16 random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
1926 assert(layout_index < indspec->layouts.size());
1927 const IndustryTileLayout &layout = indspec->layouts[layout_index];
1928 bool custom_shape_check = false;
1930 *ip = nullptr;
1932 std::vector<ClearedObjectArea> object_areas(_cleared_object_areas);
1933 CommandCost ret = CheckIfIndustryTilesAreFree(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1934 _cleared_object_areas = object_areas;
1935 if (ret.Failed()) return ret;
1937 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1938 ret = CheckIfCallBackAllowsCreation(tile, type, layout_index, random_var8f, random_initial_bits, founder, creation_type);
1939 } else {
1940 ret = _check_new_industry_procs[indspec->check_proc](tile);
1942 if (ret.Failed()) return ret;
1944 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
1945 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, layout, type)) {
1946 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1949 ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1950 if (ret.Failed()) return ret;
1952 Town *t = nullptr;
1953 ret = FindTownForIndustry(tile, type, &t);
1954 if (ret.Failed()) return ret;
1955 assert(t != nullptr);
1957 ret = CheckIfIndustryIsAllowed(tile, type, t);
1958 if (ret.Failed()) return ret;
1960 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1962 if (flags & DC_EXEC) {
1963 *ip = new Industry(tile);
1964 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, layout, type);
1965 DoCreateNewIndustry(*ip, tile, type, layout, layout_index, t, founder, random_initial_bits);
1968 return CommandCost();
1972 * Build/Fund an industry
1973 * @param tile tile where industry is built
1974 * @param flags of operations to conduct
1975 * @param p1 various bitstuffed elements
1976 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1977 * - p1 = (bit 8 - 15) - first layout to try
1978 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1979 * @param p2 seed to use for desyncfree randomisations
1980 * @param text unused
1981 * @return the cost of this operation or an error
1983 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1985 IndustryType it = GB(p1, 0, 8);
1986 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1988 const IndustrySpec *indspec = GetIndustrySpec(it);
1990 /* Check if the to-be built/founded industry is available for this climate. */
1991 if (!indspec->enabled || indspec->layouts.empty()) return CMD_ERROR;
1993 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1994 * Raw material industries are industries that do not accept cargo (at least for now) */
1995 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1996 return CMD_ERROR;
1999 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
2000 return CMD_ERROR;
2003 Randomizer randomizer;
2004 randomizer.SetSeed(p2);
2005 uint16 random_initial_bits = GB(p2, 0, 16);
2006 uint32 random_var8f = randomizer.Next();
2007 size_t num_layouts = indspec->layouts.size();
2008 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
2009 const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
2011 Industry *ind = nullptr;
2012 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
2013 if (flags & DC_EXEC) {
2014 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
2015 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
2016 /* Prospecting has a chance to fail, however we cannot guarantee that something can
2017 * be built on the map, so the chance gets lower when the map is fuller, but there
2018 * is nothing we can really do about that. */
2019 if (deity_prospect || Random() <= indspec->prospecting_chance) {
2020 for (int i = 0; i < 5000; i++) {
2021 /* We should not have more than one Random() in a function call
2022 * because parameter evaluation order is not guaranteed in the c++ standard
2024 tile = RandomTile();
2025 /* Start with a random layout */
2026 size_t layout = RandomRange((uint32)num_layouts);
2027 /* Check now each layout, starting with the random one */
2028 for (size_t j = 0; j < num_layouts; j++) {
2029 layout = (layout + 1) % num_layouts;
2030 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
2031 if (ret.Succeeded()) break;
2033 if (ret.Succeeded()) break;
2036 cur_company.Restore();
2038 } else {
2039 size_t layout = GB(p1, 8, 8);
2040 if (layout >= num_layouts) return CMD_ERROR;
2042 /* Check subsequently each layout, starting with the given layout in p1 */
2043 for (size_t i = 0; i < num_layouts; i++) {
2044 layout = (layout + 1) % num_layouts;
2045 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
2046 if (ret.Succeeded()) break;
2049 /* If it still failed, there's no suitable layout to build here, return the error */
2050 if (ret.Failed()) return ret;
2053 if ((flags & DC_EXEC) && ind != nullptr && _game_mode != GM_EDITOR) {
2054 AdvertiseIndustryOpening(ind);
2057 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
2062 * Create a new industry of random layout.
2063 * @param tile The location to build the industry.
2064 * @param type The industry type to build.
2065 * @param creation_type The circumstances the industry is created under.
2066 * @return the created industry or nullptr if it failed.
2068 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
2070 const IndustrySpec *indspec = GetIndustrySpec(type);
2072 uint32 seed = Random();
2073 uint32 seed2 = Random();
2074 Industry *i = nullptr;
2075 size_t layout_index = RandomRange((uint32)indspec->layouts.size());
2076 CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
2077 assert(i != nullptr || ret.Failed());
2078 return i;
2082 * Compute the appearance probability for an industry during map creation.
2083 * @param it Industry type to compute.
2084 * @param[out] force_at_least_one Returns whether at least one instance should be forced on map creation.
2085 * @return Relative probability for the industry to appear.
2087 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
2089 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2090 uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
2091 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2092 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
2093 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
2094 *force_at_least_one = false;
2095 return 0;
2096 } else {
2097 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
2098 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
2099 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(chance) : ScaleByMapSize(chance);
2101 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
2102 return chance;
2107 * Compute the probability for constructing a new industry during game play.
2108 * @param it Industry type to compute.
2109 * @param[out] min_number Minimal number of industries that should exist at the map.
2110 * @return Relative probability for the industry to appear.
2112 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
2114 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2115 *min_number = 0;
2116 return 0;
2119 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2120 byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2121 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2122 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
2123 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
2124 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2125 *min_number = 0;
2126 return 0;
2128 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2129 return chance;
2133 * Get wanted number of industries on the map.
2134 * @return Wanted number of industries at the map.
2136 static uint GetNumberOfIndustries()
2138 /* Number of industries on a 256x256 map. */
2139 static const uint16 numof_industry_table[] = {
2140 0, // none
2141 0, // minimal
2142 10, // very low
2143 25, // low
2144 55, // normal
2145 80, // high
2148 assert(lengthof(numof_industry_table) == ID_END);
2149 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2150 return min(IndustryPool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2154 * Try to place the industry in the game.
2155 * Since there is no feedback why placement fails, there is no other option
2156 * than to try a few times before concluding it does not work.
2157 * @param type Industry type of the desired industry.
2158 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2159 * @return Pointer to created industry, or \c nullptr if creation failed.
2161 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2163 uint tries = try_hard ? 10000u : 2000u;
2164 for (; tries > 0; tries--) {
2165 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2166 if (ind != nullptr) return ind;
2168 return nullptr;
2172 * Try to build a industry on the map.
2173 * @param type IndustryType of the desired industry
2174 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2176 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2178 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2180 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2181 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2183 cur_company.Restore();
2187 * Get total number of industries existing in the game.
2188 * @return Number of industries currently in the game.
2190 static uint GetCurrentTotalNumberOfIndustries()
2192 int total = 0;
2193 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2194 return total;
2198 /** Reset the entry. */
2199 void IndustryTypeBuildData::Reset()
2201 this->probability = 0;
2202 this->min_number = 0;
2203 this->target_count = 0;
2204 this->max_wait = 1;
2205 this->wait_count = 0;
2208 /** Completely reset the industry build data. */
2209 void IndustryBuildData::Reset()
2211 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2213 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2214 this->builddata[it].Reset();
2218 /** Monthly update of industry build data. */
2219 void IndustryBuildData::MonthlyLoop()
2221 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.
2222 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2224 /* To prevent running out of unused industries for the player to connect,
2225 * add a fraction of new industries each month, but only if the manager can keep up. */
2226 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).
2227 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2228 this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2233 * This function will create random industries during game creation.
2234 * It will scale the amount of industries by mapsize and difficulty level.
2236 void GenerateIndustries()
2238 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2240 uint32 industry_probs[NUM_INDUSTRYTYPES];
2241 bool force_at_least_one[NUM_INDUSTRYTYPES];
2242 uint32 total_prob = 0;
2243 uint num_forced = 0;
2245 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2246 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2247 total_prob += industry_probs[it];
2248 if (force_at_least_one[it]) num_forced++;
2251 uint total_amount = GetNumberOfIndustries();
2252 if (total_prob == 0 || total_amount < num_forced) {
2253 /* Only place the forced ones */
2254 total_amount = num_forced;
2257 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2259 /* Try to build one industry per type independent of any probabilities */
2260 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2261 if (force_at_least_one[it]) {
2262 assert(total_amount > 0);
2263 total_amount--;
2264 PlaceInitialIndustry(it, true);
2268 /* Add the remaining industries according to their probabilities */
2269 for (uint i = 0; i < total_amount; i++) {
2270 uint32 r = RandomRange(total_prob);
2271 IndustryType it = 0;
2272 while (r >= industry_probs[it]) {
2273 r -= industry_probs[it];
2274 it++;
2275 assert(it < NUM_INDUSTRYTYPES);
2277 assert(industry_probs[it] > 0);
2278 PlaceInitialIndustry(it, false);
2280 _industry_builder.Reset();
2284 * Monthly update of industry statistics.
2285 * @param i Industry to update.
2287 static void UpdateIndustryStatistics(Industry *i)
2289 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2290 if (i->produced_cargo[j] != CT_INVALID) {
2291 byte pct = 0;
2292 if (i->this_month_production[j] != 0) {
2293 i->last_prod_year = _cur_year;
2294 pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2296 i->last_month_pct_transported[j] = pct;
2298 i->last_month_production[j] = i->this_month_production[j];
2299 i->this_month_production[j] = 0;
2301 i->last_month_transported[j] = i->this_month_transported[j];
2302 i->this_month_transported[j] = 0;
2308 * Recompute #production_rate for current #prod_level.
2309 * This function is only valid when not using smooth economy.
2311 void Industry::RecomputeProductionMultipliers()
2313 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2314 assert(!indspec->UsesSmoothEconomy());
2316 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2317 for (size_t i = 0; i < lengthof(this->production_rate); i++) {
2318 this->production_rate[i] = min(CeilDiv(indspec->production_rate[i] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2324 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2325 * @param it Industry type.
2326 * @return At least one of the fields has changed value.
2328 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2330 byte min_number;
2331 uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2332 bool changed = min_number != this->min_number || probability != this->probability;
2333 this->min_number = min_number;
2334 this->probability = probability;
2335 return changed;
2338 /** Decide how many industries of each type are needed. */
2339 void IndustryBuildData::SetupTargetCount()
2341 bool changed = false;
2342 uint num_planned = 0; // Number of industries planned in the industry build data.
2343 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2344 changed |= this->builddata[it].GetIndustryTypeData(it);
2345 num_planned += this->builddata[it].target_count;
2347 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2348 changed |= num_planned != total_amount;
2349 if (!changed) return; // All industries are still the same, no need to re-randomize.
2351 /* Initialize the target counts. */
2352 uint force_build = 0; // Number of industries that should always be available.
2353 uint32 total_prob = 0; // Sum of probabilities.
2354 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2355 IndustryTypeBuildData *ibd = this->builddata + it;
2356 force_build += ibd->min_number;
2357 ibd->target_count = ibd->min_number;
2358 total_prob += ibd->probability;
2361 if (total_prob == 0) return; // No buildable industries.
2363 /* Subtract forced industries from the number of industries available for construction. */
2364 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2366 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2367 while (total_amount > 0) {
2368 uint32 r = RandomRange(total_prob);
2369 IndustryType it = 0;
2370 while (r >= this->builddata[it].probability) {
2371 r -= this->builddata[it].probability;
2372 it++;
2373 assert(it < NUM_INDUSTRYTYPES);
2375 assert(this->builddata[it].probability > 0);
2376 this->builddata[it].target_count++;
2377 total_amount--;
2382 * Try to create a random industry, during gameplay
2384 void IndustryBuildData::TryBuildNewIndustry()
2386 this->SetupTargetCount();
2388 int missing = 0; // Number of industries that need to be build.
2389 uint count = 0; // Number of industry types eligible for build.
2390 uint32 total_prob = 0; // Sum of probabilities.
2391 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2392 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2393 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2394 missing += difference;
2395 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2396 if (difference > 0) {
2397 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2398 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2399 if (forced_build == NUM_INDUSTRYTYPES ||
2400 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2401 forced_build = it;
2404 total_prob += difference;
2405 count++;
2409 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2411 if (count >= 1) {
2412 /* If not forced, pick a weighted random industry to build.
2413 * For the case that count == 1, there is no need to draw a random number. */
2414 IndustryType it;
2415 if (forced_build != NUM_INDUSTRYTYPES) {
2416 it = forced_build;
2417 } else {
2418 /* Non-forced, select an industry type to build (weighted random). */
2419 uint32 r = 0; // Initialized to silence the compiler.
2420 if (count > 1) r = RandomRange(total_prob);
2421 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2422 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2423 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2424 if (difference <= 0) continue; // Too many of this kind.
2425 if (count == 1) break;
2426 if (r < (uint)difference) break;
2427 r -= difference;
2429 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2432 /* Try to create the industry. */
2433 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2434 if (ind == nullptr) {
2435 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2436 this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2437 } else {
2438 AdvertiseIndustryOpening(ind);
2439 this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2443 /* Decrement wait counters. */
2444 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2445 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2450 * Protects an industry from closure if the appropriate flags and conditions are met
2451 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2452 * count of industries of this type must one (or lower) in order to be protected
2453 * against closure.
2454 * @param type IndustryType been queried
2455 * @result true if protection is on, false otherwise (except for oil wells)
2457 static bool CheckIndustryCloseDownProtection(IndustryType type)
2459 const IndustrySpec *indspec = GetIndustrySpec(type);
2461 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2462 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2463 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2467 * Can given cargo type be accepted or produced by the industry?
2468 * @param cargo: Cargo type
2469 * @param ind: Industry
2470 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2471 * @param *c_produces: Pointer to boolean for production of cargo
2472 * @return: \c *c_accepts is set when industry accepts the cargo type,
2473 * \c *c_produces is set when the industry produces the cargo type
2475 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2477 if (cargo == CT_INVALID) return;
2479 /* Check for acceptance of cargo */
2480 for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2481 if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2482 *c_accepts = true;
2483 break;
2487 /* Check for produced cargo */
2488 for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2489 if (cargo == ind->produced_cargo[j]) {
2490 *c_produces = true;
2491 break;
2497 * Compute who can service the industry.
2499 * Here, 'can service' means that he/she has trains and stations close enough
2500 * to the industry with the right cargo type and the right orders (ie has the
2501 * technical means).
2503 * @param ind: Industry being investigated.
2505 * @return: 0 if nobody can service the industry, 2 if the local company can
2506 * service the industry, and 1 otherwise (only competitors can service the
2507 * industry)
2509 static int WhoCanServiceIndustry(Industry *ind)
2511 if (ind->stations_near.size() == 0) return 0; // No stations found at all => nobody services
2513 int result = 0;
2514 for (const Vehicle *v : Vehicle::Iterate()) {
2515 /* Is it worthwhile to try this vehicle? */
2516 if (v->owner != _local_company && result != 0) continue;
2518 /* Check whether it accepts the right kind of cargo */
2519 bool c_accepts = false;
2520 bool c_produces = false;
2521 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2522 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
2523 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2525 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2526 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2527 } else {
2528 continue;
2530 if (!c_accepts && !c_produces) continue; // Wrong cargo
2532 /* Check orders of the vehicle.
2533 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2534 * may have a different cargo type.
2536 const Order *o;
2537 FOR_VEHICLE_ORDERS(v, o) {
2538 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2539 /* Vehicle visits a station to load or unload */
2540 Station *st = Station::Get(o->GetDestination());
2541 assert(st != nullptr);
2543 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2544 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2546 if (ind->stations_near.find(st) != ind->stations_near.end()) {
2547 if (v->owner == _local_company) return 2; // Company services industry
2548 result = 1; // Competitor services industry
2553 return result;
2557 * Report news that industry production has changed significantly
2559 * @param ind: Industry with changed production
2560 * @param type: Cargo type that has changed
2561 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
2563 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2565 NewsType nt;
2567 switch (WhoCanServiceIndustry(ind)) {
2568 case 0: nt = NT_INDUSTRY_NOBODY; break;
2569 case 1: nt = NT_INDUSTRY_OTHER; break;
2570 case 2: nt = NT_INDUSTRY_COMPANY; break;
2571 default: NOT_REACHED();
2573 SetDParam(2, abs(percent));
2574 SetDParam(0, CargoSpec::Get(type)->name);
2575 SetDParam(1, ind->index);
2576 AddIndustryNewsItem(
2577 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2579 ind->index
2583 static const uint PERCENT_TRANSPORTED_60 = 153;
2584 static const uint PERCENT_TRANSPORTED_80 = 204;
2587 * Change industry production or do closure
2588 * @param i Industry for which changes are performed
2589 * @param monthly true if it's the monthly call, false if it's the random call
2591 static void ChangeIndustryProduction(Industry *i, bool monthly)
2593 StringID str = STR_NULL;
2594 bool closeit = false;
2595 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2596 bool standard = false;
2597 bool suppress_message = false;
2598 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2599 /* don't use smooth economy for industries using production related callbacks */
2600 bool smooth_economy = indspec->UsesSmoothEconomy();
2601 byte div = 0;
2602 byte mul = 0;
2603 int8 increment = 0;
2605 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2606 if (callback_enabled) {
2607 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2608 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2609 suppress_message = HasBit(res, 7);
2610 /* Get the custom message if any */
2611 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2612 res = GB(res, 0, 4);
2613 switch (res) {
2614 default: NOT_REACHED();
2615 case 0x0: break; // Do nothing, but show the custom message if any
2616 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2617 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2618 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2619 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2620 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2621 case 0x8: div = res - 0x3; break; // Divide production by 32
2622 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2623 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2624 case 0xD: // decrement production
2625 case 0xE: // increment production
2626 increment = res == 0x0D ? -1 : 1;
2627 break;
2628 case 0xF: // Set production to third byte of register 0x100
2629 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2630 recalculate_multipliers = true;
2631 break;
2634 } else {
2635 if (monthly != smooth_economy) return;
2636 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2639 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2640 /* decrease or increase */
2641 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2643 if (smooth_economy) {
2644 closeit = true;
2645 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2646 if (i->produced_cargo[j] == CT_INVALID) continue;
2647 uint32 r = Random();
2648 int old_prod, new_prod, percent;
2649 /* If over 60% is transported, mult is 1, else mult is -1. */
2650 int mult = (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) ? 1 : -1;
2652 new_prod = old_prod = i->production_rate[j];
2654 /* For industries with only_decrease flags (temperate terrain Oil Wells),
2655 * the multiplier will always be -1 so they will only decrease. */
2656 if (only_decrease) {
2657 mult = -1;
2658 /* For normal industries, if over 60% is transported, 33% chance for decrease.
2659 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2660 } else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2661 mult *= -1;
2664 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2665 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2666 if (Chance16I(1, 22, r >> 16)) {
2667 new_prod += mult * (max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2670 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2671 new_prod = Clamp(new_prod, 1, 255);
2673 if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
2674 new_prod = Clamp(new_prod, 0, 16);
2677 /* Do not stop closing the industry when it has the lowest possible production rate */
2678 if (new_prod == old_prod && old_prod > 1) {
2679 closeit = false;
2680 continue;
2683 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2684 i->production_rate[j] = new_prod;
2686 /* Close the industry when it has the lowest possible production rate */
2687 if (new_prod > 1) closeit = false;
2689 if (abs(percent) >= 10) {
2690 ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
2693 } else {
2694 if (only_decrease || Chance16(1, 3)) {
2695 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2696 if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2697 mul = 1; // Increase production
2698 } else {
2699 div = 1; // Decrease production
2705 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2706 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2707 closeit = true;
2711 /* Increase if needed */
2712 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2713 i->prod_level = min(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2714 recalculate_multipliers = true;
2715 if (str == STR_NULL) str = indspec->production_up_text;
2718 /* Decrease if needed */
2719 while (div-- != 0 && !closeit) {
2720 if (i->prod_level == PRODLEVEL_MINIMUM) {
2721 closeit = true;
2722 } else {
2723 i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2724 recalculate_multipliers = true;
2725 if (str == STR_NULL) str = indspec->production_down_text;
2729 /* Increase or Decreasing the production level if needed */
2730 if (increment != 0) {
2731 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2732 closeit = true;
2733 } else {
2734 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2735 recalculate_multipliers = true;
2739 /* Recalculate production_rate
2740 * For non-smooth economy these should always be synchronized with prod_level */
2741 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2743 /* Close if needed and allowed */
2744 if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2745 i->prod_level = PRODLEVEL_CLOSURE;
2746 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2747 str = indspec->closure_text;
2750 if (!suppress_message && str != STR_NULL) {
2751 NewsType nt;
2752 /* Compute news category */
2753 if (closeit) {
2754 nt = NT_INDUSTRY_CLOSE;
2755 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2756 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2757 } else {
2758 switch (WhoCanServiceIndustry(i)) {
2759 case 0: nt = NT_INDUSTRY_NOBODY; break;
2760 case 1: nt = NT_INDUSTRY_OTHER; break;
2761 case 2: nt = NT_INDUSTRY_COMPANY; break;
2762 default: NOT_REACHED();
2765 /* Set parameters of news string */
2766 if (str > STR_LAST_STRINGID) {
2767 SetDParam(0, STR_TOWN_NAME);
2768 SetDParam(1, i->town->index);
2769 SetDParam(2, indspec->name);
2770 } else if (closeit) {
2771 SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
2772 SetDParam(1, i->town->index);
2773 SetDParam(2, indspec->name);
2774 } else {
2775 SetDParam(0, i->index);
2777 /* and report the news to the user */
2778 if (closeit) {
2779 AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
2780 } else {
2781 AddIndustryNewsItem(str, nt, i->index);
2787 * Daily handler for the industry changes
2788 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2789 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2790 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2791 * it would be way more. The daily loop handles those changes.
2793 void IndustryDailyLoop()
2795 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
2797 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2798 * the lower 16 bit are a fractional part that might accumulate over several days until it
2799 * is sufficient for an industry. */
2800 uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2802 /* Reset the active part of the counter, just keeping the "fractional part" */
2803 _economy.industry_daily_change_counter &= 0xFFFF;
2805 if (change_loop == 0) {
2806 return; // Nothing to do? get out
2809 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2811 /* perform the required industry changes for the day */
2813 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2814 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
2815 perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2817 for (uint16 j = 0; j < change_loop; j++) {
2818 if (Chance16(perc, 100)) {
2819 _industry_builder.TryBuildNewIndustry();
2820 } else {
2821 Industry *i = Industry::GetRandom();
2822 if (i != nullptr) {
2823 ChangeIndustryProduction(i, false);
2824 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2829 cur_company.Restore();
2831 /* production-change */
2832 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2835 void IndustryMonthlyLoop()
2837 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2839 _industry_builder.MonthlyLoop();
2841 for (Industry *i : Industry::Iterate()) {
2842 UpdateIndustryStatistics(i);
2843 if (i->prod_level == PRODLEVEL_CLOSURE) {
2844 delete i;
2845 } else {
2846 ChangeIndustryProduction(i, true);
2847 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2851 cur_company.Restore();
2853 /* production-change */
2854 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2858 void InitializeIndustries()
2860 Industry::ResetIndustryCounts();
2861 _industry_sound_tile = 0;
2863 _industry_builder.Reset();
2866 /** Verify whether the generated industries are complete, and warn the user if not. */
2867 void CheckIndustries()
2869 int count = 0;
2870 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2871 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2873 bool force_at_least_one;
2874 uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2875 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2877 const IndustrySpec *is = GetIndustrySpec(it);
2878 SetDParam(0, is->name);
2879 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2881 count++;
2882 if (count >= 3) break; // Don't swamp the user with errors.
2887 * Is an industry with the spec a raw industry?
2888 * @return true if it should be handled as a raw industry
2890 bool IndustrySpec::IsRawIndustry() const
2892 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2896 * Is an industry with the spec a processing industry?
2897 * @return true if it should be handled as a processing industry
2899 bool IndustrySpec::IsProcessingIndustry() const
2901 /* Lumber mills are neither raw nor processing */
2902 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2903 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2907 * Get the cost for constructing this industry
2908 * @return the cost (inflation corrected etc)
2910 Money IndustrySpec::GetConstructionCost() const
2912 /* Building raw industries like secondary uses different price base */
2913 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2914 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2918 * Get the cost for removing this industry
2919 * Take note that the cost will always be zero for non-grf industries.
2920 * Only if the grf author did specified a cost will it be applicable.
2921 * @return the cost (inflation corrected etc)
2923 Money IndustrySpec::GetRemovalCost() const
2925 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2929 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2930 * @return true if smooth economy is used.
2932 bool IndustrySpec::UsesSmoothEconomy() const
2934 return _settings_game.economy.smooth_economy &&
2935 !(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
2936 !(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
2939 IndustrySpec::~IndustrySpec()
2941 if (HasBit(this->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
2942 free(this->random_sounds);
2946 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2948 if (AutoslopeEnabled()) {
2949 /* We imitate here TTDP's behaviour:
2950 * - Both new and old slope must not be steep.
2951 * - TileMaxZ must not be changed.
2952 * - Allow autoslope by default.
2953 * - Disallow autoslope if callback succeeds and returns non-zero.
2955 Slope tileh_old = GetTileSlope(tile);
2956 /* TileMaxZ must not be changed. Slopes must not be steep. */
2957 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2958 const IndustryGfx gfx = GetIndustryGfx(tile);
2959 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2961 /* Call callback 3C 'disable autosloping for industry tiles'. */
2962 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2963 /* If the callback fails, allow autoslope. */
2964 uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2965 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2966 } else {
2967 /* allow autoslope */
2968 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2972 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2975 extern const TileTypeProcs _tile_type_industry_procs = {
2976 DrawTile_Industry, // draw_tile_proc
2977 GetSlopePixelZ_Industry, // get_slope_z_proc
2978 ClearTile_Industry, // clear_tile_proc
2979 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2980 GetTileDesc_Industry, // get_tile_desc_proc
2981 GetTileTrackStatus_Industry, // get_tile_track_status_proc
2982 ClickTile_Industry, // click_tile_proc
2983 AnimateTile_Industry, // animate_tile_proc
2984 TileLoop_Industry, // tile_loop_proc
2985 ChangeTileOwner_Industry, // change_tile_owner_proc
2986 nullptr, // add_produced_cargo_proc
2987 nullptr, // vehicle_enter_tile_proc
2988 GetFoundation_Industry, // get_foundation_proc
2989 TerraformTile_Industry, // terraform_tile_proc
2992 bool IndustryCompare::operator() (const Industry *lhs, const Industry *rhs) const
2994 return lhs->index < rhs->index;