OpenTTD
industry_cmd.cpp
Go to the documentation of this file.
1 /* $Id: industry_cmd.cpp 27932 2017-11-25 16:50:28Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "clear_map.h"
14 #include "industry.h"
15 #include "station_base.h"
16 #include "landscape.h"
17 #include "viewport_func.h"
18 #include "command_func.h"
19 #include "town.h"
20 #include "news_func.h"
21 #include "cheat_type.h"
22 #include "genworld.h"
23 #include "tree_map.h"
24 #include "newgrf_cargo.h"
25 #include "newgrf_debug.h"
26 #include "newgrf_industrytiles.h"
27 #include "autoslope.h"
28 #include "water.h"
29 #include "strings_func.h"
30 #include "window_func.h"
31 #include "date_func.h"
32 #include "vehicle_func.h"
33 #include "sound_func.h"
34 #include "animated_tile_func.h"
35 #include "effectvehicle_func.h"
36 #include "effectvehicle_base.h"
37 #include "ai/ai.hpp"
38 #include "core/pool_func.hpp"
39 #include "subsidy_func.h"
40 #include "core/backup_type.hpp"
41 #include "object_base.h"
42 #include "game/game.hpp"
43 #include "error.h"
44 
45 #include "table/strings.h"
46 #include "table/industry_land.h"
47 #include "table/build_industry.h"
48 
49 #include "safeguards.h"
50 
51 IndustryPool _industry_pool("Industry");
53 
54 void ShowIndustryViewWindow(int industry);
55 void BuildOilRig(TileIndex tile);
56 
57 static byte _industry_sound_ctr;
58 static TileIndex _industry_sound_tile;
59 
60 uint16 Industry::counts[NUM_INDUSTRYTYPES];
61 
62 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
63 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
65 
73 {
74  memset(&_industry_specs, 0, sizeof(_industry_specs));
75  memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
76 
77  /* once performed, enable only the current climate industries */
78  for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
79  _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
80  HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
81  }
82 
83  memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
84  memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
85 
86  /* Reset any overrides that have been set. */
87  _industile_mngr.ResetOverride();
88  _industry_mngr.ResetOverride();
89 }
90 
99 IndustryType GetIndustryType(TileIndex tile)
100 {
101  assert(IsTileType(tile, MP_INDUSTRY));
102 
103  const Industry *ind = Industry::GetByTile(tile);
104  assert(ind != NULL);
105  return ind->type;
106 }
107 
116 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
117 {
118  assert(thistype < NUM_INDUSTRYTYPES);
119  return &_industry_specs[thistype];
120 }
121 
130 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
131 {
132  assert(gfx < INVALID_INDUSTRYTILE);
133  return &_industry_tile_specs[gfx];
134 }
135 
136 Industry::~Industry()
137 {
138  if (CleaningPool()) return;
139 
140  /* Industry can also be destroyed when not fully initialized.
141  * This means that we do not have to clear tiles either.
142  * Also we must not decrement industry counts in that case. */
143  if (this->location.w == 0) return;
144 
145  TILE_AREA_LOOP(tile_cur, this->location) {
146  if (IsTileType(tile_cur, MP_INDUSTRY)) {
147  if (GetIndustryIndex(tile_cur) == this->index) {
148  DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur);
149 
150  /* MakeWaterKeepingClass() can also handle 'land' */
151  MakeWaterKeepingClass(tile_cur, OWNER_NONE);
152  }
153  } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
154  DeleteOilRig(tile_cur);
155  }
156  }
157 
158  if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
159  TileArea ta(this->location.tile - TileDiffXY(min(TileX(this->location.tile), 21), min(TileY(this->location.tile), 21)), 42, 42);
160  ta.ClampToMap();
161 
162  /* Remove the farmland and convert it to regular tiles over time. */
163  TILE_AREA_LOOP(tile_cur, ta) {
164  if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
165  GetIndustryIndexOfField(tile_cur) == this->index) {
166  SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
167  }
168  }
169  }
170 
171  /* don't let any disaster vehicle target invalid industry */
173 
174  /* Clear the persistent storage. */
175  delete this->psa;
176 
177  DecIndustryTypeCount(this->type);
178 
179  DeleteIndustryNews(this->index);
181  DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
182 
185 }
186 
191 void Industry::PostDestructor(size_t index)
192 {
195 }
196 
197 
203 {
204  if (Industry::GetNumItems() == 0) return NULL;
205  int num = RandomRange((uint16)Industry::GetNumItems());
206  size_t index = MAX_UVALUE(size_t);
207 
208  while (num >= 0) {
209  num--;
210  index++;
211 
212  /* Make sure we have a valid industry */
213  while (!Industry::IsValidID(index)) {
214  index++;
215  assert(index < Industry::GetPoolSize());
216  }
217  }
218 
219  return Industry::Get(index);
220 }
221 
222 
223 static void IndustryDrawSugarMine(const TileInfo *ti)
224 {
225  if (!IsIndustryCompleted(ti->tile)) return;
226 
227  const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
228 
229  AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
230 
231  if (d->image_2 != 0) {
232  AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
233  }
234 
235  if (d->image_3 != 0) {
236  AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
237  _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
238  }
239 }
240 
241 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
242 {
243  uint8 x = 0;
244 
245  if (IsIndustryCompleted(ti->tile)) {
246  x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
247  if (x == 0xFF) {
248  x = 0;
249  }
250  }
251 
252  AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
253  AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
254 }
255 
256 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
257 {
258  if (IsIndustryCompleted(ti->tile)) {
259  AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
260  }
261  AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
262 }
263 
264 static void IndustryDrawToyFactory(const TileInfo *ti)
265 {
266  const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
267 
268  if (d->image_1 != 0xFF) {
269  AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
270  }
271 
272  if (d->image_2 != 0xFF) {
273  AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
274  }
275 
276  AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
277  AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
278 }
279 
280 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
281 {
282  if (IsIndustryCompleted(ti->tile)) {
283  uint8 image = GetAnimationFrame(ti->tile);
284 
285  if (image != 0 && image < 7) {
286  AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
287  PAL_NONE,
288  _coal_plant_sparks[image - 1].x,
289  _coal_plant_sparks[image - 1].y
290  );
291  }
292  }
293 }
294 
295 typedef void IndustryDrawTileProc(const TileInfo *ti);
296 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
297  IndustryDrawSugarMine,
298  IndustryDrawToffeeQuarry,
299  IndustryDrawBubbleGenerator,
300  IndustryDrawToyFactory,
301  IndustryDrawCoalPlantSparks,
302 };
303 
304 static void DrawTile_Industry(TileInfo *ti)
305 {
306  IndustryGfx gfx = GetIndustryGfx(ti->tile);
307  Industry *ind = Industry::GetByTile(ti->tile);
308  const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
309 
310  /* Retrieve pointer to the draw industry tile struct */
311  if (gfx >= NEW_INDUSTRYTILEOFFSET) {
312  /* Draw the tile using the specialized method of newgrf industrytile.
313  * DrawNewIndustry will return false if ever the resolver could not
314  * find any sprite to display. So in this case, we will jump on the
315  * substitute gfx instead. */
316  if (indts->grf_prop.spritegroup[0] != NULL && DrawNewIndustryTile(ti, ind, gfx, indts)) {
317  return;
318  } else {
319  /* No sprite group (or no valid one) found, meaning no graphics associated.
320  * Use the substitute one instead */
321  if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
322  gfx = indts->grf_prop.subst_id;
323  /* And point the industrytile spec accordingly */
324  indts = GetIndustryTileSpec(gfx);
325  }
326  }
327  }
328 
329  const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
332 
333  SpriteID image = dits->ground.sprite;
334 
335  /* DrawFoundation() modifies ti->z and ti->tileh */
337 
338  /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
339  * Do not do this if the tile's WaterClass is 'land'. */
340  if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
341  DrawWaterClassGround(ti);
342  } else {
343  DrawGroundSprite(image, GroundSpritePaletteTransform(image, dits->ground.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)));
344  }
345 
346  /* If industries are transparent and invisible, do not draw the upper part */
347  if (IsInvisibilitySet(TO_INDUSTRIES)) return;
348 
349  /* Add industry on top of the ground? */
350  image = dits->building.sprite;
351  if (image != 0) {
352  AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)),
353  ti->x + dits->subtile_x,
354  ti->y + dits->subtile_y,
355  dits->width,
356  dits->height,
357  dits->dz,
358  ti->z,
360 
361  if (IsTransparencySet(TO_INDUSTRIES)) return;
362  }
363 
364  {
365  int proc = dits->draw_proc - 1;
366  if (proc >= 0) _industry_draw_tile_procs[proc](ti);
367  }
368 }
369 
370 static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
371 {
372  return GetTileMaxPixelZ(tile);
373 }
374 
375 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
376 {
377  IndustryGfx gfx = GetIndustryGfx(tile);
378 
379  /* For NewGRF industry tiles we might not be drawing a foundation. We need to
380  * account for this, as other structures should
381  * draw the wall of the foundation in this case.
382  */
383  if (gfx >= NEW_INDUSTRYTILEOFFSET) {
384  const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
385  if (indts->grf_prop.spritegroup[0] != NULL && HasBit(indts->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
386  uint32 callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, Industry::GetByTile(tile), tile);
387  if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(indts->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
388  }
389  }
390  return FlatteningFoundation(tileh);
391 }
392 
393 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted)
394 {
395  IndustryGfx gfx = GetIndustryGfx(tile);
396  const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
397 
398  /* When we have to use a callback, we put our data in the next two variables */
399  CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)];
400  uint8 raw_cargo_acceptance[lengthof(itspec->acceptance)];
401 
402  /* And then these will always point to a same sized array with the required data */
403  const CargoID *accepts_cargo = itspec->accepts_cargo;
404  const uint8 *cargo_acceptance = itspec->acceptance;
405 
407  uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
408  if (res != CALLBACK_FAILED) {
409  accepts_cargo = raw_accepts_cargo;
410  for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
411  }
412  }
413 
415  uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
416  if (res != CALLBACK_FAILED) {
417  cargo_acceptance = raw_cargo_acceptance;
418  for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_cargo_acceptance[i] = GB(res, i * 4, 4);
419  }
420  }
421 
422  const Industry *ind = Industry::GetByTile(tile);
423  for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
424  CargoID a = accepts_cargo[i];
425  if (a == CT_INVALID || cargo_acceptance[i] == 0) continue; // work only with valid cargoes
426 
427  /* Add accepted cargo */
428  acceptance[a] += cargo_acceptance[i];
429 
430  /* Maybe set 'always accepted' bit (if it's not set already) */
431  if (HasBit(*always_accepted, a)) continue;
432 
433  bool accepts = false;
434  for (uint cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
435  /* Test whether the industry itself accepts the cargo type */
436  if (ind->accepts_cargo[cargo_index] == a) {
437  accepts = true;
438  break;
439  }
440  }
441 
442  if (accepts) continue;
443 
444  /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
445  SetBit(*always_accepted, a);
446  }
447 }
448 
449 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
450 {
451  const Industry *i = Industry::GetByTile(tile);
452  const IndustrySpec *is = GetIndustrySpec(i->type);
453 
454  td->owner[0] = i->owner;
455  td->str = is->name;
456  if (!IsIndustryCompleted(tile)) {
457  SetDParamX(td->dparam, 0, td->str);
458  td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
459  }
460 
461  if (is->grf_prop.grffile != NULL) {
462  td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
463  }
464 }
465 
466 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
467 {
468  Industry *i = Industry::GetByTile(tile);
469  const IndustrySpec *indspec = GetIndustrySpec(i->type);
470 
471  /* water can destroy industries
472  * in editor you can bulldoze industries
473  * with magic_bulldozer cheat you can destroy industries
474  * (area around OILRIG is water, so water shouldn't flood it
475  */
476  if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
478  ((flags & DC_AUTO) != 0) ||
480  ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
481  HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
482  SetDParam(1, indspec->name);
483  return_cmd_error(flags & DC_AUTO ? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY : INVALID_STRING_ID);
484  }
485 
486  if (flags & DC_EXEC) {
487  AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
488  Game::NewEvent(new ScriptEventIndustryClose(i->index));
489  delete i;
490  }
492 }
493 
500 {
501  Industry *i = Industry::GetByTile(tile);
502  const IndustrySpec *indspec = GetIndustrySpec(i->type);
503  bool moved_cargo = false;
504 
505  StationFinder stations(i->location);
506 
507  for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
508  uint cw = min(i->produced_cargo_waiting[j], 255);
509  if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
510  i->produced_cargo_waiting[j] -= cw;
511 
512  /* fluctuating economy? */
513  if (EconomyIsInRecession()) cw = (cw + 1) / 2;
514 
515  i->this_month_production[j] += cw;
516 
517  uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
518  i->this_month_transported[j] += am;
519 
520  moved_cargo |= (am != 0);
521  }
522  }
523 
524  return moved_cargo;
525 }
526 
527 
528 static void AnimateTile_Industry(TileIndex tile)
529 {
530  IndustryGfx gfx = GetIndustryGfx(tile);
531 
532  if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
533  AnimateNewIndustryTile(tile);
534  return;
535  }
536 
537  switch (gfx) {
538  case GFX_SUGAR_MINE_SIEVE:
539  if ((_tick_counter & 1) == 0) {
540  byte m = GetAnimationFrame(tile) + 1;
541 
543  switch (m & 7) {
544  case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
545  case 6: SndPlayTileFx(SND_29_RIP, tile); break;
546  }
547  }
548 
549  if (m >= 96) {
550  m = 0;
551  DeleteAnimatedTile(tile);
552  }
553  SetAnimationFrame(tile, m);
554 
555  MarkTileDirtyByTile(tile);
556  }
557  break;
558 
559  case GFX_TOFFEE_QUARY:
560  if ((_tick_counter & 3) == 0) {
561  byte m = GetAnimationFrame(tile);
562 
563  if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
564  SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
565  }
566 
567  if (++m >= 70) {
568  m = 0;
569  DeleteAnimatedTile(tile);
570  }
571  SetAnimationFrame(tile, m);
572 
573  MarkTileDirtyByTile(tile);
574  }
575  break;
576 
577  case GFX_BUBBLE_CATCHER:
578  if ((_tick_counter & 1) == 0) {
579  byte m = GetAnimationFrame(tile);
580 
581  if (++m >= 40) {
582  m = 0;
583  DeleteAnimatedTile(tile);
584  }
585  SetAnimationFrame(tile, m);
586 
587  MarkTileDirtyByTile(tile);
588  }
589  break;
590 
591  /* Sparks on a coal plant */
592  case GFX_POWERPLANT_SPARKS:
593  if ((_tick_counter & 3) == 0) {
594  byte m = GetAnimationFrame(tile);
595  if (m == 6) {
596  SetAnimationFrame(tile, 0);
597  DeleteAnimatedTile(tile);
598  } else {
599  SetAnimationFrame(tile, m + 1);
600  MarkTileDirtyByTile(tile);
601  }
602  }
603  break;
604 
605  case GFX_TOY_FACTORY:
606  if ((_tick_counter & 1) == 0) {
607  byte m = GetAnimationFrame(tile) + 1;
608 
609  switch (m) {
610  case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
611  case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
612  case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
613  default:
614  if (m >= 50) {
615  int n = GetIndustryAnimationLoop(tile) + 1;
616  m = 0;
617  if (n >= 8) {
618  n = 0;
619  DeleteAnimatedTile(tile);
620  }
621  SetIndustryAnimationLoop(tile, n);
622  }
623  }
624 
625  SetAnimationFrame(tile, m);
626  MarkTileDirtyByTile(tile);
627  }
628  break;
629 
630  case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
631  case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
632  case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
633  case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
634  if ((_tick_counter & 3) == 0) {
635  IndustryGfx gfx = GetIndustryGfx(tile);
636 
637  gfx = (gfx < 155) ? gfx + 1 : 148;
638  SetIndustryGfx(tile, gfx);
639  MarkTileDirtyByTile(tile);
640  }
641  break;
642 
643  case GFX_OILWELL_ANIMATED_1:
644  case GFX_OILWELL_ANIMATED_2:
645  case GFX_OILWELL_ANIMATED_3:
646  if ((_tick_counter & 7) == 0) {
647  bool b = Chance16(1, 7);
648  IndustryGfx gfx = GetIndustryGfx(tile);
649 
650  byte m = GetAnimationFrame(tile) + 1;
651  if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
652  SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
654  DeleteAnimatedTile(tile);
655  } else {
656  SetAnimationFrame(tile, m);
657  SetIndustryGfx(tile, gfx);
658  MarkTileDirtyByTile(tile);
659  }
660  }
661  break;
662 
663  case GFX_COAL_MINE_TOWER_ANIMATED:
664  case GFX_COPPER_MINE_TOWER_ANIMATED:
665  case GFX_GOLD_MINE_TOWER_ANIMATED: {
666  int state = _tick_counter & 0x7FF;
667 
668  if ((state -= 0x400) < 0) return;
669 
670  if (state < 0x1A0) {
671  if (state < 0x20 || state >= 0x180) {
672  byte m = GetAnimationFrame(tile);
673  if (!(m & 0x40)) {
674  SetAnimationFrame(tile, m | 0x40);
675  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
676  }
677  if (state & 7) return;
678  } else {
679  if (state & 3) return;
680  }
681  byte m = (GetAnimationFrame(tile) + 1) | 0x40;
682  if (m > 0xC2) m = 0xC0;
683  SetAnimationFrame(tile, m);
684  MarkTileDirtyByTile(tile);
685  } else if (state >= 0x200 && state < 0x3A0) {
686  int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
687  if (state & i) return;
688 
689  byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
690  if (m < 0x80) m = 0x82;
691  SetAnimationFrame(tile, m);
692  MarkTileDirtyByTile(tile);
693  }
694  break;
695  }
696  }
697 }
698 
699 static void CreateChimneySmoke(TileIndex tile)
700 {
701  uint x = TileX(tile) * TILE_SIZE;
702  uint y = TileY(tile) * TILE_SIZE;
703  int z = GetTileMaxPixelZ(tile);
704 
705  CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
706 }
707 
708 static void MakeIndustryTileBigger(TileIndex tile)
709 {
710  byte cnt = GetIndustryConstructionCounter(tile) + 1;
711  if (cnt != 4) {
713  return;
714  }
715 
716  byte stage = GetIndustryConstructionStage(tile) + 1;
718  SetIndustryConstructionStage(tile, stage);
719  StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
720  if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
721 
722  MarkTileDirtyByTile(tile);
723 
724  if (!IsIndustryCompleted(tile)) return;
725 
726  IndustryGfx gfx = GetIndustryGfx(tile);
727  if (gfx >= NEW_INDUSTRYTILEOFFSET) {
728  /* New industries are already animated on construction. */
729  return;
730  }
731 
732  switch (gfx) {
733  case GFX_POWERPLANT_CHIMNEY:
734  CreateChimneySmoke(tile);
735  break;
736 
737  case GFX_OILRIG_1: {
738  /* Do not require an industry tile to be after the first two GFX_OILRIG_1
739  * tiles (like the default oil rig). Do a proper check to ensure the
740  * tiles belong to the same industry and based on that build the oil rig's
741  * station. */
742  TileIndex other = tile + TileDiffXY(0, 1);
743 
744  if (IsTileType(other, MP_INDUSTRY) &&
745  GetIndustryGfx(other) == GFX_OILRIG_1 &&
746  GetIndustryIndex(tile) == GetIndustryIndex(other)) {
747  BuildOilRig(tile);
748  }
749  break;
750  }
751 
752  case GFX_TOY_FACTORY:
753  case GFX_BUBBLE_CATCHER:
754  case GFX_TOFFEE_QUARY:
755  SetAnimationFrame(tile, 0);
756  SetIndustryAnimationLoop(tile, 0);
757  break;
758 
759  case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
760  case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
761  case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
762  case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
763  AddAnimatedTile(tile);
764  break;
765  }
766 }
767 
768 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
769 {
770  static const int8 _bubble_spawn_location[3][4] = {
771  { 11, 0, -4, -14 },
772  { -4, -10, -4, 1 },
773  { 49, 59, 60, 65 },
774  };
775 
776  if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
777 
778  int dir = Random() & 3;
779 
781  TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
782  TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
783  _bubble_spawn_location[2][dir],
784  EV_BUBBLE
785  );
786 
787  if (v != NULL) v->animation_substate = dir;
788 }
789 
790 static void TileLoop_Industry(TileIndex tile)
791 {
792  if (IsTileOnWater(tile)) TileLoop_Water(tile);
793 
794  /* Normally this doesn't happen, but if an industry NewGRF is removed
795  * an industry that was previously build on water can now be flooded.
796  * If this happens the tile is no longer an industry tile after
797  * returning from TileLoop_Water. */
798  if (!IsTileType(tile, MP_INDUSTRY)) return;
799 
801 
802  if (!IsIndustryCompleted(tile)) {
803  MakeIndustryTileBigger(tile);
804  return;
805  }
806 
807  if (_game_mode == GM_EDITOR) return;
808 
809  if (TransportIndustryGoods(tile) && !StartStopIndustryTileAnimation(Industry::GetByTile(tile), IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
810  uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
811 
812  if (newgfx != INDUSTRYTILE_NOANIM) {
814  SetIndustryCompleted(tile);
815  SetIndustryGfx(tile, newgfx);
816  MarkTileDirtyByTile(tile);
817  return;
818  }
819  }
820 
821  if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
822 
823  IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
824  if (newgfx != INDUSTRYTILE_NOANIM) {
826  SetIndustryGfx(tile, newgfx);
827  MarkTileDirtyByTile(tile);
828  return;
829  }
830 
831  IndustryGfx gfx = GetIndustryGfx(tile);
832  switch (gfx) {
833  case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
834  case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
835  case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
836  if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
837  switch (gfx) {
838  case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
839  case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
840  case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
841  }
842  SetIndustryGfx(tile, gfx);
843  SetAnimationFrame(tile, 0x80);
844  AddAnimatedTile(tile);
845  }
846  break;
847 
848  case GFX_OILWELL_NOT_ANIMATED:
849  if (Chance16(1, 6)) {
850  SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
851  SetAnimationFrame(tile, 0);
852  AddAnimatedTile(tile);
853  }
854  break;
855 
856  case GFX_COAL_MINE_TOWER_ANIMATED:
857  case GFX_COPPER_MINE_TOWER_ANIMATED:
858  case GFX_GOLD_MINE_TOWER_ANIMATED:
859  if (!(_tick_counter & 0x400)) {
860  switch (gfx) {
861  case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
862  case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
863  case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
864  }
865  SetIndustryGfx(tile, gfx);
866  SetIndustryCompleted(tile);
868  DeleteAnimatedTile(tile);
869  }
870  break;
871 
872  case GFX_POWERPLANT_SPARKS:
873  if (Chance16(1, 3)) {
874  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
875  AddAnimatedTile(tile);
876  }
877  break;
878 
879  case GFX_COPPER_MINE_CHIMNEY:
881  break;
882 
883 
884  case GFX_TOY_FACTORY: {
885  Industry *i = Industry::GetByTile(tile);
886  if (i->was_cargo_delivered) {
887  i->was_cargo_delivered = false;
888  SetIndustryAnimationLoop(tile, 0);
889  AddAnimatedTile(tile);
890  }
891  }
892  break;
893 
894  case GFX_BUBBLE_GENERATOR:
895  TileLoopIndustry_BubbleGenerator(tile);
896  break;
897 
898  case GFX_TOFFEE_QUARY:
899  AddAnimatedTile(tile);
900  break;
901 
902  case GFX_SUGAR_MINE_SIEVE:
903  if (Chance16(1, 3)) AddAnimatedTile(tile);
904  break;
905  }
906 }
907 
908 static bool ClickTile_Industry(TileIndex tile)
909 {
910  ShowIndustryViewWindow(GetIndustryIndex(tile));
911  return true;
912 }
913 
914 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
915 {
916  return 0;
917 }
918 
919 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
920 {
921  /* If the founder merges, the industry was created by the merged company */
922  Industry *i = Industry::GetByTile(tile);
923  if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
924 }
925 
932 {
933  /* Check for industry tile */
934  if (!IsTileType(tile, MP_INDUSTRY)) return false;
935 
936  const Industry *ind = Industry::GetByTile(tile);
937 
938  /* Check for organic industry (i.e. not processing or extractive) */
939  if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
940 
941  /* Check for wood production */
942  for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
943  /* The industry produces wood. */
944  if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
945  }
946 
947  return false;
948 }
949 
950 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
951 
959 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
960 {
961  switch (GetTileType(tile)) {
962  case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
963  case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
964  default: return false;
965  }
966 }
967 
975 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
976 {
977  TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
978 
979  do {
980  tile = TILE_MASK(tile);
981 
982  if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
983  byte or_ = type;
984 
985  if (or_ == 1 && Chance16(1, 7)) or_ = 2;
986 
987  SetFence(tile, side, or_);
988  }
989 
990  tile += diff;
991  } while (--size);
992 }
993 
994 static void PlantFarmField(TileIndex tile, IndustryID industry)
995 {
996  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
997  if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
998  }
999 
1000  /* determine field size */
1001  uint32 r = (Random() & 0x303) + 0x404;
1002  if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1003  uint size_x = GB(r, 0, 8);
1004  uint size_y = GB(r, 8, 8);
1005 
1006  TileArea ta(tile - TileDiffXY(min(TileX(tile), size_x / 2), min(TileY(tile), size_y / 2)), size_x, size_y);
1007  ta.ClampToMap();
1008 
1009  if (ta.w == 0 || ta.h == 0) return;
1010 
1011  /* check the amount of bad tiles */
1012  int count = 0;
1013  TILE_AREA_LOOP(cur_tile, ta) {
1014  assert(cur_tile < MapSize());
1015  count += IsSuitableForFarmField(cur_tile, false);
1016  }
1017  if (count * 2 < ta.w * ta.h) return;
1018 
1019  /* determine type of field */
1020  r = Random();
1021  uint counter = GB(r, 5, 3);
1022  uint field_type = GB(r, 8, 8) * 9 >> 8;
1023 
1024  /* make field */
1025  TILE_AREA_LOOP(cur_tile, ta) {
1026  assert(cur_tile < MapSize());
1027  if (IsSuitableForFarmField(cur_tile, true)) {
1028  MakeField(cur_tile, field_type, industry);
1029  SetClearCounter(cur_tile, counter);
1030  MarkTileDirtyByTile(cur_tile);
1031  }
1032  }
1033 
1034  int type = 3;
1035  if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1036  type = _plantfarmfield_type[Random() & 0xF];
1037  }
1038 
1039  SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1040  SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1041  SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1042  SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1043 }
1044 
1045 void PlantRandomFarmField(const Industry *i)
1046 {
1047  int x = i->location.w / 2 + Random() % 31 - 16;
1048  int y = i->location.h / 2 + Random() % 31 - 16;
1049 
1050  TileIndex tile = TileAddWrap(i->location.tile, x, y);
1051 
1052  if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1053 }
1054 
1061 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
1062 {
1063  if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) {
1064  /* found a tree */
1065 
1066  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1067 
1068  _industry_sound_ctr = 1;
1069  _industry_sound_tile = tile;
1070  if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1071 
1072  DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1073 
1074  cur_company.Restore();
1075  return true;
1076  }
1077  return false;
1078 }
1079 
1085 {
1086  /* We only want to cut trees if all tiles are completed. */
1087  TILE_AREA_LOOP(tile_cur, i->location) {
1088  if (i->TileBelongsToIndustry(tile_cur)) {
1089  if (!IsIndustryCompleted(tile_cur)) return;
1090  }
1091  }
1092 
1093  TileIndex tile = i->location.tile;
1094  if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, NULL)) { // 40x40 tiles to search.
1095  i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1096  }
1097 }
1098 
1099 static void ProduceIndustryGoods(Industry *i)
1100 {
1101  const IndustrySpec *indsp = GetIndustrySpec(i->type);
1102 
1103  /* play a sound? */
1104  if ((i->counter & 0x3F) == 0) {
1105  uint32 r;
1106  uint num;
1107  if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
1108  SndPlayTileFx(
1109  (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
1110  i->location.tile);
1111  }
1112  }
1113 
1114  i->counter--;
1115 
1116  /* produce some cargo */
1117  if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1119 
1120  IndustryBehaviour indbehav = indsp->behaviour;
1121  i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
1122  i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
1123 
1124  if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1125  uint16 cb_res = CALLBACK_FAILED;
1127  cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1128  }
1129 
1130  bool plant;
1131  if (cb_res != CALLBACK_FAILED) {
1133  } else {
1134  plant = Chance16(1, 8);
1135  }
1136 
1137  if (plant) PlantRandomFarmField(i);
1138  }
1139  if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1140  uint16 cb_res = CALLBACK_FAILED;
1142  cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1143  }
1144 
1145  bool cut;
1146  if (cb_res != CALLBACK_FAILED) {
1148  } else {
1149  cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1150  }
1151 
1152  if (cut) ChopLumberMillTrees(i);
1153  }
1154 
1156  StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1157  }
1158 }
1159 
1160 void OnTick_Industry()
1161 {
1162  if (_industry_sound_ctr != 0) {
1163  _industry_sound_ctr++;
1164 
1165  if (_industry_sound_ctr == 75) {
1166  if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1167  } else if (_industry_sound_ctr == 160) {
1168  _industry_sound_ctr = 0;
1169  if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1170  }
1171  }
1172 
1173  if (_game_mode == GM_EDITOR) return;
1174 
1175  Industry *i;
1176  FOR_ALL_INDUSTRIES(i) {
1177  ProduceIndustryGoods(i);
1178  }
1179 }
1180 
1187 {
1188  return CommandCost();
1189 }
1190 
1197 {
1198  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1199  if (GetTileZ(tile) < HighestSnowLine() + 2) {
1200  return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1201  }
1202  }
1203  return CommandCost();
1204 }
1205 
1212 {
1213  if (_game_mode == GM_EDITOR) return CommandCost();
1215 
1216  return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1217 }
1218 
1219 extern bool _ignore_restrictions;
1220 
1227 {
1228  if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1229  if (TileHeight(tile) == 0 &&
1231 
1232  return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1233 }
1234 
1241 {
1242  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1243  if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1244  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1245  }
1246  }
1247  return CommandCost();
1248 }
1249 
1256 {
1257  if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1258  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1259  }
1260  return CommandCost();
1261 }
1262 
1269 {
1270  if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1271  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1272  }
1273  return CommandCost();
1274 }
1275 
1282 {
1283  if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1284  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1285  }
1286  return CommandCost();
1287 }
1288 
1295 {
1296  if (GetTileZ(tile) > 4) {
1297  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1298  }
1299  return CommandCost();
1300 }
1301 
1308 
1320 };
1321 
1332 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1333 {
1334  *t = ClosestTownFromTile(tile, UINT_MAX);
1335 
1337 
1338  const Industry *i;
1339  FOR_ALL_INDUSTRIES(i) {
1340  if (i->type == (byte)type && i->town == *t) {
1341  *t = NULL;
1342  return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1343  }
1344  }
1345 
1346  return CommandCost();
1347 }
1348 
1349 bool IsSlopeRefused(Slope current, Slope refused)
1350 {
1351  if (IsSteepSlope(current)) return true;
1352  if (current != SLOPE_FLAT) {
1353  if (IsSteepSlope(refused)) return true;
1354 
1355  Slope t = ComplementSlope(current);
1356 
1357  if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1358  if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1359  if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1360  if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1361  }
1362 
1363  return false;
1364 }
1365 
1378 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, uint itspec_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = NULL)
1379 {
1380  bool refused_slope = false;
1381  bool custom_shape = false;
1382 
1383  do {
1384  IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1385  TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1386 
1387  if (!IsValidTile(cur_tile)) {
1388  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1389  }
1390 
1391  if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1392  if (!IsWaterTile(cur_tile) ||
1393  !IsTileFlat(cur_tile)) {
1394  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1395  }
1396  } else {
1397  CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1398  if (ret.Failed()) return ret;
1399  if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1400 
1401  const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1402 
1403  IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1404 
1405  /* Perform land/water check if not disabled */
1406  if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1407 
1409  custom_shape = true;
1410  CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
1411  if (ret.Failed()) return ret;
1412  } else {
1413  Slope tileh = GetTileSlope(cur_tile);
1414  refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1415  }
1416 
1417  if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1418  ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1419  if (!IsTileType(cur_tile, MP_HOUSE)) {
1420  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1421  }
1422 
1423  /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1424  Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1425  CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1426  cur_company.Restore();
1427 
1428  if (ret.Failed()) return ret;
1429  } else {
1430  /* Clear the tiles, but do not affect town ratings */
1432 
1433  if (ret.Failed()) return ret;
1434  }
1435  }
1436  } while ((++it)->ti.x != -0x80);
1437 
1438  if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1439 
1440  /* It is almost impossible to have a fully flat land in TG, so what we
1441  * do is that we check if we can make the land flat later on. See
1442  * CheckIfCanLevelIndustryPlatform(). */
1443  if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1444  return CommandCost();
1445  }
1446  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1447 }
1448 
1456 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1457 {
1458  if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1459  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1460  }
1461 
1462  if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1463  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1464  }
1465 
1466  return CommandCost();
1467 }
1468 
1469 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1470 {
1471  /* Check if we don't leave the map */
1472  if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1473 
1474  TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1475  TILE_AREA_LOOP(tile_walk, ta) {
1476  uint curh = TileHeight(tile_walk);
1477  /* Is the tile clear? */
1478  if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1479 
1480  /* Don't allow too big of a change if this is the sub-tile check */
1481  if (internal != 0 && Delta(curh, height) > 1) return false;
1482 
1483  /* Different height, so the surrounding tiles of this tile
1484  * has to be correct too (in level, or almost in level)
1485  * else you get a chain-reaction of terraforming. */
1486  if (internal == 0 && curh != height) {
1487  if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1488  return false;
1489  }
1490  }
1491  }
1492 
1493  return true;
1494 }
1495 
1500 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
1501 {
1502  const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1503  int max_x = 0;
1504  int max_y = 0;
1505 
1506  /* Finds dimensions of largest variant of this industry */
1507  do {
1508  if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1509  if (it->ti.x > max_x) max_x = it->ti.x;
1510  if (it->ti.y > max_y) max_y = it->ti.y;
1511  } while ((++it)->ti.x != MKEND);
1512 
1513  /* Remember level height */
1514  uint h = TileHeight(tile);
1515 
1516  if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1517  /* Check that all tiles in area and surrounding are clear
1518  * this determines that there are no obstructing items */
1519 
1522 
1523  if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1524 
1525  /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1526  * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1527  Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1528 
1529  TILE_AREA_LOOP(tile_walk, ta) {
1530  uint curh = TileHeight(tile_walk);
1531  if (curh != h) {
1532  /* This tile needs terraforming. Check if we can do that without
1533  * damaging the surroundings too much. */
1534  if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1535  cur_company.Restore();
1536  return false;
1537  }
1538  /* This is not 100% correct check, but the best we can do without modifying the map.
1539  * What is missing, is if the difference in height is more than 1.. */
1540  if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1541  cur_company.Restore();
1542  return false;
1543  }
1544  }
1545  }
1546 
1547  if (flags & DC_EXEC) {
1548  /* Terraform the land under the industry */
1549  TILE_AREA_LOOP(tile_walk, ta) {
1550  uint curh = TileHeight(tile_walk);
1551  while (curh != h) {
1552  /* We give the terraforming for free here, because we can't calculate
1553  * exact cost in the test-round, and as we all know, that will cause
1554  * a nice assert if they don't match ;) */
1555  DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1556  curh += (curh > h) ? -1 : 1;
1557  }
1558  }
1559  }
1560 
1561  cur_company.Restore();
1562  return true;
1563 }
1564 
1565 
1573 {
1574  const IndustrySpec *indspec = GetIndustrySpec(type);
1575  const Industry *i = NULL;
1576 
1577  /* On a large map with many industries, it may be faster to check an area. */
1578  static const int dmax = 14;
1579  if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
1580  const int tx = TileX(tile);
1581  const int ty = TileY(tile);
1582  TileArea tile_area = TileArea(TileXY(max(0, tx - dmax), max(0, ty - dmax)), TileXY(min(MapMaxX(), tx + dmax), min(MapMaxY(), ty + dmax)));
1583  TILE_AREA_LOOP(atile, tile_area) {
1584  if (GetTileType(atile) == MP_INDUSTRY) {
1585  const Industry *i2 = Industry::GetByTile(atile);
1586  if (i == i2) continue;
1587  i = i2;
1588  if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1589  if (i->type == indspec->conflicting[0] ||
1590  i->type == indspec->conflicting[1] ||
1591  i->type == indspec->conflicting[2]) {
1592  return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1593  }
1594  }
1595  }
1596  return CommandCost();
1597  }
1598 
1599  FOR_ALL_INDUSTRIES(i) {
1600  /* Within 14 tiles from another industry is considered close */
1601  if (DistanceMax(tile, i->location.tile) > 14) continue;
1602 
1603  /* check if there are any conflicting industry types around */
1604  if (i->type == indspec->conflicting[0] ||
1605  i->type == indspec->conflicting[1] ||
1606  i->type == indspec->conflicting[2]) {
1607  return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1608  }
1609  }
1610  return CommandCost();
1611 }
1612 
1617 static void AdvertiseIndustryOpening(const Industry *ind)
1618 {
1619  const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1620  SetDParam(0, ind_spc->name);
1621  if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1622  SetDParam(1, STR_TOWN_NAME);
1623  SetDParam(2, ind->town->index);
1624  } else {
1625  SetDParam(1, ind->town->index);
1626  }
1627  AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1628  AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1629  Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1630 }
1631 
1643 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1644 {
1645  const IndustrySpec *indspec = GetIndustrySpec(type);
1646 
1647  i->location = TileArea(tile, 1, 1);
1648  i->type = type;
1650 
1651  i->produced_cargo[0] = indspec->produced_cargo[0];
1652  i->produced_cargo[1] = indspec->produced_cargo[1];
1653  i->accepts_cargo[0] = indspec->accepts_cargo[0];
1654  i->accepts_cargo[1] = indspec->accepts_cargo[1];
1655  i->accepts_cargo[2] = indspec->accepts_cargo[2];
1656  i->production_rate[0] = indspec->production_rate[0];
1657  i->production_rate[1] = indspec->production_rate[1];
1658 
1659  /* don't use smooth economy for industries using production related callbacks */
1660  if (indspec->UsesSmoothEconomy()) {
1661  i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8, 255);
1662  i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8, 255);
1663  }
1664 
1665  i->town = t;
1666  i->owner = OWNER_NONE;
1667 
1668  uint16 r = Random();
1669  i->random_colour = GB(r, 0, 4);
1670  i->counter = GB(r, 4, 12);
1671  i->random = initial_random_bits;
1672  i->produced_cargo_waiting[0] = 0;
1673  i->produced_cargo_waiting[1] = 0;
1674  i->incoming_cargo_waiting[0] = 0;
1675  i->incoming_cargo_waiting[1] = 0;
1676  i->incoming_cargo_waiting[2] = 0;
1677  i->this_month_production[0] = 0;
1678  i->this_month_production[1] = 0;
1679  i->this_month_transported[0] = 0;
1680  i->this_month_transported[1] = 0;
1681  i->last_month_pct_transported[0] = 0;
1682  i->last_month_pct_transported[1] = 0;
1683  i->last_month_transported[0] = 0;
1684  i->last_month_transported[1] = 0;
1685  i->was_cargo_delivered = false;
1687  i->founder = founder;
1688 
1689  i->construction_date = _date;
1690  i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1692 
1693  /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1694  * 0 = created prior of newindustries
1695  * else, chosen layout + 1 */
1696  i->selected_layout = layout + 1;
1697 
1699 
1700  /* Call callbacks after the regular fields got initialised. */
1701 
1703  uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1704  if (res != CALLBACK_FAILED) {
1705  if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1707  } else {
1708  i->prod_level = res;
1710  }
1711  }
1712  }
1713 
1714  if (_generating_world) {
1715  i->last_month_production[0] = i->production_rate[0] * 8;
1716  i->last_month_production[1] = i->production_rate[1] * 8;
1717  } else {
1718  i->last_month_production[0] = i->last_month_production[1] = 0;
1719  }
1720 
1721  if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1722  uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1723  if (res != CALLBACK_FAILED) {
1724  if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1725  i->random_colour = GB(res, 0, 4);
1726  }
1727  }
1728 
1730  for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1731  for (uint j = 0; j < lengthof(i->accepts_cargo); j++) {
1733  if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1734  if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1736  break;
1737  }
1738  i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1739  }
1740  }
1741 
1743  for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1744  for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
1746  if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1747  if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1749  break;
1750  }
1751  i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1752  }
1753  }
1754 
1755  /* Plant the tiles */
1756 
1757  do {
1758  TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1759 
1760  if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1761  i->location.Add(cur_tile);
1762 
1763  WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1764 
1766 
1767  MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1768 
1769  if (_generating_world) {
1770  SetIndustryConstructionCounter(cur_tile, 3);
1771  SetIndustryConstructionStage(cur_tile, 2);
1772  }
1773 
1774  /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1775  IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
1776  const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1778  }
1779  } while ((++it)->ti.x != -0x80);
1780 
1782  for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1783  }
1785 
1787 }
1788 
1805 static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, uint itspec_index, uint32 random_var8f, uint16 random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
1806 {
1807  assert(itspec_index < indspec->num_table);
1808  const IndustryTileTable *it = indspec->table[itspec_index];
1809  bool custom_shape_check = false;
1810 
1811  *ip = NULL;
1812 
1813  SmallVector<ClearedObjectArea, 1> object_areas(_cleared_object_areas);
1814  CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1815  _cleared_object_areas = object_areas;
1816  if (ret.Failed()) return ret;
1817 
1818  if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1819  ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
1820  } else {
1821  ret = _check_new_industry_procs[indspec->check_proc](tile);
1822  }
1823  if (ret.Failed()) return ret;
1824 
1826  !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1827  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1828  }
1829 
1830  ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1831  if (ret.Failed()) return ret;
1832 
1833  Town *t = NULL;
1834  ret = FindTownForIndustry(tile, type, &t);
1835  if (ret.Failed()) return ret;
1836  assert(t != NULL);
1837 
1838  ret = CheckIfIndustryIsAllowed(tile, type, t);
1839  if (ret.Failed()) return ret;
1840 
1841  if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1842 
1843  if (flags & DC_EXEC) {
1844  *ip = new Industry(tile);
1845  if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
1846  DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
1847  }
1848 
1849  return CommandCost();
1850 }
1851 
1864 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1865 {
1866  IndustryType it = GB(p1, 0, 8);
1867  if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1868 
1869  const IndustrySpec *indspec = GetIndustrySpec(it);
1870 
1871  /* Check if the to-be built/founded industry is available for this climate. */
1872  if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
1873 
1874  /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1875  * Raw material industries are industries that do not accept cargo (at least for now) */
1876  if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1877  return CMD_ERROR;
1878  }
1879 
1880  if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1881  return CMD_ERROR;
1882  }
1883 
1884  Randomizer randomizer;
1885  randomizer.SetSeed(p2);
1886  uint16 random_initial_bits = GB(p2, 0, 16);
1887  uint32 random_var8f = randomizer.Next();
1888  int num_layouts = indspec->num_table;
1889  CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
1890  const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
1891 
1892  Industry *ind = NULL;
1893  if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
1894  if (flags & DC_EXEC) {
1895  /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1896  Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1897  /* Prospecting has a chance to fail, however we cannot guarantee that something can
1898  * be built on the map, so the chance gets lower when the map is fuller, but there
1899  * is nothing we can really do about that. */
1900  if (deity_prospect || Random() <= indspec->prospecting_chance) {
1901  for (int i = 0; i < 5000; i++) {
1902  /* We should not have more than one Random() in a function call
1903  * because parameter evaluation order is not guaranteed in the c++ standard
1904  */
1905  tile = RandomTile();
1906  /* Start with a random layout */
1907  int layout = RandomRange(num_layouts);
1908  /* Check now each layout, starting with the random one */
1909  for (int j = 0; j < num_layouts; j++) {
1910  layout = (layout + 1) % num_layouts;
1911  ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
1912  if (ret.Succeeded()) break;
1913  }
1914  if (ret.Succeeded()) break;
1915  }
1916  }
1917  cur_company.Restore();
1918  }
1919  } else {
1920  int layout = GB(p1, 8, 8);
1921  if (layout >= num_layouts) return CMD_ERROR;
1922 
1923  /* Check subsequently each layout, starting with the given layout in p1 */
1924  for (int i = 0; i < num_layouts; i++) {
1925  layout = (layout + 1) % num_layouts;
1926  ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
1927  if (ret.Succeeded()) break;
1928  }
1929 
1930  /* If it still failed, there's no suitable layout to build here, return the error */
1931  if (ret.Failed()) return ret;
1932  }
1933 
1934  if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1936  }
1937 
1938  return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1939 }
1940 
1941 
1949 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1950 {
1951  const IndustrySpec *indspec = GetIndustrySpec(type);
1952 
1953  uint32 seed = Random();
1954  uint32 seed2 = Random();
1955  Industry *i = NULL;
1956  CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
1957  assert(i != NULL || ret.Failed());
1958  return i;
1959 }
1960 
1967 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
1968 {
1969  const IndustrySpec *ind_spc = GetIndustrySpec(it);
1970  uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
1971  if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1972  (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
1973  (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
1974  *force_at_least_one = false;
1975  return 0;
1976  } else {
1977  /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1978  * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1979  chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(chance) : ScaleByMapSize(chance);
1980 
1981  *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
1982  return chance;
1983  }
1984 }
1985 
1992 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
1993 {
1995  *min_number = 0;
1996  return 0;
1997  }
1998 
1999  const IndustrySpec *ind_spc = GetIndustrySpec(it);
2000  byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2001  if (!ind_spc->enabled || ind_spc->num_table == 0 ||
2002  ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
2003  ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
2004  (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2005  *min_number = 0;
2006  return 0;
2007  }
2008  *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2009  return chance;
2010 }
2011 
2017 {
2018  /* Number of industries on a 256x256 map. */
2019  static const uint16 numof_industry_table[] = {
2020  0, // none
2021  0, // minimal
2022  10, // very low
2023  25, // low
2024  55, // normal
2025  80, // high
2026  };
2027 
2028  assert(lengthof(numof_industry_table) == ID_END);
2029  uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2030  return min(IndustryPool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2031 }
2032 
2041 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2042 {
2043  uint tries = try_hard ? 10000u : 2000u;
2044  for (; tries > 0; tries--) {
2045  Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2046  if (ind != NULL) return ind;
2047  }
2048  return NULL;
2049 }
2050 
2056 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2057 {
2058  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2059 
2061  PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2062 
2063  cur_company.Restore();
2064 }
2065 
2071 {
2072  int total = 0;
2073  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2074  return total;
2075 }
2076 
2077 
2080 {
2081  this->probability = 0;
2082  this->min_number = 0;
2083  this->target_count = 0;
2084  this->max_wait = 1;
2085  this->wait_count = 0;
2086 }
2087 
2090 {
2092 
2093  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2094  this->builddata[it].Reset();
2095  }
2096 }
2097 
2100 {
2101  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.
2102  if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2103 
2104  /* To prevent running out of unused industries for the player to connect,
2105  * add a fraction of new industries each month, but only if the manager can keep up. */
2106  uint max_behind = 1 + min(99u, ScaleByMapSize(3)); // At most 2 industries for small maps, and 100 at the biggest map (about 6 months industry build attempts).
2107  if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2108  this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2109  }
2110 }
2111 
2117 {
2118  if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2119 
2120  uint32 industry_probs[NUM_INDUSTRYTYPES];
2121  bool force_at_least_one[NUM_INDUSTRYTYPES];
2122  uint32 total_prob = 0;
2123  uint num_forced = 0;
2124 
2125  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2126  industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2127  total_prob += industry_probs[it];
2128  if (force_at_least_one[it]) num_forced++;
2129  }
2130 
2131  uint total_amount = GetNumberOfIndustries();
2132  if (total_prob == 0 || total_amount < num_forced) {
2133  /* Only place the forced ones */
2134  total_amount = num_forced;
2135  }
2136 
2138 
2139  /* Try to build one industry per type independent of any probabilities */
2140  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2141  if (force_at_least_one[it]) {
2142  assert(total_amount > 0);
2143  total_amount--;
2144  PlaceInitialIndustry(it, true);
2145  }
2146  }
2147 
2148  /* Add the remaining industries according to their probabilities */
2149  for (uint i = 0; i < total_amount; i++) {
2150  uint32 r = RandomRange(total_prob);
2151  IndustryType it = 0;
2152  while (r >= industry_probs[it]) {
2153  r -= industry_probs[it];
2154  it++;
2155  assert(it < NUM_INDUSTRYTYPES);
2156  }
2157  assert(industry_probs[it] > 0);
2158  PlaceInitialIndustry(it, false);
2159  }
2161 }
2162 
2168 {
2169  for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2170  if (i->produced_cargo[j] != CT_INVALID) {
2171  byte pct = 0;
2172  if (i->this_month_production[j] != 0) {
2174  pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2175  }
2176  i->last_month_pct_transported[j] = pct;
2177 
2179  i->this_month_production[j] = 0;
2180 
2182  i->this_month_transported[j] = 0;
2183  }
2184  }
2185 }
2186 
2192 {
2193  const IndustrySpec *indspec = GetIndustrySpec(this->type);
2194  assert(!indspec->UsesSmoothEconomy());
2195 
2196  /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2197  this->production_rate[0] = min(CeilDiv(indspec->production_rate[0] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2198  this->production_rate[1] = min(CeilDiv(indspec->production_rate[1] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2199 }
2200 
2201 
2208 {
2209  byte min_number;
2210  uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2211  bool changed = min_number != this->min_number || probability != this->probability;
2212  this->min_number = min_number;
2213  this->probability = probability;
2214  return changed;
2215 }
2216 
2219 {
2220  bool changed = false;
2221  uint num_planned = 0; // Number of industries planned in the industry build data.
2222  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2223  changed |= this->builddata[it].GetIndustryTypeData(it);
2224  num_planned += this->builddata[it].target_count;
2225  }
2226  uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2227  changed |= num_planned != total_amount;
2228  if (!changed) return; // All industries are still the same, no need to re-randomize.
2229 
2230  /* Initialize the target counts. */
2231  uint force_build = 0; // Number of industries that should always be available.
2232  uint32 total_prob = 0; // Sum of probabilities.
2233  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2234  IndustryTypeBuildData *ibd = this->builddata + it;
2235  force_build += ibd->min_number;
2236  ibd->target_count = ibd->min_number;
2237  total_prob += ibd->probability;
2238  }
2239 
2240  if (total_prob == 0) return; // No buildable industries.
2241 
2242  /* Subtract forced industries from the number of industries available for construction. */
2243  total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2244 
2245  /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2246  while (total_amount > 0) {
2247  uint32 r = RandomRange(total_prob);
2248  IndustryType it = 0;
2249  while (r >= this->builddata[it].probability) {
2250  r -= this->builddata[it].probability;
2251  it++;
2252  assert(it < NUM_INDUSTRYTYPES);
2253  }
2254  assert(this->builddata[it].probability > 0);
2255  this->builddata[it].target_count++;
2256  total_amount--;
2257  }
2258 }
2259 
2264 {
2265  this->SetupTargetCount();
2266 
2267  int missing = 0; // Number of industries that need to be build.
2268  uint count = 0; // Number of industry types eligible for build.
2269  uint32 total_prob = 0; // Sum of probabilities.
2270  IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2271  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2272  int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2273  missing += difference;
2274  if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2275  if (difference > 0) {
2276  if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2277  /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2278  if (forced_build == NUM_INDUSTRYTYPES ||
2279  difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2280  forced_build = it;
2281  }
2282  }
2283  total_prob += difference;
2284  count++;
2285  }
2286  }
2287 
2288  if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2289 
2290  if (count >= 1) {
2291  /* If not forced, pick a weighted random industry to build.
2292  * For the case that count == 1, there is no need to draw a random number. */
2293  IndustryType it;
2294  if (forced_build != NUM_INDUSTRYTYPES) {
2295  it = forced_build;
2296  } else {
2297  /* Non-forced, select an industry type to build (weighted random). */
2298  uint32 r = 0; // Initialized to silence the compiler.
2299  if (count > 1) r = RandomRange(total_prob);
2300  for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2301  if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2302  int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2303  if (difference <= 0) continue; // Too many of this kind.
2304  if (count == 1) break;
2305  if (r < (uint)difference) break;
2306  r -= difference;
2307  }
2308  assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2309  }
2310 
2311  /* Try to create the industry. */
2312  const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2313  if (ind == NULL) {
2314  this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2315  this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2316  } else {
2318  this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2319  }
2320  }
2321 
2322  /* Decrement wait counters. */
2323  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2324  if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2325  }
2326 }
2327 
2336 static bool CheckIndustryCloseDownProtection(IndustryType type)
2337 {
2338  const IndustrySpec *indspec = GetIndustrySpec(type);
2339 
2340  /* oil wells (or the industries with that flag set) are always allowed to closedown */
2341  if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2342  return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2343 }
2344 
2354 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2355 {
2356  if (cargo == CT_INVALID) return;
2357 
2358  /* Check for acceptance of cargo */
2359  for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2360  if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2361  *c_accepts = true;
2362  break;
2363  }
2364  }
2365 
2366  /* Check for produced cargo */
2367  for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2368  if (cargo == ind->produced_cargo[j]) {
2369  *c_produces = true;
2370  break;
2371  }
2372  }
2373 }
2374 
2389 {
2390  /* Find all stations within reach of the industry */
2391  StationList stations;
2392  FindStationsAroundTiles(ind->location, &stations);
2393 
2394  if (stations.Length() == 0) return 0; // No stations found at all => nobody services
2395 
2396  const Vehicle *v;
2397  int result = 0;
2398  FOR_ALL_VEHICLES(v) {
2399  /* Is it worthwhile to try this vehicle? */
2400  if (v->owner != _local_company && result != 0) continue;
2401 
2402  /* Check whether it accepts the right kind of cargo */
2403  bool c_accepts = false;
2404  bool c_produces = false;
2405  if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2406  for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2407  CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2408  }
2409  } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2410  CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2411  } else {
2412  continue;
2413  }
2414  if (!c_accepts && !c_produces) continue; // Wrong cargo
2415 
2416  /* Check orders of the vehicle.
2417  * We cannot check the first of shared orders only, since the first vehicle in such a chain
2418  * may have a different cargo type.
2419  */
2420  const Order *o;
2421  FOR_VEHICLE_ORDERS(v, o) {
2422  if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2423  /* Vehicle visits a station to load or unload */
2424  Station *st = Station::Get(o->GetDestination());
2425  assert(st != NULL);
2426 
2427  /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2428  if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2429 
2430  if (stations.Contains(st)) {
2431  if (v->owner == _local_company) return 2; // Company services industry
2432  result = 1; // Competitor services industry
2433  }
2434  }
2435  }
2436  }
2437  return result;
2438 }
2439 
2447 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2448 {
2449  NewsType nt;
2450 
2451  switch (WhoCanServiceIndustry(ind)) {
2452  case 0: nt = NT_INDUSTRY_NOBODY; break;
2453  case 1: nt = NT_INDUSTRY_OTHER; break;
2454  case 2: nt = NT_INDUSTRY_COMPANY; break;
2455  default: NOT_REACHED();
2456  }
2457  SetDParam(2, abs(percent));
2458  SetDParam(0, CargoSpec::Get(type)->name);
2459  SetDParam(1, ind->index);
2460  AddIndustryNewsItem(
2461  percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2462  nt,
2463  ind->index
2464  );
2465 }
2466 
2467 static const uint PERCENT_TRANSPORTED_60 = 153;
2468 static const uint PERCENT_TRANSPORTED_80 = 204;
2469 
2475 static void ChangeIndustryProduction(Industry *i, bool monthly)
2476 {
2477  StringID str = STR_NULL;
2478  bool closeit = false;
2479  const IndustrySpec *indspec = GetIndustrySpec(i->type);
2480  bool standard = false;
2481  bool suppress_message = false;
2482  bool recalculate_multipliers = false;
2483  /* don't use smooth economy for industries using production related callbacks */
2484  bool smooth_economy = indspec->UsesSmoothEconomy();
2485  byte div = 0;
2486  byte mul = 0;
2487  int8 increment = 0;
2488 
2489  bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2490  if (callback_enabled) {
2492  if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2493  suppress_message = HasBit(res, 7);
2494  /* Get the custom message if any */
2495  if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2496  res = GB(res, 0, 4);
2497  switch (res) {
2498  default: NOT_REACHED();
2499  case 0x0: break; // Do nothing, but show the custom message if any
2500  case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2501  case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2502  case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2503  case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2504  case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2505  case 0x8: div = res - 0x3; break; // Divide production by 32
2506  case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2507  case 0xC: mul = res - 0x7; break; // Multiply production by 32
2508  case 0xD: // decrement production
2509  case 0xE: // increment production
2510  increment = res == 0x0D ? -1 : 1;
2511  break;
2512  case 0xF: // Set production to third byte of register 0x100
2514  recalculate_multipliers = true;
2515  break;
2516  }
2517  }
2518  } else {
2519  if (monthly != smooth_economy) return;
2520  if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2521  }
2522 
2523  if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2524  /* decrease or increase */
2525  bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2526 
2527  if (smooth_economy) {
2528  closeit = true;
2529  for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2530  if (i->produced_cargo[j] == CT_INVALID) continue;
2531  uint32 r = Random();
2532  int old_prod, new_prod, percent;
2533  /* If over 60% is transported, mult is 1, else mult is -1. */
2534  int mult = (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) ? 1 : -1;
2535 
2536  new_prod = old_prod = i->production_rate[j];
2537 
2538  /* For industries with only_decrease flags (temperate terrain Oil Wells),
2539  * the multiplier will always be -1 so they will only decrease. */
2540  if (only_decrease) {
2541  mult = -1;
2542  /* For normal industries, if over 60% is transported, 33% chance for decrease.
2543  * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2544  } else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2545  mult *= -1;
2546  }
2547 
2548  /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2549  * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2550  if (Chance16I(1, 22, r >> 16)) {
2551  new_prod += mult * (max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2552  }
2553 
2554  /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2555  new_prod = Clamp(new_prod, 1, 255);
2556 
2557  if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
2558  new_prod = Clamp(new_prod, 0, 16);
2559  }
2560 
2561  /* Do not stop closing the industry when it has the lowest possible production rate */
2562  if (new_prod == old_prod && old_prod > 1) {
2563  closeit = false;
2564  continue;
2565  }
2566 
2567  percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2568  i->production_rate[j] = new_prod;
2569 
2570  /* Close the industry when it has the lowest possible production rate */
2571  if (new_prod > 1) closeit = false;
2572 
2573  if (abs(percent) >= 10) {
2575  }
2576  }
2577  } else {
2578  if (only_decrease || Chance16(1, 3)) {
2579  /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2580  if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2581  mul = 1; // Increase production
2582  } else {
2583  div = 1; // Decrease production
2584  }
2585  }
2586  }
2587  }
2588 
2589  if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2590  if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2591  closeit = true;
2592  }
2593  }
2594 
2595  /* Increase if needed */
2596  while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2598  recalculate_multipliers = true;
2599  if (str == STR_NULL) str = indspec->production_up_text;
2600  }
2601 
2602  /* Decrease if needed */
2603  while (div-- != 0 && !closeit) {
2604  if (i->prod_level == PRODLEVEL_MINIMUM) {
2605  closeit = true;
2606  } else {
2607  i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2608  recalculate_multipliers = true;
2609  if (str == STR_NULL) str = indspec->production_down_text;
2610  }
2611  }
2612 
2613  /* Increase or Decreasing the production level if needed */
2614  if (increment != 0) {
2615  if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2616  closeit = true;
2617  } else {
2619  recalculate_multipliers = true;
2620  }
2621  }
2622 
2623  /* Recalculate production_rate
2624  * For non-smooth economy these should always be synchronized with prod_level */
2625  if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2626 
2627  /* Close if needed and allowed */
2628  if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2631  str = indspec->closure_text;
2632  }
2633 
2634  if (!suppress_message && str != STR_NULL) {
2635  NewsType nt;
2636  /* Compute news category */
2637  if (closeit) {
2638  nt = NT_INDUSTRY_CLOSE;
2639  AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2640  Game::NewEvent(new ScriptEventIndustryClose(i->index));
2641  } else {
2642  switch (WhoCanServiceIndustry(i)) {
2643  case 0: nt = NT_INDUSTRY_NOBODY; break;
2644  case 1: nt = NT_INDUSTRY_OTHER; break;
2645  case 2: nt = NT_INDUSTRY_COMPANY; break;
2646  default: NOT_REACHED();
2647  }
2648  }
2649  /* Set parameters of news string */
2650  if (str > STR_LAST_STRINGID) {
2651  SetDParam(0, STR_TOWN_NAME);
2652  SetDParam(1, i->town->index);
2653  SetDParam(2, indspec->name);
2654  } else if (closeit) {
2655  SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
2656  SetDParam(1, i->town->index);
2657  SetDParam(2, indspec->name);
2658  } else {
2659  SetDParam(0, i->index);
2660  }
2661  /* and report the news to the user */
2662  if (closeit) {
2663  AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
2664  } else {
2665  AddIndustryNewsItem(str, nt, i->index);
2666  }
2667  }
2668 }
2669 
2678 {
2680 
2681  /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2682  * the lower 16 bit are a fractional part that might accumulate over several days until it
2683  * is sufficient for an industry. */
2684  uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2685 
2686  /* Reset the active part of the counter, just keeping the "fractional part" */
2687  _economy.industry_daily_change_counter &= 0xFFFF;
2688 
2689  if (change_loop == 0) {
2690  return; // Nothing to do? get out
2691  }
2692 
2693  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2694 
2695  /* perform the required industry changes for the day */
2696 
2697  uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2699  perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2700  }
2701  for (uint16 j = 0; j < change_loop; j++) {
2702  if (Chance16(perc, 100)) {
2704  } else {
2706  if (i != NULL) {
2707  ChangeIndustryProduction(i, false);
2709  }
2710  }
2711  }
2712 
2713  cur_company.Restore();
2714 
2715  /* production-change */
2717 }
2718 
2719 void IndustryMonthlyLoop()
2720 {
2721  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2722 
2724 
2725  Industry *i;
2726  FOR_ALL_INDUSTRIES(i) {
2728  if (i->prod_level == PRODLEVEL_CLOSURE) {
2729  delete i;
2730  } else {
2731  ChangeIndustryProduction(i, true);
2733  }
2734  }
2735 
2736  cur_company.Restore();
2737 
2738  /* production-change */
2740 }
2741 
2742 
2743 void InitializeIndustries()
2744 {
2746  _industry_sound_tile = 0;
2747 
2749 }
2750 
2753 {
2754  int count = 0;
2755  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2756  if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2757 
2758  bool force_at_least_one;
2759  uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2760  if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2761 
2762  const IndustrySpec *is = GetIndustrySpec(it);
2763  SetDParam(0, is->name);
2764  ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2765 
2766  count++;
2767  if (count >= 3) break; // Don't swamp the user with errors.
2768  }
2769 }
2770 
2776 {
2777  return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2778 }
2779 
2785 {
2786  /* Lumber mills are neither raw nor processing */
2787  return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2788  (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2789 }
2790 
2796 {
2797  /* Building raw industries like secondary uses different price base */
2798  return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2799  PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2800 }
2801 
2809 {
2810  return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2811 }
2812 
2818 {
2822 }
2823 
2824 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2825 {
2826  if (AutoslopeEnabled()) {
2827  /* We imitate here TTDP's behaviour:
2828  * - Both new and old slope must not be steep.
2829  * - TileMaxZ must not be changed.
2830  * - Allow autoslope by default.
2831  * - Disallow autoslope if callback succeeds and returns non-zero.
2832  */
2833  Slope tileh_old = GetTileSlope(tile);
2834  /* TileMaxZ must not be changed. Slopes must not be steep. */
2835  if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2836  const IndustryGfx gfx = GetIndustryGfx(tile);
2837  const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2838 
2839  /* Call callback 3C 'disable autosloping for industry tiles'. */
2840  if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2841  /* If the callback fails, allow autoslope. */
2842  uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2843  if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2844  } else {
2845  /* allow autoslope */
2846  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2847  }
2848  }
2849  }
2850  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2851 }
2852 
2853 extern const TileTypeProcs _tile_type_industry_procs = {
2854  DrawTile_Industry, // draw_tile_proc
2855  GetSlopePixelZ_Industry, // get_slope_z_proc
2856  ClearTile_Industry, // clear_tile_proc
2857  AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2858  GetTileDesc_Industry, // get_tile_desc_proc
2859  GetTileTrackStatus_Industry, // get_tile_track_status_proc
2860  ClickTile_Industry, // click_tile_proc
2861  AnimateTile_Industry, // animate_tile_proc
2862  TileLoop_Industry, // tile_loop_proc
2863  ChangeTileOwner_Industry, // change_tile_owner_proc
2864  NULL, // add_produced_cargo_proc
2865  NULL, // vehicle_enter_tile_proc
2866  GetFoundation_Industry, // get_foundation_proc
2867  TerraformTile_Industry, // terraform_tile_proc
2868 };