OpenTTD Source: src/industry_cmd.cpp Source File

OpenTTD Source 15.3

industry_cmd.cpp
Go to the documentation of this file.
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "stdafx.h"
11#include "misc/history_type.hpp"
12#include "misc/history_func.hpp"
13#include "clear_map.h"
14#include "industry.h"
15#include "station_base.h"
16#include "landscape.h"
17#include "viewport_func.h"
18#include "command_func.h"
19#include "town.h"
20#include "news_func.h"
21#include "cheat_type.h"
22#include "company_base.h"
23#include "genworld.h"
24#include "tree_map.h"
25#include "newgrf_cargo.h"
26#include "newgrf_debug.h"
27#include "newgrf_industrytiles.h"
28#include "autoslope.h"
29#include "water.h"
30#include "strings_func.h"
31#include "window_func.h"
32#include "vehicle_func.h"
33#include "sound_func.h"
34#include "animated_tile_func.h"
35#include "effectvehicle_func.h"
36#include "effectvehicle_base.h"
37#include "ai/ai.hpp"
38#include "core/pool_func.hpp"
39#include "subsidy_func.h"
40#include "core/backup_type.hpp"
41#include "object_base.h"
42#include "game/game.hpp"
43#include "error.h"
44#include "string_func.h"
45#include "industry_cmd.h"
46#include "landscape_cmd.h"
47#include "terraform_cmd.h"
48#include "map_func.h"
49#include "timer/timer.h"
50#include "timer/timer_game_calendar.h"
51#include "timer/timer_game_economy.h"
52#include "timer/timer_game_tick.h"
53
54#include "table/strings.h"
55#include "table/industry_land.h"
56#include "table/build_industry.h"
57
58#include "safeguards.h"
59
60 IndustryPool _industry_pool("Industry");
61 INSTANTIATE_POOL_METHODS(Industry)
62
63void ShowIndustryViewWindow(IndustryID industry);
64void BuildOilRig(TileIndex tile);
65
66static uint8_t _industry_sound_ctr;
67static TileIndex _industry_sound_tile;
68
69std::array<FlatSet<IndustryID>, NUM_INDUSTRYTYPES> Industry::industries;
70
71 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
72 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
73 IndustryBuildData _industry_builder;
74
75static int WhoCanServiceIndustry(Industry *ind);
76
83 void ResetIndustries()
84{
85 auto industry_insert = std::copy(std::begin(_origin_industry_specs), std::end(_origin_industry_specs), std::begin(_industry_specs));
86 std::fill(industry_insert, std::end(_industry_specs), IndustrySpec{});
87
88 /* Enable only the current climate industries */
89 for (auto it = std::begin(_industry_specs); it != industry_insert; ++it) {
90 it->enabled = it->climate_availability.Test(_settings_game.game_creation.landscape);
91 }
92
93 auto industry_tile_insert = std::copy(std::begin(_origin_industry_tile_specs), std::end(_origin_industry_tile_specs), std::begin(_industry_tile_specs));
94 std::fill(industry_tile_insert, std::end(_industry_tile_specs), IndustryTileSpec{});
95
96 /* Reset any overrides that have been set. */
97 _industile_mngr.ResetOverride();
98 _industry_mngr.ResetOverride();
99}
100
109IndustryType GetIndustryType(Tile tile)
110{
111 assert(IsTileType(tile, MP_INDUSTRY));
112
113 const Industry *ind = Industry::GetByTile(tile);
114 assert(ind != nullptr);
115 return ind->type;
116}
117
126 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
127{
128 assert(thistype < NUM_INDUSTRYTYPES);
129 return &_industry_specs[thistype];
130}
131
140 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
141{
142 assert(gfx < NUM_INDUSTRYTILES);
143 return &_industry_tile_specs[gfx];
144}
145
146Industry::~Industry()
147{
148 if (CleaningPool()) return;
149
150 /* Industry can also be destroyed when not fully initialized.
151 * This means that we do not have to clear tiles either.
152 * Also we must not decrement industry counts in that case. */
153 if (this->location.w == 0) return;
154
155 const bool has_neutral_station = this->neutral_station != nullptr;
156
157 for (TileIndex tile_cur : this->location) {
158 if (IsTileType(tile_cur, MP_INDUSTRY)) {
159 if (GetIndustryIndex(tile_cur) == this->index) {
160 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur.base());
161
162 /* MakeWaterKeepingClass() can also handle 'land' */
163 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
164 }
165 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
166 DeleteOilRig(tile_cur);
167 }
168 }
169
170 if (has_neutral_station) {
171 /* Remove possible docking tiles */
172 for (TileIndex tile_cur : this->location) {
173 ClearDockingTilesCheckingNeighbours(tile_cur);
174 }
175 }
176
177 if (GetIndustrySpec(this->type)->behaviour.Test(IndustryBehaviour::PlantFields)) {
178 TileArea ta = TileArea(this->location.tile, 0, 0).Expand(21);
179
180 /* Remove the farmland and convert it to regular tiles over time. */
181 for (TileIndex tile_cur : ta) {
182 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
183 GetIndustryIndexOfField(tile_cur) == this->index) {
184 SetIndustryIndexOfField(tile_cur, IndustryID::Invalid());
185 }
186 }
187 }
188
189 /* don't let any disaster vehicle target invalid industry */
190 ReleaseDisastersTargetingIndustry(this->index);
191
192 /* Clear the persistent storage. */
193 delete this->psa;
194
195 auto &industries = Industry::industries[type];
196 industries.erase(this->index);
197
198 DeleteIndustryNews(this->index);
199 CloseWindowById(WC_INDUSTRY_VIEW, this->index);
200 CloseWindowById(WC_INDUSTRY_PRODUCTION, this->index);
201 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
202
203 Source src{this->index, SourceType::Industry};
204 DeleteSubsidyWith(src);
205 CargoPacket::InvalidateAllFrom(src);
206
207 for (Station *st : this->stations_near) {
208 st->RemoveIndustryToDeliver(this);
209 }
210}
211
216 void Industry::PostDestructor(size_t)
217{
218 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_FORCE_REBUILD);
219 SetWindowDirty(WC_BUILD_INDUSTRY, 0);
220}
221
222
227/* static */ Industry *Industry::GetRandom()
228{
229 if (Industry::GetNumItems() == 0) return nullptr;
230 int num = RandomRange((uint16_t)Industry::GetNumItems());
231 size_t index = std::numeric_limits<size_t>::max();
232
233 while (num >= 0) {
234 num--;
235 index++;
236
237 /* Make sure we have a valid industry */
238 while (!Industry::IsValidID(index)) {
239 index++;
240 assert(index < Industry::GetPoolSize());
241 }
242 }
243
244 return Industry::Get(index);
245}
246
247
248static void IndustryDrawSugarMine(const TileInfo *ti)
249{
250 if (!IsIndustryCompleted(ti->tile)) return;
251
252 const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
253
254 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
255
256 if (d->image_2 != 0) {
257 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
258 }
259
260 if (d->image_3 != 0) {
261 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
262 _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
263 }
264}
265
266static void IndustryDrawToffeeQuarry(const TileInfo *ti)
267{
268 uint8_t x = 0;
269
270 if (IsIndustryCompleted(ti->tile)) {
271 x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
272 if (x == 0xFF) {
273 x = 0;
274 }
275 }
276
277 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
278 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
279}
280
281static void IndustryDrawBubbleGenerator( const TileInfo *ti)
282{
283 if (IsIndustryCompleted(ti->tile)) {
284 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
285 }
286 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
287}
288
289static void IndustryDrawToyFactory(const TileInfo *ti)
290{
291 const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
292
293 if (d->image_1 != 0xFF) {
294 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
295 }
296
297 if (d->image_2 != 0xFF) {
298 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
299 }
300
301 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
302 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
303}
304
305static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
306{
307 if (IsIndustryCompleted(ti->tile)) {
308 uint8_t image = GetAnimationFrame(ti->tile);
309
310 if (image != 0 && image < 7) {
311 AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
312 PAL_NONE,
313 _coal_plant_sparks[image - 1].x,
314 _coal_plant_sparks[image - 1].y
315 );
316 }
317 }
318}
319
320typedef void IndustryDrawTileProc(const TileInfo *ti);
321static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
322 IndustryDrawSugarMine,
323 IndustryDrawToffeeQuarry,
324 IndustryDrawBubbleGenerator,
325 IndustryDrawToyFactory,
326 IndustryDrawCoalPlantSparks,
327};
328
329static void DrawTile_Industry(TileInfo *ti)
330{
331 IndustryGfx gfx = GetIndustryGfx(ti->tile);
332 Industry *ind = Industry::GetByTile(ti->tile);
333 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
334
335 /* Retrieve pointer to the draw industry tile struct */
336 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
337 /* Draw the tile using the specialized method of newgrf industrytile.
338 * DrawNewIndustry will return false if ever the resolver could not
339 * find any sprite to display. So in this case, we will jump on the
340 * substitute gfx instead. */
341 if (indts->grf_prop.HasSpriteGroups() && DrawNewIndustryTile(ti, ind, gfx, indts)) {
342 return;
343 } else {
344 /* No sprite group (or no valid one) found, meaning no graphics associated.
345 * Use the substitute one instead */
346 if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
347 gfx = indts->grf_prop.subst_id;
348 /* And point the industrytile spec accordingly */
349 indts = GetIndustryTileSpec(gfx);
350 }
351 }
352 }
353
354 const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
355 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
356 GetIndustryConstructionStage(ti->tile))];
357
358 SpriteID image = dits->ground.sprite;
359
360 /* DrawFoundation() modifies ti->z and ti->tileh */
361 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
362
363 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
364 * Do not do this if the tile's WaterClass is 'land'. */
365 if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
366 DrawWaterClassGround(ti);
367 } else {
368 DrawGroundSprite(image, GroundSpritePaletteTransform(image, dits->ground.pal, GetColourPalette(ind->random_colour)));
369 }
370
371 /* If industries are transparent and invisible, do not draw the upper part */
372 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
373
374 /* Add industry on top of the ground? */
375 image = dits->building.sprite;
376 if (image != 0) {
377 AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GetColourPalette(ind->random_colour)),
378 *ti, *dits, IsTransparencySet(TO_INDUSTRIES));
379
380 if (IsTransparencySet(TO_INDUSTRIES)) return;
381 }
382
383 {
384 int proc = dits->draw_proc - 1;
385 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
386 }
387}
388
389static int GetSlopePixelZ_Industry(TileIndex tile, uint, uint, bool)
390{
391 return GetTileMaxPixelZ(tile);
392}
393
394static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
395{
396 IndustryGfx gfx = GetIndustryGfx(tile);
397
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.
401 */
402 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
403 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
404 if (indts->callback_mask.Test(IndustryTileCallbackMask::DrawFoundations)) {
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;
407 }
408 }
409 return FlatteningFoundation(tileh);
410}
411
412static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, CargoTypes &always_accepted)
413{
414 IndustryGfx gfx = GetIndustryGfx(tile);
415 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
416 const Industry *ind = Industry::GetByTile(tile);
417
418 /* Starting point for acceptance */
419 auto accepts_cargo = itspec->accepts_cargo;
420 auto cargo_acceptance = itspec->acceptance;
421
422 if (itspec->special_flags.Test(IndustryTileSpecialFlag::AcceptsAllCargo)) {
423 /* Copy all accepted cargoes from industry itself */
424 for (const auto &a : ind->accepted) {
425 auto pos = std::ranges::find(accepts_cargo, a.cargo);
426 if (pos == std::end(accepts_cargo)) {
427 /* Not found, insert */
428 pos = std::ranges::find(accepts_cargo, INVALID_CARGO);
429 if (pos == std::end(accepts_cargo)) continue; // nowhere to place, give up on this one
430 *pos = a.cargo;
431 }
432 cargo_acceptance[std::distance(std::begin(accepts_cargo), pos)] += 8;
433 }
434 }
435
436 if (itspec->callback_mask.Test(IndustryTileCallbackMask::AcceptCargo)) {
437 /* Try callback for accepts list, if success override all existing accepts */
438 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
439 if (res != CALLBACK_FAILED) {
440 accepts_cargo.fill(INVALID_CARGO);
441 for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_INPUTS; i++) accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
442 }
443 }
444
445 if (itspec->callback_mask.Test(IndustryTileCallbackMask::CargoAcceptance)) {
446 /* Try callback for acceptance list, if success override all existing acceptance */
447 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
448 if (res != CALLBACK_FAILED) {
449 cargo_acceptance.fill(0);
450 for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_INPUTS; i++) cargo_acceptance[i] = GB(res, i * 4, 4);
451 }
452 }
453
454 for (size_t i = 0; i < std::size(itspec->accepts_cargo); i++) {
455 CargoType cargo = accepts_cargo[i];
456 if (!IsValidCargoType(cargo) || cargo_acceptance[i] <= 0) continue; // work only with valid cargoes
457
458 /* Add accepted cargo */
459 acceptance[cargo] += cargo_acceptance[i];
460
461 /* Maybe set 'always accepted' bit (if it's not set already) */
462 if (HasBit(always_accepted, cargo)) continue;
463
464 /* Test whether the industry itself accepts the cargo type */
465 if (ind->IsCargoAccepted(cargo)) continue;
466
467 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
468 SetBit(always_accepted, cargo);
469 }
470}
471
472static void GetTileDesc_Industry(TileIndex tile, TileDesc &td)
473{
474 const Industry *i = Industry::GetByTile(tile);
475 const IndustrySpec *is = GetIndustrySpec(i->type);
476
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;
482 }
483
484 if (is->grf_prop.HasGrfFile()) {
485 td.grf = GetGRFConfig(is->grf_prop.grfid)->GetName();
486 }
487}
488
489static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlags flags)
490{
491 Industry *i = Industry::GetByTile(tile);
492 const IndustrySpec *indspec = GetIndustrySpec(i->type);
493
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
498 */
499 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
500 !_cheats.magic_bulldozer.value) ||
501 flags.Test(DoCommandFlag::Auto) ||
502 (_current_company == OWNER_WATER &&
503 (indspec->behaviour.Test(IndustryBehaviour::BuiltOnWater) ||
504 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
505
506 if (flags.Test(DoCommandFlag::Auto)) {
507 return CommandCostWithParam(STR_ERROR_GENERIC_OBJECT_IN_THE_WAY, indspec->name);
508 }
509 return CommandCost(INVALID_STRING_ID);
510 }
511
512 if (flags.Test(DoCommandFlag::Execute)) {
513 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
514 Game::NewEvent(new ScriptEventIndustryClose(i->index));
515 delete i;
516 }
517 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
518}
519
525 static bool TransportIndustryGoods(TileIndex tile)
526{
527 Industry *i = Industry::GetByTile(tile);
528 const IndustrySpec *indspec = GetIndustrySpec(i->type);
529 bool moved_cargo = false;
530
531 for (auto &p : i->produced) {
532 uint cw = ClampTo<uint8_t>(p.waiting);
533 if (cw > indspec->minimal_cargo && IsValidCargoType(p.cargo)) {
534 p.waiting -= cw;
535
536 /* fluctuating economy? */
537 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
538
539 p.history[THIS_MONTH].production += cw;
540
541 uint am = MoveGoodsToStation(p.cargo, cw, {i->index, SourceType::Industry}, i->stations_near, i->exclusive_consumer);
542 p.history[THIS_MONTH].transported += am;
543
544 moved_cargo |= (am != 0);
545 }
546 }
547
548 return moved_cargo;
549}
550
551static void AnimateSugarSieve(TileIndex tile)
552{
553 uint8_t m = GetAnimationFrame(tile) + 1;
554
555 if (_settings_client.sound.ambient) {
556 switch (m & 7) {
557 case 2: SndPlayTileFx(SND_2D_SUGAR_MINE_1, tile); break;
558 case 6: SndPlayTileFx(SND_29_SUGAR_MINE_2, tile); break;
559 }
560 }
561
562 if (m >= 96) {
563 m = 0;
564 DeleteAnimatedTile(tile);
565 }
566 SetAnimationFrame(tile, m);
567
568 MarkTileDirtyByTile(tile);
569}
570
571static void AnimateToffeeQuarry(TileIndex tile)
572{
573 uint8_t m = GetAnimationFrame(tile);
574
575 if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
576 SndPlayTileFx(SND_30_TOFFEE_QUARRY, tile);
577 }
578
579 if (++m >= 70) {
580 m = 0;
581 DeleteAnimatedTile(tile);
582 }
583 SetAnimationFrame(tile, m);
584
585 MarkTileDirtyByTile(tile);
586}
587
588static void AnimateBubbleCatcher(TileIndex tile)
589{
590 uint8_t m = GetAnimationFrame(tile);
591
592 if (++m >= 40) {
593 m = 0;
594 DeleteAnimatedTile(tile);
595 }
596 SetAnimationFrame(tile, m);
597
598 MarkTileDirtyByTile(tile);
599}
600
601static void AnimatePowerPlantSparks(TileIndex tile)
602{
603 uint8_t m = GetAnimationFrame(tile);
604 if (m == 6) {
605 SetAnimationFrame(tile, 0);
606 DeleteAnimatedTile(tile);
607 } else {
608 SetAnimationFrame(tile, m + 1);
609 }
610 MarkTileDirtyByTile(tile);
611}
612
613static void AnimateToyFactory(TileIndex tile)
614{
615 uint8_t m = GetAnimationFrame(tile) + 1;
616
617 switch (m) {
618 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_TOY_FACTORY_1, tile); break;
619 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_TOY_FACTORY_2, tile); break;
620 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_TOY_FACTORY_3, tile); break;
621 default:
622 if (m >= 50) {
623 int n = GetIndustryAnimationLoop(tile) + 1;
624 m = 0;
625 if (n >= 8) {
626 n = 0;
627 DeleteAnimatedTile(tile);
628 }
629 SetIndustryAnimationLoop(tile, n);
630 }
631 }
632
633 SetAnimationFrame(tile, m);
634 MarkTileDirtyByTile(tile);
635}
636
637static void AnimatePlasticFountain(TileIndex tile, IndustryGfx gfx)
638{
639 gfx = (gfx < GFX_PLASTIC_FOUNTAIN_ANIMATED_8) ? gfx + 1 : GFX_PLASTIC_FOUNTAIN_ANIMATED_1;
640 SetIndustryGfx(tile, gfx);
641 MarkTileDirtyByTile(tile);
642}
643
644static void AnimateOilWell(TileIndex tile, IndustryGfx gfx)
645{
646 bool b = Chance16(1, 7);
647 uint8_t m = GetAnimationFrame(tile) + 1;
648 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
649 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
650 SetIndustryConstructionStage(tile, 3);
651 DeleteAnimatedTile(tile);
652 } else {
653 SetAnimationFrame(tile, m);
654 SetIndustryGfx(tile, gfx);
655 }
656 MarkTileDirtyByTile(tile);
657}
658
659static void AnimateMineTower(TileIndex tile)
660{
661 int state = TimerGameTick::counter & 0x7FF;
662
663 if ((state -= 0x400) < 0) return;
664
665 if (state < 0x1A0) {
666 if (state < 0x20 || state >= 0x180) {
667 uint8_t m = GetAnimationFrame(tile);
668 if (!(m & 0x40)) {
669 SetAnimationFrame(tile, m | 0x40);
670 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINE, tile);
671 }
672 if (state & 7) return;
673 } else {
674 if (state & 3) return;
675 }
676 uint8_t m = (GetAnimationFrame(tile) + 1) | 0x40;
677 if (m > 0xC2) m = 0xC0;
678 SetAnimationFrame(tile, m);
679 MarkTileDirtyByTile(tile);
680 } else if (state >= 0x200 && state < 0x3A0) {
681 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
682 if (state & i) return;
683
684 uint8_t m = (GetAnimationFrame(tile) & 0xBF) - 1;
685 if (m < 0x80) m = 0x82;
686 SetAnimationFrame(tile, m);
687 MarkTileDirtyByTile(tile);
688 }
689}
690
691static void AnimateTile_Industry(TileIndex tile)
692{
693 IndustryGfx gfx = GetIndustryGfx(tile);
694
695 if (GetIndustryTileSpec(gfx)->animation.status != AnimationStatus::NoAnimation) {
696 AnimateNewIndustryTile(tile);
697 return;
698 }
699
700 switch (gfx) {
701 case GFX_SUGAR_MINE_SIEVE:
702 if ((TimerGameTick::counter & 1) == 0) AnimateSugarSieve(tile);
703 break;
704
705 case GFX_TOFFEE_QUARRY:
706 if ((TimerGameTick::counter & 3) == 0) AnimateToffeeQuarry(tile);
707 break;
708
709 case GFX_BUBBLE_CATCHER:
710 if ((TimerGameTick::counter & 1) == 0) AnimateBubbleCatcher(tile);
711 break;
712
713 case GFX_POWERPLANT_SPARKS:
714 if ((TimerGameTick::counter & 3) == 0) AnimatePowerPlantSparks(tile);
715 break;
716
717 case GFX_TOY_FACTORY:
718 if ((TimerGameTick::counter & 1) == 0) AnimateToyFactory(tile);
719 break;
720
721 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
722 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
723 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
724 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
725 if ((TimerGameTick::counter & 3) == 0) AnimatePlasticFountain(tile, gfx);
726 break;
727
728 case GFX_OILWELL_ANIMATED_1:
729 case GFX_OILWELL_ANIMATED_2:
730 case GFX_OILWELL_ANIMATED_3:
731 if ((TimerGameTick::counter & 7) == 0) AnimateOilWell(tile, gfx);
732 break;
733
734 case GFX_COAL_MINE_TOWER_ANIMATED:
735 case GFX_COPPER_MINE_TOWER_ANIMATED:
736 case GFX_GOLD_MINE_TOWER_ANIMATED:
737 AnimateMineTower(tile);
738 break;
739 }
740}
741
742static void CreateChimneySmoke(TileIndex tile)
743{
744 uint x = TileX(tile) * TILE_SIZE;
745 uint y = TileY(tile) * TILE_SIZE;
746 int z = GetTileMaxPixelZ(tile);
747
748 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
749}
750
751static void MakeIndustryTileBigger(TileIndex tile)
752{
753 uint8_t cnt = GetIndustryConstructionCounter(tile) + 1;
754 if (cnt != 4) {
755 SetIndustryConstructionCounter(tile, cnt);
756 return;
757 }
758
759 uint8_t stage = GetIndustryConstructionStage(tile) + 1;
760 SetIndustryConstructionCounter(tile, 0);
761 SetIndustryConstructionStage(tile, stage);
762 TriggerIndustryTileAnimation_ConstructionStageChanged(tile, false);
763 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
764
765 MarkTileDirtyByTile(tile);
766
767 if (!IsIndustryCompleted(tile)) return;
768
769 IndustryGfx gfx = GetIndustryGfx(tile);
770 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
771 /* New industries are already animated on construction. */
772 return;
773 }
774
775 switch (gfx) {
776 case GFX_POWERPLANT_CHIMNEY:
777 CreateChimneySmoke(tile);
778 break;
779
780 case GFX_OILRIG_1: {
781 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
782 * tiles (like the default oil rig). Do a proper check to ensure the
783 * tiles belong to the same industry and based on that build the oil rig's
784 * station. */
785 TileIndex other = tile + TileDiffXY(0, 1);
786
787 if (IsTileType(other, MP_INDUSTRY) &&
788 GetIndustryGfx(other) == GFX_OILRIG_1 &&
789 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
790 BuildOilRig(tile);
791 }
792 break;
793 }
794
795 case GFX_TOY_FACTORY:
796 case GFX_BUBBLE_CATCHER:
797 case GFX_TOFFEE_QUARRY:
798 SetAnimationFrame(tile, 0);
799 SetIndustryAnimationLoop(tile, 0);
800 break;
801
802 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
803 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
804 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
805 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
806 AddAnimatedTile(tile, false);
807 break;
808 }
809}
810
811static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
812{
813 static const int8_t _bubble_spawn_location[3][4] = {
814 { 11, 0, -4, -14 },
815 { -4, -10, -4, 1 },
816 { 49, 59, 60, 65 },
817 };
818
819 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_BUBBLE_GENERATOR, tile);
820
821 int dir = Random() & 3;
822
823 EffectVehicle *v = CreateEffectVehicleAbove(
824 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
825 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
826 _bubble_spawn_location[2][dir],
827 EV_BUBBLE
828 );
829
830 if (v != nullptr) v->animation_substate = dir;
831}
832
833static void TileLoop_Industry(TileIndex tile)
834{
835 if (IsTileOnWater(tile)) TileLoop_Water(tile);
836
837 /* Normally this doesn't happen, but if an industry NewGRF is removed
838 * an industry that was previously build on water can now be flooded.
839 * If this happens the tile is no longer an industry tile after
840 * returning from TileLoop_Water. */
841 if (!IsTileType(tile, MP_INDUSTRY)) return;
842
843 TriggerIndustryTileRandomisation(tile, IndustryRandomTrigger::TileLoop);
844
845 if (!IsIndustryCompleted(tile)) {
846 MakeIndustryTileBigger(tile);
847 return;
848 }
849
850 if (_game_mode == GM_EDITOR) return;
851
852 if (TransportIndustryGoods(tile) && !TriggerIndustryAnimation(Industry::GetByTile(tile), IndustryAnimationTrigger::CargoDistributed)) {
853 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
854
855 if (newgfx != INDUSTRYTILE_NOANIM) {
856 ResetIndustryConstructionStage(tile);
857 SetIndustryCompleted(tile);
858 SetIndustryGfx(tile, newgfx);
859 MarkTileDirtyByTile(tile);
860 return;
861 }
862 }
863
864 if (TriggerIndustryTileAnimation(tile, IndustryAnimationTrigger::TileLoop)) return;
865
866 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
867 if (newgfx != INDUSTRYTILE_NOANIM) {
868 ResetIndustryConstructionStage(tile);
869 SetIndustryGfx(tile, newgfx);
870 MarkTileDirtyByTile(tile);
871 return;
872 }
873
874 IndustryGfx gfx = GetIndustryGfx(tile);
875 switch (gfx) {
876 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
877 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
878 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
879 if (!(TimerGameTick::counter & 0x400) && Chance16(1, 2)) {
880 switch (gfx) {
881 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
882 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
883 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
884 }
885 SetIndustryGfx(tile, gfx);
886 SetAnimationFrame(tile, 0x80);
887 AddAnimatedTile(tile);
888 }
889 break;
890
891 case GFX_OILWELL_NOT_ANIMATED:
892 if (Chance16(1, 6)) {
893 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
894 SetAnimationFrame(tile, 0);
895 AddAnimatedTile(tile);
896 }
897 break;
898
899 case GFX_COAL_MINE_TOWER_ANIMATED:
900 case GFX_COPPER_MINE_TOWER_ANIMATED:
901 case GFX_GOLD_MINE_TOWER_ANIMATED:
902 if (!(TimerGameTick::counter & 0x400)) {
903 switch (gfx) {
904 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
905 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
906 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
907 }
908 SetIndustryGfx(tile, gfx);
909 SetIndustryCompleted(tile);
910 SetIndustryConstructionStage(tile, 3);
911 DeleteAnimatedTile(tile);
912 MarkTileDirtyByTile(tile);
913 }
914 break;
915
916 case GFX_POWERPLANT_SPARKS:
917 if (Chance16(1, 3)) {
918 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_POWER_STATION, tile);
919 AddAnimatedTile(tile);
920 }
921 break;
922
923 case GFX_COPPER_MINE_CHIMNEY:
924 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
925 break;
926
927
928 case GFX_TOY_FACTORY: {
929 Industry *i = Industry::GetByTile(tile);
930 if (i->was_cargo_delivered) {
931 i->was_cargo_delivered = false;
932 SetIndustryAnimationLoop(tile, 0);
933 AddAnimatedTile(tile);
934 }
935 }
936 break;
937
938 case GFX_BUBBLE_GENERATOR:
939 TileLoopIndustry_BubbleGenerator(tile);
940 break;
941
942 case GFX_TOFFEE_QUARRY:
943 AddAnimatedTile(tile);
944 break;
945
946 case GFX_SUGAR_MINE_SIEVE:
947 if (Chance16(1, 3)) AddAnimatedTile(tile);
948 break;
949 }
950}
951
952static bool ClickTile_Industry(TileIndex tile)
953{
954 ShowIndustryViewWindow(GetIndustryIndex(tile));
955 return true;
956}
957
958static TrackStatus GetTileTrackStatus_Industry(TileIndex, TransportType, uint, DiagDirection)
959{
960 return 0;
961}
962
963static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
964{
965 /* If the founder merges, the industry was created by the merged company */
966 Industry *i = Industry::GetByTile(tile);
967 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
968
969 if (i->exclusive_supplier == old_owner) i->exclusive_supplier = new_owner;
970 if (i->exclusive_consumer == old_owner) i->exclusive_consumer = new_owner;
971}
972
978 bool IsTileForestIndustry(TileIndex tile)
979{
980 /* Check for industry tile */
981 if (!IsTileType(tile, MP_INDUSTRY)) return false;
982
983 const Industry *ind = Industry::GetByTile(tile);
984
985 /* Check for organic industry (i.e. not processing or extractive) */
986 if (!GetIndustrySpec(ind->type)->life_type.Test(IndustryLifeType::Organic)) return false;
987
988 /* Check for wood production */
989 return std::any_of(std::begin(ind->produced), std::end(ind->produced), [](const auto &p) { return IsValidCargoType(p.cargo) && CargoSpec::Get(p.cargo)->label == CT_WOOD; });
990}
991
992static const uint8_t _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
993
1001 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields, bool allow_rough)
1002{
1003 switch (GetTileType(tile)) {
1004 case MP_CLEAR:
1005 if (IsSnowTile(tile)) return false;
1006 switch (GetClearGround(tile)) {
1007 case CLEAR_DESERT: return false;
1008 case CLEAR_ROUGH: return allow_rough;
1009 case CLEAR_FIELDS: return allow_fields;
1010 default: return true;
1011 }
1012 case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE && (allow_rough || GetTreeGround(tile) != TREE_GROUND_ROUGH);
1013 default: return false;
1014 }
1015}
1016
1024 static void SetupFarmFieldFence(TileIndex tile, int size, uint8_t type, DiagDirection side)
1025{
1026 TileIndexDiff diff = TileOffsByAxis(OtherAxis(DiagDirToAxis(side)));
1027 TileIndexDiff neighbour_diff = TileOffsByDiagDir(side);
1028
1029 do {
1030 tile = Map::WrapToMap(tile);
1031
1032 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
1033 TileIndex neighbour = tile + neighbour_diff;
1034 if (!IsTileType(neighbour, MP_CLEAR) || !IsClearGround(neighbour, CLEAR_FIELDS) || GetFence(neighbour, ReverseDiagDir(side)) == 0) {
1035 /* Add fence as long as neighbouring tile does not already have a fence in the same position. */
1036 uint8_t or_ = type;
1037
1038 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
1039
1040 SetFence(tile, side, or_);
1041 }
1042 }
1043
1044 tile += diff;
1045 } while (--size);
1046}
1047
1048static void PlantFarmField(TileIndex tile, IndustryID industry)
1049{
1050 if (_settings_game.game_creation.landscape == LandscapeType::Arctic) {
1051 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1052 }
1053
1054 /* determine field size */
1055 uint32_t r = (Random() & 0x303) + 0x404;
1056 if (_settings_game.game_creation.landscape == LandscapeType::Arctic) r += 0x404;
1057 uint size_x = GB(r, 0, 8);
1058 uint size_y = GB(r, 8, 8);
1059
1060 TileArea ta(tile - TileDiffXY(std::min(TileX(tile), size_x / 2), std::min(TileY(tile), size_y / 2)), size_x, size_y);
1061 ta.ClampToMap();
1062
1063 if (ta.w == 0 || ta.h == 0) return;
1064
1065 /* check the amount of bad tiles */
1066 int count = 0;
1067 for (TileIndex cur_tile : ta) {
1068 assert(cur_tile < Map::Size());
1069 count += IsSuitableForFarmField(cur_tile, false, false);
1070 }
1071 if (count * 2 < ta.w * ta.h) return;
1072
1073 /* determine type of field */
1074 r = Random();
1075 uint counter = GB(r, 5, 3);
1076 uint field_type = GB(r, 8, 8) * 9 >> 8;
1077
1078 /* make field */
1079 for (TileIndex cur_tile : ta) {
1080 assert(cur_tile < Map::Size());
1081 if (IsSuitableForFarmField(cur_tile, true, true)) {
1082 MakeField(cur_tile, field_type, industry);
1083 SetClearCounter(cur_tile, counter);
1084 MarkTileDirtyByTile(cur_tile);
1085 }
1086 }
1087
1088 int type = 3;
1089 if (_settings_game.game_creation.landscape != LandscapeType::Arctic && _settings_game.game_creation.landscape != LandscapeType::Tropic) {
1090 type = _plantfarmfield_type[Random() & 0xF];
1091 }
1092
1093 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1094 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1095 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1096 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1097}
1098
1099void PlantRandomFarmField(const Industry *i)
1100{
1101 int x = i->location.w / 2 + Random() % 31 - 16;
1102 int y = i->location.h / 2 + Random() % 31 - 16;
1103
1104 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1105
1106 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1107}
1108
1113 static void ChopLumberMillTrees(Industry *i)
1114{
1115 /* Don't process lumber mill if cargo is not set up correctly. */
1116 auto itp = std::begin(i->produced);
1117 if (itp == std::end(i->produced) || !IsValidCargoType(itp->cargo)) return;
1118
1119 /* We only want to cut trees if all tiles are completed. */
1120 for (TileIndex tile_cur : i->location) {
1121 if (i->TileBelongsToIndustry(tile_cur)) {
1122 if (!IsIndustryCompleted(tile_cur)) return;
1123 }
1124 }
1125
1126 for (auto tile : SpiralTileSequence(i->location.tile, 40)) { // 40x40 tiles to search.
1127 if (!IsTileType(tile, MP_TREES) || GetTreeGrowth(tile) < TreeGrowthStage::Grown) continue;
1128
1129 /* found a tree */
1130 _industry_sound_ctr = 1;
1131 _industry_sound_tile = tile;
1132 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_LUMBER_MILL_1, tile);
1133
1134 AutoRestoreBackup<CompanyID> cur_company(_current_company, OWNER_NONE);
1135 Command<CMD_LANDSCAPE_CLEAR>::Do(DoCommandFlag::Execute, tile);
1136
1137 /* Add according value to waiting cargo. */
1138 itp->waiting = ClampTo<uint16_t>(itp->waiting + ScaleByCargoScale(45, false));
1139 break;
1140 }
1141}
1142
1148 static void ProduceIndustryGoodsHelper(Industry *i, bool scale)
1149{
1150 for (auto &p : i->produced) {
1151 if (!IsValidCargoType(p.cargo)) continue;
1152
1153 uint16_t amount = p.rate;
1154 if (scale) amount = ScaleByCargoScale(amount, false);
1155
1156 p.waiting = ClampTo<uint16_t>(p.waiting + amount);
1157 }
1158}
1159
1160static void ProduceIndustryGoods(Industry *i)
1161{
1162 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1163
1164 /* play a sound? */
1165 if ((i->counter & 0x3F) == 0) {
1166 uint32_t r;
1167 if (Chance16R(1, 14, r) && !indsp->random_sounds.empty() && _settings_client.sound.ambient) {
1168 if (std::any_of(std::begin(i->produced), std::end(i->produced), [](const auto &p) { return p.history[LAST_MONTH].production > 0; })) {
1169 /* Play sound since last month had production */
1170 SndPlayTileFx(
1171 static_cast<SoundFx>(indsp->random_sounds[((r >> 16) * indsp->random_sounds.size()) >> 16]),
1172 i->location.tile);
1173 }
1174 }
1175 }
1176
1177 i->counter--;
1178
1179 /* If using an industry callback, scale the callback interval by cargo scale percentage. */
1180 if (indsp->callback_mask.Test(IndustryCallbackMask::Production256Ticks)) {
1181 if (i->counter % ScaleByInverseCargoScale(Ticks::INDUSTRY_PRODUCE_TICKS, false) == 0) {
1182 IndustryProductionCallback(i, 1);
1183 ProduceIndustryGoodsHelper(i, false);
1184 }
1185 }
1186
1187 /*
1188 * All other production and special effects happen every 256 ticks, and cargo production is just scaled by the cargo scale percentage.
1189 * 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.
1190 */
1191 if ((i->counter % Ticks::INDUSTRY_PRODUCE_TICKS) == 0) {
1192 /* Handle non-callback cargo production. */
1193 if (!indsp->callback_mask.Test(IndustryCallbackMask::Production256Ticks)) ProduceIndustryGoodsHelper(i, true);
1194
1195 IndustryBehaviours indbehav = indsp->behaviour;
1196
1197 if (indbehav.Test(IndustryBehaviour::PlantFields)) {
1198 uint16_t cb_res = CALLBACK_FAILED;
1199 if (indsp->callback_mask.Test(IndustryCallbackMask::SpecialEffect)) {
1200 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1201 }
1202
1203 bool plant;
1204 if (cb_res != CALLBACK_FAILED) {
1205 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1206 } else {
1207 plant = Chance16(1, 8);
1208 }
1209
1210 if (plant) PlantRandomFarmField(i);
1211 }
1212 if (indbehav.Test(IndustryBehaviour::CutTrees)) {
1213 uint16_t cb_res = CALLBACK_FAILED;
1214 if (indsp->callback_mask.Test(IndustryCallbackMask::SpecialEffect)) {
1215 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1216 }
1217
1218 bool cut;
1219 if (cb_res != CALLBACK_FAILED) {
1220 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1221 } else {
1222 cut = ((i->counter % Ticks::INDUSTRY_CUT_TREE_TICKS) == 0);
1223 }
1224
1225 if (cut) ChopLumberMillTrees(i);
1226 }
1227
1228 TriggerIndustryRandomisation(i, IndustryRandomTrigger::IndustryTick);
1229 TriggerIndustryAnimation(i, IndustryAnimationTrigger::IndustryTick);
1230 }
1231}
1232
1233void OnTick_Industry()
1234{
1235 if (_industry_sound_ctr != 0) {
1236 _industry_sound_ctr++;
1237
1238 if (_industry_sound_ctr == 75) {
1239 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_LUMBER_MILL_2, _industry_sound_tile);
1240 } else if (_industry_sound_ctr == 160) {
1241 _industry_sound_ctr = 0;
1242 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_LUMBER_MILL_3, _industry_sound_tile);
1243 }
1244 }
1245
1246 if (_game_mode == GM_EDITOR) return;
1247
1248 for (Industry *i : Industry::Iterate()) {
1249 ProduceIndustryGoods(i);
1250
1251 if ((TimerGameTick::counter + i->index) % Ticks::DAY_TICKS == 0) {
1252 for (auto &a : i->accepted) a.accumulated_waiting += a.waiting;
1253 }
1254 }
1255}
1256
1261 static CommandCost CheckNewIndustry_NULL(TileIndex)
1262{
1263 return CommandCost();
1264}
1265
1271 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1272{
1273 if (_settings_game.game_creation.landscape == LandscapeType::Arctic) {
1274 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1275 return CommandCost(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1276 }
1277 }
1278 return CommandCost();
1279}
1280
1288 static bool CheckScaledDistanceFromEdge(TileIndex tile, uint maxdist)
1289{
1290 uint maxdist_x = maxdist;
1291 uint maxdist_y = maxdist;
1292
1293 if (Map::SizeX() > 256) maxdist_x *= Map::SizeX() / 256;
1294 if (Map::SizeY() > 256) maxdist_y *= Map::SizeY() / 256;
1295
1296 if (DistanceFromEdgeDir(tile, DIAGDIR_NE) < maxdist_x) return true;
1297 if (DistanceFromEdgeDir(tile, DIAGDIR_NW) < maxdist_y) return true;
1298 if (DistanceFromEdgeDir(tile, DIAGDIR_SW) < maxdist_x) return true;
1299 if (DistanceFromEdgeDir(tile, DIAGDIR_SE) < maxdist_y) return true;
1300
1301 return false;
1302}
1303
1309 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1310{
1311 if (_game_mode == GM_EDITOR) return CommandCost();
1312
1313 if (CheckScaledDistanceFromEdge(TileAddXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1314
1315 return CommandCost(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1316}
1317
1318extern bool _ignore_industry_restrictions;
1319
1325 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1326{
1327 if (_game_mode == GM_EDITOR && _ignore_industry_restrictions) return CommandCost();
1328
1329 if (TileHeight(tile) == 0 &&
1330 CheckScaledDistanceFromEdge(TileAddXY(tile, 1, 1), _settings_game.game_creation.oil_refinery_limit)) return CommandCost();
1331
1332 return CommandCost(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1333}
1334
1340 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1341{
1342 if (_settings_game.game_creation.landscape == LandscapeType::Arctic) {
1343 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1344 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1345 }
1346 }
1347 return CommandCost();
1348}
1349
1355 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1356{
1357 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1358 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1359 }
1360 return CommandCost();
1361}
1362
1368 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1369{
1370 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1371 return CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1372 }
1373 return CommandCost();
1374}
1375
1381 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1382{
1383 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1384 return CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1385 }
1386 return CommandCost();
1387}
1388
1394 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1395{
1396 if (GetTileZ(tile) > 4) {
1397 return CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1398 }
1399 return CommandCost();
1400}
1401
1407 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1408
1410 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1411 CheckNewIndustry_NULL,
1412 CheckNewIndustry_Forest,
1413 CheckNewIndustry_OilRefinery,
1414 CheckNewIndustry_Farm,
1415 CheckNewIndustry_Plantation,
1416 CheckNewIndustry_Water,
1417 CheckNewIndustry_Lumbermill,
1418 CheckNewIndustry_BubbleGen,
1419 CheckNewIndustry_OilRig,
1420};
1421
1432 static CommandCost FindTownForIndustry(TileIndex tile, IndustryType type, Town **t)
1433{
1434 *t = ClosestTownFromTile(tile, UINT_MAX);
1435
1436 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1437
1438 for (const IndustryID &industry : Industry::industries[type]) {
1439 if (Industry::Get(industry)->town == *t) {
1440 *t = nullptr;
1441 return CommandCost(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1442 }
1443 }
1444
1445 return CommandCost();
1446}
1447
1448bool IsSlopeRefused(Slope current, Slope refused)
1449{
1450 if (IsSteepSlope(current)) return true;
1451 if (current != SLOPE_FLAT) {
1452 if (IsSteepSlope(refused)) return true;
1453
1454 Slope t = ComplementSlope(current);
1455
1456 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1457 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1458 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1459 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1460 }
1461
1462 return false;
1463}
1464
1472 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, IndustryType type)
1473{
1474 IndustryBehaviours ind_behav = GetIndustrySpec(type)->behaviour;
1475
1476 for (const IndustryTileLayoutTile &it : layout) {
1477 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1478 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1479
1480 if (!IsValidTile(cur_tile)) {
1481 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1482 }
1483
1484 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1485 if (!IsWaterTile(cur_tile) ||
1486 !IsTileFlat(cur_tile)) {
1487 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1488 }
1489 } else {
1490 CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1491 if (ret.Failed()) return ret;
1492 if (IsBridgeAbove(cur_tile)) return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1493
1494 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1495
1496 /* Perform land/water check if not disabled */
1497 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) != ind_behav.Test(IndustryBehaviour::BuiltOnWater))) return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1498
1499 if (ind_behav.Any({IndustryBehaviour::OnlyInTown, IndustryBehaviour::Town1200More}) || // Tile must be a house
1500 (ind_behav.Test(IndustryBehaviour::OnlyNearTown) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1501 if (!IsTileType(cur_tile, MP_HOUSE)) {
1502 return CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1503 }
1504
1505 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1506 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN);
1507 ret = Command<CMD_LANDSCAPE_CLEAR>::Do({}, cur_tile);
1508 cur_company.Restore();
1509
1510 if (ret.Failed()) return ret;
1511 } else {
1512 /* Clear the tiles, but do not affect town ratings */
1513 ret = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoTestTownRating, DoCommandFlag::NoModifyTownRating}, cur_tile);
1514 if (ret.Failed()) return ret;
1515 }
1516 }
1517 }
1518
1519 return CommandCost();
1520}
1521
1534 static CommandCost CheckIfIndustryTileSlopes(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, IndustryType type, uint16_t initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
1535{
1536 bool refused_slope = false;
1537 bool custom_shape = false;
1538
1539 for (const IndustryTileLayoutTile &it : layout) {
1540 IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
1541 TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
1542 assert(IsValidTile(cur_tile)); // checked before in CheckIfIndustryTilesAreFree
1543
1544 if (gfx != GFX_WATERTILE_SPECIALCHECK) {
1545 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1546
1547 if (its->callback_mask.Test(IndustryTileCallbackMask::ShapeCheck)) {
1548 custom_shape = true;
1549 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
1550 if (ret.Failed()) return ret;
1551 } else {
1552 Slope tileh = GetTileSlope(cur_tile);
1553 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1554 }
1555 }
1556 }
1557
1558 if (custom_shape_check != nullptr) *custom_shape_check = custom_shape;
1559
1560 /* It is almost impossible to have a fully flat land in TG, so what we
1561 * do is that we check if we can make the land flat later on. See
1562 * CheckIfCanLevelIndustryPlatform(). */
1563 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_industry_restrictions)) {
1564 return CommandCost();
1565 }
1566 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
1567}
1568
1576 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, IndustryType type, const Town *t)
1577{
1578 if (GetIndustrySpec(type)->behaviour.Test(IndustryBehaviour::Town1200More) && t->cache.population < 1200) {
1579 return CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1580 }
1581
1582 if (GetIndustrySpec(type)->behaviour.Test(IndustryBehaviour::OnlyNearTown) && DistanceMax(t->xy, tile) > 9) {
1583 return CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1584 }
1585
1586 return CommandCost();
1587}
1588
1589static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1590{
1591 /* Check if we don't leave the map */
1592 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1593
1594 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1595 for (TileIndex tile_walk : ta) {
1596 uint curh = TileHeight(tile_walk);
1597 /* Is the tile clear? */
1598 if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1599
1600 /* Don't allow too big of a change if this is the sub-tile check */
1601 if (internal != 0 && Delta(curh, height) > 1) return false;
1602
1603 /* Different height, so the surrounding tiles of this tile
1604 * has to be correct too (in level, or almost in level)
1605 * else you get a chain-reaction of terraforming. */
1606 if (internal == 0 && curh != height) {
1607 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1608 return false;
1609 }
1610 }
1611 }
1612
1613 return true;
1614}
1615
1620 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlags flags, const IndustryTileLayout &layout)
1621{
1622 int max_x = 0;
1623 int max_y = 0;
1624
1625 /* Finds dimensions of largest variant of this industry */
1626 for (const IndustryTileLayoutTile &it : layout) {
1627 if (it.gfx == GFX_WATERTILE_SPECIALCHECK) continue; // watercheck tiles don't count for footprint size
1628 if (it.ti.x > max_x) max_x = it.ti.x;
1629 if (it.ti.y > max_y) max_y = it.ti.y;
1630 }
1631
1632 /* Remember level height */
1633 uint h = TileHeight(tile);
1634
1635 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1636 /* Check that all tiles in area and surrounding are clear
1637 * this determines that there are no obstructing items */
1638
1639 /* TileArea::Expand is not used here as we need to abort
1640 * instead of clamping if the bounds cannot expanded. */
1641 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1642 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1643
1644 if (TileX(ta.tile) + ta.w >= Map::MaxX() || TileY(ta.tile) + ta.h >= Map::MaxY()) return false;
1645
1646 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1647 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1648 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN);
1649
1650 for (TileIndex tile_walk : ta) {
1651 uint curh = TileHeight(tile_walk);
1652 if (curh != h) {
1653 /* This tile needs terraforming. Check if we can do that without
1654 * damaging the surroundings too much. */
1655 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1656 cur_company.Restore();
1657 return false;
1658 }
1659 /* This is not 100% correct check, but the best we can do without modifying the map.
1660 * What is missing, is if the difference in height is more than 1.. */
1661 if (std::get<0>(Command<CMD_TERRAFORM_LAND>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), tile_walk, SLOPE_N, curh <= h)).Failed()) {
1662 cur_company.Restore();
1663 return false;
1664 }
1665 }
1666 }
1667
1668 if (flags.Test(DoCommandFlag::Execute)) {
1669 /* Terraform the land under the industry */
1670 for (TileIndex tile_walk : ta) {
1671 uint curh = TileHeight(tile_walk);
1672 while (curh != h) {
1673 /* We give the terraforming for free here, because we can't calculate
1674 * exact cost in the test-round, and as we all know, that will cause
1675 * a nice assert if they don't match ;) */
1676 Command<CMD_TERRAFORM_LAND>::Do(flags, tile_walk, SLOPE_N, curh <= h);
1677 curh += (curh > h) ? -1 : 1;
1678 }
1679 }
1680 }
1681
1682 cur_company.Restore();
1683 return true;
1684}
1685
1686
1693 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, IndustryType type)
1694{
1695 const IndustrySpec *indspec = GetIndustrySpec(type);
1696
1697 for (IndustryType conflicting_type : indspec->conflicting) {
1698 if (conflicting_type == IT_INVALID) continue;
1699
1700 for (const IndustryID &industry : Industry::industries[conflicting_type]) {
1701 /* Within 14 tiles from another industry is considered close */
1702 if (DistanceMax(tile, Industry::Get(industry)->location.tile) > 14) continue;
1703
1704 return CommandCost(STR_ERROR_INDUSTRY_TOO_CLOSE);
1705 }
1706 }
1707 return CommandCost();
1708}
1709
1714 static void AdvertiseIndustryOpening(const Industry *ind)
1715{
1716 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1717 EncodedString headline;
1718 if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1719 headline = GetEncodedString(ind_spc->new_industry_text, ind_spc->name, STR_TOWN_NAME, ind->town->index);
1720 } else {
1721 headline = GetEncodedString(ind_spc->new_industry_text, ind_spc->name, ind->town->index);
1722 }
1723 AddIndustryNewsItem(std::move(headline), NewsType::IndustryOpen, ind->index);
1724 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1725 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1726}
1727
1733 static void PopulateStationsNearby(Industry *ind)
1734{
1735 if (ind->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) {
1736 /* Industry has a neutral station. Use it and ignore any other nearby stations. */
1737 ind->stations_near.insert(ind->neutral_station);
1738 ind->neutral_station->industries_near.clear();
1739 ind->neutral_station->industries_near.insert(IndustryListEntry{0, ind});
1740 return;
1741 }
1742
1743 ForAllStationsAroundTiles(ind->location, [ind](Station *st, TileIndex tile) {
1744 if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) != ind->index) return false;
1745 ind->stations_near.insert(st);
1746 st->AddIndustryToDeliver(ind, tile);
1747 return false;
1748 });
1749}
1750
1762 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)
1763{
1764 const IndustrySpec *indspec = GetIndustrySpec(type);
1765
1766 i->location = TileArea(tile, 1, 1);
1767 i->type = type;
1768
1769 auto &industries = Industry::industries[type];
1770 industries.insert(i->index);
1771
1772 size_t produced_count = 0;
1773 for (size_t index = 0; index < std::size(indspec->produced_cargo); ++index) {
1774 if (IsValidCargoType(indspec->produced_cargo[index])) {
1775 produced_count = index + 1;
1776 }
1777 }
1778 for (size_t index = 0; index < produced_count; ++index) {
1779 Industry::ProducedCargo &p = i->produced.emplace_back();
1780 p.cargo = indspec->produced_cargo[index];
1781 p.rate = indspec->production_rate[index];
1782 }
1783
1784 size_t accepted_count = 0;
1785 for (size_t index = 0; index < std::size(indspec->accepts_cargo); ++index) {
1786 if (IsValidCargoType(indspec->accepts_cargo[index])) {
1787 accepted_count = index + 1;
1788 }
1789 }
1790 for (size_t index = 0; index < accepted_count; ++index) {
1791 Industry::AcceptedCargo &a = i->accepted.emplace_back();
1792 a.cargo = indspec->accepts_cargo[index];
1793 }
1794
1795 /* Randomize initial production if non-original economy is used and there are no production related callbacks. */
1796 if (!indspec->UsesOriginalEconomy()) {
1797 for (auto &p : i->produced) {
1798 p.rate = ClampTo<uint8_t>((RandomRange(256) + 128) * p.rate >> 8);
1799 }
1800 }
1801
1802 i->town = t;
1803 i->owner = OWNER_NONE;
1804
1805 uint16_t r = Random();
1806 i->random_colour = static_cast<Colours>(GB(r, 0, 4));
1807 i->counter = GB(r, 4, 12);
1808 i->random = initial_random_bits;
1809 i->was_cargo_delivered = false;
1810 i->last_prod_year = TimerGameEconomy::year;
1811 i->founder = founder;
1812 i->ctlflags = {};
1813
1814 i->construction_date = TimerGameCalendar::date;
1815 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1816 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1817
1818 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1819 * 0 = created prior of newindustries
1820 * else, chosen layout + 1 */
1821 i->selected_layout = (uint8_t)(layout_index + 1);
1822
1823 i->exclusive_supplier = INVALID_OWNER;
1824 i->exclusive_consumer = INVALID_OWNER;
1825
1826 i->prod_level = PRODLEVEL_DEFAULT;
1827
1828 /* Call callbacks after the regular fields got initialised. */
1829
1830 if (indspec->callback_mask.Test(IndustryCallbackMask::ProdChangeBuild)) {
1831 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1832 if (res != CALLBACK_FAILED) {
1833 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1834 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1835 } else {
1836 i->prod_level = res;
1837 i->RecomputeProductionMultipliers();
1838 }
1839 }
1840 }
1841
1842 if (_generating_world) {
1843 if (indspec->callback_mask.Test(IndustryCallbackMask::Production256Ticks)) {
1844 IndustryProductionCallback(i, 1);
1845 for (auto &p : i->produced) {
1846 if (IsValidCargoType(p.cargo)) p.history[LAST_MONTH].production = ScaleByCargoScale(p.waiting * 8, false);
1847 p.waiting = 0;
1848 }
1849 }
1850
1851 for (auto &p : i->produced) {
1852 if (IsValidCargoType(p.cargo)) p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
1853 }
1854
1855 UpdateValidHistory(i->valid_history, HISTORY_YEAR, TimerGameEconomy::month);
1856 }
1857
1858 if (indspec->callback_mask.Test(IndustryCallbackMask::DecideColour)) {
1859 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1860 if (res != CALLBACK_FAILED) {
1861 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1862 i->random_colour = static_cast<Colours>(GB(res, 0, 4));
1863 }
1864 }
1865
1866 if (indspec->callback_mask.Test(IndustryCallbackMask::InputCargoTypes)) {
1867 /* Clear all input cargo types */
1868 i->accepted.clear();
1869 /* Query actual types */
1870 uint maxcargoes = indspec->behaviour.Test(IndustryBehaviour::CargoTypesUnlimited) ? INDUSTRY_NUM_INPUTS : 3;
1871 for (uint j = 0; j < maxcargoes; j++) {
1872 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1873 if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
1874 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1875 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1876 break;
1877 }
1878 CargoType cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1879 /* Industries without "unlimited" cargo types support depend on the specific order/slots of cargo types.
1880 * They need to be able to blank out specific slots without aborting the callback sequence,
1881 * and solve this by returning undefined cargo indexes. Skip these. */
1882 if (!IsValidCargoType(cargo) && !indspec->behaviour.Test(IndustryBehaviour::CargoTypesUnlimited)) {
1883 /* As slots are allocated as needed now, this means we do need to add a slot for the invalid cargo. */
1884 Industry::AcceptedCargo &a = i->accepted.emplace_back();
1885 a.cargo = INVALID_CARGO;
1886 continue;
1887 }
1888 /* Verify valid cargo */
1889 if (std::ranges::find(indspec->accepts_cargo, cargo) == std::end(indspec->accepts_cargo)) {
1890 /* Cargo not in spec, error in NewGRF */
1891 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1892 break;
1893 }
1894 if (std::any_of(std::begin(i->accepted), std::begin(i->accepted) + j, [&cargo](const auto &a) { return a.cargo == cargo; })) {
1895 /* Duplicate cargo */
1896 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1897 break;
1898 }
1899 Industry::AcceptedCargo &a = i->accepted.emplace_back();
1900 a.cargo = cargo;
1901 }
1902 }
1903
1904 if (indspec->callback_mask.Test(IndustryCallbackMask::OutputCargoTypes)) {
1905 /* Clear all output cargo types */
1906 i->produced.clear();
1907 /* Query actual types */
1908 uint maxcargoes = indspec->behaviour.Test(IndustryBehaviour::CargoTypesUnlimited) ? INDUSTRY_NUM_OUTPUTS : 2;
1909 for (uint j = 0; j < maxcargoes; j++) {
1910 uint16_t res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1911 if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
1912 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1913 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1914 break;
1915 }
1916 CargoType cargo = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1917 /* Allow older GRFs to skip slots. */
1918 if (!IsValidCargoType(cargo) && !indspec->behaviour.Test(IndustryBehaviour::CargoTypesUnlimited)) {
1919 /* As slots are allocated as needed now, this means we do need to add a slot for the invalid cargo. */
1920 Industry::ProducedCargo &p = i->produced.emplace_back();
1921 p.cargo = INVALID_CARGO;
1922 continue;
1923 }
1924 /* Verify valid cargo */
1925 if (std::ranges::find(indspec->produced_cargo, cargo) == std::end(indspec->produced_cargo)) {
1926 /* Cargo not in spec, error in NewGRF */
1927 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1928 break;
1929 }
1930 if (std::any_of(std::begin(i->produced), std::begin(i->produced) + j, [&cargo](const auto &p) { return p.cargo == cargo; })) {
1931 /* Duplicate cargo */
1932 ErrorUnknownCallbackResult(indspec->grf_prop.grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1933 break;
1934 }
1935 Industry::ProducedCargo &p = i->produced.emplace_back();
1936 p.cargo = cargo;
1937 }
1938 }
1939
1940 /* Plant the tiles */
1941
1942 for (const IndustryTileLayoutTile &it : layout) {
1943 TileIndex cur_tile = tile + ToTileIndexDiff(it.ti);
1944
1945 if (it.gfx != GFX_WATERTILE_SPECIALCHECK) {
1946 i->location.Add(cur_tile);
1947
1948 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WaterClass::Invalid);
1949
1950 Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Execute, DoCommandFlag::NoTestTownRating, DoCommandFlag::NoModifyTownRating}, cur_tile);
1951
1952 MakeIndustry(cur_tile, i->index, it.gfx, Random(), wc);
1953
1954 if (_generating_world) {
1955 SetIndustryConstructionCounter(cur_tile, 3);
1956 SetIndustryConstructionStage(cur_tile, 2);
1957 }
1958
1959 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1960 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it.gfx);
1961 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1962 if (its->animation.status != AnimationStatus::NoAnimation) AddAnimatedTile(cur_tile);
1963 }
1964 }
1965
1966 /* Call callbacks after all tiles have been created. */
1967 for (TileIndex cur_tile : i->location) {
1968 if (i->TileBelongsToIndustry(cur_tile)) {
1969 /* There are no shared random bits, consistent with "MakeIndustryTileBigger" in tile loop.
1970 * So, trigger tiles individually */
1971 TriggerIndustryTileAnimation_ConstructionStageChanged(cur_tile, true);
1972 }
1973 }
1974
1975 if (GetIndustrySpec(i->type)->behaviour.Test(IndustryBehaviour::PlantOnBuild)) {
1976 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1977 }
1978 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_FORCE_REBUILD);
1979 SetWindowDirty(WC_BUILD_INDUSTRY, 0);
1980
1981 if (!_generating_world) PopulateStationsNearby(i);
1982}
1983
2000 static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlags flags, const IndustrySpec *indspec, size_t layout_index, uint32_t random_var8f, uint16_t random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
2001{
2002 assert(layout_index < indspec->layouts.size());
2003 const IndustryTileLayout &layout = indspec->layouts[layout_index];
2004
2005 *ip = nullptr;
2006
2007 /* 1. Cheap: Built-in checks on industry level. */
2008 CommandCost ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
2009 if (ret.Failed()) return ret;
2010
2011 Town *t = nullptr;
2012 ret = FindTownForIndustry(tile, type, &t);
2013 if (ret.Failed()) return ret;
2014 assert(t != nullptr);
2015
2016 ret = CheckIfIndustryIsAllowed(tile, type, t);
2017 if (ret.Failed()) return ret;
2018
2019 /* 2. Built-in checks on industry tiles. */
2020 std::vector<ClearedObjectArea> object_areas(_cleared_object_areas);
2021 ret = CheckIfIndustryTilesAreFree(tile, layout, type);
2022 _cleared_object_areas = std::move(object_areas);
2023 if (ret.Failed()) return ret;
2024
2025 /* 3. NewGRF-defined checks on industry level. */
2026 if (GetIndustrySpec(type)->callback_mask.Test(IndustryCallbackMask::Location)) {
2027 ret = CheckIfCallBackAllowsCreation(tile, type, layout_index, random_var8f, random_initial_bits, founder, creation_type);
2028 } else {
2029 ret = _check_new_industry_procs[indspec->check_proc](tile);
2030 }
2031 if (ret.Failed()) return ret;
2032
2033 /* 4. Expensive: NewGRF-defined checks on industry tiles. */
2034 bool custom_shape_check = false;
2035 ret = CheckIfIndustryTileSlopes(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
2036 if (ret.Failed()) return ret;
2037
2038 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
2039 !_ignore_industry_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DoCommandFlag::NoWater, layout)) {
2040 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
2041 }
2042
2043 if (!Industry::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_INDUSTRIES);
2044
2045 if (flags.Test(DoCommandFlag::Execute)) {
2046 *ip = new Industry(tile);
2047 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, {DoCommandFlag::NoWater, DoCommandFlag::Execute}, layout);
2048 DoCreateNewIndustry(*ip, tile, type, layout, layout_index, t, founder, random_initial_bits);
2049 }
2050
2051 return CommandCost();
2052}
2053
2064 CommandCost CmdBuildIndustry(DoCommandFlags flags, TileIndex tile, IndustryType it, uint32_t first_layout, bool fund, uint32_t seed)
2065{
2066 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
2067
2068 const IndustrySpec *indspec = GetIndustrySpec(it);
2069
2070 /* Check if the to-be built/founded industry is available for this climate. */
2071 if (!indspec->enabled || indspec->layouts.empty()) return CMD_ERROR;
2072
2073 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
2074 * Raw material industries are industries that do not accept cargo (at least for now) */
2075 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
2076 return CMD_ERROR;
2077 }
2078
2079 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
2080 return CMD_ERROR;
2081 }
2082
2083 Randomizer randomizer;
2084 randomizer.SetSeed(seed);
2085 uint16_t random_initial_bits = GB(seed, 0, 16);
2086 uint32_t random_var8f = randomizer.Next();
2087 size_t num_layouts = indspec->layouts.size();
2088 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
2089 const bool deity_prospect = _current_company == OWNER_DEITY && !fund;
2090
2091 Industry *ind = nullptr;
2092 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
2093 if (flags.Test(DoCommandFlag::Execute)) {
2094 /* Prospecting has a chance to fail, however we cannot guarantee that something can
2095 * be built on the map, so the chance gets lower when the map is fuller, but there
2096 * is nothing we can really do about that. */
2097 bool prospect_success = deity_prospect || Random() <= indspec->prospecting_chance;
2098 if (prospect_success) {
2099 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
2100 IndustryAvailabilityCallType calltype = _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION;
2101 Backup<CompanyID> cur_company(_current_company, OWNER_TOWN);
2102 for (int i = 0; i < 5000; i++) {
2103 /* We should not have more than one Random() in a function call
2104 * because parameter evaluation order is not guaranteed in the c++ standard
2105 */
2106 tile = RandomTile();
2107 /* Start with a random layout */
2108 size_t layout = RandomRange((uint32_t)num_layouts);
2109 /* Check now each layout, starting with the random one */
2110 for (size_t j = 0; j < num_layouts; j++) {
2111 layout = (layout + 1) % num_layouts;
2112 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), calltype, &ind);
2113 if (ret.Succeeded()) break;
2114 }
2115 if (ret.Succeeded()) break;
2116 }
2117 cur_company.Restore();
2118 }
2119 if (ret.Failed() && IsLocalCompany()) {
2120 if (prospect_success) {
2121 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_PROSPECT_INDUSTRY), GetEncodedString(STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING), WL_INFO);
2122 } else {
2123 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_PROSPECT_INDUSTRY), GetEncodedString(STR_ERROR_PROSPECTING_WAS_UNLUCKY), WL_INFO);
2124 }
2125 }
2126 }
2127 } else {
2128 size_t layout = first_layout;
2129 if (layout >= num_layouts) return CMD_ERROR;
2130
2131 /* Check subsequently each layout, starting with the given layout in p1 */
2132 for (size_t i = 0; i < num_layouts; i++) {
2133 layout = (layout + 1) % num_layouts;
2134 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
2135 if (ret.Succeeded()) break;
2136 }
2137
2138 /* If it still failed, there's no suitable layout to build here, return the error */
2139 if (ret.Failed()) return ret;
2140 }
2141
2142 if (flags.Test(DoCommandFlag::Execute) && ind != nullptr && _game_mode != GM_EDITOR) {
2143 AdvertiseIndustryOpening(ind);
2144 }
2145
2146 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
2147}
2148
2156 CommandCost CmdIndustrySetFlags(DoCommandFlags flags, IndustryID ind_id, IndustryControlFlags ctlflags)
2157{
2158 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2159
2160 Industry *ind = Industry::GetIfValid(ind_id);
2161 if (ind == nullptr) return CMD_ERROR;
2162 if (!ctlflags.IsValid()) return CMD_ERROR;
2163
2164 if (flags.Test(DoCommandFlag::Execute)) ind->ctlflags = ctlflags;
2165
2166 return CommandCost();
2167}
2168
2178 CommandCost CmdIndustrySetProduction(DoCommandFlags flags, IndustryID ind_id, uint8_t prod_level, bool show_news, const EncodedString &custom_news)
2179{
2180 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2181 if (prod_level < PRODLEVEL_MINIMUM || prod_level > PRODLEVEL_MAXIMUM) return CMD_ERROR;
2182
2183 Industry *ind = Industry::GetIfValid(ind_id);
2184 if (ind == nullptr) return CMD_ERROR;
2185
2186 if (flags.Test(DoCommandFlag::Execute)) {
2187 ind->ctlflags.Set(IndustryControlFlag::ExternalProdLevel);
2188 ind->prod_level = prod_level;
2189 ind->RecomputeProductionMultipliers();
2190
2191 /* Show news message if requested. */
2192 if (show_news && prod_level != ind->prod_level) {
2193 NewsType nt;
2194 switch (WhoCanServiceIndustry(ind)) {
2195 case 0: nt = NewsType::IndustryNobody; break;
2196 case 1: nt = NewsType::IndustryOther; break;
2197 case 2: nt = NewsType::IndustryCompany; break;
2198 default: NOT_REACHED();
2199 }
2200
2201 /* Set parameters of news string */
2202 EncodedString headline;
2203 if (!custom_news.empty()) {
2204 headline = custom_news;
2205 } else {
2206 StringID str = (prod_level > ind->prod_level)
2207 ? GetIndustrySpec(ind->type)->production_up_text
2208 : GetIndustrySpec(ind->type)->production_down_text;
2209
2210 if (str > STR_LAST_STRINGID) {
2211 headline = GetEncodedString(str, STR_TOWN_NAME, ind->town->index, GetIndustrySpec(ind->type)->name);
2212 } else {
2213 headline = GetEncodedString(str, ind->index);
2214 }
2215 }
2216
2217 AddIndustryNewsItem(std::move(headline), nt, ind->index);
2218 }
2219 }
2220
2221 return CommandCost();
2222}
2223
2233 CommandCost CmdIndustrySetExclusivity(DoCommandFlags flags, IndustryID ind_id, Owner company_id, bool consumer)
2234{
2235 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2236
2237 Industry *ind = Industry::GetIfValid(ind_id);
2238 if (ind == nullptr) return CMD_ERROR;
2239
2240 if (company_id != OWNER_NONE && company_id != INVALID_OWNER && company_id != OWNER_DEITY
2241 && !Company::IsValidID(company_id)) return CMD_ERROR;
2242
2243 if (flags.Test(DoCommandFlag::Execute)) {
2244 if (consumer) {
2245 ind->exclusive_consumer = company_id;
2246 } else {
2247 ind->exclusive_supplier = company_id;
2248 }
2249 }
2250
2251
2252 return CommandCost();
2253}
2254
2262 CommandCost CmdIndustrySetText(DoCommandFlags flags, IndustryID ind_id, const EncodedString &text)
2263{
2264 if (_current_company != OWNER_DEITY) return CMD_ERROR;
2265
2266 Industry *ind = Industry::GetIfValid(ind_id);
2267 if (ind == nullptr) return CMD_ERROR;
2268
2269 if (flags.Test(DoCommandFlag::Execute)) {
2270 ind->text.clear();
2271 if (!text.empty()) ind->text = text;
2272 InvalidateWindowData(WC_INDUSTRY_VIEW, ind->index);
2273 }
2274
2275 return CommandCost();
2276}
2277
2285 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
2286{
2287 const IndustrySpec *indspec = GetIndustrySpec(type);
2288
2289 uint32_t seed = Random();
2290 uint32_t seed2 = Random();
2291 Industry *i = nullptr;
2292 size_t layout_index = RandomRange((uint32_t)indspec->layouts.size());
2293 [[maybe_unused]] CommandCost ret = CreateNewIndustryHelper(tile, type, DoCommandFlag::Execute, indspec, layout_index, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
2294 assert(i != nullptr || ret.Failed());
2295 return i;
2296}
2297
2305 static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, std::optional<bool> water, bool *force_at_least_one)
2306{
2307 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2308 if (water.has_value() && ind_spc->behaviour.Test(IndustryBehaviour::BuiltOnWater) != *water) return 0;
2309
2310 uint32_t chance = ind_spc->appear_creation[to_underlying(_settings_game.game_creation.landscape)];
2311 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2312 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
2313 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
2314 *force_at_least_one = false;
2315 return 0;
2316 } else {
2317 chance *= 16; // to increase precision
2318 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
2319 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
2320 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? Map::ScaleBySize1D(chance) : Map::ScaleBySize(chance);
2321
2322 *force_at_least_one = (chance > 0) && !ind_spc->behaviour.Test(IndustryBehaviour::NoBuildMapCreation) && (_game_mode != GM_EDITOR);
2323 return chance;
2324 }
2325}
2326
2333 static uint16_t GetIndustryGamePlayProbability(IndustryType it, uint8_t *min_number)
2334{
2335 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2336 *min_number = 0;
2337 return 0;
2338 }
2339
2340 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2341 uint8_t chance = ind_spc->appear_ingame[to_underlying(_settings_game.game_creation.landscape)];
2342 if (!ind_spc->enabled || ind_spc->layouts.empty() ||
2343 (ind_spc->behaviour.Test(IndustryBehaviour::Before1950) && TimerGameCalendar::year > 1950) ||
2344 (ind_spc->behaviour.Test(IndustryBehaviour::After1960) && TimerGameCalendar::year < 1960) ||
2345 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2346 *min_number = 0;
2347 return 0;
2348 }
2349 *min_number = ind_spc->behaviour.Test(IndustryBehaviour::CanCloseLastInstance) ? 1 : 0;
2350 return chance;
2351}
2352
2357 static uint GetNumberOfIndustries()
2358{
2359 /* Number of industries on a 256x256 map. */
2360 static const uint16_t numof_industry_table[] = {
2361 0, // none
2362 0, // minimal
2363 10, // very low
2364 25, // low
2365 55, // normal
2366 80, // high
2367 0, // custom
2368 };
2369
2370 assert(lengthof(numof_industry_table) == ID_END);
2371 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2372
2373 if (difficulty == ID_CUSTOM) return std::min<uint>(IndustryPool::MAX_SIZE, _settings_game.game_creation.custom_industry_number);
2374
2375 return std::min<uint>(IndustryPool::MAX_SIZE, Map::ScaleBySize(numof_industry_table[difficulty]));
2376}
2377
2386 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2387{
2388 uint tries = try_hard ? 10000u : 2000u;
2389 for (; tries > 0; tries--) {
2390 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2391 if (ind != nullptr) return ind;
2392 }
2393 return nullptr;
2394}
2395
2401 static void PlaceInitialIndustry(IndustryType type, bool water, bool try_hard)
2402{
2403 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
2404
2405 IncreaseGeneratingWorldProgress(water ? GWP_WATER_INDUSTRY : GWP_LAND_INDUSTRY);
2406 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2407
2408 cur_company.Restore();
2409}
2410
2415 static uint GetCurrentTotalNumberOfIndustries()
2416{
2417 uint total = 0;
2418 for (const auto &industries : Industry::industries) {
2419 total += static_cast<uint16_t>(std::size(industries));
2420 }
2421 return total;
2422}
2423
2424
2426 void IndustryTypeBuildData::Reset()
2427{
2428 this->probability = 0;
2429 this->min_number = 0;
2430 this->target_count = 0;
2431 this->max_wait = 1;
2432 this->wait_count = 0;
2433}
2434
2436 void IndustryBuildData::Reset()
2437{
2438 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2439
2440 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2441 this->builddata[it].Reset();
2442 }
2443}
2444
2446 void IndustryBuildData::EconomyMonthlyLoop()
2447{
2448 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.
2449 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2450
2451 /* To prevent running out of unused industries for the player to connect,
2452 * add a fraction of new industries each month, but only if the manager can keep up. */
2453 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).
2454 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2455 this->wanted_inds += Map::ScaleBySize(NEWINDS_PER_MONTH);
2456 }
2457}
2458
2459 struct IndustryGenerationProbabilities {
2460 std::array<uint32_t, NUM_INDUSTRYTYPES> probs{};
2461 std::array<bool, NUM_INDUSTRYTYPES> force_one{};
2462 uint64_t total = 0;
2463 uint num_forced = 0;
2464};
2465
2471 static IndustryGenerationProbabilities GetScaledProbabilities(bool water)
2472{
2473 IndustryGenerationProbabilities p{};
2474
2475 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2476 p.probs[it] = GetScaledIndustryGenerationProbability(it, water, &p.force_one[it]);
2477 p.total += p.probs[it];
2478 if (p.force_one[it]) p.num_forced++;
2479 }
2480
2481 return p;
2482}
2483
2488 void GenerateIndustries()
2489{
2490 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2491
2492 /* Get the probabilities for all industries. This is done first as we need the total of
2493 * both land and water for scaling later. */
2494 IndustryGenerationProbabilities lprob = GetScaledProbabilities(false);
2495 IndustryGenerationProbabilities wprob = GetScaledProbabilities(true);
2496
2497 /* Run generation twice, for land and water industries in turn. */
2498 for (bool water = false;; water = true) {
2499 auto &p = water ? wprob : lprob;
2500
2501 /* Total number of industries scaled by land/water proportion. */
2502 uint total_amount = 0;
2503 if (lprob.total + wprob.total > 0) total_amount = p.total * GetNumberOfIndustries() / (lprob.total + wprob.total);
2504
2505 /* Scale land-based industries to the land proportion, unless the player has set a custom industry count. */
2506 if (!water && _settings_game.difficulty.industry_density != ID_CUSTOM) total_amount = Map::ScaleByLandProportion(total_amount);
2507
2508 /* Ensure that forced industries are generated even if the scaled amounts are too low. */
2509 if (p.total == 0 || total_amount < p.num_forced) {
2510 /* Only place the forced ones */
2511 total_amount = p.num_forced;
2512 }
2513
2514 SetGeneratingWorldProgress(water ? GWP_WATER_INDUSTRY : GWP_LAND_INDUSTRY, total_amount);
2515
2516 /* Try to build one industry per type independent of any probabilities */
2517 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2518 if (p.force_one[it]) {
2519 assert(total_amount > 0);
2520 total_amount--;
2521 PlaceInitialIndustry(it, water, true);
2522 }
2523 }
2524
2525 /* Add the remaining industries according to their probabilities */
2526 for (uint i = 0; i < total_amount; i++) {
2527 uint32_t r = RandomRange(p.total);
2528 IndustryType it = 0;
2529 while (r >= p.probs[it]) {
2530 r -= p.probs[it];
2531 it++;
2532 assert(it < NUM_INDUSTRYTYPES);
2533 }
2534 assert(p.probs[it] > 0);
2535 PlaceInitialIndustry(it, water, false);
2536 }
2537
2538 if (water) break;
2539 }
2540
2541 _industry_builder.Reset();
2542}
2543
2544template <>
2545 Industry::ProducedHistory SumHistory(std::span<const Industry::ProducedHistory> history)
2546{
2547 uint32_t production = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &p) { return r + p.production; });
2548 uint32_t transported = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &p) { return r + p.transported; });
2549 auto count = std::size(history);
2550 return {.production = ClampTo<uint16_t>(production / count), .transported = ClampTo<uint16_t>(transported / count)};
2551}
2552
2553template <>
2554 Industry::AcceptedHistory SumHistory(std::span<const Industry::AcceptedHistory> history)
2555{
2556 uint32_t accepted = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &a) { return r + a.accepted; });
2557 uint32_t waiting = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &a) { return r + a.waiting; });;
2558 auto count = std::size(history);
2559 return {.accepted = ClampTo<uint16_t>(accepted / count), .waiting = ClampTo<uint16_t>(waiting / count)};
2560}
2561
2566 static void UpdateIndustryStatistics(Industry *i)
2567{
2568 auto month = TimerGameEconomy::month;
2569 UpdateValidHistory(i->valid_history, HISTORY_YEAR, month);
2570
2571 for (auto &p : i->produced) {
2572 if (IsValidCargoType(p.cargo)) {
2573 if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
2574
2575 RotateHistory(p.history, i->valid_history, HISTORY_YEAR, month);
2576 }
2577 }
2578
2579 for (auto &a : i->accepted) {
2580 if (!IsValidCargoType(a.cargo)) continue;
2581 if (a.history == nullptr) continue;
2582
2583 (*a.history)[THIS_MONTH].waiting = GetAndResetAccumulatedAverage<uint16_t>(a.accumulated_waiting);
2584 RotateHistory(*a.history, i->valid_history, HISTORY_YEAR, month);
2585 }
2586}
2587
2592 void Industry::RecomputeProductionMultipliers()
2593{
2594 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2595 assert(indspec->UsesOriginalEconomy());
2596
2597 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2598 for (auto &p : this->produced) {
2599 p.rate = ClampTo<uint8_t>(CeilDiv(indspec->production_rate[&p - this->produced.data()] * this->prod_level, PRODLEVEL_DEFAULT));
2600 }
2601}
2602
2603void Industry::FillCachedName() const
2604{
2605 auto tmp_params = MakeParameters(this->index);
2606 this->cached_name = GetStringWithArgs(STR_INDUSTRY_NAME, tmp_params);
2607}
2608
2609void ClearAllIndustryCachedNames()
2610{
2611 for (Industry *ind : Industry::Iterate()) {
2612 ind->cached_name.clear();
2613 }
2614}
2615
2621 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2622{
2623 uint8_t min_number;
2624 uint32_t probability = GetIndustryGamePlayProbability(it, &min_number);
2625 bool changed = min_number != this->min_number || probability != this->probability;
2626 this->min_number = min_number;
2627 this->probability = probability;
2628 return changed;
2629}
2630
2632 void IndustryBuildData::SetupTargetCount()
2633{
2634 bool changed = false;
2635 uint num_planned = 0; // Number of industries planned in the industry build data.
2636 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2637 changed |= this->builddata[it].GetIndustryTypeData(it);
2638 num_planned += this->builddata[it].target_count;
2639 }
2640 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2641 changed |= num_planned != total_amount;
2642 if (!changed) return; // All industries are still the same, no need to re-randomize.
2643
2644 /* Initialize the target counts. */
2645 uint force_build = 0; // Number of industries that should always be available.
2646 uint32_t total_prob = 0; // Sum of probabilities.
2647 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2648 IndustryTypeBuildData *ibd = this->builddata + it;
2649 force_build += ibd->min_number;
2650 ibd->target_count = ibd->min_number;
2651 total_prob += ibd->probability;
2652 }
2653
2654 if (total_prob == 0) return; // No buildable industries.
2655
2656 /* Subtract forced industries from the number of industries available for construction. */
2657 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2658
2659 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2660 while (total_amount > 0) {
2661 uint32_t r = RandomRange(total_prob);
2662 IndustryType it = 0;
2663 while (r >= this->builddata[it].probability) {
2664 r -= this->builddata[it].probability;
2665 it++;
2666 assert(it < NUM_INDUSTRYTYPES);
2667 }
2668 assert(this->builddata[it].probability > 0);
2669 this->builddata[it].target_count++;
2670 total_amount--;
2671 }
2672}
2673
2677 void IndustryBuildData::TryBuildNewIndustry()
2678{
2679 this->SetupTargetCount();
2680
2681 int missing = 0; // Number of industries that need to be build.
2682 uint count = 0; // Number of industry types eligible for build.
2683 uint32_t total_prob = 0; // Sum of probabilities.
2684 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2685 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2686 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2687 missing += difference;
2688 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2689 if (difference > 0) {
2690 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2691 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2692 if (forced_build == NUM_INDUSTRYTYPES ||
2693 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2694 forced_build = it;
2695 }
2696 }
2697 total_prob += difference;
2698 count++;
2699 }
2700 }
2701
2702 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2703
2704 if (count >= 1) {
2705 /* If not forced, pick a weighted random industry to build.
2706 * For the case that count == 1, there is no need to draw a random number. */
2707 IndustryType it;
2708 if (forced_build != NUM_INDUSTRYTYPES) {
2709 it = forced_build;
2710 } else {
2711 /* Non-forced, select an industry type to build (weighted random). */
2712 uint32_t r = 0; // Initialized to silence the compiler.
2713 if (count > 1) r = RandomRange(total_prob);
2714 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2715 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2716 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2717 if (difference <= 0) continue; // Too many of this kind.
2718 if (count == 1) break;
2719 if (r < (uint)difference) break;
2720 r -= difference;
2721 }
2722 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2723 }
2724
2725 /* Try to create the industry. */
2726 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2727 if (ind == nullptr) {
2728 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2729 this->builddata[it].max_wait = std::min(1000, this->builddata[it].max_wait + 2);
2730 } else {
2731 AdvertiseIndustryOpening(ind);
2732 this->builddata[it].max_wait = std::max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2733 }
2734 }
2735
2736 /* Decrement wait counters. */
2737 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2738 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2739 }
2740}
2741
2750 static bool CheckIndustryCloseDownProtection(IndustryType type)
2751{
2752 const IndustrySpec *indspec = GetIndustrySpec(type);
2753
2754 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2755 if (indspec->behaviour.Test(IndustryBehaviour::DontIncrProd) && _settings_game.game_creation.landscape == LandscapeType::Temperate) return false;
2756 return !indspec->behaviour.Test(IndustryBehaviour::CanCloseLastInstance) && Industry::GetIndustryTypeCount(type) <= 1;
2757}
2758
2768 static void CanCargoServiceIndustry(CargoType cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2769{
2770 if (!IsValidCargoType(cargo)) return;
2771
2772 /* Check for acceptance of cargo */
2773 if (ind->IsCargoAccepted(cargo) && !IndustryTemporarilyRefusesCargo(ind, cargo)) *c_accepts = true;
2774
2775 /* Check for produced cargo */
2776 if (ind->IsCargoProduced(cargo)) *c_produces = true;
2777}
2778
2792 int WhoCanServiceIndustry(Industry *ind)
2793{
2794 if (ind->stations_near.empty()) return 0; // No stations found at all => nobody services
2795
2796 int result = 0;
2797 for (const Vehicle *v : Vehicle::Iterate()) {
2798 /* Is it worthwhile to try this vehicle? */
2799 if (v->owner != _local_company && result != 0) continue;
2800
2801 /* Check whether it accepts the right kind of cargo */
2802 bool c_accepts = false;
2803 bool c_produces = false;
2804 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2805 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
2806 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2807 }
2808 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2809 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2810 } else {
2811 continue;
2812 }
2813 if (!c_accepts && !c_produces) continue; // Wrong cargo
2814
2815 /* Check orders of the vehicle.
2816 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2817 * may have a different cargo type.
2818 */
2819 for (const Order &o : v->Orders()) {
2820 if (o.IsType(OT_GOTO_STATION) && o.GetUnloadType() != OrderUnloadType::Transfer) {
2821 /* Vehicle visits a station to load or unload */
2822 Station *st = Station::Get(o.GetDestination().ToStationID());
2823 assert(st != nullptr);
2824
2825 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2826 if (o.GetUnloadType() == OrderUnloadType::Unload && !c_accepts) break;
2827
2828 if (ind->stations_near.find(st) != ind->stations_near.end()) {
2829 if (v->owner == _local_company) return 2; // Company services industry
2830 result = 1; // Competitor services industry
2831 }
2832 }
2833 }
2834 }
2835 return result;
2836}
2837
2845 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoType cargo, int percent)
2846{
2847 NewsType nt;
2848
2849 switch (WhoCanServiceIndustry(ind)) {
2850 case 0: nt = NewsType::IndustryNobody; break;
2851 case 1: nt = NewsType::IndustryOther; break;
2852 case 2: nt = NewsType::IndustryCompany; break;
2853 default: NOT_REACHED();
2854 }
2855 AddIndustryNewsItem(
2856 GetEncodedString(percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2857 CargoSpec::Get(cargo)->name, ind->index, abs(percent)
2858 ),
2859 nt,
2860 ind->index
2861 );
2862}
2863
2864static const uint PERCENT_TRANSPORTED_60 = 153;
2865static const uint PERCENT_TRANSPORTED_80 = 204;
2866
2872 static void ChangeIndustryProduction(Industry *i, bool monthly)
2873{
2874 StringID str = STR_NULL;
2875 bool closeit = false;
2876 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2877 bool standard = false;
2878 bool suppress_message = false;
2879 bool recalculate_multipliers = false;
2880 /* use original economy for industries using production related callbacks */
2881 bool original_economy = indspec->UsesOriginalEconomy();
2882 uint8_t div = 0;
2883 uint8_t mul = 0;
2884 int8_t increment = 0;
2885
2886 bool callback_enabled = indspec->callback_mask.Test(monthly ? IndustryCallbackMask::MonthlyProdChange : IndustryCallbackMask::ProductionChange);
2887 if (callback_enabled) {
2888 std::array<int32_t, 1> regs100;
2889 uint16_t res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile, regs100);
2890 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2891 suppress_message = HasBit(res, 7);
2892 /* Get the custom message if any */
2893 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grfid, GRFStringID(GB(regs100[0], 0, 16)));
2894 res = GB(res, 0, 4);
2895 switch (res) {
2896 default: NOT_REACHED();
2897 case 0x0: break; // Do nothing, but show the custom message if any
2898 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2899 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2900 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2901 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2902 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2903 case 0x8: div = res - 0x3; break; // Divide production by 32
2904 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2905 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2906 case 0xD: // decrement production
2907 case 0xE: // increment production
2908 increment = res == 0x0D ? -1 : 1;
2909 break;
2910 case 0xF: // Set production to third byte of register 0x100
2911 i->prod_level = Clamp(GB(regs100[0], 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2912 recalculate_multipliers = true;
2913 break;
2914 }
2915 }
2916 } else {
2917 if (monthly == original_economy) return;
2918 if (!original_economy && _settings_game.economy.type == ET_FROZEN) return;
2919 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2920 }
2921
2922 if (standard || (!callback_enabled && indspec->life_type.Any({IndustryLifeType::Organic, IndustryLifeType::Extractive}))) {
2923 /* decrease or increase */
2924 bool only_decrease = indspec->behaviour.Test(IndustryBehaviour::DontIncrProd) && _settings_game.game_creation.landscape == LandscapeType::Temperate;
2925
2926 if (original_economy) {
2927 if (only_decrease || Chance16(1, 3)) {
2928 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2929 if (!only_decrease && (i->GetProduced(0).history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2930 mul = 1; // Increase production
2931 } else {
2932 div = 1; // Decrease production
2933 }
2934 }
2935 } else if (_settings_game.economy.type == ET_SMOOTH) {
2936 closeit = !i->ctlflags.Any({IndustryControlFlag::NoClosure, IndustryControlFlag::NoProductionDecrease});
2937 for (auto &p : i->produced) {
2938 if (!IsValidCargoType(p.cargo)) continue;
2939 uint32_t r = Random();
2940 int old_prod, new_prod, percent;
2941 /* If over 60% is transported, mult is 1, else mult is -1. */
2942 int mult = (p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_60) ? 1 : -1;
2943
2944 new_prod = old_prod = p.rate;
2945
2946 /* For industries with only_decrease flags (temperate terrain Oil Wells),
2947 * the multiplier will always be -1 so they will only decrease. */
2948 if (only_decrease) {
2949 mult = -1;
2950 /* For normal industries, if over 60% is transported, 33% chance for decrease.
2951 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2952 } else if (Chance16I(1, ((p.history[LAST_MONTH].PctTransported() > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2953 mult *= -1;
2954 }
2955
2956 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2957 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2958 if (Chance16I(1, 22, r >> 16)) {
2959 new_prod += mult * (std::max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2960 }
2961
2962 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2963 new_prod = Clamp(new_prod, 1, 255);
2964 if (IsValidCargoType(p.cargo) && p.cargo == GetCargoTypeByLabel(CT_PASSENGERS) && !indspec->behaviour.Test(IndustryBehaviour::NoPaxProdClamp)) {
2965 new_prod = Clamp(new_prod, 0, 16);
2966 }
2967
2968 /* If override flags are set, prevent actually changing production if any was decided on */
2969 if (i->ctlflags.Test(IndustryControlFlag::NoProductionDecrease) && new_prod < old_prod) continue;
2970 if (i->ctlflags.Test(IndustryControlFlag::NoProductionIncrease) && new_prod > old_prod) continue;
2971
2972 /* Do not stop closing the industry when it has the lowest possible production rate */
2973 if (new_prod == old_prod && old_prod > 1) {
2974 closeit = false;
2975 continue;
2976 }
2977
2978 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2979 p.rate = new_prod;
2980
2981 /* Close the industry when it has the lowest possible production rate */
2982 if (new_prod > 1) closeit = false;
2983
2984 if (abs(percent) >= 10) {
2985 ReportNewsProductionChangeIndustry(i, p.cargo, percent);
2986 }
2987 }
2988 }
2989 }
2990
2991 /* If override flags are set, prevent actually changing production if any was decided on */
2992 if (i->ctlflags.Test(IndustryControlFlag::NoProductionDecrease) && (div > 0 || increment < 0)) return;
2993 if (i->ctlflags.Test(IndustryControlFlag::NoProductionIncrease) && (mul > 0 || increment > 0)) return;
2994 if (i->ctlflags.Test(IndustryControlFlag::ExternalProdLevel)) {
2995 div = 0;
2996 mul = 0;
2997 increment = 0;
2998 }
2999
3000 if (!callback_enabled && indspec->life_type.Test(IndustryLifeType::Processing)) {
3001 if (TimerGameEconomy::year - i->last_prod_year >= PROCESSING_INDUSTRY_ABANDONMENT_YEARS && Chance16(1, original_economy ? 2 : 180)) {
3002 closeit = true;
3003 }
3004 }
3005
3006 /* Increase if needed */
3007 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
3008 i->prod_level = std::min<int>(i->prod_level * 2, PRODLEVEL_MAXIMUM);
3009 recalculate_multipliers = true;
3010 if (str == STR_NULL) str = indspec->production_up_text;
3011 }
3012
3013 /* Decrease if needed */
3014 while (div-- != 0 && !closeit) {
3015 if (i->prod_level == PRODLEVEL_MINIMUM) {
3016 closeit = true;
3017 break;
3018 } else {
3019 i->prod_level = std::max<int>(i->prod_level / 2, PRODLEVEL_MINIMUM);
3020 recalculate_multipliers = true;
3021 if (str == STR_NULL) str = indspec->production_down_text;
3022 }
3023 }
3024
3025 /* Increase or Decreasing the production level if needed */
3026 if (increment != 0) {
3027 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
3028 closeit = true;
3029 } else {
3030 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
3031 recalculate_multipliers = true;
3032 }
3033 }
3034
3035 /* Recalculate production_rate
3036 * For non-smooth economy these should always be synchronized with prod_level */
3037 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
3038
3039 /* Close if needed and allowed */
3040 if (closeit && !CheckIndustryCloseDownProtection(i->type) && !i->ctlflags.Test(IndustryControlFlag::NoClosure)) {
3041 i->prod_level = PRODLEVEL_CLOSURE;
3042 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3043 str = indspec->closure_text;
3044 }
3045
3046 if (!suppress_message && str != STR_NULL) {
3047 NewsType nt;
3048 /* Compute news category */
3049 if (closeit) {
3050 nt = NewsType::IndustryClose;
3051 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
3052 Game::NewEvent(new ScriptEventIndustryClose(i->index));
3053 } else {
3054 switch (WhoCanServiceIndustry(i)) {
3055 case 0: nt = NewsType::IndustryNobody; break;
3056 case 1: nt = NewsType::IndustryOther; break;
3057 case 2: nt = NewsType::IndustryCompany; break;
3058 default: NOT_REACHED();
3059 }
3060 }
3061 /* Set parameters of news string */
3062 EncodedString headline;
3063 if (str > STR_LAST_STRINGID) {
3064 headline = GetEncodedString(str, STR_TOWN_NAME, i->town->index, indspec->name);
3065 } else if (closeit) {
3066 headline = GetEncodedString(str, STR_FORMAT_INDUSTRY_NAME, i->town->index, indspec->name);
3067 } else {
3068 headline = GetEncodedString(str, i->index);
3069 }
3070 /* and report the news to the user */
3071 if (closeit) {
3072 AddTileNewsItem(std::move(headline), nt, i->location.tile + TileDiffXY(1, 1));
3073 } else {
3074 AddIndustryNewsItem(std::move(headline), nt, i->index);
3075 }
3076 }
3077}
3078
3086 static const IntervalTimer<TimerGameEconomy> _economy_industries_daily({TimerGameEconomy::DAY, TimerGameEconomy::Priority::INDUSTRY}, [](auto)
3087{
3088 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
3089
3090 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
3091 * the lower 16 bit are a fractional part that might accumulate over several days until it
3092 * is sufficient for an industry. */
3093 uint16_t change_loop = _economy.industry_daily_change_counter >> 16;
3094
3095 /* Reset the active part of the counter, just keeping the "fractional part" */
3096 _economy.industry_daily_change_counter &= 0xFFFF;
3097
3098 if (change_loop == 0) {
3099 return; // Nothing to do? get out
3100 }
3101
3102 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
3103
3104 /* perform the required industry changes for the day */
3105
3106 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
3107 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
3108 perc = std::min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
3109 }
3110 for (uint16_t j = 0; j < change_loop; j++) {
3111 if (Chance16(perc, 100)) {
3112 _industry_builder.TryBuildNewIndustry();
3113 } else {
3114 Industry *i = Industry::GetRandom();
3115 if (i != nullptr) {
3116 ChangeIndustryProduction(i, false);
3117 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3118 }
3119 }
3120 }
3121
3122 cur_company.Restore();
3123
3124 /* production-change */
3125 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
3126});
3127
3128static const IntervalTimer<TimerGameEconomy> _economy_industries_monthly({TimerGameEconomy::MONTH, TimerGameEconomy::Priority::INDUSTRY}, [](auto)
3129{
3130 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
3131
3132 _industry_builder.EconomyMonthlyLoop();
3133
3134 for (Industry *i : Industry::Iterate()) {
3135 UpdateIndustryStatistics(i);
3136 if (i->prod_level == PRODLEVEL_CLOSURE) {
3137 delete i;
3138 } else {
3139 ChangeIndustryProduction(i, true);
3140 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
3141 }
3142 }
3143
3144 cur_company.Restore();
3145
3146 /* production-change */
3147 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);
3148});
3149
3150
3151void InitializeIndustries()
3152{
3153 Industry::industries.fill({});
3154 _industry_sound_tile = TileIndex{};
3155
3156 _industry_builder.Reset();
3157}
3158
3160 void CheckIndustries()
3161{
3162 int count = 0;
3163 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
3164 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
3165
3166 bool force_at_least_one;
3167 uint32_t chance = GetScaledIndustryGenerationProbability(it, std::nullopt, &force_at_least_one);
3168 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
3169
3170 const IndustrySpec *is = GetIndustrySpec(it);
3171 ShowErrorMessage(GetEncodedString(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, is->name),
3172 GetEncodedString(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION), WL_WARNING);
3173
3174 count++;
3175 if (count >= 3) break; // Don't swamp the user with errors.
3176 }
3177}
3178
3183 bool IndustrySpec::IsRawIndustry() const
3184{
3185 return this->life_type.Any({IndustryLifeType::Extractive, IndustryLifeType::Organic});
3186}
3187
3192 bool IndustrySpec::IsProcessingIndustry() const
3193{
3194 /* Lumber mills are neither raw nor processing */
3195 return this->life_type.Test(IndustryLifeType::Processing) &&
3196 !this->behaviour.Test(IndustryBehaviour::CutTrees);
3197}
3198
3203 Money IndustrySpec::GetConstructionCost() const
3204{
3205 /* Building raw industries like secondary uses different price base */
3206 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
3207 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
3208}
3209
3216 Money IndustrySpec::GetRemovalCost() const
3217{
3218 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
3219}
3220
3225 bool IndustrySpec::UsesOriginalEconomy() const
3226{
3227 return _settings_game.economy.type == ET_ORIGINAL ||
3228 this->callback_mask.Any({
3229 IndustryCallbackMask::Production256Ticks,
3230 IndustryCallbackMask::ProductionCargoArrival, // production callbacks
3231 IndustryCallbackMask::MonthlyProdChange,
3232 IndustryCallbackMask::ProductionChange,
3233 IndustryCallbackMask::ProdChangeBuild}); // production change callbacks
3234}
3235
3236static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
3237{
3238 if (AutoslopeEnabled()) {
3239 /* We imitate here TTDP's behaviour:
3240 * - Both new and old slope must not be steep.
3241 * - TileMaxZ must not be changed.
3242 * - Allow autoslope by default.
3243 * - Disallow autoslope if callback succeeds and returns non-zero.
3244 */
3245 Slope tileh_old = GetTileSlope(tile);
3246 /* TileMaxZ must not be changed. Slopes must not be steep. */
3247 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
3248 const IndustryGfx gfx = GetIndustryGfx(tile);
3249 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
3250
3251 /* Call callback 3C 'disable autosloping for industry tiles'. */
3252 if (itspec->callback_mask.Test(IndustryTileCallbackMask::Autoslope)) {
3253 /* If the callback fails, allow autoslope. */
3254 uint16_t res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
3255 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3256 } else {
3257 /* allow autoslope */
3258 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
3259 }
3260 }
3261 }
3262 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
3263}
3264
3265extern const TileTypeProcs _tile_type_industry_procs = {
3266 DrawTile_Industry, // draw_tile_proc
3267 GetSlopePixelZ_Industry, // get_slope_z_proc
3268 ClearTile_Industry, // clear_tile_proc
3269 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
3270 GetTileDesc_Industry, // get_tile_desc_proc
3271 GetTileTrackStatus_Industry, // get_tile_track_status_proc
3272 ClickTile_Industry, // click_tile_proc
3273 AnimateTile_Industry, // animate_tile_proc
3274 TileLoop_Industry, // tile_loop_proc
3275 ChangeTileOwner_Industry, // change_tile_owner_proc
3276 nullptr, // add_produced_cargo_proc
3277 nullptr, // vehicle_enter_tile_proc
3278 GetFoundation_Industry, // get_foundation_proc
3279 TerraformTile_Industry, // terraform_tile_proc
3280 nullptr, // check_build_above_proc
3281};
3282
3283bool IndustryCompare::operator() (const IndustryListEntry &lhs, const IndustryListEntry &rhs) const
3284{
3285 /* Compare by distance first and use index as a tiebreaker. */
3286 return std::tie(lhs.distance, lhs.industry->index) < std::tie(rhs.distance, rhs.industry->index);
3287}
3288
3293 void TrimIndustryAcceptedProduced(Industry *ind)
3294{
3295 auto ita = std::find_if(std::rbegin(ind->accepted), std::rend(ind->accepted), [](const auto &a) { return IsValidCargoType(a.cargo); });
3296 ind->accepted.erase(ita.base(), std::end(ind->accepted));
3297 ind->accepted.shrink_to_fit();
3298
3299 auto itp = std::find_if(std::rbegin(ind->produced), std::rend(ind->produced), [](const auto &p) { return IsValidCargoType(p.cargo); });
3300 ind->produced.erase(itp.base(), std::end(ind->produced));
3301 ind->produced.shrink_to_fit();
3302}
ai.hpp
Base functions for all AIs.
AddAnimatedTile
void AddAnimatedTile(TileIndex tile, bool mark_dirty)
Add the given tile to the animated tile table (if it does not exist yet).
Definition animated_tile.cpp:56
DeleteAnimatedTile
void DeleteAnimatedTile(TileIndex tile, bool immediate)
Stops animation on the given tile.
Definition animated_tile.cpp:27
animated_tile_func.h
Tile animation!
autoslope.h
Functions related to autoslope.
AutoslopeEnabled
bool AutoslopeEnabled()
Tests if autoslope is enabled for _current_company.
Definition autoslope.h:65
backup_type.hpp
Class for backupping variables and making sure they are restored later.
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition bitmath_func.hpp:121
HasBit
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
IsBridgeAbove
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
build_industry.h
Tables with default industry layouts and behaviours.
CargoType
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:21
IsValidCargoType
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:104
CT_PASSENGERS
static constexpr CargoLabel CT_PASSENGERS
Available types of cargo Labels may be re-used between different climates.
Definition cargo_type.h:29
_cheats
Cheats _cheats
All the cheats.
Definition cheat.cpp:16
cheat_type.h
Types related to cheating.
AI::BroadcastNewEvent
static void BroadcastNewEvent(ScriptEvent *event, CompanyID skip_company=CompanyID::Invalid())
Broadcast a new event to all active AIs.
Definition ai_core.cpp:255
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
BaseBitSet::Reset
constexpr Timpl & Reset()
Reset all bits.
Definition base_bitset_type.hpp:83
BaseBitSet::IsValid
constexpr bool IsValid() const
Test that the raw value of this bit set is valid.
Definition base_bitset_type.hpp:228
BaseBitSet::Set
constexpr Timpl & Set()
Set all bits.
Definition base_bitset_type.hpp:40
BaseBitSet::Any
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Definition base_bitset_type.hpp:170
CommandCost
Common return value for all commands.
Definition command_type.h:24
CommandCost::Succeeded
bool Succeeded() const
Did this command succeed?
Definition command_type.h:168
CommandCost::Failed
bool Failed() const
Did this command fail?
Definition command_type.h:177
EncodedString
Container for an encoded string, created by GetEncodedString.
Definition strings_type.h:98
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition game_core.cpp:136
IntervalTimer
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
OverflowSafeInt< int64_t >
OverrideManagerBase::ResetOverride
void ResetOverride()
Resets the override, which is used while initializing game.
Definition newgrf_commons.cpp:79
SpiralTileSequence
Generate TileIndices around a center tile or tile area, with increasing distance.
Definition tilearea_type.h:316
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition timer_game_tick.h:75
Ticks::INDUSTRY_CUT_TREE_TICKS
static constexpr TimerGameTick::Ticks INDUSTRY_CUT_TREE_TICKS
Cycle duration for lumber mill's extra action.
Definition timer_game_tick.h:84
Ticks::INDUSTRY_PRODUCE_TICKS
static constexpr TimerGameTick::Ticks INDUSTRY_PRODUCE_TICKS
Cycle duration for industry production.
Definition timer_game_tick.h:82
Tile
Wrapper class to abstract away the way the tiles are stored.
Definition map_func.h:25
TimerGameCalendar::date
static Date date
Current date in days (day counter).
Definition timer_game_calendar.h:33
TimerGameCalendar::year
static Year year
Current year, starting at 0.
Definition timer_game_calendar.h:31
TimerGameEconomy::year
static Year year
Current year, starting at 0.
Definition timer_game_economy.h:36
TimerGameEconomy::month
static Month month
Current month (0..11).
Definition timer_game_economy.h:37
TimerGameTick::counter
static TickCounter counter
Monotonic counter, in ticks, since start of game.
Definition timer_game_tick.h:60
clear_map.h
Map accessors for 'clear' tiles.
IsClearGround
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:59
SetFence
void SetFence(Tile t, DiagDirection side, uint h)
Sets the type of fence (and whether there is one) for the given border.
Definition clear_map.h:228
GetIndustryIndexOfField
IndustryID GetIndustryIndexOfField(Tile t)
Get the industry (farm) that made the field.
Definition clear_map.h:183
CLEAR_FIELDS
@ CLEAR_FIELDS
3
Definition clear_map.h:23
CLEAR_DESERT
@ CLEAR_DESERT
1,3
Definition clear_map.h:25
CLEAR_ROUGH
@ CLEAR_ROUGH
3
Definition clear_map.h:21
GetClearGround
ClearGround GetClearGround(Tile t)
Get the type of clear tile.
Definition clear_map.h:47
SetIndustryIndexOfField
void SetIndustryIndexOfField(Tile t, IndustryID i)
Set the industry (farm) that made the field.
Definition clear_map.h:195
MakeField
void MakeField(Tile t, uint field_type, IndustryID industry)
Make a (farm) field tile.
Definition clear_map.h:268
SetClearCounter
void SetClearCounter(Tile t, uint c)
Sets the counter used to advance to the next clear density/field type.
Definition clear_map.h:132
GetFence
uint GetFence(Tile t, DiagDirection side)
Is there a fence at the given border?
Definition clear_map.h:209
IsSnowTile
bool IsSnowTile(Tile t)
Test if a tile is covered with snow.
Definition clear_map.h:35
CommandCostWithParam
CommandCost CommandCostWithParam(StringID str, uint64_t value)
Return an error status, with string and parameter.
Definition command.cpp:417
command_func.h
Functions related to commands.
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition command_func.h:28
DoCommandFlag::Auto
@ Auto
don't allow building on structures
DoCommandFlag::NoModifyTownRating
@ NoModifyTownRating
do not change town rating
DoCommandFlag::NoWater
@ NoWater
don't allow building on water
DoCommandFlag::Execute
@ Execute
execute the given command
DoCommandFlag::NoTestTownRating
@ NoTestTownRating
town rating does not disallow you from building
company_base.h
Definition of stuff that is very close to a company, like the company struct itself.
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition company_cmd.cpp:55
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
IsLocalCompany
bool IsLocalCompany()
Is the current company the local company?
Definition company_func.h:47
OWNER_DEITY
static constexpr Owner OWNER_DEITY
The object is owned by a superuser / goal script.
Definition company_type.h:28
OWNER_TOWN
static constexpr Owner OWNER_TOWN
A town owns the tile, or a town is expanding.
Definition company_type.h:25
OWNER_NONE
static constexpr Owner OWNER_NONE
The tile has no ownership.
Definition company_type.h:26
INVALID_OWNER
static constexpr Owner INVALID_OWNER
An invalid owner.
Definition company_type.h:30
OWNER_WATER
static constexpr Owner OWNER_WATER
The tile/execution is done by "water".
Definition company_type.h:27
ReverseDiagDir
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Definition direction_func.h:118
OtherAxis
Axis OtherAxis(Axis a)
Select the other axis as provided.
Definition direction_func.h:197
DiagDirToAxis
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
Definition direction_func.h:214
DiagDirection
DiagDirection
Enumeration for diagonal directions.
Definition direction_type.h:78
DIAGDIR_NE
@ DIAGDIR_NE
Northeast, upper right on your monitor.
Definition direction_type.h:80
DIAGDIR_NW
@ DIAGDIR_NW
Northwest.
Definition direction_type.h:83
DIAGDIR_SE
@ DIAGDIR_SE
Southeast.
Definition direction_type.h:81
DIAGDIR_SW
@ DIAGDIR_SW
Southwest.
Definition direction_type.h:82
ScaleByInverseCargoScale
static uint ScaleByInverseCargoScale(uint num, bool town)
Scale a number by the inverse of the cargo scale setting, e.g.
Definition economy_func.h:61
EconomyIsInRecession
bool EconomyIsInRecession()
Is the economy in recession?
Definition economy_func.h:50
ScaleByCargoScale
uint ScaleByCargoScale(uint num, bool town)
Scale a number by the cargo scale setting.
Definition economy_func.h:78
EXPENSES_CONSTRUCTION
@ EXPENSES_CONSTRUCTION
Construction costs.
Definition economy_type.h:179
EXPENSES_OTHER
@ EXPENSES_OTHER
Other expenses.
Definition economy_type.h:191
CreateEffectVehicle
EffectVehicle * CreateEffectVehicle(int x, int y, int z, EffectVehicleType type)
Create an effect vehicle at a particular location.
Definition effectvehicle.cpp:566
CreateEffectVehicleAbove
EffectVehicle * CreateEffectVehicleAbove(int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular location.
Definition effectvehicle.cpp:594
effectvehicle_base.h
Base class for all effect vehicles.
effectvehicle_func.h
Functions related to effect vehicles.
EV_BUBBLE
@ EV_BUBBLE
Bubble of bubble generator (industry).
Definition effectvehicle_func.h:26
EV_CHIMNEY_SMOKE
@ EV_CHIMNEY_SMOKE
Smoke of power plant (industry).
Definition effectvehicle_func.h:17
EV_COPPER_MINE_SMOKE
@ EV_COPPER_MINE_SMOKE
Smoke at copper mine.
Definition effectvehicle_func.h:28
to_underlying
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:17
error.h
Functions related to errors.
WL_WARNING
@ WL_WARNING
Other information.
Definition error.h:25
WL_INFO
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
ShowErrorMessage
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Definition error_gui.cpp:296
game.hpp
Base functions for all Games.
_generating_world
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
genworld.h
Functions related to world/map generation.
IncreaseGeneratingWorldProgress
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
Definition genworld_gui.cpp:1539
LG_TERRAGENESIS
@ LG_TERRAGENESIS
TerraGenesis Perlin landscape generator.
Definition genworld.h:22
GWP_LAND_INDUSTRY
@ GWP_LAND_INDUSTRY
Generate industries.
Definition genworld.h:67
GWP_WATER_INDUSTRY
@ GWP_WATER_INDUSTRY
Generate industries.
Definition genworld.h:68
SetGeneratingWorldProgress
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
Definition genworld_gui.cpp:1525
SpriteID
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
GetSnowLine
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition landscape.cpp:606
HighestSnowLine
uint8_t HighestSnowLine()
Get the highest possible snow line height, either variable or static.
Definition landscape.cpp:619
MarkTileDirtyByTile
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition viewport.cpp:2128
UpdateValidHistory
void UpdateValidHistory(ValidHistoryMask &valid_history, const HistoryRange &hr, uint cur_month)
Update mask of valid records for a historical data.
Definition history.cpp:25
history_func.hpp
Functions for storing historical data.
RotateHistory
void RotateHistory(HistoryData< T > &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint cur_month)
Rotate historical data.
Definition history_func.hpp:41
history_type.hpp
Types for storing historical data.
industry.h
Base of all industries.
PRODLEVEL_MAXIMUM
static constexpr uint8_t PRODLEVEL_MAXIMUM
the industry is running at full speed
Definition industry.h:38
ReleaseDisastersTargetingIndustry
void ReleaseDisastersTargetingIndustry(IndustryID)
Marks all disasters targeting this industry in such a way they won't call Industry::Get(v->dest_tile)...
Definition disaster_vehicle.cpp:966
PRODLEVEL_DEFAULT
static constexpr uint8_t PRODLEVEL_DEFAULT
default level set when the industry is created
Definition industry.h:37
PROCESSING_INDUSTRY_ABANDONMENT_YEARS
static const TimerGameEconomy::Year PROCESSING_INDUSTRY_ABANDONMENT_YEARS
If a processing industry doesn't produce for this many consecutive economy years, it may close.
Definition industry.h:28
PRODLEVEL_MINIMUM
static constexpr uint8_t PRODLEVEL_MINIMUM
below this level, the industry is set to be closing
Definition industry.h:36
PRODLEVEL_CLOSURE
static constexpr uint8_t PRODLEVEL_CLOSURE
signal set to actually close the industry
Definition industry.h:35
IndustryControlFlag::ExternalProdLevel
@ ExternalProdLevel
Indicates that the production level of the industry is externally controlled.
IndustryControlFlag::NoClosure
@ NoClosure
Industry can not close regardless of production level or time since last delivery.
IndustryControlFlag::NoProductionDecrease
@ NoProductionDecrease
When industry production change is evaluated, rolls to decrease are ignored.
IndustryControlFlag::NoProductionIncrease
@ NoProductionIncrease
When industry production change is evaluated, rolls to increase are ignored.
GetIndustryGamePlayProbability
static uint16_t GetIndustryGamePlayProbability(IndustryType it, uint8_t *min_number)
Compute the probability for constructing a new industry during game play.
Definition industry_cmd.cpp:2333
CheckNewIndustry_Water
static CommandCost CheckNewIndustry_Water(TileIndex tile)
Check the conditions of CHECK_WATER (Industry should be in the desert).
Definition industry_cmd.cpp:1368
_check_new_industry_procs
static CheckNewIndustryProc *const _check_new_industry_procs[CHECK_END]
Check functions for different types of industry.
Definition industry_cmd.cpp:1410
CheckIfIndustryIsAllowed
static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, IndustryType type, const Town *t)
Is the industry allowed to be built at this place for the town?
Definition industry_cmd.cpp:1576
GetIndustrySpec
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
Definition industry_cmd.cpp:126
TransportIndustryGoods
static bool TransportIndustryGoods(TileIndex tile)
Move produced cargo from industry to nearby stations.
Definition industry_cmd.cpp:525
CmdIndustrySetExclusivity
CommandCost CmdIndustrySetExclusivity(DoCommandFlags flags, IndustryID ind_id, Owner company_id, bool consumer)
Change exclusive consumer or supplier for the industry.
Definition industry_cmd.cpp:2233
CheckIfIndustryTileSlopes
static CommandCost CheckIfIndustryTileSlopes(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, IndustryType type, uint16_t initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check=nullptr)
Check slope requirements for industry tiles.
Definition industry_cmd.cpp:1534
GetScaledProbabilities
static IndustryGenerationProbabilities GetScaledProbabilities(bool water)
Get scaled industry generation probabilities.
Definition industry_cmd.cpp:2471
GetCurrentTotalNumberOfIndustries
static uint GetCurrentTotalNumberOfIndustries()
Get total number of industries existing in the game.
Definition industry_cmd.cpp:2415
CheckNewIndustry_OilRefinery
static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
Check the conditions of CHECK_REFINERY (Industry should be positioned near edge of the map).
Definition industry_cmd.cpp:1309
CheckIfIndustryTilesAreFree
static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, IndustryType type)
Are the tiles of the industry free?
Definition industry_cmd.cpp:1472
CmdIndustrySetProduction
CommandCost CmdIndustrySetProduction(DoCommandFlags flags, IndustryID ind_id, uint8_t prod_level, bool show_news, const EncodedString &custom_news)
Set industry production.
Definition industry_cmd.cpp:2178
CheckIfCanLevelIndustryPlatform
static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlags flags, const IndustryTileLayout &layout)
This function tries to flatten out the land below an industry, without damaging the surroundings too ...
Definition industry_cmd.cpp:1620
CheckNewIndustry_BubbleGen
static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
Check the conditions of CHECK_BUBBLEGEN (Industry should be in low land).
Definition industry_cmd.cpp:1394
CheckNewIndustry_Farm
static CommandCost CheckNewIndustry_Farm(TileIndex tile)
Check the conditions of CHECK_FARM (Industry should be below snow-line in arctic).
Definition industry_cmd.cpp:1340
AdvertiseIndustryOpening
static void AdvertiseIndustryOpening(const Industry *ind)
Advertise about a new industry opening.
Definition industry_cmd.cpp:1714
ChopLumberMillTrees
static void ChopLumberMillTrees(Industry *i)
Perform a circular search around the Lumber Mill in order to find trees to cut.
Definition industry_cmd.cpp:1113
GetScaledIndustryGenerationProbability
static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, std::optional< bool > water, bool *force_at_least_one)
Compute the appearance probability for an industry during map creation.
Definition industry_cmd.cpp:2305
CheckScaledDistanceFromEdge
static bool CheckScaledDistanceFromEdge(TileIndex tile, uint maxdist)
Check if a tile is within a distance from map edges, scaled by map dimensions independently.
Definition industry_cmd.cpp:1288
ReportNewsProductionChangeIndustry
static void ReportNewsProductionChangeIndustry(Industry *ind, CargoType cargo, int percent)
Report news that industry production has changed significantly.
Definition industry_cmd.cpp:2845
IsTileForestIndustry
bool IsTileForestIndustry(TileIndex tile)
Check whether the tile is a forest.
Definition industry_cmd.cpp:978
GetIndustryTileSpec
const IndustryTileSpec * GetIndustryTileSpec(IndustryGfx gfx)
Accessor for array _industry_tile_specs.
Definition industry_cmd.cpp:140
CanCargoServiceIndustry
static void CanCargoServiceIndustry(CargoType cargo, Industry *ind, bool *c_accepts, bool *c_produces)
Can given cargo type be accepted or produced by the industry?
Definition industry_cmd.cpp:2768
GenerateIndustries
void GenerateIndustries()
This function will create random industries during game creation.
Definition industry_cmd.cpp:2488
ProduceIndustryGoodsHelper
static void ProduceIndustryGoodsHelper(Industry *i, bool scale)
Helper for ProduceIndustryGoods that scales and produces cargos.
Definition industry_cmd.cpp:1148
_industry_builder
IndustryBuildData _industry_builder
In-game manager of industries.
Definition industry_cmd.cpp:73
PlaceIndustry
static Industry * PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
Try to place the industry in the game.
Definition industry_cmd.cpp:2386
_economy_industries_daily
static const IntervalTimer< TimerGameEconomy > _economy_industries_daily({TimerGameEconomy::DAY, TimerGameEconomy::Priority::INDUSTRY}, [](auto) { _economy.industry_daily_change_counter+=_economy.industry_daily_increment;uint16_t change_loop=_economy.industry_daily_change_counter > > 16;_economy.industry_daily_change_counter &=0xFFFF;if(change_loop==0) { return;} Backup< CompanyID > cur_company(_current_company, OWNER_NONE);uint perc=3;if((_industry_builder.wanted_inds > > 16) > GetCurrentTotalNumberOfIndustries()) { perc=std::min(9u, perc+(_industry_builder.wanted_inds > > 16) - GetCurrentTotalNumberOfIndustries());} for(uint16_t j=0;j< change_loop;j++) { if(Chance16(perc, 100)) { _industry_builder.TryBuildNewIndustry();} else { Industry *i=Industry::GetRandom();if(i !=nullptr) { ChangeIndustryProduction(i, false);SetWindowDirty(WC_INDUSTRY_VIEW, i->index);} } } cur_company.Restore();InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_PRODUCTION_CHANGE);})
Every economy day handler for the industry changes Taking the original map size of 256*256,...
IsSuitableForFarmField
static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields, bool allow_rough)
Check whether the tile can be replaced by a farm field.
Definition industry_cmd.cpp:1001
CheckNewIndustry_Plantation
static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
Check the conditions of CHECK_PLANTATION (Industry should NOT be in the desert).
Definition industry_cmd.cpp:1355
CheckIndustries
void CheckIndustries()
Verify whether the generated industries are complete, and warn the user if not.
Definition industry_cmd.cpp:3160
PopulateStationsNearby
static void PopulateStationsNearby(Industry *ind)
Populate an industry's list of nearby stations, and if it accepts any cargo, also add the industry to...
Definition industry_cmd.cpp:1733
CheckNewIndustry_Forest
static CommandCost CheckNewIndustry_Forest(TileIndex tile)
Check the conditions of CHECK_FOREST (Industry should be build above snow-line in arctic climate).
Definition industry_cmd.cpp:1271
DoCreateNewIndustry
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)
Put an industry on the map.
Definition industry_cmd.cpp:1762
CheckNewIndustryProc
CommandCost CheckNewIndustryProc(TileIndex tile)
Industrytype check function signature.
Definition industry_cmd.cpp:1407
CreateNewIndustryHelper
static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlags flags, const IndustrySpec *indspec, size_t layout_index, uint32_t random_var8f, uint16_t random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
Helper function for Build/Fund an industry.
Definition industry_cmd.cpp:2000
WhoCanServiceIndustry
static int WhoCanServiceIndustry(Industry *ind)
Compute who can service the industry.
Definition industry_cmd.cpp:2792
ResetIndustries
void ResetIndustries()
This function initialize the spec arrays of both industry and industry tiles.
Definition industry_cmd.cpp:83
CheckIfFarEnoughFromConflictingIndustry
static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, IndustryType type)
Check that the new industry is far enough from conflicting industries.
Definition industry_cmd.cpp:1693
CheckNewIndustry_OilRig
static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
Check the conditions of CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
Definition industry_cmd.cpp:1325
TrimIndustryAcceptedProduced
void TrimIndustryAcceptedProduced(Industry *ind)
Remove unused industry accepted/produced slots – entries after the last slot with valid cargo.
Definition industry_cmd.cpp:3293
GetNumberOfIndustries
static uint GetNumberOfIndustries()
Get wanted number of industries on the map.
Definition industry_cmd.cpp:2357
CmdBuildIndustry
CommandCost CmdBuildIndustry(DoCommandFlags flags, TileIndex tile, IndustryType it, uint32_t first_layout, bool fund, uint32_t seed)
Build/Fund an industry.
Definition industry_cmd.cpp:2064
PlaceInitialIndustry
static void PlaceInitialIndustry(IndustryType type, bool water, bool try_hard)
Try to build a industry on the map.
Definition industry_cmd.cpp:2401
CheckIndustryCloseDownProtection
static bool CheckIndustryCloseDownProtection(IndustryType type)
Protects an industry from closure if the appropriate flags and conditions are met CanCloseLastInstanc...
Definition industry_cmd.cpp:2750
SetupFarmFieldFence
static void SetupFarmFieldFence(TileIndex tile, int size, uint8_t type, DiagDirection side)
Build farm field fence.
Definition industry_cmd.cpp:1024
CmdIndustrySetFlags
CommandCost CmdIndustrySetFlags(DoCommandFlags flags, IndustryID ind_id, IndustryControlFlags ctlflags)
Set industry control flags.
Definition industry_cmd.cpp:2156
GetIndustryType
IndustryType GetIndustryType(Tile tile)
Retrieve the type for this industry.
Definition industry_cmd.cpp:109
UpdateIndustryStatistics
static void UpdateIndustryStatistics(Industry *i)
Monthly update of industry statistics.
Definition industry_cmd.cpp:2566
FindTownForIndustry
static CommandCost FindTownForIndustry(TileIndex tile, IndustryType type, Town **t)
Find a town for the industry, while checking for multiple industries in the same town.
Definition industry_cmd.cpp:1432
CheckNewIndustry_NULL
static CommandCost CheckNewIndustry_NULL(TileIndex)
Check the conditions of CHECK_NOTHING (Always succeeds).
Definition industry_cmd.cpp:1261
CreateNewIndustry
static Industry * CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
Create a new industry of random layout.
Definition industry_cmd.cpp:2285
ChangeIndustryProduction
static void ChangeIndustryProduction(Industry *i, bool monthly)
Change industry production or do closure.
Definition industry_cmd.cpp:2872
CheckNewIndustry_Lumbermill
static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
Check the conditions of CHECK_LUMBERMILL (Industry should be in the rainforest).
Definition industry_cmd.cpp:1381
CmdIndustrySetText
CommandCost CmdIndustrySetText(DoCommandFlags flags, IndustryID ind_id, const EncodedString &text)
Change additional industry text.
Definition industry_cmd.cpp:2262
industry_cmd.h
Command definitions related to industries.
industry_land.h
Information about the behaviour of the default industry tiles.
_coal_plant_sparks
static const DrawIndustryCoordinates _coal_plant_sparks[]
Movement of the sparks , only used for Power Station.
Definition industry_land.h:948
_industry_draw_tile_data
static const DrawBuildingsTileStruct _industry_draw_tile_data[NEW_INDUSTRYTILEOFFSET *4]
Structure for industry tiles drawing.
Definition industry_land.h:51
SetIndustryCompleted
void SetIndustryCompleted(Tile tile)
Set if the industry that owns the tile as under construction or not.
Definition industry_map.h:88
SetIndustryGfx
void SetIndustryGfx(Tile t, IndustryGfx gfx)
Set the industry graphics ID for the given industry tile.
Definition industry_map.h:149
ResetIndustryConstructionStage
void ResetIndustryConstructionStage(Tile tile)
Reset the construction stage counter of the industry, as well as the completion bit.
Definition industry_map.h:187
SetIndustryConstructionCounter
void SetIndustryConstructionCounter(Tile tile, uint8_t value)
Sets this industry tile's construction counter value.
Definition industry_map.h:174
GetIndustryGfx
IndustryGfx GetIndustryGfx(Tile t)
Get the industry graphics ID for the given industry tile.
Definition industry_map.h:137
IsIndustryCompleted
bool IsIndustryCompleted(Tile t)
Is this industry tile fully built?
Definition industry_map.h:75
GetIndustryIndex
IndustryID GetIndustryIndex(Tile t)
Get the industry ID of the given tile.
Definition industry_map.h:63
GetIndustryConstructionCounter
uint8_t GetIndustryConstructionCounter(Tile tile)
Returns this industry tile's construction counter value.
Definition industry_map.h:162
MakeIndustry
void MakeIndustry(Tile t, IndustryID index, IndustryGfx gfx, uint8_t random, WaterClass wc)
Make the given tile an industry tile.
Definition industry_map.h:278
SetIndustryAnimationLoop
void SetIndustryAnimationLoop(Tile tile, uint8_t count)
Set the animation loop number.
Definition industry_map.h:211
GFX_WATERTILE_SPECIALCHECK
@ GFX_WATERTILE_SPECIALCHECK
not really a tile, but rather a very special check
Definition industry_map.h:54
SetIndustryConstructionStage
void SetIndustryConstructionStage(Tile tile, uint8_t value)
Sets the industry construction stage of the specified tile.
Definition industry_map.h:112
GetIndustryAnimationLoop
uint8_t GetIndustryAnimationLoop(Tile tile)
Get the animation loop number.
Definition industry_map.h:199
GetIndustryConstructionStage
uint8_t GetIndustryConstructionStage(Tile tile)
Returns the industry construction stage of the specified tile.
Definition industry_map.h:100
NEW_INDUSTRYTILEOFFSET
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
Definition industry_type.h:51
INDUSTRYTILE_NOANIM
static const IndustryGfx INDUSTRYTILE_NOANIM
flag to mark industry tiles as having no animation
Definition industry_type.h:50
IndustryRandomTrigger::IndustryTick
@ IndustryTick
The industry has been triggered via its tick.
IndustryRandomTrigger::TileLoop
@ TileLoop
The tile of the industry has been triggered during the tileloop.
INDUSTRY_ORIGINAL_NUM_INPUTS
static const int INDUSTRY_ORIGINAL_NUM_INPUTS
Original number of accepted cargo types.
Definition industry_type.h:59
INDUSTRY_NUM_OUTPUTS
static const int INDUSTRY_NUM_OUTPUTS
Number of cargo types an industry can produce.
Definition industry_type.h:58
INDUSTRY_NUM_INPUTS
static const int INDUSTRY_NUM_INPUTS
Number of cargo types an industry can accept.
Definition industry_type.h:57
NUM_INDUSTRYTYPES
static const IndustryType NUM_INDUSTRYTYPES
total number of industry types, new and old; limited to 240 because we need some special ids like IT_...
Definition industry_type.h:45
INVALID_INDUSTRYTILE
static const IndustryGfx INVALID_INDUSTRYTILE
one above amount is considered invalid
Definition industry_type.h:53
IndustryAnimationTrigger::CargoDistributed
@ CargoDistributed
Trigger when cargo is distributed.
IndustryAnimationTrigger::IndustryTick
@ IndustryTick
Trigger every tick.
IndustryAnimationTrigger::TileLoop
@ TileLoop
Trigger in the periodic tile loop.
NUM_INDUSTRYTILES
static const IndustryGfx NUM_INDUSTRYTILES
total number of industry tiles, new and old
Definition industry_type.h:52
INDUSTRY_COMPLETED
static const int INDUSTRY_COMPLETED
final stage of industry construction.
Definition industry_type.h:55
IndustryBehaviour::NoBuildMapCreation
@ NoBuildMapCreation
Do not force one instance of this type to appear on map generation.
IndustryBehaviour::CutTrees
@ CutTrees
cuts trees and produce first output cargo from them (lumber mill)
IndustryBehaviour::PlantOnBuild
@ PlantOnBuild
Fields are planted around when built (all farms)
IndustryBehaviour::Before1950
@ Before1950
can only be built before 1950 (oil wells)
IndustryBehaviour::BuiltOnWater
@ BuiltOnWater
is built on water (oil rig)
IndustryBehaviour::DontIncrProd
@ DontIncrProd
do not increase production (oil wells) in the temperate climate
IndustryBehaviour::CargoTypesUnlimited
@ CargoTypesUnlimited
Allow produced/accepted cargoes callbacks to supply more than 2 and 3 types.
IndustryBehaviour::After1960
@ After1960
can only be built after 1960 (oil rigs)
IndustryBehaviour::PlantFields
@ PlantFields
periodically plants fields around itself (temp and arctic farms)
IndustryBehaviour::Town1200More
@ Town1200More
can only be built in towns larger than 1200 inhabitants (temperate bank)
IndustryBehaviour::NoPaxProdClamp
@ NoPaxProdClamp
Do not clamp production of passengers. (smooth economy only)
IndustryBehaviour::CanCloseLastInstance
@ CanCloseLastInstance
Allow closing down the last instance of this type.
IndustryBehaviour::OnlyNearTown
@ OnlyNearTown
is always built near towns (toy shop)
IndustryTileSpecialFlag::AcceptsAllCargo
@ AcceptsAllCargo
Tile always accepts all cargoes the associated industry accepts.
IndustryLifeType::Processing
@ Processing
Like factories.
IndustryLifeType::Organic
@ Organic
Like forests.
IndustryLifeType::Extractive
@ Extractive
Like mines.
GetTranslatedIndustryTileID
IndustryGfx GetTranslatedIndustryTileID(IndustryGfx gfx)
Do industry gfx ID translation for NewGRFs.
Definition industrytype.h:193
IndustryTileLayout
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
Definition industrytype.h:98
CHECK_REFINERY
@ CHECK_REFINERY
Industry should be positioned near edge of the map.
Definition industrytype.h:40
CHECK_END
@ CHECK_END
End marker of the industry check procedures.
Definition industrytype.h:47
CHECK_OIL_RIG
@ CHECK_OIL_RIG
Industries at sea should be positioned near edge of the map.
Definition industrytype.h:46
ICT_MAP_GENERATION
@ ICT_MAP_GENERATION
during random map creation
Definition industrytype.h:54
ICT_NORMAL_GAMEPLAY
@ ICT_NORMAL_GAMEPLAY
either by user or random creation process
Definition industrytype.h:53
ICT_SCENARIO_EDITOR
@ ICT_SCENARIO_EDITOR
while editing a scenario
Definition industrytype.h:55
INDUSTRYLIFE_BLACK_HOLE
static constexpr IndustryLifeTypes INDUSTRYLIFE_BLACK_HOLE
Like power plants and banks.
Definition industrytype.h:31
DrawFoundation
void DrawFoundation(TileInfo *ti, Foundation f)
Draw foundation f at tile ti.
Definition landscape.cpp:429
landscape.h
Functions related to OTTD's landscape.
landscape_cmd.h
Command definitions related to landscape (slopes etc.).
BorderFlag::Random
@ Random
Randomise borders.
DistanceMax
uint DistanceMax(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles.
Definition map.cpp:201
DistanceFromEdgeDir
uint DistanceFromEdgeDir(TileIndex tile, DiagDirection dir)
Gets the distance to the edge of the map in given direction.
Definition map.cpp:246
TileAddWrap
TileIndex TileAddWrap(TileIndex tile, int addx, int addy)
This function checks if we add addx/addy to tile, if we do wrap around the edges.
Definition map.cpp:120
map_func.h
Functions related to maps.
TileAddXY
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:483
ToTileIndexDiff
TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
Return the offset between two tiles from a TileIndexDiffC struct.
Definition map_func.h:453
TileDiffXY
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:401
TileOffsByAxis
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:568
TileY
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:438
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:428
RandomTile
#define RandomTile()
Get a valid random tile.
Definition map_func.h:665
TileOffsByDiagDir
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:583
TileIndexDiff
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
abs
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
CeilDiv
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition math_func.hpp:310
Delta
constexpr T Delta(const T a, const T b)
Returns the (absolute) difference between two (scalar) variables.
Definition math_func.hpp:234
Clamp
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
ClampU
constexpr uint ClampU(const uint a, const uint min, const uint max)
Clamp an unsigned integer between an interval.
Definition math_func.hpp:150
MapGRFStringID
StringID MapGRFStringID(uint32_t grfid, GRFStringID str)
Used when setting an object's property to map to the GRF's strings while taking in consideration the ...
Definition newgrf_stringmapping.cpp:129
AnimationStatus::NoAnimation
@ NoAnimation
There is no animation.
IndustryCallbackMask::InputCargoTypes
@ InputCargoTypes
customize the cargoes the industry requires
IndustryCallbackMask::ProductionChange
@ ProductionChange
controls random production change
IndustryCallbackMask::DecideColour
@ DecideColour
give a custom colour to newly build industries
IndustryCallbackMask::SpecialEffect
@ SpecialEffect
control special effects
IndustryCallbackMask::ProdChangeBuild
@ ProdChangeBuild
initialise production level on construction
IndustryCallbackMask::Production256Ticks
@ Production256Ticks
call production callback every 256 ticks
IndustryCallbackMask::Location
@ Location
check industry construction on given area
IndustryCallbackMask::MonthlyProdChange
@ MonthlyProdChange
controls monthly random production change
IndustryCallbackMask::ProductionCargoArrival
@ ProductionCargoArrival
call production callback when cargo arrives at the industry
IndustryCallbackMask::OutputCargoTypes
@ OutputCargoTypes
customize the cargoes the industry produces
CBID_INDUSTRY_OUTPUT_CARGO_TYPES
@ CBID_INDUSTRY_OUTPUT_CARGO_TYPES
Customize the output cargo types of a newly build industry.
Definition newgrf_callbacks.h:223
CBID_INDUSTRY_SPECIAL_EFFECT
@ CBID_INDUSTRY_SPECIAL_EFFECT
Called to determine industry special effects.
Definition newgrf_callbacks.h:176
CBID_INDTILE_AUTOSLOPE
@ CBID_INDTILE_AUTOSLOPE
Called to determine if industry can alter the ground below industry tile.
Definition newgrf_callbacks.h:179
CBID_INDUSTRY_DECIDE_COLOUR
@ CBID_INDUSTRY_DECIDE_COLOUR
Called to determine the colour of an industry.
Definition newgrf_callbacks.h:217
CBID_INDTILE_DRAW_FOUNDATIONS
@ CBID_INDTILE_DRAW_FOUNDATIONS
Called to determine the type (if any) of foundation to draw for industry tile.
Definition newgrf_callbacks.h:137
CBID_INDUSTRY_PRODUCTION_CHANGE
@ CBID_INDUSTRY_PRODUCTION_CHANGE
Called on production changes, so it can be adjusted.
Definition newgrf_callbacks.h:113
CBID_INDUSTRY_MONTHLYPROD_CHANGE
@ CBID_INDUSTRY_MONTHLYPROD_CHANGE
Called monthly on production changes, so it can be adjusted more frequently.
Definition newgrf_callbacks.h:155
CBID_INDUSTRY_PROD_CHANGE_BUILD
@ CBID_INDUSTRY_PROD_CHANGE_BUILD
Called when industry is built to set initial production level.
Definition newgrf_callbacks.h:280
CBID_INDTILE_CARGO_ACCEPTANCE
@ CBID_INDTILE_CARGO_ACCEPTANCE
Called to query the cargo acceptance of the industry tile.
Definition newgrf_callbacks.h:119
CBID_INDTILE_ACCEPT_CARGO
@ CBID_INDTILE_ACCEPT_CARGO
Called to determine which cargoes an industry should accept.
Definition newgrf_callbacks.h:122
CBID_INDUSTRY_INPUT_CARGO_TYPES
@ CBID_INDUSTRY_INPUT_CARGO_TYPES
Customize the input cargo types of a newly build industry.
Definition newgrf_callbacks.h:220
CALLBACK_FAILED
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
Definition newgrf_callbacks.h:439
IndustryTileCallbackMask::ShapeCheck
@ ShapeCheck
decides slope suitability
IndustryTileCallbackMask::AcceptCargo
@ AcceptCargo
decides accepted types
IndustryTileCallbackMask::CargoAcceptance
@ CargoAcceptance
decides amount of cargo acceptance
IndustryTileCallbackMask::DrawFoundations
@ DrawFoundations
decides if default foundations need to be drawn
IndustryTileCallbackMask::Autoslope
@ Autoslope
decides allowance of autosloping
GetCargoTranslation
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
Definition newgrf_cargo.cpp:80
newgrf_cargo.h
Cargo support for NewGRFs.
ErrorUnknownCallbackResult
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Definition newgrf_commons.cpp:517
ConvertBooleanCallback
bool ConvertBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
Converts a callback result into a boolean.
Definition newgrf_commons.cpp:543
GetGRFConfig
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
Definition newgrf_config.cpp:622
newgrf_debug.h
Functions/types related to NewGRF debugging.
DeleteNewGRFInspectWindow
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
Definition newgrf_debug_gui.cpp:726
CheckIfCallBackAllowsCreation
CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, size_t layout, uint32_t seed, uint16_t initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
Check that the industry callback allows creation of the industry.
Definition newgrf_industries.cpp:545
GetIndustryCallback
uint16_t GetIndustryCallback(CallbackID callback, uint32_t param1, uint32_t param2, Industry *industry, IndustryType type, TileIndex tile, std::span< int32_t > regs100)
Perform an industry callback.
Definition newgrf_industries.cpp:528
IndustryProductionCallback
void IndustryProductionCallback(Industry *ind, int reason)
Get the industry production callback and apply it to the industry.
Definition newgrf_industries.cpp:605
GetIndustryProbabilityCallback
uint32_t GetIndustryProbabilityCallback(IndustryType type, IndustryAvailabilityCallType creation_type, uint32_t default_prob)
Check with callback CBID_INDUSTRY_PROBABILITY whether the industry can be built.
Definition newgrf_industries.cpp:577
IndustryTemporarilyRefusesCargo
bool IndustryTemporarilyRefusesCargo(Industry *ind, CargoType cargo_type)
Check whether an industry temporarily refuses to accept a certain cargo.
Definition newgrf_industries.cpp:687
IndustryAvailabilityCallType
IndustryAvailabilityCallType
From where has callback CBID_INDUSTRY_PROBABILITY been called.
Definition newgrf_industries.h:81
IACT_USERCREATION
@ IACT_USERCREATION
from the Fund/build window
Definition newgrf_industries.h:84
IACT_RANDOMCREATION
@ IACT_RANDOMCREATION
during creation of random ingame industry
Definition newgrf_industries.h:83
IACT_MAPGENERATION
@ IACT_MAPGENERATION
during random map generation
Definition newgrf_industries.h:82
IACT_PROSPECTCREATION
@ IACT_PROSPECTCREATION
from the Fund/build using prospecting
Definition newgrf_industries.h:85
TriggerIndustryTileRandomisation
void TriggerIndustryTileRandomisation(TileIndex tile, IndustryRandomTrigger trigger)
Trigger a random trigger for a single industry tile.
Definition newgrf_industrytiles.cpp:375
PerformIndustryTileSlopeCheck
CommandCost PerformIndustryTileSlopeCheck(TileIndex ind_base_tile, TileIndex ind_tile, const IndustryTileSpec *its, IndustryType type, IndustryGfx gfx, size_t layout_index, uint16_t initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type)
Check the slope of a tile of a new industry.
Definition newgrf_industrytiles.cpp:232
TriggerIndustryRandomisation
void TriggerIndustryRandomisation(Industry *ind, IndustryRandomTrigger trigger)
Trigger a random trigger for all industry tiles.
Definition newgrf_industrytiles.cpp:388
newgrf_industrytiles.h
NewGRF handling of industry tiles.
news_func.h
Functions related to news.
DeleteIndustryNews
void DeleteIndustryNews(IndustryID iid)
Remove news regarding given industry.
Definition news_gui.cpp:1038
NewsType
NewsType
Type of news.
Definition news_type.h:29
NewsType::IndustryCompany
@ IndustryCompany
Production changes of industry serviced by local company.
NewsType::IndustryClose
@ IndustryClose
Closing of industries.
NewsType::IndustryOpen
@ IndustryOpen
Opening of industries.
NewsType::IndustryNobody
@ IndustryNobody
Other industry production changes.
NewsType::IndustryOther
@ IndustryOther
Production changes of industry serviced by competitor(s)
object_base.h
Base for all objects.
OrderUnloadType::Transfer
@ Transfer
Transfer all cargo onto the platform.
OrderUnloadType::Unload
@ Unload
Force unloading all cargo onto the platform, possibly not getting paid.
pool_func.hpp
Some methods of Pool are placed here in order to reduce compilation time and binary size.
INSTANTIATE_POOL_METHODS
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition pool_func.hpp:210
RandomRange
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
Definition random_func.hpp:88
Chance16I
bool Chance16I(const uint32_t a, const uint32_t b, const uint32_t r)
Checks if a given randomize-number is below a given probability.
Definition random_func.hpp:118
Chance16
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
Definition random_func.hpp:134
Chance16R
bool Chance16R(const uint32_t a, const uint32_t b, uint32_t &r, const std::source_location location=std::source_location::current())
Flips a coin with a given probability and saves the randomize-number in a variable.
Definition random_func.hpp:154
safeguards.h
A number of safeguards to prevent using unsafe methods.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
ID_CUSTOM
@ ID_CUSTOM
Custom number of industries.
Definition settings_type.h:63
ID_VERY_LOW
@ ID_VERY_LOW
Very few industries at game start.
Definition settings_type.h:58
ID_END
@ ID_END
Number of industry density settings.
Definition settings_type.h:65
ID_FUND_ONLY
@ ID_FUND_ONLY
The game does not build industries.
Definition settings_type.h:56
GetSlopeMaxZ
static constexpr int GetSlopeMaxZ(Slope s)
Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
Definition slope_func.h:160
IsSteepSlope
static constexpr bool IsSteepSlope(Slope s)
Checks if a slope is steep.
Definition slope_func.h:36
FlatteningFoundation
Foundation FlatteningFoundation(Slope s)
Returns the foundation needed to flatten a slope.
Definition slope_func.h:369
ComplementSlope
Slope ComplementSlope(Slope s)
Return the complement of a slope.
Definition slope_func.h:76
Slope
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
SLOPE_W
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:50
SLOPE_E
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:52
SLOPE_S
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:51
SLOPE_N
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:53
SLOPE_SW
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:56
SLOPE_FLAT
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:49
SLOPE_NE
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:58
SLOPE_SE
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:57
SLOPE_NW
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:55
Foundation
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
FOUNDATION_LEVELED
@ FOUNDATION_LEVELED
The tile is leveled up to a flat slope.
Definition slope_type.h:95
FOUNDATION_NONE
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:94
sound_func.h
Functions related to sound.
SoundFx
SoundFx
Sound effects from baseset.
Definition sound_type.h:45
SND_30_TOFFEE_QUARRY
@ SND_30_TOFFEE_QUARRY
48 == 0x30 Industry animation: toffee quarry: drill
Definition sound_type.h:95
SND_2E_BUBBLE_GENERATOR
@ SND_2E_BUBBLE_GENERATOR
46 == 0x2E Industry animation: bubble generator (1): generate bubble
Definition sound_type.h:93
SND_2D_SUGAR_MINE_1
@ SND_2D_SUGAR_MINE_1
45 == 0x2D Industry animation: sugar mine (1): shaking sieve
Definition sound_type.h:92
SND_2B_TOY_FACTORY_2
@ SND_2B_TOY_FACTORY_2
43 == 0x2B Industry animation: toy factory (2): stamp product
Definition sound_type.h:90
SND_38_LUMBER_MILL_1
@ SND_38_LUMBER_MILL_1
56 == 0x38 Industry animation: lumber mill (1): chainsaw
Definition sound_type.h:103
SND_29_SUGAR_MINE_2
@ SND_29_SUGAR_MINE_2
41 == 0x29 Industry animation: sugar mine (2): shaking sieve
Definition sound_type.h:88
SND_2C_TOY_FACTORY_1
@ SND_2C_TOY_FACTORY_1
44 == 0x2C Industry animation: toy factory (1): conveyor belt
Definition sound_type.h:91
SND_37_LUMBER_MILL_2
@ SND_37_LUMBER_MILL_2
55 == 0x37 Industry animation: lumber mill (2): falling tree
Definition sound_type.h:102
SND_0C_POWER_STATION
@ SND_0C_POWER_STATION
10 == 0x0A Industry animation: power station: spark
Definition sound_type.h:57
SND_0B_MINE
@ SND_0B_MINE
9 == 0x09 Industry animation: coal/copper/gold mine: headgear
Definition sound_type.h:56
SND_36_LUMBER_MILL_3
@ SND_36_LUMBER_MILL_3
54 == 0x36 Industry animation: lumber mill (3): crashing tree
Definition sound_type.h:101
SND_2A_TOY_FACTORY_3
@ SND_2A_TOY_FACTORY_3
42 == 0x2A Industry animation: toy factory (3): eject product
Definition sound_type.h:89
SourceType::Industry
@ Industry
Source/destination is an industry.
GetColourPalette
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:188
SpriteLayoutPaletteTransform
PaletteID SpriteLayoutPaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_TRANSPARENT and PALETTE_MODIFIER_COLOUR to a palette entry of a sprite layou...
Definition sprite.h:155
GroundSpritePaletteTransform
PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition sprite.h:174
station_base.h
Base classes/functions for stations.
ForAllStationsAroundTiles
void ForAllStationsAroundTiles(const TileArea &ta, Func func)
Call a function on all stations that have any part of the requested area within their catchment.
Definition station_base.h:645
ClearDockingTilesCheckingNeighbours
void ClearDockingTilesCheckingNeighbours(TileIndex tile)
Clear docking tile status from tiles around a removed dock, if the tile has no neighbours which would...
Definition station_cmd.cpp:3001
IsOilRig
bool IsOilRig(Tile t)
Is tile t part of an oilrig?
Definition station_map.h:368
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
lengthof
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
string_func.h
Functions related to low-level strings.
GetStringWithArgs
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Definition strings.cpp:336
GetEncodedString
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
strings_func.h
Functions related to OTTD's strings.
MakeParameters
auto MakeParameters(Args &&... args)
Helper to create the StringParameters with its own buffer with the given parameter values.
Definition strings_func.h:107
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
INVALID_STRING_ID
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition strings_type.h:20
AutoRestoreBackup
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Definition backup_type.hpp:150
Backup
Class to backup a specific variable and restore it later.
Definition backup_type.hpp:21
Backup::GetOriginalValue
const T & GetOriginalValue() const
Returns the backupped value.
Definition backup_type.hpp:70
Backup::Restore
void Restore()
Restore the variable.
Definition backup_type.hpp:110
BaseVehicle::type
VehicleType type
Type of vehicle.
Definition vehicle_type.h:51
CargoArray
Class for storing amounts of cargo.
Definition cargo_type.h:111
CargoPacket::InvalidateAllFrom
static void InvalidateAllFrom(Source src)
Invalidates (sets source_id to INVALID_SOURCE) all cargo packets from given source.
Definition cargopacket.cpp:132
CargoSpec::Get
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
Definition cargotype.h:137
CargoSpec::name
StringID name
Name of this type of cargo.
Definition cargotype.h:91
Cheat::value
bool value
tells if the bool cheat is active or not
Definition cheat_type.h:18
Cheats::magic_bulldozer
Cheat magic_bulldozer
dynamite industries, objects
Definition cheat_type.h:27
ClientSettings::sound
SoundSettings sound
sound effect settings
Definition settings_type.h:653
CommandHelper
Definition command_func.h:84
ConstructionSettings::raw_industry_construction
uint8_t raw_industry_construction
type of (raw) industry construction (none, "normal", prospecting)
Definition settings_type.h:421
ConstructionSettings::industry_platform
uint8_t industry_platform
the amount of flat land around an industry
Definition settings_type.h:422
DifficultySettings::industry_density
uint8_t industry_density
The industry density.
Definition settings_type.h:128
DrawBuildingsTileStruct
This structure is the same for both Industries and Houses.
Definition sprite.h:81
DrawIndustryAnimationStruct
This is used to gather some data about animation drawing in the industry code Image_1-2-3 are in fact...
Definition industry_land.h:18
DrawIndustryAnimationStruct::image_1
uint8_t image_1
image offset 1
Definition industry_land.h:20
DrawIndustryAnimationStruct::image_3
uint8_t image_3
image offset 3
Definition industry_land.h:22
DrawIndustryAnimationStruct::image_2
uint8_t image_2
image offset 2
Definition industry_land.h:21
DrawIndustryAnimationStruct::x
int x
coordinate x of the first image offset
Definition industry_land.h:19
EconomySettings::type
EconomyType type
economy type (original/smooth/frozen)
Definition settings_type.h:543
EconomySettings::multiple_industry_per_town
bool multiple_industry_per_town
allow many industries of the same type per town
Definition settings_type.h:551
Economy::industry_daily_change_counter
uint32_t industry_daily_change_counter
Bits 31-16 are number of industry to be performed, 15-0 are fractional collected daily.
Definition economy_type.h:50
Economy::industry_daily_increment
uint32_t industry_daily_increment
The value which will increment industry_daily_change_counter. Computed value. NOSAVE.
Definition economy_type.h:51
EffectVehicle
A special vehicle is one of the following:
Definition effectvehicle_base.h:24
EffectVehicle::animation_substate
uint8_t animation_substate
Sub state to time the change of the graphics/behaviour.
Definition effectvehicle_base.h:26
GRFConfig::GetName
std::string GetName() const
Get the name of this grf.
Definition newgrf_config.cpp:85
GRFFilePropsBase::grffile
const struct GRFFile * grffile
grf file that introduced this entity
Definition newgrf_commons.h:318
GRFFilePropsBase::grfid
uint32_t grfid
grfid that introduced this entity.
Definition newgrf_commons.h:317
GRFFilePropsBase::HasGrfFile
bool HasGrfFile() const
Test if this entity was introduced by NewGRF.
Definition newgrf_commons.h:326
GameCreationSettings::custom_industry_number
uint16_t custom_industry_number
manually entered number of industries
Definition settings_type.h:399
GameCreationSettings::landscape
LandscapeType landscape
the landscape we're currently in
Definition settings_type.h:395
GameCreationSettings::oil_refinery_limit
uint8_t oil_refinery_limit
distance oil refineries allowed from map edge
Definition settings_type.h:385
GameCreationSettings::land_generator
uint8_t land_generator
the landscape generator
Definition settings_type.h:384
GameSettings::economy
EconomySettings economy
settings to change the economy
Definition settings_type.h:642
GameSettings::construction
ConstructionSettings construction
construction of things in-game
Definition settings_type.h:635
GameSettings::difficulty
DifficultySettings difficulty
settings related to the difficulty
Definition settings_type.h:633
GameSettings::game_creation
GameCreationSettings game_creation
settings used during the creation of a game (map)
Definition settings_type.h:634
GameSettings::station
StationSettings station
settings related to station management
Definition settings_type.h:644
IndustryBuildData
Data for managing the number and type of industries in the game.
Definition industry.h:306
IndustryBuildData::Reset
void Reset()
Completely reset the industry build data.
Definition industry_cmd.cpp:2436
IndustryBuildData::EconomyMonthlyLoop
void EconomyMonthlyLoop()
Monthly update of industry build data.
Definition industry_cmd.cpp:2446
IndustryBuildData::wanted_inds
uint32_t wanted_inds
Number of wanted industries (bits 31-16), and a fraction (bits 15-0).
Definition industry.h:308
IndustryBuildData::SetupTargetCount
void SetupTargetCount()
Decide how many industries of each type are needed.
Definition industry_cmd.cpp:2632
IndustryBuildData::TryBuildNewIndustry
void TryBuildNewIndustry()
Try to create a random industry, during gameplay.
Definition industry_cmd.cpp:2677
IndustryBuildData::builddata
IndustryTypeBuildData builddata[NUM_INDUSTRYTYPES]
Industry build data for every industry type.
Definition industry.h:307
IndustryGenerationProbabilities
Definition industry_cmd.cpp:2459
IndustryListEntry
Definition station_base.h:506
IndustrySpec
Defines the data structure for constructing industry.
Definition industrytype.h:103
IndustrySpec::callback_mask
IndustryCallbackMasks callback_mask
Bitmask of industry callbacks that have to be called.
Definition industrytype.h:132
IndustrySpec::IsProcessingIndustry
bool IsProcessingIndustry() const
Is an industry with the spec a processing industry?
Definition industry_cmd.cpp:3192
IndustrySpec::random_sounds
std::vector< uint8_t > random_sounds
Random sounds;.
Definition industrytype.h:135
IndustrySpec::GetRemovalCost
Money GetRemovalCost() const
Get the cost for removing this industry Take note that the cost will always be zero for non-grf indus...
Definition industry_cmd.cpp:3216
IndustrySpec::accepts_cargo
std::array< CargoType, INDUSTRY_NUM_INPUTS > accepts_cargo
16 accepted cargoes.
Definition industrytype.h:117
IndustrySpec::appear_creation
uint8_t appear_creation[NUM_LANDSCAPE]
Probability of appearance during map creation.
Definition industrytype.h:130
IndustrySpec::UsesOriginalEconomy
bool UsesOriginalEconomy() const
Determines whether this industrytype uses standard/newgrf production changes.
Definition industry_cmd.cpp:3225
IndustrySpec::minimal_cargo
uint8_t minimal_cargo
minimum amount of cargo transported to the stations.
Definition industrytype.h:116
IndustrySpec::removal_cost_multiplier
uint32_t removal_cost_multiplier
Base removal cost multiplier.
Definition industrytype.h:106
IndustrySpec::prospecting_chance
uint32_t prospecting_chance
Chance prospecting succeeds.
Definition industrytype.h:107
IndustrySpec::production_up_text
StringID production_up_text
Message appearing when the industry's production is increasing.
Definition industrytype.h:126
IndustrySpec::grf_prop
SubstituteGRFFileProps grf_prop
properties related to the grf file
Definition industrytype.h:134
IndustrySpec::name
StringID name
Displayed name of the industry.
Definition industrytype.h:123
IndustrySpec::cost_multiplier
uint8_t cost_multiplier
Base construction cost multiplier.
Definition industrytype.h:105
IndustrySpec::IsRawIndustry
bool IsRawIndustry() const
Is an industry with the spec a raw industry?
Definition industry_cmd.cpp:3183
IndustrySpec::conflicting
IndustryType conflicting[3]
Industries this industry cannot be close to.
Definition industrytype.h:108
IndustrySpec::appear_ingame
uint8_t appear_ingame[NUM_LANDSCAPE]
Probability of appearance in game.
Definition industrytype.h:129
IndustrySpec::production_down_text
StringID production_down_text
Message appearing when the industry's production is decreasing.
Definition industrytype.h:127
IndustrySpec::behaviour
IndustryBehaviours behaviour
How this industry will behave, and how others entities can use it.
Definition industrytype.h:121
IndustrySpec::closure_text
StringID closure_text
Message appearing when the industry closes.
Definition industrytype.h:125
IndustrySpec::new_industry_text
StringID new_industry_text
Message appearing when the industry is built.
Definition industrytype.h:124
IndustrySpec::layouts
std::vector< IndustryTileLayout > layouts
List of possible tile layouts for the industry.
Definition industrytype.h:104
IndustrySpec::enabled
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition industrytype.h:133
IndustrySpec::GetConstructionCost
Money GetConstructionCost() const
Get the cost for constructing this industry.
Definition industry_cmd.cpp:3203
IndustrySpec::life_type
IndustryLifeTypes life_type
This is also known as Industry production flag, in newgrf specs.
Definition industrytype.h:119
IndustrySpec::check_proc
uint8_t check_proc
Index to a procedure to check for conflicting circumstances.
Definition industrytype.h:109
IndustryTileLayoutTile
Definition of one tile in an industry tile layout.
Definition industrytype.h:92
IndustryTileSpec
Defines the data structure of each individual tile of an industry.
Definition industrytype.h:152
IndustryTileSpec::anim_next
uint8_t anim_next
Next frame in an animation.
Definition industrytype.h:157
IndustryTileSpec::special_flags
IndustryTileSpecialFlags special_flags
Bitmask of extra flags used by the tile.
Definition industrytype.h:166
IndustryTileSpec::slopes_refused
Slope slopes_refused
slope pattern on which this tile cannot be built
Definition industrytype.h:155
IndustryTileSpec::animation
AnimationInfo< IndustryAnimationTriggers > animation
Information about the animation (is it looping, how many loops etc)
Definition industrytype.h:165
IndustryTileSpec::acceptance
std::array< int8_t, INDUSTRY_NUM_INPUTS > acceptance
Level of acceptance per cargo type (signed, may be negative!)
Definition industrytype.h:154
IndustryTileSpec::grf_prop
SubstituteGRFFileProps grf_prop
properties related to the grf file
Definition industrytype.h:168
IndustryTileSpec::anim_state
bool anim_state
When true, the tile has to be drawn using the animation state instead of the construction stage.
Definition industrytype.h:162
IndustryTileSpec::callback_mask
IndustryTileCallbackMasks callback_mask
Bitmask of industry tile callbacks that have to be called.
Definition industrytype.h:164
IndustryTileSpec::accepts_cargo
std::array< CargoType, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
Definition industrytype.h:153
IndustryTileSpec::anim_production
uint8_t anim_production
Animation frame to start when goods are produced.
Definition industrytype.h:156
IndustryTypeBuildData
Data for managing the number of industries of a single industry type.
Definition industry.h:291
IndustryTypeBuildData::probability
uint32_t probability
Relative probability of building this industry.
Definition industry.h:292
IndustryTypeBuildData::target_count
uint16_t target_count
Desired number of industries of this type.
Definition industry.h:294
IndustryTypeBuildData::min_number
uint8_t min_number
Smallest number of industries that should exist (either 0 or 1).
Definition industry.h:293
IndustryTypeBuildData::Reset
void Reset()
Reset the entry.
Definition industry_cmd.cpp:2426
IndustryTypeBuildData::GetIndustryTypeData
bool GetIndustryTypeData(IndustryType it)
Set the probability and min_number fields for the industry type it for a running game.
Definition industry_cmd.cpp:2621
IndustryTypeBuildData::wait_count
uint16_t wait_count
Number of turns to wait before trying to build again.
Definition industry.h:296
IndustryTypeBuildData::max_wait
uint16_t max_wait
Starting number of turns to wait (copied to wait_count).
Definition industry.h:295
Industry::AcceptedCargo
Definition industry.h:85
Industry::AcceptedCargo::cargo
CargoType cargo
Cargo type.
Definition industry.h:86
Industry::AcceptedHistory
Definition industry.h:80
Industry::ProducedCargo
Definition industry.h:73
Industry::ProducedCargo::cargo
CargoType cargo
Cargo type.
Definition industry.h:74
Industry::ProducedCargo::history
HistoryData< ProducedHistory > history
History of cargo produced and transported for this month and 24 previous months.
Definition industry.h:77
Industry::ProducedCargo::rate
uint8_t rate
Production rate.
Definition industry.h:76
Industry::ProducedHistory
Definition industry.h:63
Industry
Defines the internal data of a functional industry.
Definition industry.h:62
Industry::GetRandom
static Industry * GetRandom()
Return a random valid industry.
Definition industry_cmd.cpp:227
Industry::type
IndustryType type
type of industry.
Definition industry.h:115
Industry::exclusive_supplier
Owner exclusive_supplier
Which company has exclusive rights to deliver cargo (INVALID_OWNER = anyone)
Definition industry.h:130
Industry::construction_date
TimerGameCalendar::Date construction_date
Date of the construction of the industry.
Definition industry.h:127
Industry::ctlflags
IndustryControlFlags ctlflags
flags overriding standard behaviours
Definition industry.h:120
Industry::IsCargoAccepted
bool IsCargoAccepted() const
Test if this industry accepts any cargo.
Definition industry.h:223
Industry::psa
PersistentStorage * psa
Persistent storage for NewGRF industries.
Definition industry.h:136
Industry::prod_level
uint8_t prod_level
general production level
Definition industry.h:112
Industry::random_colour
Colours random_colour
randomized colour of the industry, for display purpose
Definition industry.h:117
Industry::RecomputeProductionMultipliers
void RecomputeProductionMultipliers()
Recompute #production_rate for current prod_level.
Definition industry_cmd.cpp:2592
Industry::text
EncodedString text
General text with additional information.
Definition industry.h:132
Industry::construction_type
uint8_t construction_type
Way the industry was constructed (.
Definition industry.h:128
Industry::cached_name
std::string cached_name
NOSAVE: Cache of the resolved name of the industry.
Definition industry.h:124
Industry::GetProduced
const ProducedCargo & GetProduced(size_t slot) const
Safely get a produced cargo slot, or an empty data if the slot does not exist.
Definition industry.h:158
Industry::valid_history
ValidHistoryMask valid_history
Mask of valid history records.
Definition industry.h:109
Industry::last_prod_year
TimerGameEconomy::Year last_prod_year
last economy year of production
Definition industry.h:118
Industry::produced
ProducedCargoes produced
produced cargo slots
Definition industry.h:110
Industry::random
uint16_t random
Random value used for randomisation of all kinds of things.
Definition industry.h:134
Industry::PostDestructor
static void PostDestructor(size_t index)
Invalidating some stuff after removing item from the pool.
Definition industry_cmd.cpp:216
Industry::town
Town * town
Nearest town.
Definition industry.h:107
Industry::founder
Owner founder
Founder of the industry.
Definition industry.h:126
Industry::selected_layout
uint8_t selected_layout
Which tile layout was used when creating the industry.
Definition industry.h:129
Industry::accepted
AcceptedCargoes accepted
accepted cargo slots
Definition industry.h:111
Industry::GetIndustryTypeCount
static uint16_t GetIndustryTypeCount(IndustryType type)
Get the count of industries for this type.
Definition industry.h:264
Industry::owner
Owner owner
owner of the industry. Which SHOULD always be (imho) OWNER_NONE
Definition industry.h:116
Industry::GetByTile
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition industry.h:251
Industry::location
TileArea location
Location of the industry.
Definition industry.h:106
Industry::neutral_station
Station * neutral_station
Associated neutral station.
Definition industry.h:108
Industry::stations_near
StationList stations_near
NOSAVE: List of nearby stations.
Definition industry.h:123
Industry::IsCargoProduced
bool IsCargoProduced() const
Test if this industry produces any cargo.
Definition industry.h:229
Industry::exclusive_consumer
Owner exclusive_consumer
Which company has exclusive rights to take cargo (INVALID_OWNER = anyone)
Definition industry.h:131
Industry::counter
uint16_t counter
used for animation and/or production (if available cargo)
Definition industry.h:113
Industry::was_cargo_delivered
uint8_t was_cargo_delivered
flag that indicate this has been the closest industry chosen for cargo delivery by a station....
Definition industry.h:119
Industry::TileBelongsToIndustry
bool TileBelongsToIndustry(TileIndex tile) const
Check if a given tile belongs to this industry.
Definition industry.h:148
Industry::industries
static std::array< FlatSet< IndustryID >, NUM_INDUSTRYTYPES > industries
List of industries of each type.
Definition industry.h:276
Map::SizeX
static uint SizeX()
Get the size of the map along the X.
Definition map_func.h:272
Map::WrapToMap
static TileIndex WrapToMap(TileIndex tile)
'Wraps' the given "tile" so it is within the map.
Definition map_func.h:329
Map::ScaleBySize
static uint ScaleBySize(uint n)
Scales the given value by the map size, where the given value is for a 256 by 256 map.
Definition map_func.h:340
Map::SizeY
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:281
Map::ScaleByLandProportion
static uint ScaleByLandProportion(uint n)
Scales the given value by the number of water tiles.
Definition map_func.h:318
Map::ScaleBySize1D
static uint ScaleBySize1D(uint n)
Scales the given value by the maps circumference, where the given value is for a 256 by 256 map.
Definition map_func.h:353
Map::MaxY
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition map_func.h:308
Map::MaxX
static uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition map_func.h:299
Map::Size
static uint Size()
Get the size of the map.
Definition map_func.h:290
Order
Definition order_base.h:33
OrthogonalTileArea
Represents the covered area of e.g.
Definition tilearea_type.h:18
OrthogonalTileArea::ClampToMap
void ClampToMap()
Clamp the tile area to map borders.
Definition tilearea.cpp:142
OrthogonalTileArea::w
uint16_t w
The width of the area.
Definition tilearea_type.h:20
OrthogonalTileArea::Add
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition tilearea.cpp:43
OrthogonalTileArea::tile
TileIndex tile
The base tile of the area.
Definition tilearea_type.h:19
OrthogonalTileArea::h
uint16_t h
The height of the area.
Definition tilearea_type.h:21
OrthogonalTileArea::Expand
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
Definition tilearea.cpp:123
PalSpriteID::sprite
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PalSpriteID::pal
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:24
PoolID
Templated helper to make a PoolID a single POD value.
Definition pool_type.hpp:43
Pool::PoolItem<&_vehicle_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition pool_type.hpp:436
Pool::PoolItem<&_industry_pool >::GetPoolSize
static size_t GetPoolSize()
Returns first unused index.
Definition pool_type.hpp:408
Pool::PoolItem<&_industry_pool >::Get
static Titem * Get(auto index)
Returns Titem with given index.
Definition pool_type.hpp:387
Pool::PoolItem<&_industry_pool >::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition pool_type.hpp:417
Pool::PoolItem<&_industry_pool >::index
Tindex index
Index of this pool item.
Definition pool_type.hpp:286
Pool::PoolItem<&_industry_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition pool_type.hpp:357
Pool::PoolItem<&_industry_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
Pool::PoolItem<&_industry_pool >::CleaningPool
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition pool_type.hpp:366
Pool::PoolItem<&_industry_pool >::GetIfValid
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Definition pool_type.hpp:398
Pool
Base class for all pools.
Definition pool_type.hpp:133
Pool::MAX_SIZE
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition pool_type.hpp:135
Randomizer
Structure to encapsulate the pseudo random number generators.
Definition random_func.hpp:27
Randomizer::SetSeed
void SetSeed(uint32_t seed)
(Re)set the state of the random number generator.
Definition random_func.cpp:55
Randomizer::Next
uint32_t Next()
Generate the next pseudo random number.
Definition random_func.cpp:42
SoundSettings::ambient
bool ambient
Play ambient, industry and town sounds.
Definition settings_type.h:279
Source
A location from where cargo can come from (or go to).
Definition source_type.h:32
SpecializedStation< Station, false >::Get
static Station * Get(auto index)
Gets station with given index.
Definition base_station_base.h:248
SpecializedVehicle::Next
T * Next() const
Get next vehicle in the chain.
Definition vehicle_base.h:1049
StandardGRFFileProps::HasSpriteGroups
bool HasSpriteGroups() const
Check whether the entity has sprite groups.
Definition newgrf_commons.h:385
StationSettings::serve_neutral_industries
bool serve_neutral_industries
company stations can serve industries with attached neutral stations
Definition settings_type.h:594
Station
Station data structure.
Definition station_base.h:520
Station::industries_near
IndustryList industries_near
Cached list of industries near the station that can accept cargo,.
Definition station_base.h:552
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
TileDesc
Tile description for the 'land area information' tool.
Definition tile_cmd.h:36
TileDesc::grf
std::optional< std::string > grf
newGRF used for the tile contents
Definition tile_cmd.h:47
TileDesc::str
StringID str
Description of the tile.
Definition tile_cmd.h:37
TileDesc::owner
std::array< Owner, 4 > owner
Name of the owner(s)
Definition tile_cmd.h:39
TileDesc::dparam
uint64_t dparam
Parameter of the str string.
Definition tile_cmd.h:38
TileInfo
Tile information, used while rendering the tile.
Definition tile_cmd.h:30
TileInfo::tileh
Slope tileh
Slope of the tile.
Definition tile_cmd.h:31
TileInfo::tile
TileIndex tile
Tile index.
Definition tile_cmd.h:32
TileTypeProcs
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:152
TownCache::population
uint32_t population
Current population of people.
Definition town.h:53
Town
Town data structure.
Definition town.h:63
Town::xy
TileIndex xy
town center tile
Definition town.h:64
Town::cache
TownCache cache
Container for all cacheable data.
Definition town.h:66
Vehicle
Vehicle data structure.
Definition vehicle_base.h:205
Vehicle::cargo_type
CargoType cargo_type
type of cargo this vehicle is carrying
Definition vehicle_base.h:297
Vehicle::IsFrontEngine
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition vehicle_base.h:913
Vehicle::owner
Owner owner
Which company owns the vehicle?
Definition vehicle_base.h:270
DeleteSubsidyWith
void DeleteSubsidyWith(Source source)
Delete the subsidies associated with a given cargo source type and id.
Definition subsidy.cpp:119
subsidy_func.h
Functions related to subsidies.
terraform_cmd.h
Command definitions related to terraforming.
IsTileFlat
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition tile_map.cpp:95
GetTileMaxZ
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:136
GetTileZ
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
IsTileType
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
TileHeight
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
GetTileMaxPixelZ
int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition tile_map.h:312
GetAnimationFrame
uint8_t GetAnimationFrame(Tile t)
Get the current animation frame.
Definition tile_map.h:250
IsValidTile
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
GetTropicZone
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
SetAnimationFrame
void SetAnimationFrame(Tile t, uint8_t frame)
Set a new animation frame.
Definition tile_map.h:262
GetTileSlope
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
GetTileType
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
TROPICZONE_RAINFOREST
@ TROPICZONE_RAINFOREST
Rainforest tile.
Definition tile_type.h:79
TROPICZONE_DESERT
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
INVALID_TILE
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
TILE_SIZE
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
MP_TREES
@ MP_TREES
Tile got trees.
Definition tile_type.h:52
MP_STATION
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
MP_CLEAR
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
MP_HOUSE
@ MP_HOUSE
A house by a town.
Definition tile_type.h:51
MP_INDUSTRY
@ MP_INDUSTRY
Part of an industry.
Definition tile_type.h:56
MP_VOID
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition tile_type.h:55
TileArea
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition tilearea_type.h:102
timer.h
Definition of Interval and OneShot timers.
timer_game_calendar.h
Definition of the game-calendar-timer.
timer_game_economy.h
Definition of the game-economy-timer.
timer_game_tick.h
Definition of the tick-based game-timer.
town.h
Base of the town class.
ClosestTownFromTile
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
Definition town_cmd.cpp:3961
IsTransparencySet
bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren't in the game menu (there's never transpar...
Definition transparency.h:50
IsInvisibilitySet
bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren't in the game menu (there's never transpar...
Definition transparency.h:61
TO_INDUSTRIES
@ TO_INDUSTRIES
industries
Definition transparency.h:27
TransportType
TransportType
Available types of transport.
Definition transport_type.h:17
tree_map.h
Map accessors for tree tiles.
GetTreeGrowth
TreeGrowthStage GetTreeGrowth(Tile t)
Returns the tree growth stage.
Definition tree_map.h:195
GetTreeGround
TreeGround GetTreeGround(Tile t)
Returns the groundtype for tree tiles.
Definition tree_map.h:102
TREE_GROUND_SHORE
@ TREE_GROUND_SHORE
shore
Definition tree_map.h:56
TREE_GROUND_ROUGH
@ TREE_GROUND_ROUGH
some rough tile
Definition tree_map.h:54
TreeGrowthStage::Grown
@ Grown
Fully grown tree.
EnsureNoVehicleOnGround
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition vehicle.cpp:527
vehicle_func.h
Functions related to vehicles.
VEH_ROAD
@ VEH_ROAD
Road vehicle type.
Definition vehicle_type.h:26
VEH_AIRCRAFT
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition vehicle_type.h:28
VEH_SHIP
@ VEH_SHIP
Ship vehicle type.
Definition vehicle_type.h:27
VEH_TRAIN
@ VEH_TRAIN
Train vehicle type.
Definition vehicle_type.h:25
AddSortableSpriteToDraw
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:663
AddChildSpriteScreen
void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool transparent, const SubSprite *sub, bool scale, bool relative)
Add a child sprite to a parent sprite.
Definition viewport.cpp:824
DrawGroundSprite
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition viewport.cpp:579
viewport_func.h
Functions related to (drawing on) viewports.
water.h
Functions related to water (management)
TileLoop_Water
void TileLoop_Water(TileIndex tile)
Let a water tile floods its diagonal adjoining tiles called from tunnelbridge_cmd,...
Definition water_cmd.cpp:1269
IsTileOnWater
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition water_map.h:138
WaterClass
WaterClass
classes of water (for WaterTileType::Clear water tile type).
Definition water_map.h:39
WaterClass::Invalid
@ Invalid
Used for industry tiles on land (also for oilrig if newgrf says so).
HasTileWaterClass
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:103
GetWaterClass
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:114
IsWaterTile
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:192
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1195
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3297
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3179
window_func.h
Window functions not directly related to making/drawing windows.
WC_INDUSTRY_DIRECTORY
@ WC_INDUSTRY_DIRECTORY
Industry directory; Window numbers:
Definition window_type.h:271
WC_INDUSTRY_PRODUCTION
@ WC_INDUSTRY_PRODUCTION
Industry production history graph; Window numbers:
Definition window_type.h:586
WC_INDUSTRY_VIEW
@ WC_INDUSTRY_VIEW
Industry view; Window numbers:
Definition window_type.h:368
WC_BUILD_INDUSTRY
@ WC_BUILD_INDUSTRY
Build industry; Window numbers:
Definition window_type.h:446