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