OpenTTD
industry_cmd.cpp
Go to the documentation of this file.
1 /* $Id: industry_cmd.cpp 26879 2014-09-21 11:24:51Z rubidium $ */
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 
494 static void TransportIndustryGoods(TileIndex tile)
495 {
496  Industry *i = Industry::GetByTile(tile);
497  const IndustrySpec *indspec = GetIndustrySpec(i->type);
498  bool moved_cargo = false;
499 
500  StationFinder stations(i->location);
501 
502  for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
503  uint cw = min(i->produced_cargo_waiting[j], 255);
504  if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
505  i->produced_cargo_waiting[j] -= cw;
506 
507  /* fluctuating economy? */
508  if (EconomyIsInRecession()) cw = (cw + 1) / 2;
509 
510  i->this_month_production[j] += cw;
511 
512  uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
513  i->this_month_transported[j] += am;
514 
515  moved_cargo |= (am != 0);
516  }
517  }
518 
519  if (moved_cargo && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
520  uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
521 
522  if (newgfx != INDUSTRYTILE_NOANIM) {
524  SetIndustryCompleted(tile);
525  SetIndustryGfx(tile, newgfx);
526  MarkTileDirtyByTile(tile);
527  }
528  }
529 }
530 
531 
532 static void AnimateTile_Industry(TileIndex tile)
533 {
534  IndustryGfx gfx = GetIndustryGfx(tile);
535 
536  if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
537  AnimateNewIndustryTile(tile);
538  return;
539  }
540 
541  switch (gfx) {
542  case GFX_SUGAR_MINE_SIEVE:
543  if ((_tick_counter & 1) == 0) {
544  byte m = GetAnimationFrame(tile) + 1;
545 
547  switch (m & 7) {
548  case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
549  case 6: SndPlayTileFx(SND_29_RIP, tile); break;
550  }
551  }
552 
553  if (m >= 96) {
554  m = 0;
555  DeleteAnimatedTile(tile);
556  }
557  SetAnimationFrame(tile, m);
558 
559  MarkTileDirtyByTile(tile);
560  }
561  break;
562 
563  case GFX_TOFFEE_QUARY:
564  if ((_tick_counter & 3) == 0) {
565  byte m = GetAnimationFrame(tile);
566 
567  if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
568  SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
569  }
570 
571  if (++m >= 70) {
572  m = 0;
573  DeleteAnimatedTile(tile);
574  }
575  SetAnimationFrame(tile, m);
576 
577  MarkTileDirtyByTile(tile);
578  }
579  break;
580 
581  case GFX_BUBBLE_CATCHER:
582  if ((_tick_counter & 1) == 0) {
583  byte m = GetAnimationFrame(tile);
584 
585  if (++m >= 40) {
586  m = 0;
587  DeleteAnimatedTile(tile);
588  }
589  SetAnimationFrame(tile, m);
590 
591  MarkTileDirtyByTile(tile);
592  }
593  break;
594 
595  /* Sparks on a coal plant */
596  case GFX_POWERPLANT_SPARKS:
597  if ((_tick_counter & 3) == 0) {
598  byte m = GetAnimationFrame(tile);
599  if (m == 6) {
600  SetAnimationFrame(tile, 0);
601  DeleteAnimatedTile(tile);
602  } else {
603  SetAnimationFrame(tile, m + 1);
604  MarkTileDirtyByTile(tile);
605  }
606  }
607  break;
608 
609  case GFX_TOY_FACTORY:
610  if ((_tick_counter & 1) == 0) {
611  byte m = GetAnimationFrame(tile) + 1;
612 
613  switch (m) {
614  case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
615  case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
616  case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
617  default:
618  if (m >= 50) {
619  int n = GetIndustryAnimationLoop(tile) + 1;
620  m = 0;
621  if (n >= 8) {
622  n = 0;
623  DeleteAnimatedTile(tile);
624  }
625  SetIndustryAnimationLoop(tile, n);
626  }
627  }
628 
629  SetAnimationFrame(tile, m);
630  MarkTileDirtyByTile(tile);
631  }
632  break;
633 
634  case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
635  case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
636  case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
637  case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
638  if ((_tick_counter & 3) == 0) {
639  IndustryGfx gfx = GetIndustryGfx(tile);
640 
641  gfx = (gfx < 155) ? gfx + 1 : 148;
642  SetIndustryGfx(tile, gfx);
643  MarkTileDirtyByTile(tile);
644  }
645  break;
646 
647  case GFX_OILWELL_ANIMATED_1:
648  case GFX_OILWELL_ANIMATED_2:
649  case GFX_OILWELL_ANIMATED_3:
650  if ((_tick_counter & 7) == 0) {
651  bool b = Chance16(1, 7);
652  IndustryGfx gfx = GetIndustryGfx(tile);
653 
654  byte m = GetAnimationFrame(tile) + 1;
655  if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
656  SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
658  DeleteAnimatedTile(tile);
659  } else {
660  SetAnimationFrame(tile, m);
661  SetIndustryGfx(tile, gfx);
662  MarkTileDirtyByTile(tile);
663  }
664  }
665  break;
666 
667  case GFX_COAL_MINE_TOWER_ANIMATED:
668  case GFX_COPPER_MINE_TOWER_ANIMATED:
669  case GFX_GOLD_MINE_TOWER_ANIMATED: {
670  int state = _tick_counter & 0x7FF;
671 
672  if ((state -= 0x400) < 0) return;
673 
674  if (state < 0x1A0) {
675  if (state < 0x20 || state >= 0x180) {
676  byte m = GetAnimationFrame(tile);
677  if (!(m & 0x40)) {
678  SetAnimationFrame(tile, m | 0x40);
679  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
680  }
681  if (state & 7) return;
682  } else {
683  if (state & 3) return;
684  }
685  byte m = (GetAnimationFrame(tile) + 1) | 0x40;
686  if (m > 0xC2) m = 0xC0;
687  SetAnimationFrame(tile, m);
688  MarkTileDirtyByTile(tile);
689  } else if (state >= 0x200 && state < 0x3A0) {
690  int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
691  if (state & i) return;
692 
693  byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
694  if (m < 0x80) m = 0x82;
695  SetAnimationFrame(tile, m);
696  MarkTileDirtyByTile(tile);
697  }
698  break;
699  }
700  }
701 }
702 
703 static void CreateChimneySmoke(TileIndex tile)
704 {
705  uint x = TileX(tile) * TILE_SIZE;
706  uint y = TileY(tile) * TILE_SIZE;
707  int z = GetTileMaxPixelZ(tile);
708 
709  CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
710 }
711 
712 static void MakeIndustryTileBigger(TileIndex tile)
713 {
714  byte cnt = GetIndustryConstructionCounter(tile) + 1;
715  if (cnt != 4) {
717  return;
718  }
719 
720  byte stage = GetIndustryConstructionStage(tile) + 1;
722  SetIndustryConstructionStage(tile, stage);
723  StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
724  if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
725 
726  MarkTileDirtyByTile(tile);
727 
728  if (!IsIndustryCompleted(tile)) return;
729 
730  IndustryGfx gfx = GetIndustryGfx(tile);
731  if (gfx >= NEW_INDUSTRYTILEOFFSET) {
732  /* New industries are already animated on construction. */
733  return;
734  }
735 
736  switch (gfx) {
737  case GFX_POWERPLANT_CHIMNEY:
738  CreateChimneySmoke(tile);
739  break;
740 
741  case GFX_OILRIG_1: {
742  /* Do not require an industry tile to be after the first two GFX_OILRIG_1
743  * tiles (like the default oil rig). Do a proper check to ensure the
744  * tiles belong to the same industry and based on that build the oil rig's
745  * station. */
746  TileIndex other = tile + TileDiffXY(0, 1);
747 
748  if (IsTileType(other, MP_INDUSTRY) &&
749  GetIndustryGfx(other) == GFX_OILRIG_1 &&
750  GetIndustryIndex(tile) == GetIndustryIndex(other)) {
751  BuildOilRig(tile);
752  }
753  break;
754  }
755 
756  case GFX_TOY_FACTORY:
757  case GFX_BUBBLE_CATCHER:
758  case GFX_TOFFEE_QUARY:
759  SetAnimationFrame(tile, 0);
760  SetIndustryAnimationLoop(tile, 0);
761  break;
762 
763  case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
764  case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
765  case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
766  case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
767  AddAnimatedTile(tile);
768  break;
769  }
770 }
771 
772 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
773 {
774  static const int8 _bubble_spawn_location[3][4] = {
775  { 11, 0, -4, -14 },
776  { -4, -10, -4, 1 },
777  { 49, 59, 60, 65 },
778  };
779 
780  if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
781 
782  int dir = Random() & 3;
783 
785  TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
786  TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
787  _bubble_spawn_location[2][dir],
788  EV_BUBBLE
789  );
790 
791  if (v != NULL) v->animation_substate = dir;
792 }
793 
794 static void TileLoop_Industry(TileIndex tile)
795 {
796  if (IsTileOnWater(tile)) TileLoop_Water(tile);
797 
798  /* Normally this doesn't happen, but if an industry NewGRF is removed
799  * an industry that was previously build on water can now be flooded.
800  * If this happens the tile is no longer an industry tile after
801  * returning from TileLoop_Water. */
802  if (!IsTileType(tile, MP_INDUSTRY)) return;
803 
805 
806  if (!IsIndustryCompleted(tile)) {
807  MakeIndustryTileBigger(tile);
808  return;
809  }
810 
811  if (_game_mode == GM_EDITOR) return;
812 
813  TransportIndustryGoods(tile);
814 
815  if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
816 
817  IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
818  if (newgfx != INDUSTRYTILE_NOANIM) {
820  SetIndustryGfx(tile, newgfx);
821  MarkTileDirtyByTile(tile);
822  return;
823  }
824 
825  IndustryGfx gfx = GetIndustryGfx(tile);
826  switch (gfx) {
827  case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
828  case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
829  case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
830  if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
831  switch (gfx) {
832  case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
833  case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
834  case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
835  }
836  SetIndustryGfx(tile, gfx);
837  SetAnimationFrame(tile, 0x80);
838  AddAnimatedTile(tile);
839  }
840  break;
841 
842  case GFX_OILWELL_NOT_ANIMATED:
843  if (Chance16(1, 6)) {
844  SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
845  SetAnimationFrame(tile, 0);
846  AddAnimatedTile(tile);
847  }
848  break;
849 
850  case GFX_COAL_MINE_TOWER_ANIMATED:
851  case GFX_COPPER_MINE_TOWER_ANIMATED:
852  case GFX_GOLD_MINE_TOWER_ANIMATED:
853  if (!(_tick_counter & 0x400)) {
854  switch (gfx) {
855  case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
856  case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
857  case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
858  }
859  SetIndustryGfx(tile, gfx);
860  SetIndustryCompleted(tile);
862  DeleteAnimatedTile(tile);
863  }
864  break;
865 
866  case GFX_POWERPLANT_SPARKS:
867  if (Chance16(1, 3)) {
868  if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
869  AddAnimatedTile(tile);
870  }
871  break;
872 
873  case GFX_COPPER_MINE_CHIMNEY:
875  break;
876 
877 
878  case GFX_TOY_FACTORY: {
879  Industry *i = Industry::GetByTile(tile);
880  if (i->was_cargo_delivered) {
881  i->was_cargo_delivered = false;
882  SetIndustryAnimationLoop(tile, 0);
883  AddAnimatedTile(tile);
884  }
885  }
886  break;
887 
888  case GFX_BUBBLE_GENERATOR:
889  TileLoopIndustry_BubbleGenerator(tile);
890  break;
891 
892  case GFX_TOFFEE_QUARY:
893  AddAnimatedTile(tile);
894  break;
895 
896  case GFX_SUGAR_MINE_SIEVE:
897  if (Chance16(1, 3)) AddAnimatedTile(tile);
898  break;
899  }
900 }
901 
902 static bool ClickTile_Industry(TileIndex tile)
903 {
904  ShowIndustryViewWindow(GetIndustryIndex(tile));
905  return true;
906 }
907 
908 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
909 {
910  return 0;
911 }
912 
913 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
914 {
915  /* If the founder merges, the industry was created by the merged company */
916  Industry *i = Industry::GetByTile(tile);
917  if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
918 }
919 
926 {
927  /* Check for industry tile */
928  if (!IsTileType(tile, MP_INDUSTRY)) return false;
929 
930  const Industry *ind = Industry::GetByTile(tile);
931 
932  /* Check for organic industry (i.e. not processing or extractive) */
933  if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
934 
935  /* Check for wood production */
936  for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
937  /* The industry produces wood. */
938  if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
939  }
940 
941  return false;
942 }
943 
944 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
945 
953 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
954 {
955  switch (GetTileType(tile)) {
956  case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
957  case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
958  default: return false;
959  }
960 }
961 
969 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
970 {
971  TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
972 
973  do {
974  tile = TILE_MASK(tile);
975 
976  if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
977  byte or_ = type;
978 
979  if (or_ == 1 && Chance16(1, 7)) or_ = 2;
980 
981  SetFence(tile, side, or_);
982  }
983 
984  tile += diff;
985  } while (--size);
986 }
987 
988 static void PlantFarmField(TileIndex tile, IndustryID industry)
989 {
990  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
991  if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
992  }
993 
994  /* determine field size */
995  uint32 r = (Random() & 0x303) + 0x404;
996  if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
997  uint size_x = GB(r, 0, 8);
998  uint size_y = GB(r, 8, 8);
999 
1000  TileArea ta(tile - TileDiffXY(min(TileX(tile), size_x / 2), min(TileY(tile), size_y / 2)), size_x, size_y);
1001  ta.ClampToMap();
1002 
1003  if (ta.w == 0 || ta.h == 0) return;
1004 
1005  /* check the amount of bad tiles */
1006  int count = 0;
1007  TILE_AREA_LOOP(cur_tile, ta) {
1008  assert(cur_tile < MapSize());
1009  count += IsSuitableForFarmField(cur_tile, false);
1010  }
1011  if (count * 2 < ta.w * ta.h) return;
1012 
1013  /* determine type of field */
1014  r = Random();
1015  uint counter = GB(r, 5, 3);
1016  uint field_type = GB(r, 8, 8) * 9 >> 8;
1017 
1018  /* make field */
1019  TILE_AREA_LOOP(cur_tile, ta) {
1020  assert(cur_tile < MapSize());
1021  if (IsSuitableForFarmField(cur_tile, true)) {
1022  MakeField(cur_tile, field_type, industry);
1023  SetClearCounter(cur_tile, counter);
1024  MarkTileDirtyByTile(cur_tile);
1025  }
1026  }
1027 
1028  int type = 3;
1029  if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1030  type = _plantfarmfield_type[Random() & 0xF];
1031  }
1032 
1033  SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1034  SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1035  SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1036  SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1037 }
1038 
1039 void PlantRandomFarmField(const Industry *i)
1040 {
1041  int x = i->location.w / 2 + Random() % 31 - 16;
1042  int y = i->location.h / 2 + Random() % 31 - 16;
1043 
1044  TileIndex tile = TileAddWrap(i->location.tile, x, y);
1045 
1046  if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1047 }
1048 
1055 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
1056 {
1057  if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) {
1058  /* found a tree */
1059 
1060  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1061 
1062  _industry_sound_ctr = 1;
1063  _industry_sound_tile = tile;
1064  if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1065 
1066  DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1067 
1068  cur_company.Restore();
1069  return true;
1070  }
1071  return false;
1072 }
1073 
1079 {
1080  /* We only want to cut trees if all tiles are completed. */
1081  TILE_AREA_LOOP(tile_cur, i->location) {
1082  if (i->TileBelongsToIndustry(tile_cur)) {
1083  if (!IsIndustryCompleted(tile_cur)) return;
1084  }
1085  }
1086 
1087  TileIndex tile = i->location.tile;
1088  if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, NULL)) { // 40x40 tiles to search.
1089  i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1090  }
1091 }
1092 
1093 static void ProduceIndustryGoods(Industry *i)
1094 {
1095  const IndustrySpec *indsp = GetIndustrySpec(i->type);
1096 
1097  /* play a sound? */
1098  if ((i->counter & 0x3F) == 0) {
1099  uint32 r;
1100  uint num;
1101  if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
1102  SndPlayTileFx(
1103  (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
1104  i->location.tile);
1105  }
1106  }
1107 
1108  i->counter--;
1109 
1110  /* produce some cargo */
1111  if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1113 
1114  IndustryBehaviour indbehav = indsp->behaviour;
1115  i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
1116  i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
1117 
1118  if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1119  uint16 cb_res = CALLBACK_FAILED;
1121  cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1122  }
1123 
1124  bool plant;
1125  if (cb_res != CALLBACK_FAILED) {
1127  } else {
1128  plant = Chance16(1, 8);
1129  }
1130 
1131  if (plant) PlantRandomFarmField(i);
1132  }
1133  if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1134  uint16 cb_res = CALLBACK_FAILED;
1136  cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1137  }
1138 
1139  bool cut;
1140  if (cb_res != CALLBACK_FAILED) {
1142  } else {
1143  cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1144  }
1145 
1146  if (cut) ChopLumberMillTrees(i);
1147  }
1148 
1150  StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1151  }
1152 }
1153 
1154 void OnTick_Industry()
1155 {
1156  if (_industry_sound_ctr != 0) {
1157  _industry_sound_ctr++;
1158 
1159  if (_industry_sound_ctr == 75) {
1160  if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1161  } else if (_industry_sound_ctr == 160) {
1162  _industry_sound_ctr = 0;
1163  if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1164  }
1165  }
1166 
1167  if (_game_mode == GM_EDITOR) return;
1168 
1169  Industry *i;
1170  FOR_ALL_INDUSTRIES(i) {
1171  ProduceIndustryGoods(i);
1172  }
1173 }
1174 
1181 {
1182  return CommandCost();
1183 }
1184 
1191 {
1192  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1193  if (GetTileZ(tile) < HighestSnowLine() + 2) {
1194  return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1195  }
1196  }
1197  return CommandCost();
1198 }
1199 
1206 {
1207  if (_game_mode == GM_EDITOR) return CommandCost();
1209 
1210  return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1211 }
1212 
1213 extern bool _ignore_restrictions;
1214 
1221 {
1222  if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1223  if (TileHeight(tile) == 0 &&
1225 
1226  return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1227 }
1228 
1235 {
1236  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1237  if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1238  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1239  }
1240  }
1241  return CommandCost();
1242 }
1243 
1250 {
1251  if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1252  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1253  }
1254  return CommandCost();
1255 }
1256 
1263 {
1264  if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1265  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1266  }
1267  return CommandCost();
1268 }
1269 
1276 {
1277  if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1278  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1279  }
1280  return CommandCost();
1281 }
1282 
1289 {
1290  if (GetTileZ(tile) > 4) {
1291  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1292  }
1293  return CommandCost();
1294 }
1295 
1302 
1314 };
1315 
1326 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1327 {
1328  *t = ClosestTownFromTile(tile, UINT_MAX);
1329 
1331 
1332  const Industry *i;
1333  FOR_ALL_INDUSTRIES(i) {
1334  if (i->type == (byte)type && i->town == *t) {
1335  *t = NULL;
1336  return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1337  }
1338  }
1339 
1340  return CommandCost();
1341 }
1342 
1343 bool IsSlopeRefused(Slope current, Slope refused)
1344 {
1345  if (IsSteepSlope(current)) return true;
1346  if (current != SLOPE_FLAT) {
1347  if (IsSteepSlope(refused)) return true;
1348 
1349  Slope t = ComplementSlope(current);
1350 
1351  if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1352  if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1353  if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1354  if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1355  }
1356 
1357  return false;
1358 }
1359 
1372 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)
1373 {
1374  bool refused_slope = false;
1375  bool custom_shape = false;
1376 
1377  do {
1378  IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1379  TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1380 
1381  if (!IsValidTile(cur_tile)) {
1382  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1383  }
1384 
1385  if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1386  if (!IsTileType(cur_tile, MP_WATER) ||
1387  !IsTileFlat(cur_tile)) {
1388  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1389  }
1390  } else {
1391  CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1392  if (ret.Failed()) return ret;
1393  if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1394 
1395  const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1396 
1397  IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1398 
1399  /* Perform land/water check if not disabled */
1400  if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1401 
1403  custom_shape = true;
1404  CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
1405  if (ret.Failed()) return ret;
1406  } else {
1407  Slope tileh = GetTileSlope(cur_tile);
1408  refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1409  }
1410 
1411  if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1412  ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1413  if (!IsTileType(cur_tile, MP_HOUSE)) {
1414  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1415  }
1416 
1417  /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1418  Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1419  CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1420  cur_company.Restore();
1421 
1422  if (ret.Failed()) return ret;
1423  } else {
1424  /* Clear the tiles, but do not affect town ratings */
1426 
1427  if (ret.Failed()) return ret;
1428  }
1429  }
1430  } while ((++it)->ti.x != -0x80);
1431 
1432  if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1433 
1434  /* It is almost impossible to have a fully flat land in TG, so what we
1435  * do is that we check if we can make the land flat later on. See
1436  * CheckIfCanLevelIndustryPlatform(). */
1437  if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1438  return CommandCost();
1439  }
1440  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1441 }
1442 
1450 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1451 {
1452  if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1453  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1454  }
1455 
1456  if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1457  return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1458  }
1459 
1460  return CommandCost();
1461 }
1462 
1463 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1464 {
1465  /* Check if we don't leave the map */
1466  if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1467 
1468  TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1469  TILE_AREA_LOOP(tile_walk, ta) {
1470  uint curh = TileHeight(tile_walk);
1471  /* Is the tile clear? */
1472  if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1473 
1474  /* Don't allow too big of a change if this is the sub-tile check */
1475  if (internal != 0 && Delta(curh, height) > 1) return false;
1476 
1477  /* Different height, so the surrounding tiles of this tile
1478  * has to be correct too (in level, or almost in level)
1479  * else you get a chain-reaction of terraforming. */
1480  if (internal == 0 && curh != height) {
1481  if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1482  return false;
1483  }
1484  }
1485  }
1486 
1487  return true;
1488 }
1489 
1494 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
1495 {
1496  const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1497  int max_x = 0;
1498  int max_y = 0;
1499 
1500  /* Finds dimensions of largest variant of this industry */
1501  do {
1502  if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1503  if (it->ti.x > max_x) max_x = it->ti.x;
1504  if (it->ti.y > max_y) max_y = it->ti.y;
1505  } while ((++it)->ti.x != MKEND);
1506 
1507  /* Remember level height */
1508  uint h = TileHeight(tile);
1509 
1510  if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1511  /* Check that all tiles in area and surrounding are clear
1512  * this determines that there are no obstructing items */
1513 
1516 
1517  if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1518 
1519  /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1520  * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1521  Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1522 
1523  TILE_AREA_LOOP(tile_walk, ta) {
1524  uint curh = TileHeight(tile_walk);
1525  if (curh != h) {
1526  /* This tile needs terraforming. Check if we can do that without
1527  * damaging the surroundings too much. */
1528  if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1529  cur_company.Restore();
1530  return false;
1531  }
1532  /* This is not 100% correct check, but the best we can do without modifying the map.
1533  * What is missing, is if the difference in height is more than 1.. */
1534  if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1535  cur_company.Restore();
1536  return false;
1537  }
1538  }
1539  }
1540 
1541  if (flags & DC_EXEC) {
1542  /* Terraform the land under the industry */
1543  TILE_AREA_LOOP(tile_walk, ta) {
1544  uint curh = TileHeight(tile_walk);
1545  while (curh != h) {
1546  /* We give the terraforming for free here, because we can't calculate
1547  * exact cost in the test-round, and as we all know, that will cause
1548  * a nice assert if they don't match ;) */
1549  DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1550  curh += (curh > h) ? -1 : 1;
1551  }
1552  }
1553  }
1554 
1555  cur_company.Restore();
1556  return true;
1557 }
1558 
1559 
1567 {
1568  const IndustrySpec *indspec = GetIndustrySpec(type);
1569  const Industry *i = NULL;
1570 
1571  /* On a large map with many industries, it may be faster to check an area. */
1572  static const int dmax = 14;
1573  if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
1574  const int tx = TileX(tile);
1575  const int ty = TileY(tile);
1576  TileArea tile_area = TileArea(TileXY(max(0, tx - dmax), max(0, ty - dmax)), TileXY(min(MapMaxX(), tx + dmax), min(MapMaxY(), ty + dmax)));
1577  TILE_AREA_LOOP(atile, tile_area) {
1578  if (GetTileType(atile) == MP_INDUSTRY) {
1579  const Industry *i2 = Industry::GetByTile(atile);
1580  if (i == i2) continue;
1581  i = i2;
1582  if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1583  if (i->type == indspec->conflicting[0] ||
1584  i->type == indspec->conflicting[1] ||
1585  i->type == indspec->conflicting[2]) {
1586  return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1587  }
1588  }
1589  }
1590  return CommandCost();
1591  }
1592 
1593  FOR_ALL_INDUSTRIES(i) {
1594  /* Within 14 tiles from another industry is considered close */
1595  if (DistanceMax(tile, i->location.tile) > 14) continue;
1596 
1597  /* check if there are any conflicting industry types around */
1598  if (i->type == indspec->conflicting[0] ||
1599  i->type == indspec->conflicting[1] ||
1600  i->type == indspec->conflicting[2]) {
1601  return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1602  }
1603  }
1604  return CommandCost();
1605 }
1606 
1611 static void AdvertiseIndustryOpening(const Industry *ind)
1612 {
1613  const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1614  SetDParam(0, ind_spc->name);
1615  if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1616  SetDParam(1, STR_TOWN_NAME);
1617  SetDParam(2, ind->town->index);
1618  } else {
1619  SetDParam(1, ind->town->index);
1620  }
1621  AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1622  AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1623  Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1624 }
1625 
1637 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1638 {
1639  const IndustrySpec *indspec = GetIndustrySpec(type);
1640 
1641  i->location = TileArea(tile, 1, 1);
1642  i->type = type;
1644 
1645  i->produced_cargo[0] = indspec->produced_cargo[0];
1646  i->produced_cargo[1] = indspec->produced_cargo[1];
1647  i->accepts_cargo[0] = indspec->accepts_cargo[0];
1648  i->accepts_cargo[1] = indspec->accepts_cargo[1];
1649  i->accepts_cargo[2] = indspec->accepts_cargo[2];
1650  i->production_rate[0] = indspec->production_rate[0];
1651  i->production_rate[1] = indspec->production_rate[1];
1652 
1653  /* don't use smooth economy for industries using production related callbacks */
1654  if (indspec->UsesSmoothEconomy()) {
1655  i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8, 255);
1656  i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8, 255);
1657  }
1658 
1659  i->town = t;
1660  i->owner = OWNER_NONE;
1661 
1662  uint16 r = Random();
1663  i->random_colour = GB(r, 0, 4);
1664  i->counter = GB(r, 4, 12);
1665  i->random = initial_random_bits;
1666  i->produced_cargo_waiting[0] = 0;
1667  i->produced_cargo_waiting[1] = 0;
1668  i->incoming_cargo_waiting[0] = 0;
1669  i->incoming_cargo_waiting[1] = 0;
1670  i->incoming_cargo_waiting[2] = 0;
1671  i->this_month_production[0] = 0;
1672  i->this_month_production[1] = 0;
1673  i->this_month_transported[0] = 0;
1674  i->this_month_transported[1] = 0;
1675  i->last_month_pct_transported[0] = 0;
1676  i->last_month_pct_transported[1] = 0;
1677  i->last_month_transported[0] = 0;
1678  i->last_month_transported[1] = 0;
1679  i->was_cargo_delivered = false;
1681  i->founder = founder;
1682 
1683  i->construction_date = _date;
1684  i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1686 
1687  /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1688  * 0 = created prior of newindustries
1689  * else, chosen layout + 1 */
1690  i->selected_layout = layout + 1;
1691 
1693 
1694  /* Call callbacks after the regular fields got initialised. */
1695 
1697  uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1698  if (res != CALLBACK_FAILED) {
1699  if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1701  } else {
1702  i->prod_level = res;
1704  }
1705  }
1706  }
1707 
1708  if (_generating_world) {
1709  i->last_month_production[0] = i->production_rate[0] * 8;
1710  i->last_month_production[1] = i->production_rate[1] * 8;
1711  } else {
1712  i->last_month_production[0] = i->last_month_production[1] = 0;
1713  }
1714 
1715  if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1716  uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1717  if (res != CALLBACK_FAILED) {
1718  if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1719  i->random_colour = GB(res, 0, 4);
1720  }
1721  }
1722 
1724  for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1725  for (uint j = 0; j < lengthof(i->accepts_cargo); j++) {
1727  if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1728  if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1730  break;
1731  }
1732  i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1733  }
1734  }
1735 
1737  for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1738  for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
1740  if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1741  if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1743  break;
1744  }
1745  i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1746  }
1747  }
1748 
1749  /* Plant the tiles */
1750 
1751  do {
1752  TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1753 
1754  if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1755  i->location.Add(cur_tile);
1756 
1757  WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1758 
1760 
1761  MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1762 
1763  if (_generating_world) {
1764  SetIndustryConstructionCounter(cur_tile, 3);
1765  SetIndustryConstructionStage(cur_tile, 2);
1766  }
1767 
1768  /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1769  IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
1770  const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1772  }
1773  } while ((++it)->ti.x != -0x80);
1774 
1776  for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1777  }
1779 
1781 }
1782 
1799 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)
1800 {
1801  assert(itspec_index < indspec->num_table);
1802  const IndustryTileTable *it = indspec->table[itspec_index];
1803  bool custom_shape_check = false;
1804 
1805  *ip = NULL;
1806 
1807  SmallVector<ClearedObjectArea, 1> object_areas(_cleared_object_areas);
1808  CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1809  _cleared_object_areas = object_areas;
1810  if (ret.Failed()) return ret;
1811 
1812  if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1813  ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
1814  } else {
1815  ret = _check_new_industry_procs[indspec->check_proc](tile);
1816  }
1817  if (ret.Failed()) return ret;
1818 
1820  !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1821  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1822  }
1823 
1824  ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1825  if (ret.Failed()) return ret;
1826 
1827  Town *t = NULL;
1828  ret = FindTownForIndustry(tile, type, &t);
1829  if (ret.Failed()) return ret;
1830  assert(t != NULL);
1831 
1832  ret = CheckIfIndustryIsAllowed(tile, type, t);
1833  if (ret.Failed()) return ret;
1834 
1835  if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1836 
1837  if (flags & DC_EXEC) {
1838  *ip = new Industry(tile);
1839  if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
1840  DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
1841  }
1842 
1843  return CommandCost();
1844 }
1845 
1858 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1859 {
1860  IndustryType it = GB(p1, 0, 8);
1861  if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1862 
1863  const IndustrySpec *indspec = GetIndustrySpec(it);
1864 
1865  /* Check if the to-be built/founded industry is available for this climate. */
1866  if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
1867 
1868  /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1869  * Raw material industries are industries that do not accept cargo (at least for now) */
1870  if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1871  return CMD_ERROR;
1872  }
1873 
1874  if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1875  return CMD_ERROR;
1876  }
1877 
1878  Randomizer randomizer;
1879  randomizer.SetSeed(p2);
1880  uint16 random_initial_bits = GB(p2, 0, 16);
1881  uint32 random_var8f = randomizer.Next();
1882  int num_layouts = indspec->num_table;
1883  CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
1884  const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
1885 
1886  Industry *ind = NULL;
1887  if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
1888  if (flags & DC_EXEC) {
1889  /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1890  Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1891  /* Prospecting has a chance to fail, however we cannot guarantee that something can
1892  * be built on the map, so the chance gets lower when the map is fuller, but there
1893  * is nothing we can really do about that. */
1894  if (deity_prospect || Random() <= indspec->prospecting_chance) {
1895  for (int i = 0; i < 5000; i++) {
1896  /* We should not have more than one Random() in a function call
1897  * because parameter evaluation order is not guaranteed in the c++ standard
1898  */
1899  tile = RandomTile();
1900  /* Start with a random layout */
1901  int layout = RandomRange(num_layouts);
1902  /* Check now each layout, starting with the random one */
1903  for (int j = 0; j < num_layouts; j++) {
1904  layout = (layout + 1) % num_layouts;
1905  ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
1906  if (ret.Succeeded()) break;
1907  }
1908  if (ret.Succeeded()) break;
1909  }
1910  }
1911  cur_company.Restore();
1912  }
1913  } else {
1914  int layout = GB(p1, 8, 8);
1915  if (layout >= num_layouts) return CMD_ERROR;
1916 
1917  /* Check subsequently each layout, starting with the given layout in p1 */
1918  for (int i = 0; i < num_layouts; i++) {
1919  layout = (layout + 1) % num_layouts;
1920  ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
1921  if (ret.Succeeded()) break;
1922  }
1923 
1924  /* If it still failed, there's no suitable layout to build here, return the error */
1925  if (ret.Failed()) return ret;
1926  }
1927 
1928  if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1930  }
1931 
1932  return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1933 }
1934 
1935 
1943 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1944 {
1945  const IndustrySpec *indspec = GetIndustrySpec(type);
1946 
1947  uint32 seed = Random();
1948  uint32 seed2 = Random();
1949  Industry *i = NULL;
1950  CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
1951  assert(i != NULL || ret.Failed());
1952  return i;
1953 }
1954 
1961 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
1962 {
1963  const IndustrySpec *ind_spc = GetIndustrySpec(it);
1964  uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
1965  if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1966  (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
1967  (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
1968  *force_at_least_one = false;
1969  return 0;
1970  } else {
1971  /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1972  * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1973  chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(chance) : ScaleByMapSize(chance);
1974 
1975  *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
1976  return chance;
1977  }
1978 }
1979 
1986 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
1987 {
1989  *min_number = 0;
1990  return 0;
1991  }
1992 
1993  const IndustrySpec *ind_spc = GetIndustrySpec(it);
1994  byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
1995  if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1996  ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
1997  ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
1998  (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
1999  *min_number = 0;
2000  return 0;
2001  }
2002  *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2003  return chance;
2004 }
2005 
2011 {
2012  /* Number of industries on a 256x256 map. */
2013  static const uint16 numof_industry_table[] = {
2014  0, // none
2015  0, // minimal
2016  10, // very low
2017  25, // low
2018  55, // normal
2019  80, // high
2020  };
2021 
2022  assert(lengthof(numof_industry_table) == ID_END);
2023  uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2024  return min(IndustryPool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2025 }
2026 
2035 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2036 {
2037  uint tries = try_hard ? 10000u : 2000u;
2038  for (; tries > 0; tries--) {
2039  Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2040  if (ind != NULL) return ind;
2041  }
2042  return NULL;
2043 }
2044 
2050 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2051 {
2052  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2053 
2055  PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2056 
2057  cur_company.Restore();
2058 }
2059 
2065 {
2066  int total = 0;
2067  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2068  return total;
2069 }
2070 
2071 
2074 {
2075  this->probability = 0;
2076  this->min_number = 0;
2077  this->target_count = 0;
2078  this->max_wait = 1;
2079  this->wait_count = 0;
2080 }
2081 
2084 {
2086 
2087  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2088  this->builddata[it].Reset();
2089  }
2090 }
2091 
2094 {
2095  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.
2096  if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2097 
2098  /* To prevent running out of unused industries for the player to connect,
2099  * add a fraction of new industries each month, but only if the manager can keep up. */
2100  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).
2101  if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2102  this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2103  }
2104 }
2105 
2111 {
2112  if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2113 
2114  uint32 industry_probs[NUM_INDUSTRYTYPES];
2115  bool force_at_least_one[NUM_INDUSTRYTYPES];
2116  uint32 total_prob = 0;
2117  uint num_forced = 0;
2118 
2119  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2120  industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2121  total_prob += industry_probs[it];
2122  if (force_at_least_one[it]) num_forced++;
2123  }
2124 
2125  uint total_amount = GetNumberOfIndustries();
2126  if (total_prob == 0 || total_amount < num_forced) {
2127  /* Only place the forced ones */
2128  total_amount = num_forced;
2129  }
2130 
2132 
2133  /* Try to build one industry per type independent of any probabilities */
2134  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2135  if (force_at_least_one[it]) {
2136  assert(total_amount > 0);
2137  total_amount--;
2138  PlaceInitialIndustry(it, true);
2139  }
2140  }
2141 
2142  /* Add the remaining industries according to their probabilities */
2143  for (uint i = 0; i < total_amount; i++) {
2144  uint32 r = RandomRange(total_prob);
2145  IndustryType it = 0;
2146  while (r >= industry_probs[it]) {
2147  r -= industry_probs[it];
2148  it++;
2149  assert(it < NUM_INDUSTRYTYPES);
2150  }
2151  assert(industry_probs[it] > 0);
2152  PlaceInitialIndustry(it, false);
2153  }
2155 }
2156 
2162 {
2163  for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2164  if (i->produced_cargo[j] != CT_INVALID) {
2165  byte pct = 0;
2166  if (i->this_month_production[j] != 0) {
2168  pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2169  }
2170  i->last_month_pct_transported[j] = pct;
2171 
2173  i->this_month_production[j] = 0;
2174 
2176  i->this_month_transported[j] = 0;
2177  }
2178  }
2179 }
2180 
2186 {
2187  const IndustrySpec *indspec = GetIndustrySpec(this->type);
2188  assert(!indspec->UsesSmoothEconomy());
2189 
2190  /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2191  this->production_rate[0] = min(CeilDiv(indspec->production_rate[0] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2192  this->production_rate[1] = min(CeilDiv(indspec->production_rate[1] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2193 }
2194 
2195 
2202 {
2203  byte min_number;
2204  uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2205  bool changed = min_number != this->min_number || probability != this->probability;
2206  this->min_number = min_number;
2207  this->probability = probability;
2208  return changed;
2209 }
2210 
2213 {
2214  bool changed = false;
2215  uint num_planned = 0; // Number of industries planned in the industry build data.
2216  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2217  changed |= this->builddata[it].GetIndustryTypeData(it);
2218  num_planned += this->builddata[it].target_count;
2219  }
2220  uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2221  changed |= num_planned != total_amount;
2222  if (!changed) return; // All industries are still the same, no need to re-randomize.
2223 
2224  /* Initialize the target counts. */
2225  uint force_build = 0; // Number of industries that should always be available.
2226  uint32 total_prob = 0; // Sum of probabilities.
2227  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2228  IndustryTypeBuildData *ibd = this->builddata + it;
2229  force_build += ibd->min_number;
2230  ibd->target_count = ibd->min_number;
2231  total_prob += ibd->probability;
2232  }
2233 
2234  if (total_prob == 0) return; // No buildable industries.
2235 
2236  /* Subtract forced industries from the number of industries available for construction. */
2237  total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2238 
2239  /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2240  while (total_amount > 0) {
2241  uint32 r = RandomRange(total_prob);
2242  IndustryType it = 0;
2243  while (r >= this->builddata[it].probability) {
2244  r -= this->builddata[it].probability;
2245  it++;
2246  assert(it < NUM_INDUSTRYTYPES);
2247  }
2248  assert(this->builddata[it].probability > 0);
2249  this->builddata[it].target_count++;
2250  total_amount--;
2251  }
2252 }
2253 
2258 {
2259  this->SetupTargetCount();
2260 
2261  int missing = 0; // Number of industries that need to be build.
2262  uint count = 0; // Number of industry types eligible for build.
2263  uint32 total_prob = 0; // Sum of probabilities.
2264  IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2265  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2266  int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2267  missing += difference;
2268  if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2269  if (difference > 0) {
2270  if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2271  /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2272  if (forced_build == NUM_INDUSTRYTYPES ||
2273  difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2274  forced_build = it;
2275  }
2276  }
2277  total_prob += difference;
2278  count++;
2279  }
2280  }
2281 
2282  if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2283 
2284  if (count >= 1) {
2285  /* If not forced, pick a weighted random industry to build.
2286  * For the case that count == 1, there is no need to draw a random number. */
2287  IndustryType it;
2288  if (forced_build != NUM_INDUSTRYTYPES) {
2289  it = forced_build;
2290  } else {
2291  /* Non-forced, select an industry type to build (weighted random). */
2292  uint32 r = 0; // Initialized to silence the compiler.
2293  if (count > 1) r = RandomRange(total_prob);
2294  for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2295  if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2296  int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2297  if (difference <= 0) continue; // Too many of this kind.
2298  if (count == 1) break;
2299  if (r < (uint)difference) break;
2300  r -= difference;
2301  }
2302  assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2303  }
2304 
2305  /* Try to create the industry. */
2306  const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2307  if (ind == NULL) {
2308  this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2309  this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2310  } else {
2312  this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2313  }
2314  }
2315 
2316  /* Decrement wait counters. */
2317  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2318  if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2319  }
2320 }
2321 
2330 static bool CheckIndustryCloseDownProtection(IndustryType type)
2331 {
2332  const IndustrySpec *indspec = GetIndustrySpec(type);
2333 
2334  /* oil wells (or the industries with that flag set) are always allowed to closedown */
2335  if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2336  return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2337 }
2338 
2348 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2349 {
2350  if (cargo == CT_INVALID) return;
2351 
2352  /* Check for acceptance of cargo */
2353  for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2354  if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2355  *c_accepts = true;
2356  break;
2357  }
2358  }
2359 
2360  /* Check for produced cargo */
2361  for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2362  if (cargo == ind->produced_cargo[j]) {
2363  *c_produces = true;
2364  break;
2365  }
2366  }
2367 }
2368 
2383 {
2384  /* Find all stations within reach of the industry */
2385  StationList stations;
2386  FindStationsAroundTiles(ind->location, &stations);
2387 
2388  if (stations.Length() == 0) return 0; // No stations found at all => nobody services
2389 
2390  const Vehicle *v;
2391  int result = 0;
2392  FOR_ALL_VEHICLES(v) {
2393  /* Is it worthwhile to try this vehicle? */
2394  if (v->owner != _local_company && result != 0) continue;
2395 
2396  /* Check whether it accepts the right kind of cargo */
2397  bool c_accepts = false;
2398  bool c_produces = false;
2399  if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2400  for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2401  CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2402  }
2403  } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2404  CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2405  } else {
2406  continue;
2407  }
2408  if (!c_accepts && !c_produces) continue; // Wrong cargo
2409 
2410  /* Check orders of the vehicle.
2411  * We cannot check the first of shared orders only, since the first vehicle in such a chain
2412  * may have a different cargo type.
2413  */
2414  const Order *o;
2415  FOR_VEHICLE_ORDERS(v, o) {
2416  if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2417  /* Vehicle visits a station to load or unload */
2418  Station *st = Station::Get(o->GetDestination());
2419  assert(st != NULL);
2420 
2421  /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2422  if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2423 
2424  if (stations.Contains(st)) {
2425  if (v->owner == _local_company) return 2; // Company services industry
2426  result = 1; // Competitor services industry
2427  }
2428  }
2429  }
2430  }
2431  return result;
2432 }
2433 
2441 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2442 {
2443  NewsType nt;
2444 
2445  switch (WhoCanServiceIndustry(ind)) {
2446  case 0: nt = NT_INDUSTRY_NOBODY; break;
2447  case 1: nt = NT_INDUSTRY_OTHER; break;
2448  case 2: nt = NT_INDUSTRY_COMPANY; break;
2449  default: NOT_REACHED();
2450  }
2451  SetDParam(2, abs(percent));
2452  SetDParam(0, CargoSpec::Get(type)->name);
2453  SetDParam(1, ind->index);
2454  AddIndustryNewsItem(
2455  percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2456  nt,
2457  ind->index
2458  );
2459 }
2460 
2461 static const uint PERCENT_TRANSPORTED_60 = 153;
2462 static const uint PERCENT_TRANSPORTED_80 = 204;
2463 
2469 static void ChangeIndustryProduction(Industry *i, bool monthly)
2470 {
2471  StringID str = STR_NULL;
2472  bool closeit = false;
2473  const IndustrySpec *indspec = GetIndustrySpec(i->type);
2474  bool standard = false;
2475  bool suppress_message = false;
2476  bool recalculate_multipliers = false;
2477  /* don't use smooth economy for industries using production related callbacks */
2478  bool smooth_economy = indspec->UsesSmoothEconomy();
2479  byte div = 0;
2480  byte mul = 0;
2481  int8 increment = 0;
2482 
2483  bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2484  if (callback_enabled) {
2486  if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2487  suppress_message = HasBit(res, 7);
2488  /* Get the custom message if any */
2489  if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2490  res = GB(res, 0, 4);
2491  switch (res) {
2492  default: NOT_REACHED();
2493  case 0x0: break; // Do nothing, but show the custom message if any
2494  case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2495  case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2496  case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2497  case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2498  case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2499  case 0x8: div = res - 0x3; break; // Divide production by 32
2500  case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2501  case 0xC: mul = res - 0x7; break; // Multiply production by 32
2502  case 0xD: // decrement production
2503  case 0xE: // increment production
2504  increment = res == 0x0D ? -1 : 1;
2505  break;
2506  case 0xF: // Set production to third byte of register 0x100
2508  recalculate_multipliers = true;
2509  break;
2510  }
2511  }
2512  } else {
2513  if (monthly != smooth_economy) return;
2514  if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2515  }
2516 
2517  if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2518  /* decrease or increase */
2519  bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2520 
2521  if (smooth_economy) {
2522  closeit = true;
2523  for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2524  if (i->produced_cargo[j] == CT_INVALID) continue;
2525  uint32 r = Random();
2526  int old_prod, new_prod, percent;
2527  /* If over 60% is transported, mult is 1, else mult is -1. */
2528  int mult = (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) ? 1 : -1;
2529 
2530  new_prod = old_prod = i->production_rate[j];
2531 
2532  /* For industries with only_decrease flags (temperate terrain Oil Wells),
2533  * the multiplier will always be -1 so they will only decrease. */
2534  if (only_decrease) {
2535  mult = -1;
2536  /* For normal industries, if over 60% is transported, 33% chance for decrease.
2537  * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2538  } else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2539  mult *= -1;
2540  }
2541 
2542  /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2543  * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2544  if (Chance16I(1, 22, r >> 16)) {
2545  new_prod += mult * (max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2546  }
2547 
2548  /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2549  new_prod = Clamp(new_prod, 1, 255);
2550 
2551  if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
2552  new_prod = Clamp(new_prod, 0, 16);
2553  }
2554 
2555  /* Do not stop closing the industry when it has the lowest possible production rate */
2556  if (new_prod == old_prod && old_prod > 1) {
2557  closeit = false;
2558  continue;
2559  }
2560 
2561  percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2562  i->production_rate[j] = new_prod;
2563 
2564  /* Close the industry when it has the lowest possible production rate */
2565  if (new_prod > 1) closeit = false;
2566 
2567  if (abs(percent) >= 10) {
2569  }
2570  }
2571  } else {
2572  if (only_decrease || Chance16(1, 3)) {
2573  /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2574  if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2575  mul = 1; // Increase production
2576  } else {
2577  div = 1; // Decrease production
2578  }
2579  }
2580  }
2581  }
2582 
2583  if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2584  if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2585  closeit = true;
2586  }
2587  }
2588 
2589  /* Increase if needed */
2590  while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2592  recalculate_multipliers = true;
2593  if (str == STR_NULL) str = indspec->production_up_text;
2594  }
2595 
2596  /* Decrease if needed */
2597  while (div-- != 0 && !closeit) {
2598  if (i->prod_level == PRODLEVEL_MINIMUM) {
2599  closeit = true;
2600  } else {
2601  i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2602  recalculate_multipliers = true;
2603  if (str == STR_NULL) str = indspec->production_down_text;
2604  }
2605  }
2606 
2607  /* Increase or Decreasing the production level if needed */
2608  if (increment != 0) {
2609  if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2610  closeit = true;
2611  } else {
2613  recalculate_multipliers = true;
2614  }
2615  }
2616 
2617  /* Recalculate production_rate
2618  * For non-smooth economy these should always be synchronized with prod_level */
2619  if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2620 
2621  /* Close if needed and allowed */
2622  if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2625  str = indspec->closure_text;
2626  }
2627 
2628  if (!suppress_message && str != STR_NULL) {
2629  NewsType nt;
2630  /* Compute news category */
2631  if (closeit) {
2632  nt = NT_INDUSTRY_CLOSE;
2633  AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2634  Game::NewEvent(new ScriptEventIndustryClose(i->index));
2635  } else {
2636  switch (WhoCanServiceIndustry(i)) {
2637  case 0: nt = NT_INDUSTRY_NOBODY; break;
2638  case 1: nt = NT_INDUSTRY_OTHER; break;
2639  case 2: nt = NT_INDUSTRY_COMPANY; break;
2640  default: NOT_REACHED();
2641  }
2642  }
2643  /* Set parameters of news string */
2644  if (str > STR_LAST_STRINGID) {
2645  SetDParam(0, STR_TOWN_NAME);
2646  SetDParam(1, i->town->index);
2647  SetDParam(2, indspec->name);
2648  } else if (closeit) {
2649  SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
2650  SetDParam(1, i->town->index);
2651  SetDParam(2, indspec->name);
2652  } else {
2653  SetDParam(0, i->index);
2654  }
2655  /* and report the news to the user */
2656  if (closeit) {
2657  AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
2658  } else {
2659  AddIndustryNewsItem(str, nt, i->index);
2660  }
2661  }
2662 }
2663 
2672 {
2674 
2675  /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2676  * the lower 16 bit are a fractional part that might accumulate over several days until it
2677  * is sufficient for an industry. */
2678  uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2679 
2680  /* Reset the active part of the counter, just keeping the "fractional part" */
2681  _economy.industry_daily_change_counter &= 0xFFFF;
2682 
2683  if (change_loop == 0) {
2684  return; // Nothing to do? get out
2685  }
2686 
2687  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2688 
2689  /* perform the required industry changes for the day */
2690 
2691  uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2693  perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2694  }
2695  for (uint16 j = 0; j < change_loop; j++) {
2696  if (Chance16(perc, 100)) {
2698  } else {
2700  if (i != NULL) {
2701  ChangeIndustryProduction(i, false);
2703  }
2704  }
2705  }
2706 
2707  cur_company.Restore();
2708 
2709  /* production-change */
2711 }
2712 
2713 void IndustryMonthlyLoop()
2714 {
2715  Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2716 
2718 
2719  Industry *i;
2720  FOR_ALL_INDUSTRIES(i) {
2722  if (i->prod_level == PRODLEVEL_CLOSURE) {
2723  delete i;
2724  } else {
2725  ChangeIndustryProduction(i, true);
2727  }
2728  }
2729 
2730  cur_company.Restore();
2731 
2732  /* production-change */
2734 }
2735 
2736 
2737 void InitializeIndustries()
2738 {
2740  _industry_sound_tile = 0;
2741 
2743 }
2744 
2747 {
2748  int count = 0;
2749  for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2750  if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2751 
2752  bool force_at_least_one;
2753  uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2754  if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2755 
2756  const IndustrySpec *is = GetIndustrySpec(it);
2757  SetDParam(0, is->name);
2758  ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2759 
2760  count++;
2761  if (count >= 3) break; // Don't swamp the user with errors.
2762  }
2763 }
2764 
2770 {
2771  return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2772 }
2773 
2779 {
2780  /* Lumber mills are neither raw nor processing */
2781  return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2782  (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2783 }
2784 
2790 {
2791  /* Building raw industries like secondary uses different price base */
2792  return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2793  PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2794 }
2795 
2803 {
2804  return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2805 }
2806 
2812 {
2816 }
2817 
2818 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2819 {
2820  if (AutoslopeEnabled()) {
2821  /* We imitate here TTDP's behaviour:
2822  * - Both new and old slope must not be steep.
2823  * - TileMaxZ must not be changed.
2824  * - Allow autoslope by default.
2825  * - Disallow autoslope if callback succeeds and returns non-zero.
2826  */
2827  Slope tileh_old = GetTileSlope(tile);
2828  /* TileMaxZ must not be changed. Slopes must not be steep. */
2829  if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2830  const IndustryGfx gfx = GetIndustryGfx(tile);
2831  const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2832 
2833  /* Call callback 3C 'disable autosloping for industry tiles'. */
2834  if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2835  /* If the callback fails, allow autoslope. */
2836  uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2837  if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2838  } else {
2839  /* allow autoslope */
2840  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2841  }
2842  }
2843  }
2844  return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2845 }
2846 
2847 extern const TileTypeProcs _tile_type_industry_procs = {
2848  DrawTile_Industry, // draw_tile_proc
2849  GetSlopePixelZ_Industry, // get_slope_z_proc
2850  ClearTile_Industry, // clear_tile_proc
2851  AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2852  GetTileDesc_Industry, // get_tile_desc_proc
2853  GetTileTrackStatus_Industry, // get_tile_track_status_proc
2854  ClickTile_Industry, // click_tile_proc
2855  AnimateTile_Industry, // animate_tile_proc
2856  TileLoop_Industry, // tile_loop_proc
2857  ChangeTileOwner_Industry, // change_tile_owner_proc
2858  NULL, // add_produced_cargo_proc
2859  NULL, // vehicle_enter_tile_proc
2860  GetFoundation_Industry, // get_foundation_proc
2861  TerraformTile_Industry, // terraform_tile_proc
2862 };