Fix #10490: Allow ships to exit depots if another is not moving at the exit point...
[openttd-github.git] / src / industry_cmd.cpp
blob0264e6cbd04266a588d51f1746e4481bbbf53654
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 byte _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 for (IndustryType i = 0; i < lengthof(_origin_industry_specs); i++) {
86 /* Enable only the current climate industries */
87 _industry_specs[i].enabled = HasBit(_industry_specs[i].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 < 3; 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 < 3; i++) cargo_acceptance[i] = GB(res, i * 4, 4);
454 for (byte 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 byte 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 byte 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 byte 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 byte m = GetAnimationFrame(tile);
601 if (m == 6) {
602 SetAnimationFrame(tile, 0);
603 DeleteAnimatedTile(tile);
604 } else {
605 SetAnimationFrame(tile, m + 1);
606 MarkTileDirtyByTile(tile);
610 static void AnimateToyFactory(TileIndex tile)
612 byte 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 byte 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);
652 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 byte 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 byte 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 byte 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 byte cnt = GetIndustryConstructionCounter(tile) + 1;
751 if (cnt != 4) {
752 SetIndustryConstructionCounter(tile, cnt);
753 return;
756 byte 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);
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);
910 break;
912 case GFX_POWERPLANT_SPARKS:
913 if (Chance16(1, 3)) {
914 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_POWER_STATION, tile);
915 AddAnimatedTile(tile);
917 break;
919 case GFX_COPPER_MINE_CHIMNEY:
920 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
921 break;
924 case GFX_TOY_FACTORY: {
925 Industry *i = Industry::GetByTile(tile);
926 if (i->was_cargo_delivered) {
927 i->was_cargo_delivered = false;
928 SetIndustryAnimationLoop(tile, 0);
929 AddAnimatedTile(tile);
932 break;
934 case GFX_BUBBLE_GENERATOR:
935 TileLoopIndustry_BubbleGenerator(tile);
936 break;
938 case GFX_TOFFEE_QUARY:
939 AddAnimatedTile(tile);
940 break;
942 case GFX_SUGAR_MINE_SIEVE:
943 if (Chance16(1, 3)) AddAnimatedTile(tile);
944 break;
948 static bool ClickTile_Industry(TileIndex tile)
950 ShowIndustryViewWindow(GetIndustryIndex(tile));
951 return true;
954 static TrackStatus GetTileTrackStatus_Industry(TileIndex, TransportType, uint, DiagDirection)
956 return 0;
959 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
961 /* If the founder merges, the industry was created by the merged company */
962 Industry *i = Industry::GetByTile(tile);
963 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
965 if (i->exclusive_supplier == old_owner) i->exclusive_supplier = new_owner;
966 if (i->exclusive_consumer == old_owner) i->exclusive_consumer = new_owner;
970 * Check whether the tile is a forest.
971 * @param tile the tile to investigate.
972 * @return true if and only if the tile is a forest
974 bool IsTileForestIndustry(TileIndex tile)
976 /* Check for industry tile */
977 if (!IsTileType(tile, MP_INDUSTRY)) return false;
979 const Industry *ind = Industry::GetByTile(tile);
981 /* Check for organic industry (i.e. not processing or extractive) */
982 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
984 /* Check for wood production */
985 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; });
988 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
991 * Check whether the tile can be replaced by a farm field.
992 * @param tile the tile to investigate.
993 * @param allow_fields if true, the method will return true even if
994 * the tile is a farm tile, otherwise the tile may not be a farm tile
995 * @return true if the tile can become a farm field
997 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
999 switch (GetTileType(tile)) {
1000 case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
1001 case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
1002 default: return false;
1007 * Build farm field fence
1008 * @param tile the tile to position the fence on
1009 * @param size the size of the field being planted in tiles
1010 * @param type type of fence to set
1011 * @param side the side of the tile to attempt placement
1013 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
1015 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
1016 TileIndexDiff neighbour_diff = TileOffsByDiagDir(side);
1018 do {
1019 tile = Map::WrapToMap(tile);
1021 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
1022 TileIndex neighbour = tile + neighbour_diff;
1023 if (!IsTileType(neighbour, MP_CLEAR) || !IsClearGround(neighbour, CLEAR_FIELDS) || GetFence(neighbour, ReverseDiagDir(side)) == 0) {
1024 /* Add fence as long as neighbouring tile does not already have a fence in the same position. */
1025 byte or_ = type;
1027 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
1029 SetFence(tile, side, or_);
1033 tile += diff;
1034 } while (--size);
1037 static void PlantFarmField(TileIndex tile, IndustryID industry)
1039 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1040 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1043 /* determine field size */
1044 uint32_t r = (Random() & 0x303) + 0x404;
1045 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1046 uint size_x = GB(r, 0, 8);
1047 uint size_y = GB(r, 8, 8);
1049 TileArea ta(tile - TileDiffXY(std::min(TileX(tile), size_x / 2), std::min(TileY(tile), size_y / 2)), size_x, size_y);
1050 ta.ClampToMap();
1052 if (ta.w == 0 || ta.h == 0) return;
1054 /* check the amount of bad tiles */
1055 int count = 0;
1056 for (TileIndex cur_tile : ta) {
1057 assert(cur_tile < Map::Size());
1058 count += IsSuitableForFarmField(cur_tile, false);
1060 if (count * 2 < ta.w * ta.h) return;
1062 /* determine type of field */
1063 r = Random();
1064 uint counter = GB(r, 5, 3);
1065 uint field_type = GB(r, 8, 8) * 9 >> 8;
1067 /* make field */
1068 for (TileIndex cur_tile : ta) {
1069 assert(cur_tile < Map::Size());
1070 if (IsSuitableForFarmField(cur_tile, true)) {
1071 MakeField(cur_tile, field_type, industry);
1072 SetClearCounter(cur_tile, counter);
1073 MarkTileDirtyByTile(cur_tile);
1077 int type = 3;
1078 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1079 type = _plantfarmfield_type[Random() & 0xF];
1082 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1083 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1084 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1085 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1088 void PlantRandomFarmField(const Industry *i)
1090 int x = i->location.w / 2 + Random() % 31 - 16;
1091 int y = i->location.h / 2 + Random() % 31 - 16;
1093 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1095 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1099 * Search callback function for ChopLumberMillTrees
1100 * @param tile to test
1101 * @return the result of the test
1103 static bool SearchLumberMillTrees(TileIndex tile, void *)
1105 if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1106 /* found a tree */
1108 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1110 _industry_sound_ctr = 1;
1111 _industry_sound_tile = tile;
1112 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_LUMBER_MILL_1, tile);
1114 Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC, tile);
1116 cur_company.Restore();
1117 return true;
1119 return false;
1123 * Perform a circular search around the Lumber Mill in order to find trees to cut
1124 * @param i industry
1126 static void ChopLumberMillTrees(Industry *i)
1128 /* Skip production if cargo slot is invalid. */
1129 if (!IsValidCargoID(i->produced[0].cargo)) return;
1131 /* We only want to cut trees if all tiles are completed. */
1132 for (TileIndex tile_cur : i->location) {
1133 if (i->TileBelongsToIndustry(tile_cur)) {
1134 if (!IsIndustryCompleted(tile_cur)) return;
1138 TileIndex tile = i->location.tile;
1139 if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, nullptr)) { // 40x40 tiles to search.
1140 i->produced[0].waiting = ClampTo<uint16_t>(i->produced[0].waiting + ScaleByCargoScale(45, false)); // Found a tree, add according value to waiting cargo.
1145 * Helper for ProduceIndustryGoods that scales and produces cargos.
1146 * @param i The industry
1147 * @param scale Should we scale production of this cargo directly?
1149 static void ProduceIndustryGoodsHelper(Industry *i, bool scale)
1151 for (auto &p : i->produced) {
1152 if (!IsValidCargoID(p.cargo)) continue;
1154 uint16_t amount = p.rate;
1155 if (scale) amount = ScaleByCargoScale(amount, false);
1157 p.waiting = ClampTo<uint16_t>(p.waiting + amount);
1161 static void ProduceIndustryGoods(Industry *i)
1163 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1165 /* play a sound? */
1166 if ((i->counter & 0x3F) == 0) {
1167 uint32_t r;
1168 if (Chance16R(1, 14, r) && indsp->number_of_sounds != 0 && _settings_client.sound.ambient) {
1169 if (std::any_of(std::begin(i->produced), std::end(i->produced), [](const auto &p) { return p.history[LAST_MONTH].production > 0; })) {
1170 /* Play sound since last month had production */
1171 SndPlayTileFx(
1172 (SoundFx)(indsp->random_sounds[((r >> 16) * indsp->number_of_sounds) >> 16]),
1173 i->location.tile);
1178 i->counter--;
1180 /* If using an industry callback, scale the callback interval by cargo scale percentage. */
1181 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
1182 if (i->counter % ScaleByInverseCargoScale(Ticks::INDUSTRY_PRODUCE_TICKS, false) == 0) {
1183 IndustryProductionCallback(i, 1);
1184 ProduceIndustryGoodsHelper(i, false);
1189 * All other production and special effects happen every 256 ticks, and cargo production is just scaled by the cargo scale percentage.
1190 * 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.
1192 if ((i->counter % Ticks::INDUSTRY_PRODUCE_TICKS) == 0) {
1193 /* Handle non-callback cargo production. */
1194 if (!HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) ProduceIndustryGoodsHelper(i, true);
1196 IndustryBehaviour indbehav = indsp->behaviour;
1198 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1199 uint16_t cb_res = CALLBACK_FAILED;
1200 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1201 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1204 bool plant;
1205 if (cb_res != CALLBACK_FAILED) {
1206 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1207 } else {
1208 plant = Chance16(1, 8);
1211 if (plant) PlantRandomFarmField(i);
1213 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1214 uint16_t cb_res = CALLBACK_FAILED;
1215 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1216 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1219 bool cut;
1220 if (cb_res != CALLBACK_FAILED) {
1221 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1222 } else {
1223 cut = ((i->counter % Ticks::INDUSTRY_CUT_TREE_TICKS) == 0);
1226 if (cut) ChopLumberMillTrees(i);
1229 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1230 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1234 void OnTick_Industry()
1236 if (_industry_sound_ctr != 0) {
1237 _industry_sound_ctr++;
1239 if (_industry_sound_ctr == 75) {
1240 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_LUMBER_MILL_2, _industry_sound_tile);
1241 } else if (_industry_sound_ctr == 160) {
1242 _industry_sound_ctr = 0;
1243 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_LUMBER_MILL_3, _industry_sound_tile);
1247 if (_game_mode == GM_EDITOR) return;
1249 for (Industry *i : Industry::Iterate()) {
1250 ProduceIndustryGoods(i);
1255 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1256 * @return Succeeded or failed command.
1258 static CommandCost CheckNewIndustry_NULL(TileIndex)
1260 return CommandCost();
1264 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1265 * @param tile %Tile to perform the checking.
1266 * @return Succeeded or failed command.
1268 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1270 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1271 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1272 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1275 return CommandCost();
1279 * Check if a tile is within a distance from map edges, scaled by map dimensions independently.
1280 * Each dimension is checked independently, and dimensions smaller than 256 are not scaled.
1281 * @param tile Which tile to check distance of.
1282 * @param maxdist Normal distance on a 256x256 map.
1283 * @return True if the tile is near the map edge.
1285 static bool CheckScaledDistanceFromEdge(TileIndex tile, uint maxdist)
1287 uint maxdist_x = maxdist;
1288 uint maxdist_y = maxdist;
1290 if (Map::SizeX() > 256) maxdist_x *= Map::SizeX() / 256;
1291 if (Map::SizeY() > 256) maxdist_y *= Map::SizeY() / 256;
1293 if (DistanceFromEdgeDir(tile, DIAGDIR_NE) < maxdist_x) return true;
1294 if (DistanceFromEdgeDir(tile, DIAGDIR_NW) < maxdist_y) return true;
1295 if (DistanceFromEdgeDir(tile, DIAGDIR_SW) < maxdist_x) return true;
1296 if (DistanceFromEdgeDir(tile, DIAGDIR_SE) < maxdist_y) return true;
1298 return false;
1302 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1303 * @param tile %Tile to perform the checking.
1304 * @return Succeeded or failed command.
1306 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1308 if (_game_mode == GM_EDITOR) return CommandCost();
1310 if (CheckScaledDistanceFromEdge(TILE_ADDXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1312 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1315 extern bool _ignore_restrictions;
1318 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1319 * @param tile %Tile to perform the checking.
1320 * @return Succeeded or failed command.
1322 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1324 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1326 if (TileHeight(tile) == 0 &&
1327 CheckScaledDistanceFromEdge(TILE_ADDXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1329 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1333 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1334 * @param tile %Tile to perform the checking.
1335 * @return Succeeded or failed command.
1337 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1339 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1340 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1341 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1344 return CommandCost();
1348 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1349 * @param tile %Tile to perform the checking.
1350 * @return Succeeded or failed command.
1352 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1354 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1355 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1357 return CommandCost();
1361 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1362 * @param tile %Tile to perform the checking.
1363 * @return Succeeded or failed command.
1365 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1367 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1368 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1370 return CommandCost();
1374 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1375 * @param tile %Tile to perform the checking.
1376 * @return Succeeded or failed command.
1378 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1380 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1381 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1383 return CommandCost();
1387 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1388 * @param tile %Tile to perform the checking.
1389 * @return Succeeded or failed command.
1391 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1393 if (GetTileZ(tile) > 4) {
1394 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1396 return CommandCost();
1400 * Industrytype check function signature.
1401 * @param tile %Tile to check.
1402 * @return Succeeded or failed command.
1404 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1406 /** Check functions for different types of industry. */
1407 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1408 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1409 CheckNewIndustry_Forest, ///< CHECK_FOREST
1410 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1411 CheckNewIndustry_Farm, ///< CHECK_FARM
1412 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1413 CheckNewIndustry_Water, ///< CHECK_WATER
1414 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1415 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1416 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1420 * Find a town for the industry, while checking for multiple industries in the same town.
1421 * @param tile Position of the industry to build.
1422 * @param type Industry type.
1423 * @param[out] t Pointer to return town for the new industry, \c nullptr is written if no good town can be found.
1424 * @return Succeeded or failed command.
1426 * @pre \c *t != nullptr
1427 * @post \c *t points to a town on success, and \c nullptr on failure.
1429 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1431 *t = ClosestTownFromTile(tile, UINT_MAX);
1433 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1435 for (const Industry *i : Industry::Iterate()) {
1436 if (i->type == (byte)type && i->town == *t) {
1437 *t = nullptr;
1438 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1442 return CommandCost();
1445 bool IsSlopeRefused(Slope current, Slope refused)
1447 if (IsSteepSlope(current)) return true;
1448 if (current != SLOPE_FLAT) {
1449 if (IsSteepSlope(refused)) return true;
1451 Slope t = ComplementSlope(current);
1453 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1454 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1455 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1456 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1459 return false;
1463 * Are the tiles of the industry free?
1464 * @param tile Position to check.
1465 * @param layout Industry tiles table.
1466 * @param type Type of the industry.
1467 * @return Failed or succeeded command.
1469 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, IndustryType type)
1471 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1473 for (const IndustryTileLayoutTile &it : layout) {
1474 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1475 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1477 if (!IsValidTile(cur_tile)) {
1478 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1481 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1482 if (!IsWaterTile(cur_tile) ||
1483 !IsTileFlat(cur_tile)) {
1484 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1486 } else {
1487 CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1488 if (ret.Failed()) return ret;
1489 if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1491 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1493 /* Perform land/water check if not disabled */
1494 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1496 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1497 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1498 if (!IsTileType(cur_tile, MP_HOUSE)) {
1499 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1502 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1503 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1504 ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_NONE, cur_tile);
1505 cur_company.Restore();
1507 if (ret.Failed()) return ret;
1508 } else {
1509 /* Clear the tiles, but do not affect town ratings */
1510 ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile);
1511 if (ret.Failed()) return ret;
1516 return CommandCost();
1520 * Check slope requirements for industry tiles.
1521 * @param tile Position to check.
1522 * @param layout Industry tiles table.
1523 * @param layout_index The index of the layout to build/fund
1524 * @param type Type of the industry.
1525 * @param initial_random_bits The random bits the industry is going to have after construction.
1526 * @param founder Industry founder
1527 * @param creation_type The circumstances the industry is created under.
1528 * @param[out] custom_shape_check Perform custom check for the site.
1529 * @return Failed or succeeded command.
1531 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)
1533 bool refused_slope = false;
1534 bool custom_shape = false;
1536 for (const IndustryTileLayoutTile &it : layout) {
1537 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1538 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1539 assert(IsValidTile(cur_tile)); // checked before in CheckIfIndustryTilesAreFree
1541 if (gfx != GFX_WATERTILE_SPECIALCHECK) {
1542 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1544 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1545 custom_shape = true;
1546 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
1547 if (ret.Failed()) return ret;
1548 } else {
1549 Slope tileh = GetTileSlope(cur_tile);
1550 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1555 if (custom_shape_check != nullptr) *custom_shape_check = custom_shape;
1557 /* It is almost impossible to have a fully flat land in TG, so what we
1558 * do is that we check if we can make the land flat later on. See
1559 * CheckIfCanLevelIndustryPlatform(). */
1560 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1561 return CommandCost();
1563 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1567 * Is the industry allowed to be built at this place for the town?
1568 * @param tile Tile to construct the industry.
1569 * @param type Type of the industry.
1570 * @param t Town authority that the industry belongs to.
1571 * @return Succeeded or failed command.
1573 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1575 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1576 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1579 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1580 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1583 return CommandCost();
1586 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1588 /* Check if we don't leave the map */
1589 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1591 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1592 for (TileIndex tile_walk : ta) {
1593 uint curh = TileHeight(tile_walk);
1594 /* Is the tile clear? */
1595 if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1597 /* Don't allow too big of a change if this is the sub-tile check */
1598 if (internal != 0 && Delta(curh, height) > 1) return false;
1600 /* Different height, so the surrounding tiles of this tile
1601 * has to be correct too (in level, or almost in level)
1602 * else you get a chain-reaction of terraforming. */
1603 if (internal == 0 && curh != height) {
1604 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1605 return false;
1610 return true;
1614 * This function tries to flatten out the land below an industry, without
1615 * damaging the surroundings too much.
1617 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileLayout &layout)
1619 int max_x = 0;
1620 int max_y = 0;
1622 /* Finds dimensions of largest variant of this industry */
1623 for (const IndustryTileLayoutTile &it : layout) {
1624 if (it.gfx == GFX_WATERTILE_SPECIALCHECK) continue; // watercheck tiles don't count for footprint size
1625 if (it.ti.x > max_x) max_x = it.ti.x;
1626 if (it.ti.y > max_y) max_y = it.ti.y;
1629 /* Remember level height */
1630 uint h = TileHeight(tile);
1632 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1633 /* Check that all tiles in area and surrounding are clear
1634 * this determines that there are no obstructing items */
1636 /* TileArea::Expand is not used here as we need to abort
1637 * instead of clamping if the bounds cannot expanded. */
1638 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1639 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1641 if (TileX(ta.tile) + ta.w >= Map::MaxX() || TileY(ta.tile) + ta.h >= Map::MaxY()) return false;
1643 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1644 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1645 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1647 for (TileIndex tile_walk : ta) {
1648 uint curh = TileHeight(tile_walk);
1649 if (curh != h) {
1650 /* This tile needs terraforming. Check if we can do that without
1651 * damaging the surroundings too much. */
1652 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1653 cur_company.Restore();
1654 return false;
1656 /* This is not 100% correct check, but the best we can do without modifying the map.
1657 * What is missing, is if the difference in height is more than 1.. */
1658 if (std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(flags & ~DC_EXEC, tile_walk, SLOPE_N, curh <= h)).Failed()) {
1659 cur_company.Restore();
1660 return false;
1665 if (flags & DC_EXEC) {
1666 /* Terraform the land under the industry */
1667 for (TileIndex tile_walk : ta) {
1668 uint curh = TileHeight(tile_walk);
1669 while (curh != h) {
1670 /* We give the terraforming for free here, because we can't calculate
1671 * exact cost in the test-round, and as we all know, that will cause
1672 * a nice assert if they don't match ;) */
1673 Command<CMD_TERRAFORM_LAND>::Do(flags, tile_walk, SLOPE_N, curh <= h);
1674 curh += (curh > h) ? -1 : 1;
1679 cur_company.Restore();
1680 return true;
1685 * Check that the new industry is far enough from conflicting industries.
1686 * @param tile Tile to construct the industry.
1687 * @param type Type of the new industry.
1688 * @return Succeeded or failed command.
1690 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1692 const IndustrySpec *indspec = GetIndustrySpec(type);
1694 /* On a large map with many industries, it may be faster to check an area. */
1695 static const int dmax = 14;
1696 if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
1697 const Industry *i = nullptr;
1698 TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax);
1699 for (TileIndex atile : tile_area) {
1700 if (GetTileType(atile) == MP_INDUSTRY) {
1701 const Industry *i2 = Industry::GetByTile(atile);
1702 if (i == i2) continue;
1703 i = i2;
1704 if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1705 if (i->type == indspec->conflicting[0] ||
1706 i->type == indspec->conflicting[1] ||
1707 i->type == indspec->conflicting[2]) {
1708 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1712 return CommandCost();
1715 for (const Industry *i : Industry::Iterate()) {
1716 /* Within 14 tiles from another industry is considered close */
1717 if (DistanceMax(tile, i->location.tile) > 14) continue;
1719 /* check if there are any conflicting industry types around */
1720 if (i->type == indspec->conflicting[0] ||
1721 i->type == indspec->conflicting[1] ||
1722 i->type == indspec->conflicting[2]) {
1723 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1726 return CommandCost();
1730 * Advertise about a new industry opening.
1731 * @param ind Industry being opened.
1733 static void AdvertiseIndustryOpening(const Industry *ind)
1735 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1736 SetDParam(0, ind_spc->name);
1737 if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1738 SetDParam(1, STR_TOWN_NAME);
1739 SetDParam(2, ind->town->index);
1740 } else {
1741 SetDParam(1, ind->town->index);
1743 AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1744 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1745 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1749 * Populate an industry's list of nearby stations, and if it accepts any cargo, also
1750 * add the industry to each station's nearby industry list.
1751 * @param ind Industry
1753 static void PopulateStationsNearby(Industry *ind)
1755 if (ind->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) {
1756 /* Industry has a neutral station. Use it and ignore any other nearby stations. */
1757 ind->stations_near.insert(ind->neutral_station);
1758 ind->neutral_station->industries_near.clear();
1759 ind->neutral_station->industries_near.insert(IndustryListEntry{0, ind});
1760 return;
1763 ForAllStationsAroundTiles(ind->location, [ind](Station *st, TileIndex tile) {
1764 if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) != ind->index) return false;
1765 ind->stations_near.insert(st);
1766 st->AddIndustryToDeliver(ind, tile);
1767 return false;
1772 * Put an industry on the map.
1773 * @param i Just allocated poolitem, mostly empty.
1774 * @param tile North tile of the industry.
1775 * @param type Type of the industry.
1776 * @param layout Industrylayout to build.
1777 * @param layout_index Number of the industry layout.
1778 * @param t Nearest town.
1779 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1780 * @param initial_random_bits Random bits for the industry.
1782 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)
1784 const IndustrySpec *indspec = GetIndustrySpec(type);
1786 i->location = TileArea(tile, 1, 1);
1787 i->type = type;
1788 Industry::IncIndustryTypeCount(type);
1790 for (auto it = std::begin(i->produced); it != std::end(i->produced); ++it) {
1791 size_t index = it - std::begin(i->produced);
1792 it->cargo = indspec->produced_cargo[index];
1793 it->rate = indspec->production_rate[index];
1796 for (auto it = std::begin(i->accepted); it != std::end(i->accepted); ++it) {
1797 size_t index = it - std::begin(i->accepted);
1798 it->cargo = indspec->accepts_cargo[index];
1801 /* Randomize inital production if non-original economy is used and there are no production related callbacks. */
1802 if (!indspec->UsesOriginalEconomy()) {
1803 for (auto &p : i->produced) {
1804 p.rate = ClampTo<byte>((RandomRange(256) + 128) * p.rate >> 8);
1808 i->town = t;
1809 i->owner = OWNER_NONE;
1811 uint16_t r = Random();
1812 i->random_colour = static_cast<Colours>(GB(r, 0, 4));
1813 i->counter = GB(r, 4, 12);
1814 i->random = initial_random_bits;
1815 i->was_cargo_delivered = false;
1816 i->last_prod_year = TimerGameEconomy::year;
1817 i->founder = founder;
1818 i->ctlflags = INDCTL_NONE;
1820 i->construction_date = TimerGameCalendar::date;
1821 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1822 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1824 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1825 * 0 = created prior of newindustries
1826 * else, chosen layout + 1 */
1827 i->selected_layout = (byte)(layout_index + 1);
1829 i->exclusive_supplier = INVALID_OWNER;
1830 i->exclusive_consumer = INVALID_OWNER;
1832 i->prod_level = PRODLEVEL_DEFAULT;
1834 /* Call callbacks after the regular fields got initialised. */
1836 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1837 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1838 if (res != CALLBACK_FAILED) {
1839 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1840 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1841 } else {
1842 i->prod_level = res;
1843 i->RecomputeProductionMultipliers();
1848 if (_generating_world) {
1849 if (HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) {
1850 IndustryProductionCallback(i, 1);
1851 for (auto &p : i->produced) {
1852 p.history[LAST_MONTH].production = p.waiting * 8;
1853 p.waiting = 0;
1857 for (auto &p : i->produced) {
1858 p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
1862 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1863 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1864 if (res != CALLBACK_FAILED) {
1865 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1866 i->random_colour = static_cast<Colours>(GB(res, 0, 4));
1870 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1871 /* Clear all input cargo types */
1872 for (auto &a : i->accepted) a.cargo = INVALID_CARGO;
1873 /* Query actual types */
1874 uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? static_cast<uint>(i->accepted.size()) : 3;
1875 for (uint j = 0; j < maxcargoes; j++) {
1876 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1877 if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
1878 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1879 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1880 break;
1882 CargoID cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1883 /* Industries without "unlimited" cargo types support depend on the specific order/slots of cargo types.
1884 * They need to be able to blank out specific slots without aborting the callback sequence,
1885 * and solve this by returning undefined cargo indexes. Skip these. */
1886 if (!IsValidCargoID(cargo) && !(indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED)) continue;
1887 /* Verify valid cargo */
1888 if (std::find(indspec->accepts_cargo, endof(indspec->accepts_cargo), cargo) == endof(indspec->accepts_cargo)) {
1889 /* Cargo not in spec, error in NewGRF */
1890 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1891 break;
1893 if (std::any_of(std::begin(i->accepted), std::begin(i->accepted) + j, [&cargo](const auto &a) { return a.cargo == cargo; })) {
1894 /* Duplicate cargo */
1895 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1896 break;
1898 i->accepted[j].cargo = cargo;
1902 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1903 /* Clear all output cargo types */
1904 for (auto &p : i->produced) p.cargo = INVALID_CARGO;
1905 /* Query actual types */
1906 uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? static_cast<uint>(i->produced.size()) : 2;
1907 for (uint j = 0; j < maxcargoes; j++) {
1908 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1909 if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
1910 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1911 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1912 break;
1914 CargoID cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1915 /* Allow older GRFs to skip slots. */
1916 if (!IsValidCargoID(cargo) && !(indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED)) continue;
1917 /* Verify valid cargo */
1918 if (std::find(indspec->produced_cargo, endof(indspec->produced_cargo), cargo) == endof(indspec->produced_cargo)) {
1919 /* Cargo not in spec, error in NewGRF */
1920 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1921 break;
1923 if (std::any_of(std::begin(i->produced), std::begin(i->produced) + j, [&cargo](const auto &p) { return p.cargo == cargo; })) {
1924 /* Duplicate cargo */
1925 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1926 break;
1928 i->produced[j].cargo = cargo;
1932 /* Plant the tiles */
1934 for (const IndustryTileLayoutTile &it : layout) {
1935 TileIndex cur_tile = tile + ToTileIndexDiff(it.ti);
1937 if (it.gfx != GFX_WATERTILE_SPECIALCHECK) {
1938 i->location.Add(cur_tile);
1940 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1942 Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile);
1944 MakeIndustry(cur_tile, i->index, it.gfx, Random(), wc);
1946 if (_generating_world) {
1947 SetIndustryConstructionCounter(cur_tile, 3);
1948 SetIndustryConstructionStage(cur_tile, 2);
1951 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1952 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it.gfx);
1953 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1954 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1958 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1959 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1961 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_FORCE_REBUILD);
1962 SetWindowDirty(WC_BUILD_INDUSTRY, 0);
1964 if (!_generating_world) PopulateStationsNearby(i);
1968 * Helper function for Build/Fund an industry
1969 * @param tile tile where industry is built
1970 * @param type of industry to build
1971 * @param flags of operations to conduct
1972 * @param indspec pointer to industry specifications
1973 * @param layout_index the index of the itsepc to build/fund
1974 * @param random_var8f random seed (possibly) used by industries
1975 * @param random_initial_bits The random bits the industry is going to have after construction.
1976 * @param founder Founder of the industry
1977 * @param creation_type The circumstances the industry is created under.
1978 * @param[out] ip Pointer to store newly created industry.
1979 * @return Succeeded or failed command.
1981 * @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.
1983 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)
1985 assert(layout_index < indspec->layouts.size());
1986 const IndustryTileLayout &layout = indspec->layouts[layout_index];
1988 *ip = nullptr;
1990 /* 1. Cheap: Built-in checks on industry level. */
1991 CommandCost ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1992 if (ret.Failed()) return ret;
1994 Town *t = nullptr;
1995 ret = FindTownForIndustry(tile, type, &t);
1996 if (ret.Failed()) return ret;
1997 assert(t != nullptr);
1999 ret = CheckIfIndustryIsAllowed(tile, type, t);
2000 if (ret.Failed()) return ret;
2002 /* 2. Built-in checks on industry tiles. */
2003 std::vector<ClearedObjectArea> object_areas(_cleared_object_areas);
2004 ret = CheckIfIndustryTilesAreFree(tile, layout, type);
2005 _cleared_object_areas = object_areas;
2006 if (ret.Failed()) return ret;
2008 /* 3. NewGRF-defined checks on industry level. */
2009 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
2010 ret = CheckIfCallBackAllowsCreation(tile, type, layout_index, random_var8f, random_initial_bits, founder, creation_type);
2011 } else {
2012 ret = _check_new_industry_procs[indspec->check_proc](tile);
2014 if (ret.Failed()) return ret;
2016 /* 4. Expensive: NewGRF-defined checks on industry tiles. */
2017 bool custom_shape_check = false;
2018 ret = CheckIfIndustryTileSlopes(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
2019 if (ret.Failed()) return ret;
2021 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
2022 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, layout)) {
2023 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
2026 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
2028 if (flags & DC_EXEC) {
2029 *ip = new Industry(tile);
2030 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, layout);
2031 DoCreateNewIndustry(*ip, tile, type, layout, layout_index, t, founder, random_initial_bits);
2034 return CommandCost();
2038 * Build/Fund an industry
2039 * @param flags of operations to conduct
2040 * @param tile tile where industry is built
2041 * @param it industry type see build_industry.h and see industry.h
2042 * @param first_layout first layout to try
2043 * @param fund false = prospect, true = fund (only valid if current company is DEITY)
2044 * @param seed seed to use for desyncfree randomisations
2045 * @return the cost of this operation or an error
2047 CommandCost CmdBuildIndustry(DoCommandFlag flags, TileIndex tile, IndustryType it, uint32_t first_layout, bool fund, uint32_t seed)
2049 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
2051 const IndustrySpec *indspec = GetIndustrySpec(it);
2053 /* Check if the to-be built/founded industry is available for this climate. */
2054 if (!indspec->enabled || indspec->layouts.empty()) return CMD_ERROR;
2056 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
2057 * Raw material industries are industries that do not accept cargo (at least for now) */
2058 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
2059 return CMD_ERROR;
2062 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
2063 return CMD_ERROR;
2066 Randomizer randomizer;
2067 randomizer.SetSeed(seed);
2068 uint16_t random_initial_bits = GB(seed, 0, 16);
2069 uint32_t random_var8f = randomizer.Next();
2070 size_t num_layouts = indspec->layouts.size();
2071 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
2072 const bool deity_prospect = _current_company == OWNER_DEITY && !fund;
2074 Industry *ind = nullptr;
2075 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
2076 if (flags & DC_EXEC) {
2077 /* Prospecting has a chance to fail, however we cannot guarantee that something can
2078 * be built on the map, so the chance gets lower when the map is fuller, but there
2079 * is nothing we can really do about that. */
2080 bool prospect_success = deity_prospect || Random() <= indspec->prospecting_chance;
2081 if (prospect_success) {
2082 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
2083 IndustryAvailabilityCallType calltype = _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION;
2084 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
2085 for (int i = 0; i < 5000; i++) {
2086 /* We should not have more than one Random() in a function call
2087 * because parameter evaluation order is not guaranteed in the c++ standard
2089 tile = RandomTile();
2090 /* Start with a random layout */
2091 size_t layout = RandomRange((uint32_t)num_layouts);
2092 /* Check now each layout, starting with the random one */
2093 for (size_t j = 0; j < num_layouts; j++) {
2094 layout = (layout + 1) % num_layouts;
2095 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), calltype, &ind);
2096 if (ret.Succeeded()) break;
2098 if (ret.Succeeded()) break;
2100 cur_company.Restore();
2102 if (ret.Failed() && IsLocalCompany()) {
2103 if (prospect_success) {
2104 ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING, WL_INFO);
2105 } else {
2106 ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_PROSPECTING_WAS_UNLUCKY, WL_INFO);
2110 } else {
2111 size_t layout = first_layout;
2112 if (layout >= num_layouts) return CMD_ERROR;
2114 /* Check subsequently each layout, starting with the given layout in p1 */
2115 for (size_t i = 0; i < num_layouts; i++) {
2116 layout = (layout + 1) % num_layouts;
2117 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
2118 if (ret.Succeeded()) break;
2121 /* If it still failed, there's no suitable layout to build here, return the error */
2122 if (ret.Failed()) return ret;
2125 if ((flags & DC_EXEC) && ind != nullptr && _game_mode != GM_EDITOR) {
2126 AdvertiseIndustryOpening(ind);
2129 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
2133 * Set industry control flags.
2134 * @param flags Type of operation.
2135 * @param ind_id IndustryID
2136 * @param ctlflags IndustryControlFlags
2137 * @return Empty cost or an error.
2139 CommandCost CmdIndustrySetFlags(DoCommandFlag flags, IndustryID ind_id, IndustryControlFlags ctlflags)
2141 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2143 Industry *ind = Industry::GetIfValid(ind_id);
2144 if (ind == nullptr) return CMD_ERROR;
2146 if (flags & DC_EXEC) ind->ctlflags = ctlflags & INDCTL_MASK;
2148 return CommandCost();
2152 * Set industry production.
2153 * @param flags Type of operation.
2154 * @param ind_id IndustryID
2155 * @param prod_level Production level.
2156 * @param show_news Show a news message on production change.
2157 * @param custom_news Custom news message text.
2158 * @return Empty cost or an error.
2160 CommandCost CmdIndustrySetProduction(DoCommandFlag flags, IndustryID ind_id, byte prod_level, bool show_news, const std::string &custom_news)
2162 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2163 if (prod_level < PRODLEVEL_MINIMUM || prod_level > PRODLEVEL_MAXIMUM) return CMD_ERROR;
2165 Industry *ind = Industry::GetIfValid(ind_id);
2166 if (ind == nullptr) return CMD_ERROR;
2168 if (flags & DC_EXEC) {
2169 StringID str = STR_NULL;
2170 if (prod_level > ind->prod_level) {
2171 str = GetIndustrySpec(ind->type)->production_up_text;
2172 } else if (prod_level < ind->prod_level) {
2173 str = GetIndustrySpec(ind->type)->production_down_text;
2175 if (prod_level != ind->prod_level && !custom_news.empty()) str = STR_NEWS_CUSTOM_ITEM;
2177 ind->ctlflags |= INDCTL_EXTERNAL_PROD_LEVEL;
2178 ind->prod_level = prod_level;
2179 ind->RecomputeProductionMultipliers();
2181 /* Show news message if requested. */
2182 if (show_news && str != STR_NULL) {
2183 NewsType nt;
2184 switch (WhoCanServiceIndustry(ind)) {
2185 case 0: nt = NT_INDUSTRY_NOBODY; break;
2186 case 1: nt = NT_INDUSTRY_OTHER; break;
2187 case 2: nt = NT_INDUSTRY_COMPANY; break;
2188 default: NOT_REACHED();
2191 /* Set parameters of news string */
2192 NewsAllocatedData *data = nullptr;
2193 if (str == STR_NEWS_CUSTOM_ITEM) {
2194 NewsStringData *news = new NewsStringData(custom_news);
2195 SetDParamStr(0, news->string);
2196 } else if (str > STR_LAST_STRINGID) {
2197 SetDParam(0, STR_TOWN_NAME);
2198 SetDParam(1, ind->town->index);
2199 SetDParam(2, GetIndustrySpec(ind->type)->name);
2200 } else {
2201 SetDParam(0, ind->index);
2203 AddIndustryNewsItem(str, nt, ind->index, data);
2207 return CommandCost();
2211 * Change exclusive consumer or supplier for the industry.
2212 * @param flags Type of operation.
2213 * @param ind_id IndustryID
2214 * @param company_id CompanyID to set or INVALID_OWNER (available to everyone) or
2215 * OWNER_NONE (neutral stations only) or OWNER_DEITY (no one)
2216 * @param consumer Set exclusive consumer if true, supplier if false.
2217 * @return Empty cost or an error.
2219 CommandCost CmdIndustrySetExclusivity(DoCommandFlag flags, IndustryID ind_id, Owner company_id, bool consumer)
2221 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2223 Industry *ind = Industry::GetIfValid(ind_id);
2224 if (ind == nullptr) return CMD_ERROR;
2226 if (company_id != OWNER_NONE && company_id != INVALID_OWNER && company_id != OWNER_DEITY
2227 && !Company::IsValidID(company_id)) return CMD_ERROR;
2229 if (flags & DC_EXEC) {
2230 if (consumer) {
2231 ind->exclusive_consumer = company_id;
2232 } else {
2233 ind->exclusive_supplier = company_id;
2238 return CommandCost();
2242 * Change additional industry text.
2243 * @param flags Type of operation.
2244 * @param ind_id IndustryID
2245 * @param text - Additional industry text.
2246 * @return Empty cost or an error.
2248 CommandCost CmdIndustrySetText(DoCommandFlag flags, IndustryID ind_id, const std::string &text)
2250 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2252 Industry *ind = Industry::GetIfValid(ind_id);
2253 if (ind == nullptr) return CMD_ERROR;
2255 if (flags & DC_EXEC) {
2256 ind->text.clear();
2257 if (!text.empty()) ind->text = text;
2258 InvalidateWindowData(WC_INDUSTRY_VIEW, ind->index);
2261 return CommandCost();
2265 * Create a new industry of random layout.
2266 * @param tile The location to build the industry.
2267 * @param type The industry type to build.
2268 * @param creation_type The circumstances the industry is created under.
2269 * @return the created industry or nullptr if it failed.
2271 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
2273 const IndustrySpec *indspec = GetIndustrySpec(type);
2275 uint32_t seed = Random();
2276 uint32_t seed2 = Random();
2277 Industry *i = nullptr;
2278 size_t layout_index = RandomRange((uint32_t)indspec->layouts.size());
2279 [[maybe_unused]] CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
2280 assert(i != nullptr || ret.Failed());
2281 return i;
2285 * Compute the appearance probability for an industry during map creation.
2286 * @param it Industry type to compute.
2287 * @param[out] force_at_least_one Returns whether at least one instance should be forced on map creation.
2288 * @return Relative probability for the industry to appear.
2290 static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
2292 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2293 uint32_t chance = ind_spc->appear_creation[_settings_game.game_creation.landscape];
2294 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2295 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
2296 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
2297 *force_at_least_one = false;
2298 return 0;
2299 } else {
2300 chance *= 16; // to increase precision
2301 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
2302 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
2303 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? Map::ScaleBySize1D(chance) : Map::ScaleBySize(chance);
2305 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
2306 return chance;
2311 * Compute the probability for constructing a new industry during game play.
2312 * @param it Industry type to compute.
2313 * @param[out] min_number Minimal number of industries that should exist at the map.
2314 * @return Relative probability for the industry to appear.
2316 static uint16_t GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
2318 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2319 *min_number = 0;
2320 return 0;
2323 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2324 byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2325 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2326 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && TimerGameCalendar::year > 1950) ||
2327 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && TimerGameCalendar::year < 1960) ||
2328 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2329 *min_number = 0;
2330 return 0;
2332 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2333 return chance;
2337 * Get wanted number of industries on the map.
2338 * @return Wanted number of industries at the map.
2340 static uint GetNumberOfIndustries()
2342 /* Number of industries on a 256x256 map. */
2343 static const uint16_t numof_industry_table[] = {
2344 0, // none
2345 0, // minimal
2346 10, // very low
2347 25, // low
2348 55, // normal
2349 80, // high
2350 0, // custom
2353 assert(lengthof(numof_industry_table) == ID_END);
2354 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2356 if (difficulty == ID_CUSTOM) return std::min<uint>(IndustryPool::MAX_SIZE, _settings_game.game_creation.custom_industry_number);
2358 return std::min<uint>(IndustryPool::MAX_SIZE, Map::ScaleBySize(numof_industry_table[difficulty]));
2362 * Try to place the industry in the game.
2363 * Since there is no feedback why placement fails, there is no other option
2364 * than to try a few times before concluding it does not work.
2365 * @param type Industry type of the desired industry.
2366 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2367 * @return Pointer to created industry, or \c nullptr if creation failed.
2369 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2371 uint tries = try_hard ? 10000u : 2000u;
2372 for (; tries > 0; tries--) {
2373 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2374 if (ind != nullptr) return ind;
2376 return nullptr;
2380 * Try to build a industry on the map.
2381 * @param type IndustryType of the desired industry
2382 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2384 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2386 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2388 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2389 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2391 cur_company.Restore();
2395 * Get total number of industries existing in the game.
2396 * @return Number of industries currently in the game.
2398 static uint GetCurrentTotalNumberOfIndustries()
2400 int total = 0;
2401 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2402 return total;
2406 /** Reset the entry. */
2407 void IndustryTypeBuildData::Reset()
2409 this->probability = 0;
2410 this->min_number = 0;
2411 this->target_count = 0;
2412 this->max_wait = 1;
2413 this->wait_count = 0;
2416 /** Completely reset the industry build data. */
2417 void IndustryBuildData::Reset()
2419 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2421 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2422 this->builddata[it].Reset();
2426 /** Monthly update of industry build data. */
2427 void IndustryBuildData::EconomyMonthlyLoop()
2429 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.
2430 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2432 /* To prevent running out of unused industries for the player to connect,
2433 * add a fraction of new industries each month, but only if the manager can keep up. */
2434 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).
2435 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2436 this->wanted_inds += Map::ScaleBySize(NEWINDS_PER_MONTH);
2441 * This function will create random industries during game creation.
2442 * It will scale the amount of industries by mapsize and difficulty level.
2444 void GenerateIndustries()
2446 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2448 uint32_t industry_probs[NUM_INDUSTRYTYPES];
2449 bool force_at_least_one[NUM_INDUSTRYTYPES];
2450 uint32_t total_prob = 0;
2451 uint num_forced = 0;
2453 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2454 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2455 total_prob += industry_probs[it];
2456 if (force_at_least_one[it]) num_forced++;
2459 uint total_amount = GetNumberOfIndustries();
2460 if (total_prob == 0 || total_amount < num_forced) {
2461 /* Only place the forced ones */
2462 total_amount = num_forced;
2465 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2467 /* Try to build one industry per type independent of any probabilities */
2468 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2469 if (force_at_least_one[it]) {
2470 assert(total_amount > 0);
2471 total_amount--;
2472 PlaceInitialIndustry(it, true);
2476 /* Add the remaining industries according to their probabilities */
2477 for (uint i = 0; i < total_amount; i++) {
2478 uint32_t r = RandomRange(total_prob);
2479 IndustryType it = 0;
2480 while (r >= industry_probs[it]) {
2481 r -= industry_probs[it];
2482 it++;
2483 assert(it < NUM_INDUSTRYTYPES);
2485 assert(industry_probs[it] > 0);
2486 PlaceInitialIndustry(it, false);
2488 _industry_builder.Reset();
2492 * Monthly update of industry statistics.
2493 * @param i Industry to update.
2495 static void UpdateIndustryStatistics(Industry *i)
2497 for (auto &p : i->produced) {
2498 if (IsValidCargoID(p.cargo)) {
2499 if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
2501 /* Move history from this month to last month. */
2502 std::rotate(std::rbegin(p.history), std::rbegin(p.history) + 1, std::rend(p.history));
2503 p.history[THIS_MONTH].production = 0;
2504 p.history[THIS_MONTH].transported = 0;
2510 * Recompute #production_rate for current #prod_level.
2511 * This function is only valid when not using smooth economy.
2513 void Industry::RecomputeProductionMultipliers()
2515 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2516 assert(indspec->UsesOriginalEconomy());
2518 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2519 for (auto &p : this->produced) {
2520 p.rate = ClampTo<uint8_t>(CeilDiv(indspec->production_rate[&p - this->produced.data()] * this->prod_level, PRODLEVEL_DEFAULT));
2524 void Industry::FillCachedName() const
2526 auto tmp_params = MakeParameters(this->index);
2527 this->cached_name = GetStringWithArgs(STR_INDUSTRY_NAME, tmp_params);
2530 void ClearAllIndustryCachedNames()
2532 for (Industry *ind : Industry::Iterate()) {
2533 ind->cached_name.clear();
2538 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2539 * @param it Industry type.
2540 * @return At least one of the fields has changed value.
2542 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2544 byte min_number;
2545 uint32_t probability = GetIndustryGamePlayProbability(it, &min_number);
2546 bool changed = min_number != this->min_number || probability != this->probability;
2547 this->min_number = min_number;
2548 this->probability = probability;
2549 return changed;
2552 /** Decide how many industries of each type are needed. */
2553 void IndustryBuildData::SetupTargetCount()
2555 bool changed = false;
2556 uint num_planned = 0; // Number of industries planned in the industry build data.
2557 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2558 changed |= this->builddata[it].GetIndustryTypeData(it);
2559 num_planned += this->builddata[it].target_count;
2561 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2562 changed |= num_planned != total_amount;
2563 if (!changed) return; // All industries are still the same, no need to re-randomize.
2565 /* Initialize the target counts. */
2566 uint force_build = 0; // Number of industries that should always be available.
2567 uint32_t total_prob = 0; // Sum of probabilities.
2568 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2569 IndustryTypeBuildData *ibd = this->builddata + it;
2570 force_build += ibd->min_number;
2571 ibd->target_count = ibd->min_number;
2572 total_prob += ibd->probability;
2575 if (total_prob == 0) return; // No buildable industries.
2577 /* Subtract forced industries from the number of industries available for construction. */
2578 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2580 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2581 while (total_amount > 0) {
2582 uint32_t r = RandomRange(total_prob);
2583 IndustryType it = 0;
2584 while (r >= this->builddata[it].probability) {
2585 r -= this->builddata[it].probability;
2586 it++;
2587 assert(it < NUM_INDUSTRYTYPES);
2589 assert(this->builddata[it].probability > 0);
2590 this->builddata[it].target_count++;
2591 total_amount--;
2596 * Try to create a random industry, during gameplay
2598 void IndustryBuildData::TryBuildNewIndustry()
2600 this->SetupTargetCount();
2602 int missing = 0; // Number of industries that need to be build.
2603 uint count = 0; // Number of industry types eligible for build.
2604 uint32_t total_prob = 0; // Sum of probabilities.
2605 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2606 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2607 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2608 missing += difference;
2609 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2610 if (difference > 0) {
2611 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2612 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2613 if (forced_build == NUM_INDUSTRYTYPES ||
2614 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2615 forced_build = it;
2618 total_prob += difference;
2619 count++;
2623 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2625 if (count >= 1) {
2626 /* If not forced, pick a weighted random industry to build.
2627 * For the case that count == 1, there is no need to draw a random number. */
2628 IndustryType it;
2629 if (forced_build != NUM_INDUSTRYTYPES) {
2630 it = forced_build;
2631 } else {
2632 /* Non-forced, select an industry type to build (weighted random). */
2633 uint32_t r = 0; // Initialized to silence the compiler.
2634 if (count > 1) r = RandomRange(total_prob);
2635 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2636 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2637 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2638 if (difference <= 0) continue; // Too many of this kind.
2639 if (count == 1) break;
2640 if (r < (uint)difference) break;
2641 r -= difference;
2643 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2646 /* Try to create the industry. */
2647 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2648 if (ind == nullptr) {
2649 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2650 this->builddata[it].max_wait = std::min(1000, this->builddata[it].max_wait + 2);
2651 } else {
2652 AdvertiseIndustryOpening(ind);
2653 this->builddata[it].max_wait = std::max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2657 /* Decrement wait counters. */
2658 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2659 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2664 * Protects an industry from closure if the appropriate flags and conditions are met
2665 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2666 * count of industries of this type must one (or lower) in order to be protected
2667 * against closure.
2668 * @param type IndustryType been queried
2669 * @result true if protection is on, false otherwise (except for oil wells)
2671 static bool CheckIndustryCloseDownProtection(IndustryType type)
2673 const IndustrySpec *indspec = GetIndustrySpec(type);
2675 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2676 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2677 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2681 * Can given cargo type be accepted or produced by the industry?
2682 * @param cargo: Cargo type
2683 * @param ind: Industry
2684 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2685 * @param *c_produces: Pointer to boolean for production of cargo
2686 * @return: \c *c_accepts is set when industry accepts the cargo type,
2687 * \c *c_produces is set when the industry produces the cargo type
2689 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2691 if (!IsValidCargoID(cargo)) return;
2693 /* Check for acceptance of cargo */
2694 if (ind->IsCargoAccepted(cargo) && !IndustryTemporarilyRefusesCargo(ind, cargo)) *c_accepts = true;
2696 /* Check for produced cargo */
2697 if (ind->IsCargoProduced(cargo)) *c_produces = true;
2701 * Compute who can service the industry.
2703 * Here, 'can service' means that they have trains and stations close enough
2704 * to the industry with the right cargo type and the right orders (ie has the
2705 * technical means).
2707 * @param ind: Industry being investigated.
2709 * @return: 0 if nobody can service the industry, 2 if the local company can
2710 * service the industry, and 1 otherwise (only competitors can service the
2711 * industry)
2713 int WhoCanServiceIndustry(Industry *ind)
2715 if (ind->stations_near.empty()) return 0; // No stations found at all => nobody services
2717 int result = 0;
2718 for (const Vehicle *v : Vehicle::Iterate()) {
2719 /* Is it worthwhile to try this vehicle? */
2720 if (v->owner != _local_company && result != 0) continue;
2722 /* Check whether it accepts the right kind of cargo */
2723 bool c_accepts = false;
2724 bool c_produces = false;
2725 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2726 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
2727 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2729 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2730 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2731 } else {
2732 continue;
2734 if (!c_accepts && !c_produces) continue; // Wrong cargo
2736 /* Check orders of the vehicle.
2737 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2738 * may have a different cargo type.
2740 for (const Order *o : v->Orders()) {
2741 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2742 /* Vehicle visits a station to load or unload */
2743 Station *st = Station::Get(o->GetDestination());
2744 assert(st != nullptr);
2746 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2747 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2749 if (ind->stations_near.find(st) != ind->stations_near.end()) {
2750 if (v->owner == _local_company) return 2; // Company services industry
2751 result = 1; // Competitor services industry
2756 return result;
2760 * Report news that industry production has changed significantly
2762 * @param ind: Industry with changed production
2763 * @param type: Cargo type that has changed
2764 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
2766 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2768 NewsType nt;
2770 switch (WhoCanServiceIndustry(ind)) {
2771 case 0: nt = NT_INDUSTRY_NOBODY; break;
2772 case 1: nt = NT_INDUSTRY_OTHER; break;
2773 case 2: nt = NT_INDUSTRY_COMPANY; break;
2774 default: NOT_REACHED();
2776 SetDParam(2, abs(percent));
2777 SetDParam(0, CargoSpec::Get(type)->name);
2778 SetDParam(1, ind->index);
2779 AddIndustryNewsItem(
2780 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2782 ind->index
2786 static const uint PERCENT_TRANSPORTED_60 = 153;
2787 static const uint PERCENT_TRANSPORTED_80 = 204;
2790 * Change industry production or do closure
2791 * @param i Industry for which changes are performed
2792 * @param monthly true if it's the monthly call, false if it's the random call
2794 static void ChangeIndustryProduction(Industry *i, bool monthly)
2796 StringID str = STR_NULL;
2797 bool closeit = false;
2798 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2799 bool standard = false;
2800 bool suppress_message = false;
2801 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2802 /* use original economy for industries using production related callbacks */
2803 bool original_economy = indspec->UsesOriginalEconomy();
2804 byte div = 0;
2805 byte mul = 0;
2806 int8_t increment = 0;
2808 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2809 if (callback_enabled) {
2810 uint16_t res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2811 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2812 suppress_message = HasBit(res, 7);
2813 /* Get the custom message if any */
2814 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2815 res = GB(res, 0, 4);
2816 switch (res) {
2817 default: NOT_REACHED();
2818 case 0x0: break; // Do nothing, but show the custom message if any
2819 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2820 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2821 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2822 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2823 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2824 case 0x8: div = res - 0x3; break; // Divide production by 32
2825 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2826 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2827 case 0xD: // decrement production
2828 case 0xE: // increment production
2829 increment = res == 0x0D ? -1 : 1;
2830 break;
2831 case 0xF: // Set production to third byte of register 0x100
2832 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2833 recalculate_multipliers = true;
2834 break;
2837 } else {
2838 if (monthly == original_economy) return;
2839 if (!original_economy && _settings_game.economy.type == ET_FROZEN) return;
2840 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2843 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2844 /* decrease or increase */
2845 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2847 if (original_economy) {
2848 if (only_decrease || Chance16(1, 3)) {
2849 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2850 if (!only_decrease && (i->produced[0].history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2851 mul = 1; // Increase production
2852 } else {
2853 div = 1; // Decrease production
2856 } else if (_settings_game.economy.type == ET_SMOOTH) {
2857 closeit = !(i->ctlflags & (INDCTL_NO_CLOSURE | INDCTL_NO_PRODUCTION_DECREASE));
2858 for (auto &p : i->produced) {
2859 if (!IsValidCargoID(p.cargo)) continue;
2860 uint32_t r = Random();
2861 int old_prod, new_prod, percent;
2862 /* If over 60% is transported, mult is 1, else mult is -1. */
2863 int mult = (p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) ? 1 : -1;
2865 new_prod = old_prod = p.rate;
2867 /* For industries with only_decrease flags (temperate terrain Oil Wells),
2868 * the multiplier will always be -1 so they will only decrease. */
2869 if (only_decrease) {
2870 mult = -1;
2871 /* For normal industries, if over 60% is transported, 33% chance for decrease.
2872 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2873 } else if (Chance16I(1, ((p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2874 mult *= -1;
2877 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2878 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2879 if (Chance16I(1, 22, r >> 16)) {
2880 new_prod += mult * (std::max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2883 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2884 new_prod = Clamp(new_prod, 1, 255);
2885 if (IsValidCargoID(p.cargo) && p.cargo == GetCargoIDByLabel(CT_PASSENGERS) && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
2886 new_prod = Clamp(new_prod, 0, 16);
2889 /* If override flags are set, prevent actually changing production if any was decided on */
2890 if ((i->ctlflags & INDCTL_NO_PRODUCTION_DECREASE) && new_prod < old_prod) continue;
2891 if ((i->ctlflags & INDCTL_NO_PRODUCTION_INCREASE) && new_prod > old_prod) continue;
2893 /* Do not stop closing the industry when it has the lowest possible production rate */
2894 if (new_prod == old_prod && old_prod > 1) {
2895 closeit = false;
2896 continue;
2899 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2900 p.rate = new_prod;
2902 /* Close the industry when it has the lowest possible production rate */
2903 if (new_prod > 1) closeit = false;
2905 if (abs(percent) >= 10) {
2906 ReportNewsProductionChangeIndustry(i, p.cargo, percent);
2912 /* If override flags are set, prevent actually changing production if any was decided on */
2913 if ((i->ctlflags & INDCTL_NO_PRODUCTION_DECREASE) && (div > 0 || increment < 0)) return;
2914 if ((i->ctlflags & INDCTL_NO_PRODUCTION_INCREASE) && (mul > 0 || increment > 0)) return;
2915 if (i->ctlflags & INDCTL_EXTERNAL_PROD_LEVEL) {
2916 div = 0;
2917 mul = 0;
2918 increment = 0;
2921 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2922 if (TimerGameEconomy::year - i->last_prod_year >= PROCESSING_INDUSTRY_ABANDONMENT_YEARS && Chance16(1, original_economy ? 2 : 180)) {
2923 closeit = true;
2927 /* Increase if needed */
2928 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2929 i->prod_level = std::min<int>(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2930 recalculate_multipliers = true;
2931 if (str == STR_NULL) str = indspec->production_up_text;
2934 /* Decrease if needed */
2935 while (div-- != 0 && !closeit) {
2936 if (i->prod_level == PRODLEVEL_MINIMUM) {
2937 closeit = true;
2938 break;
2939 } else {
2940 i->prod_level = std::max<int>(i->prod_level / 2, PRODLEVEL_MINIMUM);
2941 recalculate_multipliers = true;
2942 if (str == STR_NULL) str = indspec->production_down_text;
2946 /* Increase or Decreasing the production level if needed */
2947 if (increment != 0) {
2948 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2949 closeit = true;
2950 } else {
2951 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2952 recalculate_multipliers = true;
2956 /* Recalculate production_rate
2957 * For non-smooth economy these should always be synchronized with prod_level */
2958 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2960 /* Close if needed and allowed */
2961 if (closeit && !CheckIndustryCloseDownProtection(i->type) && !(i->ctlflags & INDCTL_NO_CLOSURE)) {
2962 i->prod_level = PRODLEVEL_CLOSURE;
2963 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2964 str = indspec->closure_text;
2967 if (!suppress_message && str != STR_NULL) {
2968 NewsType nt;
2969 /* Compute news category */
2970 if (closeit) {
2971 nt = NT_INDUSTRY_CLOSE;
2972 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2973 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2974 } else {
2975 switch (WhoCanServiceIndustry(i)) {
2976 case 0: nt = NT_INDUSTRY_NOBODY; break;
2977 case 1: nt = NT_INDUSTRY_OTHER; break;
2978 case 2: nt = NT_INDUSTRY_COMPANY; break;
2979 default: NOT_REACHED();
2982 /* Set parameters of news string */
2983 if (str > STR_LAST_STRINGID) {
2984 SetDParam(0, STR_TOWN_NAME);
2985 SetDParam(1, i->town->index);
2986 SetDParam(2, indspec->name);
2987 } else if (closeit) {
2988 SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
2989 SetDParam(1, i->town->index);
2990 SetDParam(2, indspec->name);
2991 } else {
2992 SetDParam(0, i->index);
2994 /* and report the news to the user */
2995 if (closeit) {
2996 AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
2997 } else {
2998 AddIndustryNewsItem(str, nt, i->index);
3004 * Every economy day handler for the industry changes
3005 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
3006 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
3007 * For small maps, it implies that less than one change per month is required, while on bigger maps,
3008 * it would be way more. The daily loop handles those changes.
3010 static IntervalTimer<TimerGameEconomy> _economy_industries_daily({TimerGameEconomy::DAY, TimerGameEconomy::Priority::INDUSTRY}, [](auto)
3012 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
3014 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
3015 * the lower 16 bit are a fractional part that might accumulate over several days until it
3016 * is sufficient for an industry. */
3017 uint16_t change_loop = _economy.industry_daily_change_counter >> 16;
3019 /* Reset the active part of the counter, just keeping the "fractional part" */
3020 _economy.industry_daily_change_counter &= 0xFFFF;
3022 if (change_loop == 0) {
3023 return; // Nothing to do? get out
3026 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
3028 /* perform the required industry changes for the day */
3030 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
3031 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
3032 perc = std::min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
3034 for (uint16_t j = 0; j < change_loop; j++) {
3035 if (Chance16(perc, 100)) {
3036 _industry_builder.TryBuildNewIndustry();
3037 } else {
3038 Industry *i = Industry::GetRandom();
3039 if (i != nullptr) {
3040 ChangeIndustryProduction(i, false);
3041 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3046 cur_company.Restore();
3048 /* production-change */
3049 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
3052 static IntervalTimer<TimerGameEconomy> _economy_industries_monthly({TimerGameEconomy::MONTH, TimerGameEconomy::Priority::INDUSTRY}, [](auto)
3054 Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
3056 _industry_builder.EconomyMonthlyLoop();
3058 for (Industry *i : Industry::Iterate()) {
3059 UpdateIndustryStatistics(i);
3060 if (i->prod_level == PRODLEVEL_CLOSURE) {
3061 delete i;
3062 } else {
3063 ChangeIndustryProduction(i, true);
3064 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3068 cur_company.Restore();
3070 /* production-change */
3071 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
3075 void InitializeIndustries()
3077 Industry::ResetIndustryCounts();
3078 _industry_sound_tile = 0;
3080 _industry_builder.Reset();
3083 /** Verify whether the generated industries are complete, and warn the user if not. */
3084 void CheckIndustries()
3086 int count = 0;
3087 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
3088 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
3090 bool force_at_least_one;
3091 uint32_t chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
3092 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
3094 const IndustrySpec *is = GetIndustrySpec(it);
3095 SetDParam(0, is->name);
3096 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
3098 count++;
3099 if (count >= 3) break; // Don't swamp the user with errors.
3104 * Is an industry with the spec a raw industry?
3105 * @return true if it should be handled as a raw industry
3107 bool IndustrySpec::IsRawIndustry() const
3109 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
3113 * Is an industry with the spec a processing industry?
3114 * @return true if it should be handled as a processing industry
3116 bool IndustrySpec::IsProcessingIndustry() const
3118 /* Lumber mills are neither raw nor processing */
3119 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
3120 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
3124 * Get the cost for constructing this industry
3125 * @return the cost (inflation corrected etc)
3127 Money IndustrySpec::GetConstructionCost() const
3129 /* Building raw industries like secondary uses different price base */
3130 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
3131 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
3135 * Get the cost for removing this industry
3136 * Take note that the cost will always be zero for non-grf industries.
3137 * Only if the grf author did specified a cost will it be applicable.
3138 * @return the cost (inflation corrected etc)
3140 Money IndustrySpec::GetRemovalCost() const
3142 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
3146 * Determines whether this industrytype uses standard/newgrf production changes.
3147 * @return true if original economy is used.
3149 bool IndustrySpec::UsesOriginalEconomy() const
3151 return _settings_game.economy.type == ET_ORIGINAL ||
3152 HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || // production callbacks
3153 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
3156 IndustrySpec::~IndustrySpec()
3158 if (HasBit(this->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
3159 free(this->random_sounds);
3163 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
3165 if (AutoslopeEnabled()) {
3166 /* We imitate here TTDP's behaviour:
3167 * - Both new and old slope must not be steep.
3168 * - TileMaxZ must not be changed.
3169 * - Allow autoslope by default.
3170 * - Disallow autoslope if callback succeeds and returns non-zero.
3172 Slope tileh_old = GetTileSlope(tile);
3173 /* TileMaxZ must not be changed. Slopes must not be steep. */
3174 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
3175 const IndustryGfx gfx = GetIndustryGfx(tile);
3176 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
3178 /* Call callback 3C 'disable autosloping for industry tiles'. */
3179 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
3180 /* If the callback fails, allow autoslope. */
3181 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
3182 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3183 } else {
3184 /* allow autoslope */
3185 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3189 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
3192 extern const TileTypeProcs _tile_type_industry_procs = {
3193 DrawTile_Industry, // draw_tile_proc
3194 GetSlopePixelZ_Industry, // get_slope_z_proc
3195 ClearTile_Industry, // clear_tile_proc
3196 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
3197 GetTileDesc_Industry, // get_tile_desc_proc
3198 GetTileTrackStatus_Industry, // get_tile_track_status_proc
3199 ClickTile_Industry, // click_tile_proc
3200 AnimateTile_Industry, // animate_tile_proc
3201 TileLoop_Industry, // tile_loop_proc
3202 ChangeTileOwner_Industry, // change_tile_owner_proc
3203 nullptr, // add_produced_cargo_proc
3204 nullptr, // vehicle_enter_tile_proc
3205 GetFoundation_Industry, // get_foundation_proc
3206 TerraformTile_Industry, // terraform_tile_proc
3209 bool IndustryCompare::operator() (const IndustryListEntry &lhs, const IndustryListEntry &rhs) const
3211 /* Compare by distance first and use index as a tiebreaker. */
3212 return std::tie(lhs.distance, lhs.industry->index) < std::tie(rhs.distance, rhs.industry->index);