Update: Translations from eints
[openttd-github.git] / src / industry_cmd.cpp
blob07e18d658730659b279d0440158e43804b6909b3
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 "company_base.h"
21 #include "genworld.h"
22 #include "tree_map.h"
23 #include "newgrf_cargo.h"
24 #include "newgrf_debug.h"
25 #include "newgrf_industrytiles.h"
26 #include "autoslope.h"
27 #include "water.h"
28 #include "strings_internal.h"
29 #include "window_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"
42 #include "string_func.h"
43 #include "industry_cmd.h"
44 #include "landscape_cmd.h"
45 #include "terraform_cmd.h"
46 #include "timer/timer.h"
47 #include "timer/timer_game_calendar.h"
48 #include "timer/timer_game_economy.h"
49 #include "timer/timer_game_tick.h"
51 #include "table/strings.h"
52 #include "table/industry_land.h"
53 #include "table/build_industry.h"
55 #include "safeguards.h"
57 IndustryPool _industry_pool("Industry");
58 INSTANTIATE_POOL_METHODS(Industry)
60 void ShowIndustryViewWindow(int industry);
61 void BuildOilRig(TileIndex tile);
63 static uint8_t _industry_sound_ctr;
64 static TileIndex _industry_sound_tile;
66 uint16_t Industry::counts[NUM_INDUSTRYTYPES];
68 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
69 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
70 IndustryBuildData _industry_builder; ///< In-game manager of industries.
72 static int WhoCanServiceIndustry(Industry *ind);
74 /**
75 * This function initialize the spec arrays of both
76 * industry and industry tiles.
77 * It adjusts the enabling of the industry too, based on climate availability.
78 * This will allow for clearer testings
80 void ResetIndustries()
82 auto industry_insert = std::copy(std::begin(_origin_industry_specs), std::end(_origin_industry_specs), std::begin(_industry_specs));
83 std::fill(industry_insert, std::end(_industry_specs), IndustrySpec{});
85 /* Enable only the current climate industries */
86 for (auto it = std::begin(_industry_specs); it != industry_insert; ++it) {
87 it->enabled = HasBit(it->climate_availability, _settings_game.game_creation.landscape);
90 auto industry_tile_insert = std::copy(std::begin(_origin_industry_tile_specs), std::end(_origin_industry_tile_specs), std::begin(_industry_tile_specs));
91 std::fill(industry_tile_insert, std::end(_industry_tile_specs), IndustryTileSpec{});
93 /* Reset any overrides that have been set. */
94 _industile_mngr.ResetOverride();
95 _industry_mngr.ResetOverride();
98 /**
99 * Retrieve the type for this industry. Although it is accessed by a tile,
100 * it will return the general type of industry, and not the sprite index
101 * as would do GetIndustryGfx.
102 * @param tile that is queried
103 * @pre IsTileType(tile, MP_INDUSTRY)
104 * @return general type for this industry, as defined in industry.h
106 IndustryType GetIndustryType(Tile tile)
108 assert(IsTileType(tile, MP_INDUSTRY));
110 const Industry *ind = Industry::GetByTile(tile);
111 assert(ind != nullptr);
112 return ind->type;
116 * Accessor for array _industry_specs.
117 * This will ensure at once : proper access and
118 * not allowing modifications of it.
119 * @param thistype of industry (which is the index in _industry_specs)
120 * @pre thistype < NUM_INDUSTRYTYPES
121 * @return a pointer to the corresponding industry spec
123 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
125 assert(thistype < NUM_INDUSTRYTYPES);
126 return &_industry_specs[thistype];
130 * Accessor for array _industry_tile_specs.
131 * This will ensure at once : proper access and
132 * not allowing modifications of it.
133 * @param gfx of industrytile (which is the index in _industry_tile_specs)
134 * @pre gfx < INVALID_INDUSTRYTILE
135 * @return a pointer to the corresponding industrytile spec
137 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
139 assert(gfx < INVALID_INDUSTRYTILE);
140 return &_industry_tile_specs[gfx];
143 Industry::~Industry()
145 if (CleaningPool()) return;
147 /* Industry can also be destroyed when not fully initialized.
148 * This means that we do not have to clear tiles either.
149 * Also we must not decrement industry counts in that case. */
150 if (this->location.w == 0) return;
152 const bool has_neutral_station = this->neutral_station != nullptr;
154 for (TileIndex tile_cur : this->location) {
155 if (IsTileType(tile_cur, MP_INDUSTRY)) {
156 if (GetIndustryIndex(tile_cur) == this->index) {
157 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur.base());
159 /* MakeWaterKeepingClass() can also handle 'land' */
160 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
162 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
163 DeleteOilRig(tile_cur);
167 if (has_neutral_station) {
168 /* Remove possible docking tiles */
169 for (TileIndex tile_cur : this->location) {
170 ClearDockingTilesCheckingNeighbours(tile_cur);
174 if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
175 TileArea ta = TileArea(this->location.tile, 0, 0).Expand(21);
177 /* Remove the farmland and convert it to regular tiles over time. */
178 for (TileIndex tile_cur : ta) {
179 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
180 GetIndustryIndexOfField(tile_cur) == this->index) {
181 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
186 /* don't let any disaster vehicle target invalid industry */
187 ReleaseDisastersTargetingIndustry(this->index);
189 /* Clear the persistent storage. */
190 delete this->psa;
192 DecIndustryTypeCount(this->type);
194 DeleteIndustryNews(this->index);
195 CloseWindowById(WC_INDUSTRY_VIEW, this->index);
196 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
198 DeleteSubsidyWith(SourceType::Industry, this->index);
199 CargoPacket::InvalidateAllFrom(SourceType::Industry, this->index);
201 for (Station *st : this->stations_near) {
202 st->RemoveIndustryToDeliver(this);
207 * Invalidating some stuff after removing item from the pool.
208 * @param index index of deleted item
210 void Industry::PostDestructor(size_t)
212 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_FORCE_REBUILD);
213 SetWindowDirty(WC_BUILD_INDUSTRY, 0);
218 * Return a random valid industry.
219 * @return random industry, nullptr if there are no industries
221 /* static */ Industry *Industry::GetRandom()
223 if (Industry::GetNumItems() == 0) return nullptr;
224 int num = RandomRange((uint16_t)Industry::GetNumItems());
225 size_t index = MAX_UVALUE(size_t);
227 while (num >= 0) {
228 num--;
229 index++;
231 /* Make sure we have a valid industry */
232 while (!Industry::IsValidID(index)) {
233 index++;
234 assert(index < Industry::GetPoolSize());
238 return Industry::Get(index);
242 static void IndustryDrawSugarMine(const TileInfo *ti)
244 if (!IsIndustryCompleted(ti->tile)) return;
246 const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
248 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
250 if (d->image_2 != 0) {
251 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
254 if (d->image_3 != 0) {
255 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
256 _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
260 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
262 uint8_t x = 0;
264 if (IsIndustryCompleted(ti->tile)) {
265 x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
266 if (x == 0xFF) {
267 x = 0;
271 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
272 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
275 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
277 if (IsIndustryCompleted(ti->tile)) {
278 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
280 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
283 static void IndustryDrawToyFactory(const TileInfo *ti)
285 const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
287 if (d->image_1 != 0xFF) {
288 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
291 if (d->image_2 != 0xFF) {
292 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
295 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
296 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
299 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
301 if (IsIndustryCompleted(ti->tile)) {
302 uint8_t image = GetAnimationFrame(ti->tile);
304 if (image != 0 && image < 7) {
305 AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
306 PAL_NONE,
307 _coal_plant_sparks[image - 1].x,
308 _coal_plant_sparks[image - 1].y
314 typedef void IndustryDrawTileProc(const TileInfo *ti);
315 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
316 IndustryDrawSugarMine,
317 IndustryDrawToffeeQuarry,
318 IndustryDrawBubbleGenerator,
319 IndustryDrawToyFactory,
320 IndustryDrawCoalPlantSparks,
323 static void DrawTile_Industry(TileInfo *ti)
325 IndustryGfx gfx = GetIndustryGfx(ti->tile);
326 Industry *ind = Industry::GetByTile(ti->tile);
327 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
329 /* Retrieve pointer to the draw industry tile struct */
330 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
331 /* Draw the tile using the specialized method of newgrf industrytile.
332 * DrawNewIndustry will return false if ever the resolver could not
333 * find any sprite to display. So in this case, we will jump on the
334 * substitute gfx instead. */
335 if (indts->grf_prop.spritegroup[0] != nullptr && DrawNewIndustryTile(ti, ind, gfx, indts)) {
336 return;
337 } else {
338 /* No sprite group (or no valid one) found, meaning no graphics associated.
339 * Use the substitute one instead */
340 if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
341 gfx = indts->grf_prop.subst_id;
342 /* And point the industrytile spec accordingly */
343 indts = GetIndustryTileSpec(gfx);
348 const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
349 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
350 GetIndustryConstructionStage(ti->tile))];
352 SpriteID image = dits->ground.sprite;
354 /* DrawFoundation() modifies ti->z and ti->tileh */
355 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
357 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
358 * Do not do this if the tile's WaterClass is 'land'. */
359 if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
360 DrawWaterClassGround(ti);
361 } else {
362 DrawGroundSprite(image, GroundSpritePaletteTransform(image, dits->ground.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)));
365 /* If industries are transparent and invisible, do not draw the upper part */
366 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
368 /* Add industry on top of the ground? */
369 image = dits->building.sprite;
370 if (image != 0) {
371 AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)),
372 ti->x + dits->subtile_x,
373 ti->y + dits->subtile_y,
374 dits->width,
375 dits->height,
376 dits->dz,
377 ti->z,
378 IsTransparencySet(TO_INDUSTRIES));
380 if (IsTransparencySet(TO_INDUSTRIES)) return;
384 int proc = dits->draw_proc - 1;
385 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
389 static int GetSlopePixelZ_Industry(TileIndex tile, uint, uint, bool)
391 return GetTileMaxPixelZ(tile);
394 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
396 IndustryGfx gfx = GetIndustryGfx(tile);
398 /* For NewGRF industry tiles we might not be drawing a foundation. We need to
399 * account for this, as other structures should
400 * draw the wall of the foundation in this case.
402 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
403 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
404 if (indts->grf_prop.spritegroup[0] != nullptr && HasBit(indts->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
405 uint32_t callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, Industry::GetByTile(tile), tile);
406 if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(indts->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
409 return FlatteningFoundation(tileh);
412 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, CargoTypes &always_accepted)
414 IndustryGfx gfx = GetIndustryGfx(tile);
415 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
416 const Industry *ind = Industry::GetByTile(tile);
418 /* Starting point for acceptance */
419 auto accepts_cargo = itspec->accepts_cargo;
420 auto cargo_acceptance = itspec->acceptance;
422 if (itspec->special_flags & INDTILE_SPECIAL_ACCEPTS_ALL_CARGO) {
423 /* Copy all accepted cargoes from industry itself */
424 for (const auto &a : ind->accepted) {
425 auto pos = std::find(std::begin(accepts_cargo), std::end(accepts_cargo), a.cargo);
426 if (pos == std::end(accepts_cargo)) {
427 /* Not found, insert */
428 pos = std::find(std::begin(accepts_cargo), std::end(accepts_cargo), INVALID_CARGO);
429 if (pos == std::end(accepts_cargo)) continue; // nowhere to place, give up on this one
430 *pos = a.cargo;
432 cargo_acceptance[std::distance(std::begin(accepts_cargo), pos)] += 8;
436 if (HasBit(itspec->callback_mask, CBM_INDT_ACCEPT_CARGO)) {
437 /* Try callback for accepts list, if success override all existing accepts */
438 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
439 if (res != CALLBACK_FAILED) {
440 accepts_cargo.fill(INVALID_CARGO);
441 for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_INPUTS; i++) accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
445 if (HasBit(itspec->callback_mask, CBM_INDT_CARGO_ACCEPTANCE)) {
446 /* Try callback for acceptance list, if success override all existing acceptance */
447 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
448 if (res != CALLBACK_FAILED) {
449 cargo_acceptance.fill(0);
450 for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_INPUTS; i++) cargo_acceptance[i] = GB(res, i * 4, 4);
454 for (uint8_t i = 0; i < std::size(itspec->accepts_cargo); i++) {
455 CargoID a = accepts_cargo[i];
456 if (!IsValidCargoID(a) || cargo_acceptance[i] <= 0) continue; // work only with valid cargoes
458 /* Add accepted cargo */
459 acceptance[a] += cargo_acceptance[i];
461 /* Maybe set 'always accepted' bit (if it's not set already) */
462 if (HasBit(always_accepted, a)) continue;
464 /* Test whether the industry itself accepts the cargo type */
465 if (ind->IsCargoAccepted(a)) continue;
467 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
468 SetBit(always_accepted, a);
472 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
474 const Industry *i = Industry::GetByTile(tile);
475 const IndustrySpec *is = GetIndustrySpec(i->type);
477 td->owner[0] = i->owner;
478 td->str = is->name;
479 if (!IsIndustryCompleted(tile)) {
480 td->dparam = td->str;
481 td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
484 if (is->grf_prop.grffile != nullptr) {
485 td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
489 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
491 Industry *i = Industry::GetByTile(tile);
492 const IndustrySpec *indspec = GetIndustrySpec(i->type);
494 /* water can destroy industries
495 * in editor you can bulldoze industries
496 * with magic_bulldozer cheat you can destroy industries
497 * (area around OILRIG is water, so water shouldn't flood it
499 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
500 !_cheats.magic_bulldozer.value) ||
501 ((flags & DC_AUTO) != 0) ||
502 (_current_company == OWNER_WATER &&
503 ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
504 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
505 SetDParam(1, indspec->name);
506 return_cmd_error(flags & DC_AUTO ? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY : INVALID_STRING_ID);
509 if (flags & DC_EXEC) {
510 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
511 Game::NewEvent(new ScriptEventIndustryClose(i->index));
512 delete i;
514 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
518 * Move produced cargo from industry to nearby stations.
519 * @param tile Industry tile
520 * @return true if any cargo was moved.
522 static bool TransportIndustryGoods(TileIndex tile)
524 Industry *i = Industry::GetByTile(tile);
525 const IndustrySpec *indspec = GetIndustrySpec(i->type);
526 bool moved_cargo = false;
528 for (auto &p : i->produced) {
529 uint cw = ClampTo<uint8_t>(p.waiting);
530 if (cw > indspec->minimal_cargo && IsValidCargoID(p.cargo)) {
531 p.waiting -= cw;
533 /* fluctuating economy? */
534 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
536 p.history[THIS_MONTH].production += cw;
538 uint am = MoveGoodsToStation(p.cargo, cw, SourceType::Industry, i->index, &i->stations_near, i->exclusive_consumer);
539 p.history[THIS_MONTH].transported += am;
541 moved_cargo |= (am != 0);
545 return moved_cargo;
548 static void AnimateSugarSieve(TileIndex tile)
550 uint8_t m = GetAnimationFrame(tile) + 1;
552 if (_settings_client.sound.ambient) {
553 switch (m & 7) {
554 case 2: SndPlayTileFx(SND_2D_SUGAR_MINE_1, tile); break;
555 case 6: SndPlayTileFx(SND_29_SUGAR_MINE_2, tile); break;
559 if (m >= 96) {
560 m = 0;
561 DeleteAnimatedTile(tile);
563 SetAnimationFrame(tile, m);
565 MarkTileDirtyByTile(tile);
568 static void AnimateToffeeQuarry(TileIndex tile)
570 uint8_t m = GetAnimationFrame(tile);
572 if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
573 SndPlayTileFx(SND_30_TOFFEE_QUARRY, tile);
576 if (++m >= 70) {
577 m = 0;
578 DeleteAnimatedTile(tile);
580 SetAnimationFrame(tile, m);
582 MarkTileDirtyByTile(tile);
585 static void AnimateBubbleCatcher(TileIndex tile)
587 uint8_t m = GetAnimationFrame(tile);
589 if (++m >= 40) {
590 m = 0;
591 DeleteAnimatedTile(tile);
593 SetAnimationFrame(tile, m);
595 MarkTileDirtyByTile(tile);
598 static void AnimatePowerPlantSparks(TileIndex tile)
600 uint8_t m = GetAnimationFrame(tile);
601 if (m == 6) {
602 SetAnimationFrame(tile, 0);
603 DeleteAnimatedTile(tile);
604 } else {
605 SetAnimationFrame(tile, m + 1);
607 MarkTileDirtyByTile(tile);
610 static void AnimateToyFactory(TileIndex tile)
612 uint8_t m = GetAnimationFrame(tile) + 1;
614 switch (m) {
615 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_TOY_FACTORY_1, tile); break;
616 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_TOY_FACTORY_2, tile); break;
617 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_TOY_FACTORY_3, tile); break;
618 default:
619 if (m >= 50) {
620 int n = GetIndustryAnimationLoop(tile) + 1;
621 m = 0;
622 if (n >= 8) {
623 n = 0;
624 DeleteAnimatedTile(tile);
626 SetIndustryAnimationLoop(tile, n);
630 SetAnimationFrame(tile, m);
631 MarkTileDirtyByTile(tile);
634 static void AnimatePlasticFountain(TileIndex tile, IndustryGfx gfx)
636 gfx = (gfx < GFX_PLASTIC_FOUNTAIN_ANIMATED_8) ? gfx + 1 : GFX_PLASTIC_FOUNTAIN_ANIMATED_1;
637 SetIndustryGfx(tile, gfx);
638 MarkTileDirtyByTile(tile);
641 static void AnimateOilWell(TileIndex tile, IndustryGfx gfx)
643 bool b = Chance16(1, 7);
644 uint8_t m = GetAnimationFrame(tile) + 1;
645 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
646 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
647 SetIndustryConstructionStage(tile, 3);
648 DeleteAnimatedTile(tile);
649 } else {
650 SetAnimationFrame(tile, m);
651 SetIndustryGfx(tile, gfx);
653 MarkTileDirtyByTile(tile);
656 static void AnimateMineTower(TileIndex tile)
658 int state = TimerGameTick::counter & 0x7FF;
660 if ((state -= 0x400) < 0) return;
662 if (state < 0x1A0) {
663 if (state < 0x20 || state >= 0x180) {
664 uint8_t m = GetAnimationFrame(tile);
665 if (!(m & 0x40)) {
666 SetAnimationFrame(tile, m | 0x40);
667 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINE, tile);
669 if (state & 7) return;
670 } else {
671 if (state & 3) return;
673 uint8_t m = (GetAnimationFrame(tile) + 1) | 0x40;
674 if (m > 0xC2) m = 0xC0;
675 SetAnimationFrame(tile, m);
676 MarkTileDirtyByTile(tile);
677 } else if (state >= 0x200 && state < 0x3A0) {
678 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
679 if (state & i) return;
681 uint8_t m = (GetAnimationFrame(tile) & 0xBF) - 1;
682 if (m < 0x80) m = 0x82;
683 SetAnimationFrame(tile, m);
684 MarkTileDirtyByTile(tile);
688 static void AnimateTile_Industry(TileIndex tile)
690 IndustryGfx gfx = GetIndustryGfx(tile);
692 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
693 AnimateNewIndustryTile(tile);
694 return;
697 switch (gfx) {
698 case GFX_SUGAR_MINE_SIEVE:
699 if ((TimerGameTick::counter & 1) == 0) AnimateSugarSieve(tile);
700 break;
702 case GFX_TOFFEE_QUARY:
703 if ((TimerGameTick::counter & 3) == 0) AnimateToffeeQuarry(tile);
704 break;
706 case GFX_BUBBLE_CATCHER:
707 if ((TimerGameTick::counter & 1) == 0) AnimateBubbleCatcher(tile);
708 break;
710 case GFX_POWERPLANT_SPARKS:
711 if ((TimerGameTick::counter & 3) == 0) AnimatePowerPlantSparks(tile);
712 break;
714 case GFX_TOY_FACTORY:
715 if ((TimerGameTick::counter & 1) == 0) AnimateToyFactory(tile);
716 break;
718 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
719 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
720 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
721 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
722 if ((TimerGameTick::counter & 3) == 0) AnimatePlasticFountain(tile, gfx);
723 break;
725 case GFX_OILWELL_ANIMATED_1:
726 case GFX_OILWELL_ANIMATED_2:
727 case GFX_OILWELL_ANIMATED_3:
728 if ((TimerGameTick::counter & 7) == 0) AnimateOilWell(tile, gfx);
729 break;
731 case GFX_COAL_MINE_TOWER_ANIMATED:
732 case GFX_COPPER_MINE_TOWER_ANIMATED:
733 case GFX_GOLD_MINE_TOWER_ANIMATED:
734 AnimateMineTower(tile);
735 break;
739 static void CreateChimneySmoke(TileIndex tile)
741 uint x = TileX(tile) * TILE_SIZE;
742 uint y = TileY(tile) * TILE_SIZE;
743 int z = GetTileMaxPixelZ(tile);
745 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
748 static void MakeIndustryTileBigger(TileIndex tile)
750 uint8_t cnt = GetIndustryConstructionCounter(tile) + 1;
751 if (cnt != 4) {
752 SetIndustryConstructionCounter(tile, cnt);
753 return;
756 uint8_t stage = GetIndustryConstructionStage(tile) + 1;
757 SetIndustryConstructionCounter(tile, 0);
758 SetIndustryConstructionStage(tile, stage);
759 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
760 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
762 MarkTileDirtyByTile(tile);
764 if (!IsIndustryCompleted(tile)) return;
766 IndustryGfx gfx = GetIndustryGfx(tile);
767 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
768 /* New industries are already animated on construction. */
769 return;
772 switch (gfx) {
773 case GFX_POWERPLANT_CHIMNEY:
774 CreateChimneySmoke(tile);
775 break;
777 case GFX_OILRIG_1: {
778 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
779 * tiles (like the default oil rig). Do a proper check to ensure the
780 * tiles belong to the same industry and based on that build the oil rig's
781 * station. */
782 TileIndex other = tile + TileDiffXY(0, 1);
784 if (IsTileType(other, MP_INDUSTRY) &&
785 GetIndustryGfx(other) == GFX_OILRIG_1 &&
786 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
787 BuildOilRig(tile);
789 break;
792 case GFX_TOY_FACTORY:
793 case GFX_BUBBLE_CATCHER:
794 case GFX_TOFFEE_QUARY:
795 SetAnimationFrame(tile, 0);
796 SetIndustryAnimationLoop(tile, 0);
797 break;
799 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
800 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
801 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
802 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
803 AddAnimatedTile(tile, false);
804 break;
808 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
810 static const int8_t _bubble_spawn_location[3][4] = {
811 { 11, 0, -4, -14 },
812 { -4, -10, -4, 1 },
813 { 49, 59, 60, 65 },
816 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_BUBBLE_GENERATOR, tile);
818 int dir = Random() & 3;
820 EffectVehicle *v = CreateEffectVehicleAbove(
821 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
822 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
823 _bubble_spawn_location[2][dir],
824 EV_BUBBLE
827 if (v != nullptr) v->animation_substate = dir;
830 static void TileLoop_Industry(TileIndex tile)
832 if (IsTileOnWater(tile)) TileLoop_Water(tile);
834 /* Normally this doesn't happen, but if an industry NewGRF is removed
835 * an industry that was previously build on water can now be flooded.
836 * If this happens the tile is no longer an industry tile after
837 * returning from TileLoop_Water. */
838 if (!IsTileType(tile, MP_INDUSTRY)) return;
840 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
842 if (!IsIndustryCompleted(tile)) {
843 MakeIndustryTileBigger(tile);
844 return;
847 if (_game_mode == GM_EDITOR) return;
849 if (TransportIndustryGoods(tile) && !StartStopIndustryTileAnimation(Industry::GetByTile(tile), IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
850 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
852 if (newgfx != INDUSTRYTILE_NOANIM) {
853 ResetIndustryConstructionStage(tile);
854 SetIndustryCompleted(tile);
855 SetIndustryGfx(tile, newgfx);
856 MarkTileDirtyByTile(tile);
857 return;
861 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
863 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
864 if (newgfx != INDUSTRYTILE_NOANIM) {
865 ResetIndustryConstructionStage(tile);
866 SetIndustryGfx(tile, newgfx);
867 MarkTileDirtyByTile(tile);
868 return;
871 IndustryGfx gfx = GetIndustryGfx(tile);
872 switch (gfx) {
873 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
874 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
875 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
876 if (!(TimerGameTick::counter & 0x400) && Chance16(1, 2)) {
877 switch (gfx) {
878 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
879 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
880 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
882 SetIndustryGfx(tile, gfx);
883 SetAnimationFrame(tile, 0x80);
884 AddAnimatedTile(tile);
886 break;
888 case GFX_OILWELL_NOT_ANIMATED:
889 if (Chance16(1, 6)) {
890 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
891 SetAnimationFrame(tile, 0);
892 AddAnimatedTile(tile);
894 break;
896 case GFX_COAL_MINE_TOWER_ANIMATED:
897 case GFX_COPPER_MINE_TOWER_ANIMATED:
898 case GFX_GOLD_MINE_TOWER_ANIMATED:
899 if (!(TimerGameTick::counter & 0x400)) {
900 switch (gfx) {
901 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
902 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
903 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
905 SetIndustryGfx(tile, gfx);
906 SetIndustryCompleted(tile);
907 SetIndustryConstructionStage(tile, 3);
908 DeleteAnimatedTile(tile);
909 MarkTileDirtyByTile(tile);
911 break;
913 case GFX_POWERPLANT_SPARKS:
914 if (Chance16(1, 3)) {
915 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_POWER_STATION, tile);
916 AddAnimatedTile(tile);
918 break;
920 case GFX_COPPER_MINE_CHIMNEY:
921 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
922 break;
925 case GFX_TOY_FACTORY: {
926 Industry *i = Industry::GetByTile(tile);
927 if (i->was_cargo_delivered) {
928 i->was_cargo_delivered = false;
929 SetIndustryAnimationLoop(tile, 0);
930 AddAnimatedTile(tile);
933 break;
935 case GFX_BUBBLE_GENERATOR:
936 TileLoopIndustry_BubbleGenerator(tile);
937 break;
939 case GFX_TOFFEE_QUARY:
940 AddAnimatedTile(tile);
941 break;
943 case GFX_SUGAR_MINE_SIEVE:
944 if (Chance16(1, 3)) AddAnimatedTile(tile);
945 break;
949 static bool ClickTile_Industry(TileIndex tile)
951 ShowIndustryViewWindow(GetIndustryIndex(tile));
952 return true;
955 static TrackStatus GetTileTrackStatus_Industry(TileIndex, TransportType, uint, DiagDirection)
957 return 0;
960 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
962 /* If the founder merges, the industry was created by the merged company */
963 Industry *i = Industry::GetByTile(tile);
964 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
966 if (i->exclusive_supplier == old_owner) i->exclusive_supplier = new_owner;
967 if (i->exclusive_consumer == old_owner) i->exclusive_consumer = new_owner;
971 * Check whether the tile is a forest.
972 * @param tile the tile to investigate.
973 * @return true if and only if the tile is a forest
975 bool IsTileForestIndustry(TileIndex tile)
977 /* Check for industry tile */
978 if (!IsTileType(tile, MP_INDUSTRY)) return false;
980 const Industry *ind = Industry::GetByTile(tile);
982 /* Check for organic industry (i.e. not processing or extractive) */
983 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
985 /* Check for wood production */
986 return std::any_of(std::begin(ind->produced), std::end(ind->produced), [](const auto &p) { return IsValidCargoID(p.cargo) && CargoSpec::Get(p.cargo)->label == CT_WOOD; });
989 static const uint8_t _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
992 * Check whether the tile can be replaced by a farm field.
993 * @param tile the tile to investigate.
994 * @param allow_fields if true, the method will return true even if
995 * the tile is a farm tile, otherwise the tile may not be a farm tile
996 * @return true if the tile can become a farm field
998 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
1000 switch (GetTileType(tile)) {
1001 case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
1002 case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
1003 default: return false;
1008 * Build farm field fence
1009 * @param tile the tile to position the fence on
1010 * @param size the size of the field being planted in tiles
1011 * @param type type of fence to set
1012 * @param side the side of the tile to attempt placement
1014 static void SetupFarmFieldFence(TileIndex tile, int size, uint8_t type, DiagDirection side)
1016 TileIndexDiff diff = TileOffsByAxis(OtherAxis(DiagDirToAxis(side)));
1017 TileIndexDiff neighbour_diff = TileOffsByDiagDir(side);
1019 do {
1020 tile = Map::WrapToMap(tile);
1022 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
1023 TileIndex neighbour = tile + neighbour_diff;
1024 if (!IsTileType(neighbour, MP_CLEAR) || !IsClearGround(neighbour, CLEAR_FIELDS) || GetFence(neighbour, ReverseDiagDir(side)) == 0) {
1025 /* Add fence as long as neighbouring tile does not already have a fence in the same position. */
1026 uint8_t or_ = type;
1028 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
1030 SetFence(tile, side, or_);
1034 tile += diff;
1035 } while (--size);
1038 static void PlantFarmField(TileIndex tile, IndustryID industry)
1040 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1041 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1044 /* determine field size */
1045 uint32_t r = (Random() & 0x303) + 0x404;
1046 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1047 uint size_x = GB(r, 0, 8);
1048 uint size_y = GB(r, 8, 8);
1050 TileArea ta(tile - TileDiffXY(std::min(TileX(tile), size_x / 2), std::min(TileY(tile), size_y / 2)), size_x, size_y);
1051 ta.ClampToMap();
1053 if (ta.w == 0 || ta.h == 0) return;
1055 /* check the amount of bad tiles */
1056 int count = 0;
1057 for (TileIndex cur_tile : ta) {
1058 assert(cur_tile < Map::Size());
1059 count += IsSuitableForFarmField(cur_tile, false);
1061 if (count * 2 < ta.w * ta.h) return;
1063 /* determine type of field */
1064 r = Random();
1065 uint counter = GB(r, 5, 3);
1066 uint field_type = GB(r, 8, 8) * 9 >> 8;
1068 /* make field */
1069 for (TileIndex cur_tile : ta) {
1070 assert(cur_tile < Map::Size());
1071 if (IsSuitableForFarmField(cur_tile, true)) {
1072 MakeField(cur_tile, field_type, industry);
1073 SetClearCounter(cur_tile, counter);
1074 MarkTileDirtyByTile(cur_tile);
1078 int type = 3;
1079 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1080 type = _plantfarmfield_type[Random() & 0xF];
1083 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1084 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1085 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1086 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1089 void PlantRandomFarmField(const Industry *i)
1091 int x = i->location.w / 2 + Random() % 31 - 16;
1092 int y = i->location.h / 2 + Random() % 31 - 16;
1094 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1096 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1100 * Search callback function for ChopLumberMillTrees
1101 * @param tile to test
1102 * @return the result of the test
1104 static bool SearchLumberMillTrees(TileIndex tile, void *)
1106 if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) >= TreeGrowthStage::Grown) {
1107 /* found a tree */
1109 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
1111 _industry_sound_ctr = 1;
1112 _industry_sound_tile = tile;
1113 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_LUMBER_MILL_1, tile);
1115 Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC, tile);
1117 cur_company.Restore();
1118 return true;
1120 return false;
1124 * Perform a circular search around the Lumber Mill in order to find trees to cut
1125 * @param i industry
1127 static void ChopLumberMillTrees(Industry *i)
1129 /* Don't process lumber mill if cargo is not set up correctly. */
1130 auto itp = std::begin(i->produced);
1131 if (itp == std::end(i->produced) || !IsValidCargoID(itp->cargo)) return;
1133 /* We only want to cut trees if all tiles are completed. */
1134 for (TileIndex tile_cur : i->location) {
1135 if (i->TileBelongsToIndustry(tile_cur)) {
1136 if (!IsIndustryCompleted(tile_cur)) return;
1140 TileIndex tile = i->location.tile;
1141 if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, nullptr)) { // 40x40 tiles to search.
1142 itp->waiting = ClampTo<uint16_t>(itp->waiting + ScaleByCargoScale(45, false)); // Found a tree, add according value to waiting cargo.
1147 * Helper for ProduceIndustryGoods that scales and produces cargos.
1148 * @param i The industry
1149 * @param scale Should we scale production of this cargo directly?
1151 static void ProduceIndustryGoodsHelper(Industry *i, bool scale)
1153 for (auto &p : i->produced) {
1154 if (!IsValidCargoID(p.cargo)) continue;
1156 uint16_t amount = p.rate;
1157 if (scale) amount = ScaleByCargoScale(amount, false);
1159 p.waiting = ClampTo<uint16_t>(p.waiting + amount);
1163 static void ProduceIndustryGoods(Industry *i)
1165 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1167 /* play a sound? */
1168 if ((i->counter & 0x3F) == 0) {
1169 uint32_t r;
1170 if (Chance16R(1, 14, r) && !indsp->random_sounds.empty() && _settings_client.sound.ambient) {
1171 if (std::any_of(std::begin(i->produced), std::end(i->produced), [](const auto &p) { return p.history[LAST_MONTH].production > 0; })) {
1172 /* Play sound since last month had production */
1173 SndPlayTileFx(
1174 static_cast<SoundFx>(indsp->random_sounds[((r >> 16) * indsp->random_sounds.size()) >> 16]),
1175 i->location.tile);
1180 i->counter--;
1182 /* If using an industry callback, scale the callback interval by cargo scale percentage. */
1183 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
1184 if (i->counter % ScaleByInverseCargoScale(Ticks::INDUSTRY_PRODUCE_TICKS, false) == 0) {
1185 IndustryProductionCallback(i, 1);
1186 ProduceIndustryGoodsHelper(i, false);
1191 * All other production and special effects happen every 256 ticks, and cargo production is just scaled by the cargo scale percentage.
1192 * This keeps a slow trickle of production to avoid confusion at low scale factors when the industry seems to be doing nothing for a long period of time.
1194 if ((i->counter % Ticks::INDUSTRY_PRODUCE_TICKS) == 0) {
1195 /* Handle non-callback cargo production. */
1196 if (!HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) ProduceIndustryGoodsHelper(i, true);
1198 IndustryBehaviour indbehav = indsp->behaviour;
1200 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1201 uint16_t cb_res = CALLBACK_FAILED;
1202 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1203 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1206 bool plant;
1207 if (cb_res != CALLBACK_FAILED) {
1208 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1209 } else {
1210 plant = Chance16(1, 8);
1213 if (plant) PlantRandomFarmField(i);
1215 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1216 uint16_t cb_res = CALLBACK_FAILED;
1217 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1218 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1221 bool cut;
1222 if (cb_res != CALLBACK_FAILED) {
1223 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1224 } else {
1225 cut = ((i->counter % Ticks::INDUSTRY_CUT_TREE_TICKS) == 0);
1228 if (cut) ChopLumberMillTrees(i);
1231 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1232 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1236 void OnTick_Industry()
1238 if (_industry_sound_ctr != 0) {
1239 _industry_sound_ctr++;
1241 if (_industry_sound_ctr == 75) {
1242 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_LUMBER_MILL_2, _industry_sound_tile);
1243 } else if (_industry_sound_ctr == 160) {
1244 _industry_sound_ctr = 0;
1245 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_LUMBER_MILL_3, _industry_sound_tile);
1249 if (_game_mode == GM_EDITOR) return;
1251 for (Industry *i : Industry::Iterate()) {
1252 ProduceIndustryGoods(i);
1257 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1258 * @return Succeeded or failed command.
1260 static CommandCost CheckNewIndustry_NULL(TileIndex)
1262 return CommandCost();
1266 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1267 * @param tile %Tile to perform the checking.
1268 * @return Succeeded or failed command.
1270 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1272 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1273 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1274 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1277 return CommandCost();
1281 * Check if a tile is within a distance from map edges, scaled by map dimensions independently.
1282 * Each dimension is checked independently, and dimensions smaller than 256 are not scaled.
1283 * @param tile Which tile to check distance of.
1284 * @param maxdist Normal distance on a 256x256 map.
1285 * @return True if the tile is near the map edge.
1287 static bool CheckScaledDistanceFromEdge(TileIndex tile, uint maxdist)
1289 uint maxdist_x = maxdist;
1290 uint maxdist_y = maxdist;
1292 if (Map::SizeX() > 256) maxdist_x *= Map::SizeX() / 256;
1293 if (Map::SizeY() > 256) maxdist_y *= Map::SizeY() / 256;
1295 if (DistanceFromEdgeDir(tile, DIAGDIR_NE) < maxdist_x) return true;
1296 if (DistanceFromEdgeDir(tile, DIAGDIR_NW) < maxdist_y) return true;
1297 if (DistanceFromEdgeDir(tile, DIAGDIR_SW) < maxdist_x) return true;
1298 if (DistanceFromEdgeDir(tile, DIAGDIR_SE) < maxdist_y) return true;
1300 return false;
1304 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1305 * @param tile %Tile to perform the checking.
1306 * @return Succeeded or failed command.
1308 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1310 if (_game_mode == GM_EDITOR) return CommandCost();
1312 if (CheckScaledDistanceFromEdge(TileAddXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1314 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1317 extern bool _ignore_restrictions;
1320 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1321 * @param tile %Tile to perform the checking.
1322 * @return Succeeded or failed command.
1324 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1326 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1328 if (TileHeight(tile) == 0 &&
1329 CheckScaledDistanceFromEdge(TileAddXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1331 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1335 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1336 * @param tile %Tile to perform the checking.
1337 * @return Succeeded or failed command.
1339 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1341 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1342 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1343 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1346 return CommandCost();
1350 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1351 * @param tile %Tile to perform the checking.
1352 * @return Succeeded or failed command.
1354 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1356 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1357 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1359 return CommandCost();
1363 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1364 * @param tile %Tile to perform the checking.
1365 * @return Succeeded or failed command.
1367 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1369 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1370 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1372 return CommandCost();
1376 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1377 * @param tile %Tile to perform the checking.
1378 * @return Succeeded or failed command.
1380 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1382 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1383 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1385 return CommandCost();
1389 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1390 * @param tile %Tile to perform the checking.
1391 * @return Succeeded or failed command.
1393 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1395 if (GetTileZ(tile) > 4) {
1396 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1398 return CommandCost();
1402 * Industrytype check function signature.
1403 * @param tile %Tile to check.
1404 * @return Succeeded or failed command.
1406 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1408 /** Check functions for different types of industry. */
1409 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1410 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1411 CheckNewIndustry_Forest, ///< CHECK_FOREST
1412 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1413 CheckNewIndustry_Farm, ///< CHECK_FARM
1414 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1415 CheckNewIndustry_Water, ///< CHECK_WATER
1416 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1417 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1418 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1422 * Find a town for the industry, while checking for multiple industries in the same town.
1423 * @param tile Position of the industry to build.
1424 * @param type Industry type.
1425 * @param[out] t Pointer to return town for the new industry, \c nullptr is written if no good town can be found.
1426 * @return Succeeded or failed command.
1428 * @pre \c *t != nullptr
1429 * @post \c *t points to a town on success, and \c nullptr on failure.
1431 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1433 *t = ClosestTownFromTile(tile, UINT_MAX);
1435 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1437 for (const Industry *i : Industry::Iterate()) {
1438 if (i->type == (uint8_t)type && i->town == *t) {
1439 *t = nullptr;
1440 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1444 return CommandCost();
1447 bool IsSlopeRefused(Slope current, Slope refused)
1449 if (IsSteepSlope(current)) return true;
1450 if (current != SLOPE_FLAT) {
1451 if (IsSteepSlope(refused)) return true;
1453 Slope t = ComplementSlope(current);
1455 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1456 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1457 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1458 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1461 return false;
1465 * Are the tiles of the industry free?
1466 * @param tile Position to check.
1467 * @param layout Industry tiles table.
1468 * @param type Type of the industry.
1469 * @return Failed or succeeded command.
1471 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, IndustryType type)
1473 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1475 for (const IndustryTileLayoutTile &it : layout) {
1476 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1477 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1479 if (!IsValidTile(cur_tile)) {
1480 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1483 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1484 if (!IsWaterTile(cur_tile) ||
1485 !IsTileFlat(cur_tile)) {
1486 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1488 } else {
1489 CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1490 if (ret.Failed()) return ret;
1491 if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1493 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1495 /* Perform land/water check if not disabled */
1496 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1498 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1499 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1500 if (!IsTileType(cur_tile, MP_HOUSE)) {
1501 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1504 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1505 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN);
1506 ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_NONE, cur_tile);
1507 cur_company.Restore();
1509 if (ret.Failed()) return ret;
1510 } else {
1511 /* Clear the tiles, but do not affect town ratings */
1512 ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile);
1513 if (ret.Failed()) return ret;
1518 return CommandCost();
1522 * Check slope requirements for industry tiles.
1523 * @param tile Position to check.
1524 * @param layout Industry tiles table.
1525 * @param layout_index The index of the layout to build/fund
1526 * @param type Type of the industry.
1527 * @param initial_random_bits The random bits the industry is going to have after construction.
1528 * @param founder Industry founder
1529 * @param creation_type The circumstances the industry is created under.
1530 * @param[out] custom_shape_check Perform custom check for the site.
1531 * @return Failed or succeeded command.
1533 static CommandCost CheckIfIndustryTileSlopes(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, int type, uint16_t initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
1535 bool refused_slope = false;
1536 bool custom_shape = false;
1538 for (const IndustryTileLayoutTile &it : layout) {
1539 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1540 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1541 assert(IsValidTile(cur_tile)); // checked before in CheckIfIndustryTilesAreFree
1543 if (gfx != GFX_WATERTILE_SPECIALCHECK) {
1544 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1546 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1547 custom_shape = true;
1548 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
1549 if (ret.Failed()) return ret;
1550 } else {
1551 Slope tileh = GetTileSlope(cur_tile);
1552 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1557 if (custom_shape_check != nullptr) *custom_shape_check = custom_shape;
1559 /* It is almost impossible to have a fully flat land in TG, so what we
1560 * do is that we check if we can make the land flat later on. See
1561 * CheckIfCanLevelIndustryPlatform(). */
1562 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1563 return CommandCost();
1565 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1569 * Is the industry allowed to be built at this place for the town?
1570 * @param tile Tile to construct the industry.
1571 * @param type Type of the industry.
1572 * @param t Town authority that the industry belongs to.
1573 * @return Succeeded or failed command.
1575 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1577 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1578 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1581 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1582 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1585 return CommandCost();
1588 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1590 /* Check if we don't leave the map */
1591 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1593 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1594 for (TileIndex tile_walk : ta) {
1595 uint curh = TileHeight(tile_walk);
1596 /* Is the tile clear? */
1597 if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1599 /* Don't allow too big of a change if this is the sub-tile check */
1600 if (internal != 0 && Delta(curh, height) > 1) return false;
1602 /* Different height, so the surrounding tiles of this tile
1603 * has to be correct too (in level, or almost in level)
1604 * else you get a chain-reaction of terraforming. */
1605 if (internal == 0 && curh != height) {
1606 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1607 return false;
1612 return true;
1616 * This function tries to flatten out the land below an industry, without
1617 * damaging the surroundings too much.
1619 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileLayout &layout)
1621 int max_x = 0;
1622 int max_y = 0;
1624 /* Finds dimensions of largest variant of this industry */
1625 for (const IndustryTileLayoutTile &it : layout) {
1626 if (it.gfx == GFX_WATERTILE_SPECIALCHECK) continue; // watercheck tiles don't count for footprint size
1627 if (it.ti.x > max_x) max_x = it.ti.x;
1628 if (it.ti.y > max_y) max_y = it.ti.y;
1631 /* Remember level height */
1632 uint h = TileHeight(tile);
1634 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1635 /* Check that all tiles in area and surrounding are clear
1636 * this determines that there are no obstructing items */
1638 /* TileArea::Expand is not used here as we need to abort
1639 * instead of clamping if the bounds cannot expanded. */
1640 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1641 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1643 if (TileX(ta.tile) + ta.w >= Map::MaxX() || TileY(ta.tile) + ta.h >= Map::MaxY()) return false;
1645 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1646 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1647 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN);
1649 for (TileIndex tile_walk : ta) {
1650 uint curh = TileHeight(tile_walk);
1651 if (curh != h) {
1652 /* This tile needs terraforming. Check if we can do that without
1653 * damaging the surroundings too much. */
1654 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1655 cur_company.Restore();
1656 return false;
1658 /* This is not 100% correct check, but the best we can do without modifying the map.
1659 * What is missing, is if the difference in height is more than 1.. */
1660 if (std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(flags & ~DC_EXEC, tile_walk, SLOPE_N, curh <= h)).Failed()) {
1661 cur_company.Restore();
1662 return false;
1667 if (flags & DC_EXEC) {
1668 /* Terraform the land under the industry */
1669 for (TileIndex tile_walk : ta) {
1670 uint curh = TileHeight(tile_walk);
1671 while (curh != h) {
1672 /* We give the terraforming for free here, because we can't calculate
1673 * exact cost in the test-round, and as we all know, that will cause
1674 * a nice assert if they don't match ;) */
1675 Command<CMD_TERRAFORM_LAND>::Do(flags, tile_walk, SLOPE_N, curh <= h);
1676 curh += (curh > h) ? -1 : 1;
1681 cur_company.Restore();
1682 return true;
1687 * Check that the new industry is far enough from conflicting industries.
1688 * @param tile Tile to construct the industry.
1689 * @param type Type of the new industry.
1690 * @return Succeeded or failed command.
1692 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1694 const IndustrySpec *indspec = GetIndustrySpec(type);
1696 /* On a large map with many industries, it may be faster to check an area. */
1697 static const int dmax = 14;
1698 if (Industry::GetNumItems() > static_cast<size_t>(dmax * dmax * 2)) {
1699 const Industry *i = nullptr;
1700 TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax);
1701 for (TileIndex atile : tile_area) {
1702 if (GetTileType(atile) == MP_INDUSTRY) {
1703 const Industry *i2 = Industry::GetByTile(atile);
1704 if (i == i2) continue;
1705 i = i2;
1706 if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1707 if (i->type == indspec->conflicting[0] ||
1708 i->type == indspec->conflicting[1] ||
1709 i->type == indspec->conflicting[2]) {
1710 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1714 return CommandCost();
1717 for (const Industry *i : Industry::Iterate()) {
1718 /* Within 14 tiles from another industry is considered close */
1719 if (DistanceMax(tile, i->location.tile) > 14) continue;
1721 /* check if there are any conflicting industry types around */
1722 if (i->type == indspec->conflicting[0] ||
1723 i->type == indspec->conflicting[1] ||
1724 i->type == indspec->conflicting[2]) {
1725 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1728 return CommandCost();
1732 * Advertise about a new industry opening.
1733 * @param ind Industry being opened.
1735 static void AdvertiseIndustryOpening(const Industry *ind)
1737 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1738 SetDParam(0, ind_spc->name);
1739 if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1740 SetDParam(1, STR_TOWN_NAME);
1741 SetDParam(2, ind->town->index);
1742 } else {
1743 SetDParam(1, ind->town->index);
1745 AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1746 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1747 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1751 * Populate an industry's list of nearby stations, and if it accepts any cargo, also
1752 * add the industry to each station's nearby industry list.
1753 * @param ind Industry
1755 static void PopulateStationsNearby(Industry *ind)
1757 if (ind->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) {
1758 /* Industry has a neutral station. Use it and ignore any other nearby stations. */
1759 ind->stations_near.insert(ind->neutral_station);
1760 ind->neutral_station->industries_near.clear();
1761 ind->neutral_station->industries_near.insert(IndustryListEntry{0, ind});
1762 return;
1765 ForAllStationsAroundTiles(ind->location, [ind](Station *st, TileIndex tile) {
1766 if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) != ind->index) return false;
1767 ind->stations_near.insert(st);
1768 st->AddIndustryToDeliver(ind, tile);
1769 return false;
1774 * Put an industry on the map.
1775 * @param i Just allocated poolitem, mostly empty.
1776 * @param tile North tile of the industry.
1777 * @param type Type of the industry.
1778 * @param layout Industrylayout to build.
1779 * @param layout_index Number of the industry layout.
1780 * @param t Nearest town.
1781 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1782 * @param initial_random_bits Random bits for the industry.
1784 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileLayout &layout, size_t layout_index, Town *t, Owner founder, uint16_t initial_random_bits)
1786 const IndustrySpec *indspec = GetIndustrySpec(type);
1788 i->location = TileArea(tile, 1, 1);
1789 i->type = type;
1790 Industry::IncIndustryTypeCount(type);
1792 for (size_t index = 0; index < std::size(indspec->produced_cargo); ++index) {
1793 if (!IsValidCargoID(indspec->produced_cargo[index])) break;
1795 Industry::ProducedCargo &p = i->produced.emplace_back();
1796 p.cargo = indspec->produced_cargo[index];
1797 p.rate = indspec->production_rate[index];
1800 for (size_t index = 0; index < std::size(indspec->accepts_cargo); ++index) {
1801 if (!IsValidCargoID(indspec->accepts_cargo[index])) break;
1803 Industry::AcceptedCargo &a = i->accepted.emplace_back();
1804 a.cargo = indspec->accepts_cargo[index];
1807 /* Randomize inital production if non-original economy is used and there are no production related callbacks. */
1808 if (!indspec->UsesOriginalEconomy()) {
1809 for (auto &p : i->produced) {
1810 p.rate = ClampTo<uint8_t>((RandomRange(256) + 128) * p.rate >> 8);
1814 i->town = t;
1815 i->owner = OWNER_NONE;
1817 uint16_t r = Random();
1818 i->random_colour = static_cast<Colours>(GB(r, 0, 4));
1819 i->counter = GB(r, 4, 12);
1820 i->random = initial_random_bits;
1821 i->was_cargo_delivered = false;
1822 i->last_prod_year = TimerGameEconomy::year;
1823 i->founder = founder;
1824 i->ctlflags = INDCTL_NONE;
1826 i->construction_date = TimerGameCalendar::date;
1827 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1828 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1830 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1831 * 0 = created prior of newindustries
1832 * else, chosen layout + 1 */
1833 i->selected_layout = (uint8_t)(layout_index + 1);
1835 i->exclusive_supplier = INVALID_OWNER;
1836 i->exclusive_consumer = INVALID_OWNER;
1838 i->prod_level = PRODLEVEL_DEFAULT;
1840 /* Call callbacks after the regular fields got initialised. */
1842 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1843 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1844 if (res != CALLBACK_FAILED) {
1845 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1846 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1847 } else {
1848 i->prod_level = res;
1849 i->RecomputeProductionMultipliers();
1854 if (_generating_world) {
1855 if (HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
1856 IndustryProductionCallback(i, 1);
1857 for (auto &p : i->produced) {
1858 p.history[LAST_MONTH].production = p.waiting * 8;
1859 p.waiting = 0;
1863 for (auto &p : i->produced) {
1864 p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
1868 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1869 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1870 if (res != CALLBACK_FAILED) {
1871 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1872 i->random_colour = static_cast<Colours>(GB(res, 0, 4));
1876 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1877 /* Clear all input cargo types */
1878 i->accepted.clear();
1879 /* Query actual types */
1880 uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? INDUSTRY_NUM_INPUTS : 3;
1881 for (uint j = 0; j < maxcargoes; j++) {
1882 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1883 if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
1884 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1885 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1886 break;
1888 CargoID cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1889 /* Industries without "unlimited" cargo types support depend on the specific order/slots of cargo types.
1890 * They need to be able to blank out specific slots without aborting the callback sequence,
1891 * and solve this by returning undefined cargo indexes. Skip these. */
1892 if (!IsValidCargoID(cargo) && !(indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED)) {
1893 /* As slots are allocated as needed now, this means we do need to add a slot for the invalid cargo. */
1894 Industry::AcceptedCargo &a = i->accepted.emplace_back();
1895 a.cargo = INVALID_CARGO;
1896 continue;
1898 /* Verify valid cargo */
1899 if (std::find(std::begin(indspec->accepts_cargo), std::end(indspec->accepts_cargo), cargo) == std::end(indspec->accepts_cargo)) {
1900 /* Cargo not in spec, error in NewGRF */
1901 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1902 break;
1904 if (std::any_of(std::begin(i->accepted), std::begin(i->accepted) + j, [&cargo](const auto &a) { return a.cargo == cargo; })) {
1905 /* Duplicate cargo */
1906 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1907 break;
1909 Industry::AcceptedCargo &a = i->accepted.emplace_back();
1910 a.cargo = cargo;
1914 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1915 /* Clear all output cargo types */
1916 i->produced.clear();
1917 /* Query actual types */
1918 uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? INDUSTRY_NUM_OUTPUTS : 2;
1919 for (uint j = 0; j < maxcargoes; j++) {
1920 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1921 if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
1922 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1923 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1924 break;
1926 CargoID cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1927 /* Allow older GRFs to skip slots. */
1928 if (!IsValidCargoID(cargo) && !(indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED)) {
1929 /* As slots are allocated as needed now, this means we do need to add a slot for the invalid cargo. */
1930 Industry::ProducedCargo &p = i->produced.emplace_back();
1931 p.cargo = INVALID_CARGO;
1932 continue;
1934 /* Verify valid cargo */
1935 if (std::find(std::begin(indspec->produced_cargo), std::end(indspec->produced_cargo), cargo) == std::end(indspec->produced_cargo)) {
1936 /* Cargo not in spec, error in NewGRF */
1937 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1938 break;
1940 if (std::any_of(std::begin(i->produced), std::begin(i->produced) + j, [&cargo](const auto &p) { return p.cargo == cargo; })) {
1941 /* Duplicate cargo */
1942 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1943 break;
1945 Industry::ProducedCargo &p = i->produced.emplace_back();
1946 p.cargo = cargo;
1950 /* Plant the tiles */
1952 for (const IndustryTileLayoutTile &it : layout) {
1953 TileIndex cur_tile = tile + ToTileIndexDiff(it.ti);
1955 if (it.gfx != GFX_WATERTILE_SPECIALCHECK) {
1956 i->location.Add(cur_tile);
1958 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1960 Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile);
1962 MakeIndustry(cur_tile, i->index, it.gfx, Random(), wc);
1964 if (_generating_world) {
1965 SetIndustryConstructionCounter(cur_tile, 3);
1966 SetIndustryConstructionStage(cur_tile, 2);
1969 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1970 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it.gfx);
1971 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1972 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1976 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1977 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1979 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_FORCE_REBUILD);
1980 SetWindowDirty(WC_BUILD_INDUSTRY, 0);
1982 if (!_generating_world) PopulateStationsNearby(i);
1986 * Helper function for Build/Fund an industry
1987 * @param tile tile where industry is built
1988 * @param type of industry to build
1989 * @param flags of operations to conduct
1990 * @param indspec pointer to industry specifications
1991 * @param layout_index the index of the itsepc to build/fund
1992 * @param random_var8f random seed (possibly) used by industries
1993 * @param random_initial_bits The random bits the industry is going to have after construction.
1994 * @param founder Founder of the industry
1995 * @param creation_type The circumstances the industry is created under.
1996 * @param[out] ip Pointer to store newly created industry.
1997 * @return Succeeded or failed command.
1999 * @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.
2001 static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, size_t layout_index, uint32_t random_var8f, uint16_t random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
2003 assert(layout_index < indspec->layouts.size());
2004 const IndustryTileLayout &layout = indspec->layouts[layout_index];
2006 *ip = nullptr;
2008 /* 1. Cheap: Built-in checks on industry level. */
2009 CommandCost ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
2010 if (ret.Failed()) return ret;
2012 Town *t = nullptr;
2013 ret = FindTownForIndustry(tile, type, &t);
2014 if (ret.Failed()) return ret;
2015 assert(t != nullptr);
2017 ret = CheckIfIndustryIsAllowed(tile, type, t);
2018 if (ret.Failed()) return ret;
2020 /* 2. Built-in checks on industry tiles. */
2021 std::vector<ClearedObjectArea> object_areas(_cleared_object_areas);
2022 ret = CheckIfIndustryTilesAreFree(tile, layout, type);
2023 _cleared_object_areas = object_areas;
2024 if (ret.Failed()) return ret;
2026 /* 3. NewGRF-defined checks on industry level. */
2027 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
2028 ret = CheckIfCallBackAllowsCreation(tile, type, layout_index, random_var8f, random_initial_bits, founder, creation_type);
2029 } else {
2030 ret = _check_new_industry_procs[indspec->check_proc](tile);
2032 if (ret.Failed()) return ret;
2034 /* 4. Expensive: NewGRF-defined checks on industry tiles. */
2035 bool custom_shape_check = false;
2036 ret = CheckIfIndustryTileSlopes(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
2037 if (ret.Failed()) return ret;
2039 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
2040 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, layout)) {
2041 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2044 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
2046 if (flags & DC_EXEC) {
2047 *ip = new Industry(tile);
2048 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, layout);
2049 DoCreateNewIndustry(*ip, tile, type, layout, layout_index, t, founder, random_initial_bits);
2052 return CommandCost();
2056 * Build/Fund an industry
2057 * @param flags of operations to conduct
2058 * @param tile tile where industry is built
2059 * @param it industry type see build_industry.h and see industry.h
2060 * @param first_layout first layout to try
2061 * @param fund false = prospect, true = fund (only valid if current company is DEITY)
2062 * @param seed seed to use for desyncfree randomisations
2063 * @return the cost of this operation or an error
2065 CommandCost CmdBuildIndustry(DoCommandFlag flags, TileIndex tile, IndustryType it, uint32_t first_layout, bool fund, uint32_t seed)
2067 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
2069 const IndustrySpec *indspec = GetIndustrySpec(it);
2071 /* Check if the to-be built/founded industry is available for this climate. */
2072 if (!indspec->enabled || indspec->layouts.empty()) return CMD_ERROR;
2074 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
2075 * Raw material industries are industries that do not accept cargo (at least for now) */
2076 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
2077 return CMD_ERROR;
2080 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
2081 return CMD_ERROR;
2084 Randomizer randomizer;
2085 randomizer.SetSeed(seed);
2086 uint16_t random_initial_bits = GB(seed, 0, 16);
2087 uint32_t random_var8f = randomizer.Next();
2088 size_t num_layouts = indspec->layouts.size();
2089 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
2090 const bool deity_prospect = _current_company == OWNER_DEITY && !fund;
2092 Industry *ind = nullptr;
2093 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
2094 if (flags & DC_EXEC) {
2095 /* Prospecting has a chance to fail, however we cannot guarantee that something can
2096 * be built on the map, so the chance gets lower when the map is fuller, but there
2097 * is nothing we can really do about that. */
2098 bool prospect_success = deity_prospect || Random() <= indspec->prospecting_chance;
2099 if (prospect_success) {
2100 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
2101 IndustryAvailabilityCallType calltype = _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION;
2102 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN);
2103 for (int i = 0; i < 5000; i++) {
2104 /* We should not have more than one Random() in a function call
2105 * because parameter evaluation order is not guaranteed in the c++ standard
2107 tile = RandomTile();
2108 /* Start with a random layout */
2109 size_t layout = RandomRange((uint32_t)num_layouts);
2110 /* Check now each layout, starting with the random one */
2111 for (size_t j = 0; j < num_layouts; j++) {
2112 layout = (layout + 1) % num_layouts;
2113 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), calltype, &ind);
2114 if (ret.Succeeded()) break;
2116 if (ret.Succeeded()) break;
2118 cur_company.Restore();
2120 if (ret.Failed() && IsLocalCompany()) {
2121 if (prospect_success) {
2122 ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING, WL_INFO);
2123 } else {
2124 ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_PROSPECTING_WAS_UNLUCKY, WL_INFO);
2128 } else {
2129 size_t layout = first_layout;
2130 if (layout >= num_layouts) return CMD_ERROR;
2132 /* Check subsequently each layout, starting with the given layout in p1 */
2133 for (size_t i = 0; i < num_layouts; i++) {
2134 layout = (layout + 1) % num_layouts;
2135 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
2136 if (ret.Succeeded()) break;
2139 /* If it still failed, there's no suitable layout to build here, return the error */
2140 if (ret.Failed()) return ret;
2143 if ((flags & DC_EXEC) && ind != nullptr && _game_mode != GM_EDITOR) {
2144 AdvertiseIndustryOpening(ind);
2147 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
2151 * Set industry control flags.
2152 * @param flags Type of operation.
2153 * @param ind_id IndustryID
2154 * @param ctlflags IndustryControlFlags
2155 * @return Empty cost or an error.
2157 CommandCost CmdIndustrySetFlags(DoCommandFlag flags, IndustryID ind_id, IndustryControlFlags ctlflags)
2159 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2161 Industry *ind = Industry::GetIfValid(ind_id);
2162 if (ind == nullptr) return CMD_ERROR;
2164 if (flags & DC_EXEC) ind->ctlflags = ctlflags & INDCTL_MASK;
2166 return CommandCost();
2170 * Set industry production.
2171 * @param flags Type of operation.
2172 * @param ind_id IndustryID
2173 * @param prod_level Production level.
2174 * @param show_news Show a news message on production change.
2175 * @param custom_news Custom news message text.
2176 * @return Empty cost or an error.
2178 CommandCost CmdIndustrySetProduction(DoCommandFlag flags, IndustryID ind_id, uint8_t prod_level, bool show_news, const std::string &custom_news)
2180 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2181 if (prod_level < PRODLEVEL_MINIMUM || prod_level > PRODLEVEL_MAXIMUM) return CMD_ERROR;
2183 Industry *ind = Industry::GetIfValid(ind_id);
2184 if (ind == nullptr) return CMD_ERROR;
2186 if (flags & DC_EXEC) {
2187 StringID str = STR_NULL;
2188 if (prod_level > ind->prod_level) {
2189 str = GetIndustrySpec(ind->type)->production_up_text;
2190 } else if (prod_level < ind->prod_level) {
2191 str = GetIndustrySpec(ind->type)->production_down_text;
2193 if (prod_level != ind->prod_level && !custom_news.empty()) str = STR_NEWS_CUSTOM_ITEM;
2195 ind->ctlflags |= INDCTL_EXTERNAL_PROD_LEVEL;
2196 ind->prod_level = prod_level;
2197 ind->RecomputeProductionMultipliers();
2199 /* Show news message if requested. */
2200 if (show_news && str != STR_NULL) {
2201 NewsType nt;
2202 switch (WhoCanServiceIndustry(ind)) {
2203 case 0: nt = NT_INDUSTRY_NOBODY; break;
2204 case 1: nt = NT_INDUSTRY_OTHER; break;
2205 case 2: nt = NT_INDUSTRY_COMPANY; break;
2206 default: NOT_REACHED();
2209 /* Set parameters of news string */
2210 if (str == STR_NEWS_CUSTOM_ITEM) {
2211 SetDParamStr(0, custom_news);
2212 } else if (str > STR_LAST_STRINGID) {
2213 SetDParam(0, STR_TOWN_NAME);
2214 SetDParam(1, ind->town->index);
2215 SetDParam(2, GetIndustrySpec(ind->type)->name);
2216 } else {
2217 SetDParam(0, ind->index);
2219 AddIndustryNewsItem(str, nt, ind->index);
2223 return CommandCost();
2227 * Change exclusive consumer or supplier for the industry.
2228 * @param flags Type of operation.
2229 * @param ind_id IndustryID
2230 * @param company_id CompanyID to set or INVALID_OWNER (available to everyone) or
2231 * OWNER_NONE (neutral stations only) or OWNER_DEITY (no one)
2232 * @param consumer Set exclusive consumer if true, supplier if false.
2233 * @return Empty cost or an error.
2235 CommandCost CmdIndustrySetExclusivity(DoCommandFlag flags, IndustryID ind_id, Owner company_id, bool consumer)
2237 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2239 Industry *ind = Industry::GetIfValid(ind_id);
2240 if (ind == nullptr) return CMD_ERROR;
2242 if (company_id != OWNER_NONE && company_id != INVALID_OWNER && company_id != OWNER_DEITY
2243 && !Company::IsValidID(company_id)) return CMD_ERROR;
2245 if (flags & DC_EXEC) {
2246 if (consumer) {
2247 ind->exclusive_consumer = company_id;
2248 } else {
2249 ind->exclusive_supplier = company_id;
2254 return CommandCost();
2258 * Change additional industry text.
2259 * @param flags Type of operation.
2260 * @param ind_id IndustryID
2261 * @param text - Additional industry text.
2262 * @return Empty cost or an error.
2264 CommandCost CmdIndustrySetText(DoCommandFlag flags, IndustryID ind_id, const std::string &text)
2266 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2268 Industry *ind = Industry::GetIfValid(ind_id);
2269 if (ind == nullptr) return CMD_ERROR;
2271 if (flags & DC_EXEC) {
2272 ind->text.clear();
2273 if (!text.empty()) ind->text = text;
2274 InvalidateWindowData(WC_INDUSTRY_VIEW, ind->index);
2277 return CommandCost();
2281 * Create a new industry of random layout.
2282 * @param tile The location to build the industry.
2283 * @param type The industry type to build.
2284 * @param creation_type The circumstances the industry is created under.
2285 * @return the created industry or nullptr if it failed.
2287 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
2289 const IndustrySpec *indspec = GetIndustrySpec(type);
2291 uint32_t seed = Random();
2292 uint32_t seed2 = Random();
2293 Industry *i = nullptr;
2294 size_t layout_index = RandomRange((uint32_t)indspec->layouts.size());
2295 [[maybe_unused]] CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
2296 assert(i != nullptr || ret.Failed());
2297 return i;
2301 * Compute the appearance probability for an industry during map creation.
2302 * @param it Industry type to compute.
2303 * @param[out] force_at_least_one Returns whether at least one instance should be forced on map creation.
2304 * @return Relative probability for the industry to appear.
2306 static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
2308 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2309 uint32_t chance = ind_spc->appear_creation[_settings_game.game_creation.landscape];
2310 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2311 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
2312 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
2313 *force_at_least_one = false;
2314 return 0;
2315 } else {
2316 chance *= 16; // to increase precision
2317 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
2318 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
2319 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? Map::ScaleBySize1D(chance) : Map::ScaleBySize(chance);
2321 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
2322 return chance;
2327 * Compute the probability for constructing a new industry during game play.
2328 * @param it Industry type to compute.
2329 * @param[out] min_number Minimal number of industries that should exist at the map.
2330 * @return Relative probability for the industry to appear.
2332 static uint16_t GetIndustryGamePlayProbability(IndustryType it, uint8_t *min_number)
2334 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2335 *min_number = 0;
2336 return 0;
2339 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2340 uint8_t chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2341 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2342 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && TimerGameCalendar::year > 1950) ||
2343 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && TimerGameCalendar::year < 1960) ||
2344 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2345 *min_number = 0;
2346 return 0;
2348 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2349 return chance;
2353 * Get wanted number of industries on the map.
2354 * @return Wanted number of industries at the map.
2356 static uint GetNumberOfIndustries()
2358 /* Number of industries on a 256x256 map. */
2359 static const uint16_t numof_industry_table[] = {
2360 0, // none
2361 0, // minimal
2362 10, // very low
2363 25, // low
2364 55, // normal
2365 80, // high
2366 0, // custom
2369 assert(lengthof(numof_industry_table) == ID_END);
2370 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2372 if (difficulty == ID_CUSTOM) return std::min<uint>(IndustryPool::MAX_SIZE, _settings_game.game_creation.custom_industry_number);
2374 return std::min<uint>(IndustryPool::MAX_SIZE, Map::ScaleBySize(numof_industry_table[difficulty]));
2378 * Try to place the industry in the game.
2379 * Since there is no feedback why placement fails, there is no other option
2380 * than to try a few times before concluding it does not work.
2381 * @param type Industry type of the desired industry.
2382 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2383 * @return Pointer to created industry, or \c nullptr if creation failed.
2385 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2387 uint tries = try_hard ? 10000u : 2000u;
2388 for (; tries > 0; tries--) {
2389 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2390 if (ind != nullptr) return ind;
2392 return nullptr;
2396 * Try to build a industry on the map.
2397 * @param type IndustryType of the desired industry
2398 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2400 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2402 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
2404 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2405 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2407 cur_company.Restore();
2411 * Get total number of industries existing in the game.
2412 * @return Number of industries currently in the game.
2414 static uint GetCurrentTotalNumberOfIndustries()
2416 int total = 0;
2417 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2418 return total;
2422 /** Reset the entry. */
2423 void IndustryTypeBuildData::Reset()
2425 this->probability = 0;
2426 this->min_number = 0;
2427 this->target_count = 0;
2428 this->max_wait = 1;
2429 this->wait_count = 0;
2432 /** Completely reset the industry build data. */
2433 void IndustryBuildData::Reset()
2435 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2437 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2438 this->builddata[it].Reset();
2442 /** Monthly update of industry build data. */
2443 void IndustryBuildData::EconomyMonthlyLoop()
2445 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.
2446 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2448 /* To prevent running out of unused industries for the player to connect,
2449 * add a fraction of new industries each month, but only if the manager can keep up. */
2450 uint max_behind = 1 + std::min(99u, Map::ScaleBySize(3)); // At most 2 industries for small maps, and 100 at the biggest map (about 6 months industry build attempts).
2451 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2452 this->wanted_inds += Map::ScaleBySize(NEWINDS_PER_MONTH);
2457 * This function will create random industries during game creation.
2458 * It will scale the amount of industries by mapsize and difficulty level.
2460 void GenerateIndustries()
2462 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2464 uint32_t industry_probs[NUM_INDUSTRYTYPES];
2465 bool force_at_least_one[NUM_INDUSTRYTYPES];
2466 uint32_t total_prob = 0;
2467 uint num_forced = 0;
2469 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2470 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2471 total_prob += industry_probs[it];
2472 if (force_at_least_one[it]) num_forced++;
2475 uint total_amount = GetNumberOfIndustries();
2476 if (total_prob == 0 || total_amount < num_forced) {
2477 /* Only place the forced ones */
2478 total_amount = num_forced;
2481 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2483 /* Try to build one industry per type independent of any probabilities */
2484 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2485 if (force_at_least_one[it]) {
2486 assert(total_amount > 0);
2487 total_amount--;
2488 PlaceInitialIndustry(it, true);
2492 /* Add the remaining industries according to their probabilities */
2493 for (uint i = 0; i < total_amount; i++) {
2494 uint32_t r = RandomRange(total_prob);
2495 IndustryType it = 0;
2496 while (r >= industry_probs[it]) {
2497 r -= industry_probs[it];
2498 it++;
2499 assert(it < NUM_INDUSTRYTYPES);
2501 assert(industry_probs[it] > 0);
2502 PlaceInitialIndustry(it, false);
2504 _industry_builder.Reset();
2508 * Monthly update of industry statistics.
2509 * @param i Industry to update.
2511 static void UpdateIndustryStatistics(Industry *i)
2513 for (auto &p : i->produced) {
2514 if (IsValidCargoID(p.cargo)) {
2515 if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
2517 /* Move history from this month to last month. */
2518 std::rotate(std::rbegin(p.history), std::rbegin(p.history) + 1, std::rend(p.history));
2519 p.history[THIS_MONTH].production = 0;
2520 p.history[THIS_MONTH].transported = 0;
2526 * Recompute #production_rate for current #prod_level.
2527 * This function is only valid when not using smooth economy.
2529 void Industry::RecomputeProductionMultipliers()
2531 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2532 assert(indspec->UsesOriginalEconomy());
2534 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2535 for (auto &p : this->produced) {
2536 p.rate = ClampTo<uint8_t>(CeilDiv(indspec->production_rate[&p - this->produced.data()] * this->prod_level, PRODLEVEL_DEFAULT));
2540 void Industry::FillCachedName() const
2542 auto tmp_params = MakeParameters(this->index);
2543 this->cached_name = GetStringWithArgs(STR_INDUSTRY_NAME, tmp_params);
2546 void ClearAllIndustryCachedNames()
2548 for (Industry *ind : Industry::Iterate()) {
2549 ind->cached_name.clear();
2554 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2555 * @param it Industry type.
2556 * @return At least one of the fields has changed value.
2558 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2560 uint8_t min_number;
2561 uint32_t probability = GetIndustryGamePlayProbability(it, &min_number);
2562 bool changed = min_number != this->min_number || probability != this->probability;
2563 this->min_number = min_number;
2564 this->probability = probability;
2565 return changed;
2568 /** Decide how many industries of each type are needed. */
2569 void IndustryBuildData::SetupTargetCount()
2571 bool changed = false;
2572 uint num_planned = 0; // Number of industries planned in the industry build data.
2573 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2574 changed |= this->builddata[it].GetIndustryTypeData(it);
2575 num_planned += this->builddata[it].target_count;
2577 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2578 changed |= num_planned != total_amount;
2579 if (!changed) return; // All industries are still the same, no need to re-randomize.
2581 /* Initialize the target counts. */
2582 uint force_build = 0; // Number of industries that should always be available.
2583 uint32_t total_prob = 0; // Sum of probabilities.
2584 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2585 IndustryTypeBuildData *ibd = this->builddata + it;
2586 force_build += ibd->min_number;
2587 ibd->target_count = ibd->min_number;
2588 total_prob += ibd->probability;
2591 if (total_prob == 0) return; // No buildable industries.
2593 /* Subtract forced industries from the number of industries available for construction. */
2594 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2596 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2597 while (total_amount > 0) {
2598 uint32_t r = RandomRange(total_prob);
2599 IndustryType it = 0;
2600 while (r >= this->builddata[it].probability) {
2601 r -= this->builddata[it].probability;
2602 it++;
2603 assert(it < NUM_INDUSTRYTYPES);
2605 assert(this->builddata[it].probability > 0);
2606 this->builddata[it].target_count++;
2607 total_amount--;
2612 * Try to create a random industry, during gameplay
2614 void IndustryBuildData::TryBuildNewIndustry()
2616 this->SetupTargetCount();
2618 int missing = 0; // Number of industries that need to be build.
2619 uint count = 0; // Number of industry types eligible for build.
2620 uint32_t total_prob = 0; // Sum of probabilities.
2621 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2622 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2623 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2624 missing += difference;
2625 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2626 if (difference > 0) {
2627 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2628 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2629 if (forced_build == NUM_INDUSTRYTYPES ||
2630 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2631 forced_build = it;
2634 total_prob += difference;
2635 count++;
2639 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2641 if (count >= 1) {
2642 /* If not forced, pick a weighted random industry to build.
2643 * For the case that count == 1, there is no need to draw a random number. */
2644 IndustryType it;
2645 if (forced_build != NUM_INDUSTRYTYPES) {
2646 it = forced_build;
2647 } else {
2648 /* Non-forced, select an industry type to build (weighted random). */
2649 uint32_t r = 0; // Initialized to silence the compiler.
2650 if (count > 1) r = RandomRange(total_prob);
2651 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2652 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2653 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2654 if (difference <= 0) continue; // Too many of this kind.
2655 if (count == 1) break;
2656 if (r < (uint)difference) break;
2657 r -= difference;
2659 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2662 /* Try to create the industry. */
2663 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2664 if (ind == nullptr) {
2665 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2666 this->builddata[it].max_wait = std::min(1000, this->builddata[it].max_wait + 2);
2667 } else {
2668 AdvertiseIndustryOpening(ind);
2669 this->builddata[it].max_wait = std::max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2673 /* Decrement wait counters. */
2674 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2675 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2680 * Protects an industry from closure if the appropriate flags and conditions are met
2681 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2682 * count of industries of this type must one (or lower) in order to be protected
2683 * against closure.
2684 * @param type IndustryType been queried
2685 * @result true if protection is on, false otherwise (except for oil wells)
2687 static bool CheckIndustryCloseDownProtection(IndustryType type)
2689 const IndustrySpec *indspec = GetIndustrySpec(type);
2691 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2692 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2693 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2697 * Can given cargo type be accepted or produced by the industry?
2698 * @param cargo: Cargo type
2699 * @param ind: Industry
2700 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2701 * @param *c_produces: Pointer to boolean for production of cargo
2702 * @return: \c *c_accepts is set when industry accepts the cargo type,
2703 * \c *c_produces is set when the industry produces the cargo type
2705 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2707 if (!IsValidCargoID(cargo)) return;
2709 /* Check for acceptance of cargo */
2710 if (ind->IsCargoAccepted(cargo) && !IndustryTemporarilyRefusesCargo(ind, cargo)) *c_accepts = true;
2712 /* Check for produced cargo */
2713 if (ind->IsCargoProduced(cargo)) *c_produces = true;
2717 * Compute who can service the industry.
2719 * Here, 'can service' means that they have trains and stations close enough
2720 * to the industry with the right cargo type and the right orders (ie has the
2721 * technical means).
2723 * @param ind: Industry being investigated.
2725 * @return: 0 if nobody can service the industry, 2 if the local company can
2726 * service the industry, and 1 otherwise (only competitors can service the
2727 * industry)
2729 int WhoCanServiceIndustry(Industry *ind)
2731 if (ind->stations_near.empty()) return 0; // No stations found at all => nobody services
2733 int result = 0;
2734 for (const Vehicle *v : Vehicle::Iterate()) {
2735 /* Is it worthwhile to try this vehicle? */
2736 if (v->owner != _local_company && result != 0) continue;
2738 /* Check whether it accepts the right kind of cargo */
2739 bool c_accepts = false;
2740 bool c_produces = false;
2741 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2742 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
2743 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2745 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2746 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2747 } else {
2748 continue;
2750 if (!c_accepts && !c_produces) continue; // Wrong cargo
2752 /* Check orders of the vehicle.
2753 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2754 * may have a different cargo type.
2756 for (const Order *o : v->Orders()) {
2757 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2758 /* Vehicle visits a station to load or unload */
2759 Station *st = Station::Get(o->GetDestination());
2760 assert(st != nullptr);
2762 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2763 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2765 if (ind->stations_near.find(st) != ind->stations_near.end()) {
2766 if (v->owner == _local_company) return 2; // Company services industry
2767 result = 1; // Competitor services industry
2772 return result;
2776 * Report news that industry production has changed significantly
2778 * @param ind: Industry with changed production
2779 * @param type: Cargo type that has changed
2780 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
2782 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2784 NewsType nt;
2786 switch (WhoCanServiceIndustry(ind)) {
2787 case 0: nt = NT_INDUSTRY_NOBODY; break;
2788 case 1: nt = NT_INDUSTRY_OTHER; break;
2789 case 2: nt = NT_INDUSTRY_COMPANY; break;
2790 default: NOT_REACHED();
2792 SetDParam(2, abs(percent));
2793 SetDParam(0, CargoSpec::Get(type)->name);
2794 SetDParam(1, ind->index);
2795 AddIndustryNewsItem(
2796 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2798 ind->index
2802 static const uint PERCENT_TRANSPORTED_60 = 153;
2803 static const uint PERCENT_TRANSPORTED_80 = 204;
2806 * Change industry production or do closure
2807 * @param i Industry for which changes are performed
2808 * @param monthly true if it's the monthly call, false if it's the random call
2810 static void ChangeIndustryProduction(Industry *i, bool monthly)
2812 StringID str = STR_NULL;
2813 bool closeit = false;
2814 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2815 bool standard = false;
2816 bool suppress_message = false;
2817 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2818 /* use original economy for industries using production related callbacks */
2819 bool original_economy = indspec->UsesOriginalEconomy();
2820 uint8_t div = 0;
2821 uint8_t mul = 0;
2822 int8_t increment = 0;
2824 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2825 if (callback_enabled) {
2826 uint16_t res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2827 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2828 suppress_message = HasBit(res, 7);
2829 /* Get the custom message if any */
2830 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2831 res = GB(res, 0, 4);
2832 switch (res) {
2833 default: NOT_REACHED();
2834 case 0x0: break; // Do nothing, but show the custom message if any
2835 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2836 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2837 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2838 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2839 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2840 case 0x8: div = res - 0x3; break; // Divide production by 32
2841 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2842 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2843 case 0xD: // decrement production
2844 case 0xE: // increment production
2845 increment = res == 0x0D ? -1 : 1;
2846 break;
2847 case 0xF: // Set production to third byte of register 0x100
2848 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2849 recalculate_multipliers = true;
2850 break;
2853 } else {
2854 if (monthly == original_economy) return;
2855 if (!original_economy && _settings_game.economy.type == ET_FROZEN) return;
2856 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2859 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2860 /* decrease or increase */
2861 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2863 if (original_economy) {
2864 if (only_decrease || Chance16(1, 3)) {
2865 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2866 if (!only_decrease && (i->GetProduced(0).history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2867 mul = 1; // Increase production
2868 } else {
2869 div = 1; // Decrease production
2872 } else if (_settings_game.economy.type == ET_SMOOTH) {
2873 closeit = !(i->ctlflags & (INDCTL_NO_CLOSURE | INDCTL_NO_PRODUCTION_DECREASE));
2874 for (auto &p : i->produced) {
2875 if (!IsValidCargoID(p.cargo)) continue;
2876 uint32_t r = Random();
2877 int old_prod, new_prod, percent;
2878 /* If over 60% is transported, mult is 1, else mult is -1. */
2879 int mult = (p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) ? 1 : -1;
2881 new_prod = old_prod = p.rate;
2883 /* For industries with only_decrease flags (temperate terrain Oil Wells),
2884 * the multiplier will always be -1 so they will only decrease. */
2885 if (only_decrease) {
2886 mult = -1;
2887 /* For normal industries, if over 60% is transported, 33% chance for decrease.
2888 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2889 } else if (Chance16I(1, ((p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2890 mult *= -1;
2893 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2894 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2895 if (Chance16I(1, 22, r >> 16)) {
2896 new_prod += mult * (std::max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2899 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2900 new_prod = Clamp(new_prod, 1, 255);
2901 if (IsValidCargoID(p.cargo) && p.cargo == GetCargoIDByLabel(CT_PASSENGERS) && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
2902 new_prod = Clamp(new_prod, 0, 16);
2905 /* If override flags are set, prevent actually changing production if any was decided on */
2906 if ((i->ctlflags & INDCTL_NO_PRODUCTION_DECREASE) && new_prod < old_prod) continue;
2907 if ((i->ctlflags & INDCTL_NO_PRODUCTION_INCREASE) && new_prod > old_prod) continue;
2909 /* Do not stop closing the industry when it has the lowest possible production rate */
2910 if (new_prod == old_prod && old_prod > 1) {
2911 closeit = false;
2912 continue;
2915 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2916 p.rate = new_prod;
2918 /* Close the industry when it has the lowest possible production rate */
2919 if (new_prod > 1) closeit = false;
2921 if (abs(percent) >= 10) {
2922 ReportNewsProductionChangeIndustry(i, p.cargo, percent);
2928 /* If override flags are set, prevent actually changing production if any was decided on */
2929 if ((i->ctlflags & INDCTL_NO_PRODUCTION_DECREASE) && (div > 0 || increment < 0)) return;
2930 if ((i->ctlflags & INDCTL_NO_PRODUCTION_INCREASE) && (mul > 0 || increment > 0)) return;
2931 if (i->ctlflags & INDCTL_EXTERNAL_PROD_LEVEL) {
2932 div = 0;
2933 mul = 0;
2934 increment = 0;
2937 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2938 if (TimerGameEconomy::year - i->last_prod_year >= PROCESSING_INDUSTRY_ABANDONMENT_YEARS && Chance16(1, original_economy ? 2 : 180)) {
2939 closeit = true;
2943 /* Increase if needed */
2944 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2945 i->prod_level = std::min<int>(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2946 recalculate_multipliers = true;
2947 if (str == STR_NULL) str = indspec->production_up_text;
2950 /* Decrease if needed */
2951 while (div-- != 0 && !closeit) {
2952 if (i->prod_level == PRODLEVEL_MINIMUM) {
2953 closeit = true;
2954 break;
2955 } else {
2956 i->prod_level = std::max<int>(i->prod_level / 2, PRODLEVEL_MINIMUM);
2957 recalculate_multipliers = true;
2958 if (str == STR_NULL) str = indspec->production_down_text;
2962 /* Increase or Decreasing the production level if needed */
2963 if (increment != 0) {
2964 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2965 closeit = true;
2966 } else {
2967 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2968 recalculate_multipliers = true;
2972 /* Recalculate production_rate
2973 * For non-smooth economy these should always be synchronized with prod_level */
2974 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2976 /* Close if needed and allowed */
2977 if (closeit && !CheckIndustryCloseDownProtection(i->type) && !(i->ctlflags & INDCTL_NO_CLOSURE)) {
2978 i->prod_level = PRODLEVEL_CLOSURE;
2979 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2980 str = indspec->closure_text;
2983 if (!suppress_message && str != STR_NULL) {
2984 NewsType nt;
2985 /* Compute news category */
2986 if (closeit) {
2987 nt = NT_INDUSTRY_CLOSE;
2988 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2989 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2990 } else {
2991 switch (WhoCanServiceIndustry(i)) {
2992 case 0: nt = NT_INDUSTRY_NOBODY; break;
2993 case 1: nt = NT_INDUSTRY_OTHER; break;
2994 case 2: nt = NT_INDUSTRY_COMPANY; break;
2995 default: NOT_REACHED();
2998 /* Set parameters of news string */
2999 if (str > STR_LAST_STRINGID) {
3000 SetDParam(0, STR_TOWN_NAME);
3001 SetDParam(1, i->town->index);
3002 SetDParam(2, indspec->name);
3003 } else if (closeit) {
3004 SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
3005 SetDParam(1, i->town->index);
3006 SetDParam(2, indspec->name);
3007 } else {
3008 SetDParam(0, i->index);
3010 /* and report the news to the user */
3011 if (closeit) {
3012 AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
3013 } else {
3014 AddIndustryNewsItem(str, nt, i->index);
3020 * Every economy day handler for the industry changes
3021 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
3022 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
3023 * For small maps, it implies that less than one change per month is required, while on bigger maps,
3024 * it would be way more. The daily loop handles those changes.
3026 static IntervalTimer<TimerGameEconomy> _economy_industries_daily({TimerGameEconomy::DAY, TimerGameEconomy::Priority::INDUSTRY}, [](auto)
3028 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
3030 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
3031 * the lower 16 bit are a fractional part that might accumulate over several days until it
3032 * is sufficient for an industry. */
3033 uint16_t change_loop = _economy.industry_daily_change_counter >> 16;
3035 /* Reset the active part of the counter, just keeping the "fractional part" */
3036 _economy.industry_daily_change_counter &= 0xFFFF;
3038 if (change_loop == 0) {
3039 return; // Nothing to do? get out
3042 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
3044 /* perform the required industry changes for the day */
3046 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
3047 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
3048 perc = std::min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
3050 for (uint16_t j = 0; j < change_loop; j++) {
3051 if (Chance16(perc, 100)) {
3052 _industry_builder.TryBuildNewIndustry();
3053 } else {
3054 Industry *i = Industry::GetRandom();
3055 if (i != nullptr) {
3056 ChangeIndustryProduction(i, false);
3057 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3062 cur_company.Restore();
3064 /* production-change */
3065 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
3068 static IntervalTimer<TimerGameEconomy> _economy_industries_monthly({TimerGameEconomy::MONTH, TimerGameEconomy::Priority::INDUSTRY}, [](auto)
3070 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
3072 _industry_builder.EconomyMonthlyLoop();
3074 for (Industry *i : Industry::Iterate()) {
3075 UpdateIndustryStatistics(i);
3076 if (i->prod_level == PRODLEVEL_CLOSURE) {
3077 delete i;
3078 } else {
3079 ChangeIndustryProduction(i, true);
3080 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3084 cur_company.Restore();
3086 /* production-change */
3087 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
3091 void InitializeIndustries()
3093 Industry::ResetIndustryCounts();
3094 _industry_sound_tile = 0;
3096 _industry_builder.Reset();
3099 /** Verify whether the generated industries are complete, and warn the user if not. */
3100 void CheckIndustries()
3102 int count = 0;
3103 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
3104 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
3106 bool force_at_least_one;
3107 uint32_t chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
3108 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
3110 const IndustrySpec *is = GetIndustrySpec(it);
3111 SetDParam(0, is->name);
3112 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
3114 count++;
3115 if (count >= 3) break; // Don't swamp the user with errors.
3120 * Is an industry with the spec a raw industry?
3121 * @return true if it should be handled as a raw industry
3123 bool IndustrySpec::IsRawIndustry() const
3125 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
3129 * Is an industry with the spec a processing industry?
3130 * @return true if it should be handled as a processing industry
3132 bool IndustrySpec::IsProcessingIndustry() const
3134 /* Lumber mills are neither raw nor processing */
3135 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
3136 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
3140 * Get the cost for constructing this industry
3141 * @return the cost (inflation corrected etc)
3143 Money IndustrySpec::GetConstructionCost() const
3145 /* Building raw industries like secondary uses different price base */
3146 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
3147 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
3151 * Get the cost for removing this industry
3152 * Take note that the cost will always be zero for non-grf industries.
3153 * Only if the grf author did specified a cost will it be applicable.
3154 * @return the cost (inflation corrected etc)
3156 Money IndustrySpec::GetRemovalCost() const
3158 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
3162 * Determines whether this industrytype uses standard/newgrf production changes.
3163 * @return true if original economy is used.
3165 bool IndustrySpec::UsesOriginalEconomy() const
3167 return _settings_game.economy.type == ET_ORIGINAL ||
3168 HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || // production callbacks
3169 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
3172 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
3174 if (AutoslopeEnabled()) {
3175 /* We imitate here TTDP's behaviour:
3176 * - Both new and old slope must not be steep.
3177 * - TileMaxZ must not be changed.
3178 * - Allow autoslope by default.
3179 * - Disallow autoslope if callback succeeds and returns non-zero.
3181 Slope tileh_old = GetTileSlope(tile);
3182 /* TileMaxZ must not be changed. Slopes must not be steep. */
3183 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
3184 const IndustryGfx gfx = GetIndustryGfx(tile);
3185 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
3187 /* Call callback 3C 'disable autosloping for industry tiles'. */
3188 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
3189 /* If the callback fails, allow autoslope. */
3190 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
3191 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3192 } else {
3193 /* allow autoslope */
3194 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3198 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
3201 extern const TileTypeProcs _tile_type_industry_procs = {
3202 DrawTile_Industry, // draw_tile_proc
3203 GetSlopePixelZ_Industry, // get_slope_z_proc
3204 ClearTile_Industry, // clear_tile_proc
3205 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
3206 GetTileDesc_Industry, // get_tile_desc_proc
3207 GetTileTrackStatus_Industry, // get_tile_track_status_proc
3208 ClickTile_Industry, // click_tile_proc
3209 AnimateTile_Industry, // animate_tile_proc
3210 TileLoop_Industry, // tile_loop_proc
3211 ChangeTileOwner_Industry, // change_tile_owner_proc
3212 nullptr, // add_produced_cargo_proc
3213 nullptr, // vehicle_enter_tile_proc
3214 GetFoundation_Industry, // get_foundation_proc
3215 TerraformTile_Industry, // terraform_tile_proc
3218 bool IndustryCompare::operator() (const IndustryListEntry &lhs, const IndustryListEntry &rhs) const
3220 /* Compare by distance first and use index as a tiebreaker. */
3221 return std::tie(lhs.distance, lhs.industry->index) < std::tie(rhs.distance, rhs.industry->index);
3225 * Remove unused industry accepted/produced slots -- entries after the last slot with valid cargo.
3226 * @param ind Industry to trim slots.
3228 void TrimIndustryAcceptedProduced(Industry *ind)
3230 auto ita = std::find_if(std::rbegin(ind->accepted), std::rend(ind->accepted), [](const auto &a) { return IsValidCargoID(a.cargo); });
3231 ind->accepted.erase(ita.base(), std::end(ind->accepted));
3232 ind->accepted.shrink_to_fit();
3234 auto itp = std::find_if(std::rbegin(ind->produced), std::rend(ind->produced), [](const auto &p) { return IsValidCargoID(p.cargo); });
3235 ind->produced.erase(itp.base(), std::end(ind->produced));
3236 ind->produced.shrink_to_fit();