(svn r27770) -Fix [FS#6540]: Initialize variables in station_sl.cpp (JGR)
[openttd.git] / src / industry_cmd.cpp
blob5971964fd729c58a7c52cedfcbbcd6984a2fa48c
1 /* $Id$ */
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 */
10 /** @file industry_cmd.cpp Handling of industry tiles. */
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"
45 #include "table/strings.h"
46 #include "table/industry_land.h"
47 #include "table/build_industry.h"
49 #include "safeguards.h"
51 IndustryPool _industry_pool("Industry");
52 INSTANTIATE_POOL_METHODS(Industry)
54 void ShowIndustryViewWindow(int industry);
55 void BuildOilRig(TileIndex tile);
57 static byte _industry_sound_ctr;
58 static TileIndex _industry_sound_tile;
60 uint16 Industry::counts[NUM_INDUSTRYTYPES];
62 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
63 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
64 IndustryBuildData _industry_builder; ///< In-game manager of industries.
66 /**
67 * This function initialize the spec arrays of both
68 * industry and industry tiles.
69 * It adjusts the enabling of the industry too, based on climate availability.
70 * This will allow for clearer testings
72 void ResetIndustries()
74 memset(&_industry_specs, 0, sizeof(_industry_specs));
75 memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
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);
83 memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
84 memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
86 /* Reset any overrides that have been set. */
87 _industile_mngr.ResetOverride();
88 _industry_mngr.ResetOverride();
91 /**
92 * Retrieve the type for this industry. Although it is accessed by a tile,
93 * it will return the general type of industry, and not the sprite index
94 * as would do GetIndustryGfx.
95 * @param tile that is queried
96 * @pre IsTileType(tile, MP_INDUSTRY)
97 * @return general type for this industry, as defined in industry.h
99 IndustryType GetIndustryType(TileIndex tile)
101 assert(IsTileType(tile, MP_INDUSTRY));
103 const Industry *ind = Industry::GetByTile(tile);
104 assert(ind != NULL);
105 return ind->type;
109 * Accessor for array _industry_specs.
110 * This will ensure at once : proper access and
111 * not allowing modifications of it.
112 * @param thistype of industry (which is the index in _industry_specs)
113 * @pre thistype < NUM_INDUSTRYTYPES
114 * @return a pointer to the corresponding industry spec
116 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
118 assert(thistype < NUM_INDUSTRYTYPES);
119 return &_industry_specs[thistype];
123 * Accessor for array _industry_tile_specs.
124 * This will ensure at once : proper access and
125 * not allowing modifications of it.
126 * @param gfx of industrytile (which is the index in _industry_tile_specs)
127 * @pre gfx < INVALID_INDUSTRYTILE
128 * @return a pointer to the corresponding industrytile spec
130 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
132 assert(gfx < INVALID_INDUSTRYTILE);
133 return &_industry_tile_specs[gfx];
136 Industry::~Industry()
138 if (CleaningPool()) return;
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;
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);
150 /* MakeWaterKeepingClass() can also handle 'land' */
151 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
153 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
154 DeleteOilRig(tile_cur);
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();
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);
171 /* don't let any disaster vehicle target invalid industry */
172 ReleaseDisastersTargetingIndustry(this->index);
174 /* Clear the persistent storage. */
175 delete this->psa;
177 DecIndustryTypeCount(this->type);
179 DeleteIndustryNews(this->index);
180 DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
181 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
183 DeleteSubsidyWith(ST_INDUSTRY, this->index);
184 CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
188 * Invalidating some stuff after removing item from the pool.
189 * @param index index of deleted item
191 void Industry::PostDestructor(size_t index)
193 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
194 Station::RecomputeIndustriesNearForAll();
199 * Return a random valid industry.
200 * @return random industry, NULL if there are no industries
202 /* static */ Industry *Industry::GetRandom()
204 if (Industry::GetNumItems() == 0) return NULL;
205 int num = RandomRange((uint16)Industry::GetNumItems());
206 size_t index = MAX_UVALUE(size_t);
208 while (num >= 0) {
209 num--;
210 index++;
212 /* Make sure we have a valid industry */
213 while (!Industry::IsValidID(index)) {
214 index++;
215 assert(index < Industry::GetPoolSize());
219 return Industry::Get(index);
223 static void IndustryDrawSugarMine(const TileInfo *ti)
225 if (!IsIndustryCompleted(ti->tile)) return;
227 const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
229 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
231 if (d->image_2 != 0) {
232 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
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);
241 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
243 uint8 x = 0;
245 if (IsIndustryCompleted(ti->tile)) {
246 x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
247 if (x == 0xFF) {
248 x = 0;
252 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
253 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
256 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
258 if (IsIndustryCompleted(ti->tile)) {
259 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
261 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
264 static void IndustryDrawToyFactory(const TileInfo *ti)
266 const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
268 if (d->image_1 != 0xFF) {
269 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
272 if (d->image_2 != 0xFF) {
273 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
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);
280 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
282 if (IsIndustryCompleted(ti->tile)) {
283 uint8 image = GetAnimationFrame(ti->tile);
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
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,
304 static void DrawTile_Industry(TileInfo *ti)
306 IndustryGfx gfx = GetIndustryGfx(ti->tile);
307 Industry *ind = Industry::GetByTile(ti->tile);
308 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
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);
329 const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
330 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
331 GetIndustryConstructionStage(ti->tile))];
333 SpriteID image = dits->ground.sprite;
335 /* DrawFoundation() modifies ti->z and ti->tileh */
336 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
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)));
346 /* If industries are transparent and invisible, do not draw the upper part */
347 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
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,
359 IsTransparencySet(TO_INDUSTRIES));
361 if (IsTransparencySet(TO_INDUSTRIES)) return;
365 int proc = dits->draw_proc - 1;
366 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
370 static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
372 return GetTileMaxPixelZ(tile);
375 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
377 IndustryGfx gfx = GetIndustryGfx(tile);
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.
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;
390 return FlatteningFoundation(tileh);
393 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted)
395 IndustryGfx gfx = GetIndustryGfx(tile);
396 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
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)];
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;
406 if (HasBit(itspec->callback_mask, CBM_INDT_ACCEPT_CARGO)) {
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);
414 if (HasBit(itspec->callback_mask, CBM_INDT_CARGO_ACCEPTANCE)) {
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);
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
427 /* Add accepted cargo */
428 acceptance[a] += cargo_acceptance[i];
430 /* Maybe set 'always accepted' bit (if it's not set already) */
431 if (HasBit(*always_accepted, a)) continue;
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;
442 if (accepts) continue;
444 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
445 SetBit(*always_accepted, a);
449 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
451 const Industry *i = Industry::GetByTile(tile);
452 const IndustrySpec *is = GetIndustrySpec(i->type);
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;
461 if (is->grf_prop.grffile != NULL) {
462 td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
466 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
468 Industry *i = Industry::GetByTile(tile);
469 const IndustrySpec *indspec = GetIndustrySpec(i->type);
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
476 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
477 !_cheats.magic_bulldozer.value) ||
478 ((flags & DC_AUTO) != 0) ||
479 (_current_company == OWNER_WATER &&
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);
486 if (flags & DC_EXEC) {
487 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
488 Game::NewEvent(new ScriptEventIndustryClose(i->index));
489 delete i;
491 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
494 static void TransportIndustryGoods(TileIndex tile)
496 Industry *i = Industry::GetByTile(tile);
497 const IndustrySpec *indspec = GetIndustrySpec(i->type);
498 bool moved_cargo = false;
500 StationFinder stations(i->location);
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;
507 /* fluctuating economy? */
508 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
510 i->this_month_production[j] += cw;
512 uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
513 i->this_month_transported[j] += am;
515 moved_cargo |= (am != 0);
519 if (moved_cargo && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
520 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
522 if (newgfx != INDUSTRYTILE_NOANIM) {
523 ResetIndustryConstructionStage(tile);
524 SetIndustryCompleted(tile);
525 SetIndustryGfx(tile, newgfx);
526 MarkTileDirtyByTile(tile);
532 static void AnimateTile_Industry(TileIndex tile)
534 IndustryGfx gfx = GetIndustryGfx(tile);
536 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
537 AnimateNewIndustryTile(tile);
538 return;
541 switch (gfx) {
542 case GFX_SUGAR_MINE_SIEVE:
543 if ((_tick_counter & 1) == 0) {
544 byte m = GetAnimationFrame(tile) + 1;
546 if (_settings_client.sound.ambient) {
547 switch (m & 7) {
548 case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
549 case 6: SndPlayTileFx(SND_29_RIP, tile); break;
553 if (m >= 96) {
554 m = 0;
555 DeleteAnimatedTile(tile);
557 SetAnimationFrame(tile, m);
559 MarkTileDirtyByTile(tile);
561 break;
563 case GFX_TOFFEE_QUARY:
564 if ((_tick_counter & 3) == 0) {
565 byte m = GetAnimationFrame(tile);
567 if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
568 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
571 if (++m >= 70) {
572 m = 0;
573 DeleteAnimatedTile(tile);
575 SetAnimationFrame(tile, m);
577 MarkTileDirtyByTile(tile);
579 break;
581 case GFX_BUBBLE_CATCHER:
582 if ((_tick_counter & 1) == 0) {
583 byte m = GetAnimationFrame(tile);
585 if (++m >= 40) {
586 m = 0;
587 DeleteAnimatedTile(tile);
589 SetAnimationFrame(tile, m);
591 MarkTileDirtyByTile(tile);
593 break;
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);
607 break;
609 case GFX_TOY_FACTORY:
610 if ((_tick_counter & 1) == 0) {
611 byte m = GetAnimationFrame(tile) + 1;
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);
625 SetIndustryAnimationLoop(tile, n);
629 SetAnimationFrame(tile, m);
630 MarkTileDirtyByTile(tile);
632 break;
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);
641 gfx = (gfx < 155) ? gfx + 1 : 148;
642 SetIndustryGfx(tile, gfx);
643 MarkTileDirtyByTile(tile);
645 break;
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);
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);
657 SetIndustryConstructionStage(tile, 3);
658 DeleteAnimatedTile(tile);
659 } else {
660 SetAnimationFrame(tile, m);
661 SetIndustryGfx(tile, gfx);
662 MarkTileDirtyByTile(tile);
665 break;
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;
672 if ((state -= 0x400) < 0) return;
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);
681 if (state & 7) return;
682 } else {
683 if (state & 3) return;
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;
693 byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
694 if (m < 0x80) m = 0x82;
695 SetAnimationFrame(tile, m);
696 MarkTileDirtyByTile(tile);
698 break;
703 static void CreateChimneySmoke(TileIndex tile)
705 uint x = TileX(tile) * TILE_SIZE;
706 uint y = TileY(tile) * TILE_SIZE;
707 int z = GetTileMaxPixelZ(tile);
709 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
712 static void MakeIndustryTileBigger(TileIndex tile)
714 byte cnt = GetIndustryConstructionCounter(tile) + 1;
715 if (cnt != 4) {
716 SetIndustryConstructionCounter(tile, cnt);
717 return;
720 byte stage = GetIndustryConstructionStage(tile) + 1;
721 SetIndustryConstructionCounter(tile, 0);
722 SetIndustryConstructionStage(tile, stage);
723 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
724 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
726 MarkTileDirtyByTile(tile);
728 if (!IsIndustryCompleted(tile)) return;
730 IndustryGfx gfx = GetIndustryGfx(tile);
731 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
732 /* New industries are already animated on construction. */
733 return;
736 switch (gfx) {
737 case GFX_POWERPLANT_CHIMNEY:
738 CreateChimneySmoke(tile);
739 break;
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);
748 if (IsTileType(other, MP_INDUSTRY) &&
749 GetIndustryGfx(other) == GFX_OILRIG_1 &&
750 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
751 BuildOilRig(tile);
753 break;
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;
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;
772 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
774 static const int8 _bubble_spawn_location[3][4] = {
775 { 11, 0, -4, -14 },
776 { -4, -10, -4, 1 },
777 { 49, 59, 60, 65 },
780 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
782 int dir = Random() & 3;
784 EffectVehicle *v = CreateEffectVehicleAbove(
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
791 if (v != NULL) v->animation_substate = dir;
794 static void TileLoop_Industry(TileIndex tile)
796 if (IsTileOnWater(tile)) TileLoop_Water(tile);
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;
804 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
806 if (!IsIndustryCompleted(tile)) {
807 MakeIndustryTileBigger(tile);
808 return;
811 if (_game_mode == GM_EDITOR) return;
813 TransportIndustryGoods(tile);
815 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
817 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
818 if (newgfx != INDUSTRYTILE_NOANIM) {
819 ResetIndustryConstructionStage(tile);
820 SetIndustryGfx(tile, newgfx);
821 MarkTileDirtyByTile(tile);
822 return;
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;
836 SetIndustryGfx(tile, gfx);
837 SetAnimationFrame(tile, 0x80);
838 AddAnimatedTile(tile);
840 break;
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);
848 break;
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;
859 SetIndustryGfx(tile, gfx);
860 SetIndustryCompleted(tile);
861 SetIndustryConstructionStage(tile, 3);
862 DeleteAnimatedTile(tile);
864 break;
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);
871 break;
873 case GFX_COPPER_MINE_CHIMNEY:
874 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
875 break;
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);
886 break;
888 case GFX_BUBBLE_GENERATOR:
889 TileLoopIndustry_BubbleGenerator(tile);
890 break;
892 case GFX_TOFFEE_QUARY:
893 AddAnimatedTile(tile);
894 break;
896 case GFX_SUGAR_MINE_SIEVE:
897 if (Chance16(1, 3)) AddAnimatedTile(tile);
898 break;
902 static bool ClickTile_Industry(TileIndex tile)
904 ShowIndustryViewWindow(GetIndustryIndex(tile));
905 return true;
908 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
910 return 0;
913 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
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;
921 * Check whether the tile is a forest.
922 * @param tile the tile to investigate.
923 * @return true if and only if the tile is a forest
925 bool IsTileForestIndustry(TileIndex tile)
927 /* Check for industry tile */
928 if (!IsTileType(tile, MP_INDUSTRY)) return false;
930 const Industry *ind = Industry::GetByTile(tile);
932 /* Check for organic industry (i.e. not processing or extractive) */
933 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
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;
941 return false;
944 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
947 * Check whether the tile can be replaced by a farm field.
948 * @param tile the tile to investigate.
949 * @param allow_fields if true, the method will return true even if
950 * the tile is a farm tile, otherwise the tile may not be a farm tile
951 * @return true if the tile can become a farm field
953 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
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;
963 * Build farm field fence
964 * @param tile the tile to position the fence on
965 * @param size the size of the field being planted in tiles
966 * @param type type of fence to set
967 * @param side the side of the tile to attempt placement
969 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
971 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
973 do {
974 tile = TILE_MASK(tile);
976 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
977 byte or_ = type;
979 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
981 SetFence(tile, side, or_);
984 tile += diff;
985 } while (--size);
988 static void PlantFarmField(TileIndex tile, IndustryID industry)
990 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
991 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
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);
1000 TileArea ta(tile - TileDiffXY(min(TileX(tile), size_x / 2), min(TileY(tile), size_y / 2)), size_x, size_y);
1001 ta.ClampToMap();
1003 if (ta.w == 0 || ta.h == 0) return;
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);
1011 if (count * 2 < ta.w * ta.h) return;
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;
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);
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];
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);
1039 void PlantRandomFarmField(const Industry *i)
1041 int x = i->location.w / 2 + Random() % 31 - 16;
1042 int y = i->location.h / 2 + Random() % 31 - 16;
1044 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1046 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1050 * Search callback function for ChopLumberMillTrees
1051 * @param tile to test
1052 * @param user_data that is passed by the caller. In this case, nothing
1053 * @return the result of the test
1055 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
1057 if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1058 /* found a tree */
1060 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1062 _industry_sound_ctr = 1;
1063 _industry_sound_tile = tile;
1064 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1066 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1068 cur_company.Restore();
1069 return true;
1071 return false;
1075 * Perform a circular search around the Lumber Mill in order to find trees to cut
1076 * @param i industry
1078 static void ChopLumberMillTrees(Industry *i)
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;
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.
1093 static void ProduceIndustryGoods(Industry *i)
1095 const IndustrySpec *indsp = GetIndustrySpec(i->type);
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);
1108 i->counter--;
1110 /* produce some cargo */
1111 if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1112 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
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]);
1118 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1119 uint16 cb_res = CALLBACK_FAILED;
1120 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1121 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1124 bool plant;
1125 if (cb_res != CALLBACK_FAILED) {
1126 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1127 } else {
1128 plant = Chance16(1, 8);
1131 if (plant) PlantRandomFarmField(i);
1133 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1134 uint16 cb_res = CALLBACK_FAILED;
1135 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1136 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1139 bool cut;
1140 if (cb_res != CALLBACK_FAILED) {
1141 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1142 } else {
1143 cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1146 if (cut) ChopLumberMillTrees(i);
1149 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1150 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1154 void OnTick_Industry()
1156 if (_industry_sound_ctr != 0) {
1157 _industry_sound_ctr++;
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);
1167 if (_game_mode == GM_EDITOR) return;
1169 Industry *i;
1170 FOR_ALL_INDUSTRIES(i) {
1171 ProduceIndustryGoods(i);
1176 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1177 * @param tile %Tile to perform the checking.
1178 * @return Succeeded or failed command.
1180 static CommandCost CheckNewIndustry_NULL(TileIndex tile)
1182 return CommandCost();
1186 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1187 * @param tile %Tile to perform the checking.
1188 * @return Succeeded or failed command.
1190 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
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);
1197 return CommandCost();
1201 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1202 * @param tile %Tile to perform the checking.
1203 * @return Succeeded or failed command.
1205 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1207 if (_game_mode == GM_EDITOR) return CommandCost();
1208 if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1210 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1213 extern bool _ignore_restrictions;
1216 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1217 * @param tile %Tile to perform the checking.
1218 * @return Succeeded or failed command.
1220 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1222 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1223 if (TileHeight(tile) == 0 &&
1224 DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1226 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1230 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1231 * @param tile %Tile to perform the checking.
1232 * @return Succeeded or failed command.
1234 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1236 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1237 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1238 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1241 return CommandCost();
1245 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1246 * @param tile %Tile to perform the checking.
1247 * @return Succeeded or failed command.
1249 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1251 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1252 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1254 return CommandCost();
1258 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1259 * @param tile %Tile to perform the checking.
1260 * @return Succeeded or failed command.
1262 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1264 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1265 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1267 return CommandCost();
1271 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1272 * @param tile %Tile to perform the checking.
1273 * @return Succeeded or failed command.
1275 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1277 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1278 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1280 return CommandCost();
1284 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1285 * @param tile %Tile to perform the checking.
1286 * @return Succeeded or failed command.
1288 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1290 if (GetTileZ(tile) > 4) {
1291 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1293 return CommandCost();
1297 * Industrytype check function signature.
1298 * @param tile %Tile to check.
1299 * @return Succeeded or failed command.
1301 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1303 /** Check functions for different types of industry. */
1304 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1305 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1306 CheckNewIndustry_Forest, ///< CHECK_FOREST
1307 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1308 CheckNewIndustry_Farm, ///< CHECK_FARM
1309 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1310 CheckNewIndustry_Water, ///< CHECK_WATER
1311 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1312 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1313 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1317 * Find a town for the industry, while checking for multiple industries in the same town.
1318 * @param tile Position of the industry to build.
1319 * @param type Industry type.
1320 * @param [out] town Pointer to return town for the new industry, \c NULL is written if no good town can be found.
1321 * @return Succeeded or failed command.
1323 * @pre \c *t != NULL
1324 * @post \c *t points to a town on success, and \c NULL on failure.
1326 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1328 *t = ClosestTownFromTile(tile, UINT_MAX);
1330 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
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);
1340 return CommandCost();
1343 bool IsSlopeRefused(Slope current, Slope refused)
1345 if (IsSteepSlope(current)) return true;
1346 if (current != SLOPE_FLAT) {
1347 if (IsSteepSlope(refused)) return true;
1349 Slope t = ComplementSlope(current);
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;
1357 return false;
1361 * Are the tiles of the industry free?
1362 * @param tile Position to check.
1363 * @param it Industry tiles table.
1364 * @param itspec_index The index of the itsepc to build/fund
1365 * @param type Type of the industry.
1366 * @param initial_random_bits The random bits the industry is going to have after construction.
1367 * @param founder Industry founder
1368 * @param creation_type The circumstances the industry is created under.
1369 * @param [out] custom_shape_check Perform custom check for the site.
1370 * @return Failed or succeeded command.
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)
1374 bool refused_slope = false;
1375 bool custom_shape = false;
1377 do {
1378 IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1379 TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1381 if (!IsValidTile(cur_tile)) {
1382 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
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);
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);
1395 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1397 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
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);
1402 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
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);
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);
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();
1422 if (ret.Failed()) return ret;
1423 } else {
1424 /* Clear the tiles, but do not affect town ratings */
1425 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1427 if (ret.Failed()) return ret;
1430 } while ((++it)->ti.x != -0x80);
1432 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
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();
1440 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1444 * Is the industry allowed to be built at this place for the town?
1445 * @param tile Tile to construct the industry.
1446 * @param type Type of the industry.
1447 * @param t Town authority that the industry belongs to.
1448 * @return Succeeded or failed command.
1450 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
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);
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);
1460 return CommandCost();
1463 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1465 /* Check if we don't leave the map */
1466 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
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;
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;
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;
1487 return true;
1491 * This function tries to flatten out the land below an industry, without
1492 * damaging the surroundings too much.
1494 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
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;
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);
1507 /* Remember level height */
1508 uint h = TileHeight(tile);
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 */
1514 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1515 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1517 if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
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);
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;
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;
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;
1555 cur_company.Restore();
1556 return true;
1561 * Check that the new industry is far enough from conflicting industries.
1562 * @param tile Tile to construct the industry.
1563 * @param type Type of the new industry.
1564 * @return Succeeded or failed command.
1566 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1568 const IndustrySpec *indspec = GetIndustrySpec(type);
1569 const Industry *i = NULL;
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);
1590 return CommandCost();
1593 FOR_ALL_INDUSTRIES(i) {
1594 /* Within 14 tiles from another industry is considered close */
1595 if (DistanceMax(tile, i->location.tile) > 14) continue;
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);
1604 return CommandCost();
1608 * Advertise about a new industry opening.
1609 * @param ind Industry being opened.
1611 static void AdvertiseIndustryOpening(const Industry *ind)
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);
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));
1627 * Put an industry on the map.
1628 * @param i Just allocated poolitem, mostly empty.
1629 * @param tile North tile of the industry.
1630 * @param type Type of the industry.
1631 * @param it Industrylayout to build.
1632 * @param layout Number of the layout.
1633 * @param t Nearest town.
1634 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1635 * @param initial_random_bits Random bits for the industry.
1637 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1639 const IndustrySpec *indspec = GetIndustrySpec(type);
1641 i->location = TileArea(tile, 1, 1);
1642 i->type = type;
1643 Industry::IncIndustryTypeCount(type);
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];
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);
1659 i->town = t;
1660 i->owner = OWNER_NONE;
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;
1680 i->last_prod_year = _cur_year;
1681 i->founder = founder;
1683 i->construction_date = _date;
1684 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1685 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
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;
1692 i->prod_level = PRODLEVEL_DEFAULT;
1694 /* Call callbacks after the regular fields got initialised. */
1696 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
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) {
1700 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1701 } else {
1702 i->prod_level = res;
1703 i->RecomputeProductionMultipliers();
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;
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);
1723 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
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++) {
1726 uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1727 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1728 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1729 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1730 break;
1732 i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1736 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
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++) {
1739 uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1740 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1741 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1742 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1743 break;
1745 i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1749 /* Plant the tiles */
1751 do {
1752 TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1754 if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1755 i->location.Add(cur_tile);
1757 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1759 DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1761 MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1763 if (_generating_world) {
1764 SetIndustryConstructionCounter(cur_tile, 3);
1765 SetIndustryConstructionStage(cur_tile, 2);
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);
1771 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1773 } while ((++it)->ti.x != -0x80);
1775 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1776 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1778 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
1780 Station::RecomputeIndustriesNearForAll();
1784 * Helper function for Build/Fund an industry
1785 * @param tile tile where industry is built
1786 * @param type of industry to build
1787 * @param flags of operations to conduct
1788 * @param indspec pointer to industry specifications
1789 * @param itspec_index the index of the itsepc to build/fund
1790 * @param seed random seed (possibly) used by industries
1791 * @param initial_random_bits The random bits the industry is going to have after construction.
1792 * @param founder Founder of the industry
1793 * @param creation_type The circumstances the industry is created under.
1794 * @param [out] ip Pointer to store newly created industry.
1795 * @return Succeeded or failed command.
1797 * @post \c *ip contains the newly created industry if all checks are successful and the \a flags request actual creation, else it contains \c NULL afterwards.
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)
1801 assert(itspec_index < indspec->num_table);
1802 const IndustryTileTable *it = indspec->table[itspec_index];
1803 bool custom_shape_check = false;
1805 *ip = NULL;
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;
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);
1817 if (ret.Failed()) return ret;
1819 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
1820 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1821 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1824 ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1825 if (ret.Failed()) return ret;
1827 Town *t = NULL;
1828 ret = FindTownForIndustry(tile, type, &t);
1829 if (ret.Failed()) return ret;
1830 assert(t != NULL);
1832 ret = CheckIfIndustryIsAllowed(tile, type, t);
1833 if (ret.Failed()) return ret;
1835 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
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);
1843 return CommandCost();
1847 * Build/Fund an industry
1848 * @param tile tile where industry is built
1849 * @param flags of operations to conduct
1850 * @param p1 various bitstuffed elements
1851 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1852 * - p1 = (bit 8 - 15) - first layout to try
1853 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1854 * @param p2 seed to use for desyncfree randomisations
1855 * @param text unused
1856 * @return the cost of this operation or an error
1858 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1860 IndustryType it = GB(p1, 0, 8);
1861 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1863 const IndustrySpec *indspec = GetIndustrySpec(it);
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;
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;
1874 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1875 return CMD_ERROR;
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);
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
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;
1908 if (ret.Succeeded()) break;
1911 cur_company.Restore();
1913 } else {
1914 int layout = GB(p1, 8, 8);
1915 if (layout >= num_layouts) return CMD_ERROR;
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;
1924 /* If it still failed, there's no suitable layout to build here, return the error */
1925 if (ret.Failed()) return ret;
1928 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1929 AdvertiseIndustryOpening(ind);
1932 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1937 * Create a new industry of random layout.
1938 * @param tile The location to build the industry.
1939 * @param type The industry type to build.
1940 * @param creation_type The circumstances the industry is created under.
1941 * @return the created industry or NULL if it failed.
1943 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1945 const IndustrySpec *indspec = GetIndustrySpec(type);
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;
1956 * Compute the appearance probability for an industry during map creation.
1957 * @param it Industry type to compute.
1958 * @param [out] force_at_least_one Returns whether at least one instance should be forced on map creation.
1959 * @return Relative probability for the industry to appear.
1961 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
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);
1975 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
1976 return chance;
1981 * Compute the probability for constructing a new industry during game play.
1982 * @param it Industry type to compute.
1983 * @param [out] min_number Minimal number of industries that should exist at the map.
1984 * @return Relative probability for the industry to appear.
1986 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
1988 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
1989 *min_number = 0;
1990 return 0;
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;
2002 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2003 return chance;
2007 * Get wanted number of industries on the map.
2008 * @return Wanted number of industries at the map.
2010 static uint GetNumberOfIndustries()
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
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]));
2028 * Try to place the industry in the game.
2029 * Since there is no feedback why placement fails, there is no other option
2030 * than to try a few times before concluding it does not work.
2031 * @param type Industry type of the desired industry.
2032 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2033 * @return Pointer to created industry, or \c NULL if creation failed.
2035 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
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;
2042 return NULL;
2046 * Try to build a industry on the map.
2047 * @param type IndustryType of the desired industry
2048 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2050 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2052 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2054 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2055 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2057 cur_company.Restore();
2061 * Get total number of industries existing in the game.
2062 * @return Number of industries currently in the game.
2064 static uint GetCurrentTotalNumberOfIndustries()
2066 int total = 0;
2067 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2068 return total;
2072 /** Reset the entry. */
2073 void IndustryTypeBuildData::Reset()
2075 this->probability = 0;
2076 this->min_number = 0;
2077 this->target_count = 0;
2078 this->max_wait = 1;
2079 this->wait_count = 0;
2082 /** Completely reset the industry build data. */
2083 void IndustryBuildData::Reset()
2085 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2087 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2088 this->builddata[it].Reset();
2092 /** Monthly update of industry build data. */
2093 void IndustryBuildData::MonthlyLoop()
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.
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);
2107 * This function will create random industries during game creation.
2108 * It will scale the amount of industries by mapsize and difficulty level.
2110 void GenerateIndustries()
2112 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2114 uint32 industry_probs[NUM_INDUSTRYTYPES];
2115 bool force_at_least_one[NUM_INDUSTRYTYPES];
2116 uint32 total_prob = 0;
2117 uint num_forced = 0;
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++;
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;
2131 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
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);
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);
2151 assert(industry_probs[it] > 0);
2152 PlaceInitialIndustry(it, false);
2154 _industry_builder.Reset();
2158 * Monthly update of industry statistics.
2159 * @param i Industry to update.
2161 static void UpdateIndustryStatistics(Industry *i)
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) {
2167 i->last_prod_year = _cur_year;
2168 pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2170 i->last_month_pct_transported[j] = pct;
2172 i->last_month_production[j] = i->this_month_production[j];
2173 i->this_month_production[j] = 0;
2175 i->last_month_transported[j] = i->this_month_transported[j];
2176 i->this_month_transported[j] = 0;
2182 * Recompute #production_rate for current #prod_level.
2183 * This function is only valid when not using smooth economy.
2185 void Industry::RecomputeProductionMultipliers()
2187 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2188 assert(!indspec->UsesSmoothEconomy());
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);
2197 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2198 * @param it Industry type.
2199 * @return At least one of the fields has changed value.
2201 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
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;
2211 /** Decide how many industries of each type are needed. */
2212 void IndustryBuildData::SetupTargetCount()
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;
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.
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;
2234 if (total_prob == 0) return; // No buildable industries.
2236 /* Subtract forced industries from the number of industries available for construction. */
2237 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
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);
2248 assert(this->builddata[it].probability > 0);
2249 this->builddata[it].target_count++;
2250 total_amount--;
2255 * Try to create a random industry, during gameplay
2257 void IndustryBuildData::TryBuildNewIndustry()
2259 this->SetupTargetCount();
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;
2277 total_prob += difference;
2278 count++;
2282 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
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;
2302 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
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 {
2311 AdvertiseIndustryOpening(ind);
2312 this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
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--;
2323 * Protects an industry from closure if the appropriate flags and conditions are met
2324 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2325 * count of industries of this type must one (or lower) in order to be protected
2326 * against closure.
2327 * @param type IndustryType been queried
2328 * @result true if protection is on, false otherwise (except for oil wells)
2330 static bool CheckIndustryCloseDownProtection(IndustryType type)
2332 const IndustrySpec *indspec = GetIndustrySpec(type);
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;
2340 * Can given cargo type be accepted or produced by the industry?
2341 * @param cargo: Cargo type
2342 * @param ind: Industry
2343 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2344 * @param *c_produces: Pointer to boolean for production of cargo
2345 * @return: \c *c_accepts is set when industry accepts the cargo type,
2346 * \c *c_produces is set when the industry produces the cargo type
2348 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2350 if (cargo == CT_INVALID) return;
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;
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;
2370 * Compute who can service the industry.
2372 * Here, 'can service' means that he/she has trains and stations close enough
2373 * to the industry with the right cargo type and the right orders (ie has the
2374 * technical means).
2376 * @param ind: Industry being investigated.
2378 * @return: 0 if nobody can service the industry, 2 if the local company can
2379 * service the industry, and 1 otherwise (only competitors can service the
2380 * industry)
2382 static int WhoCanServiceIndustry(Industry *ind)
2384 /* Find all stations within reach of the industry */
2385 StationList stations;
2386 FindStationsAroundTiles(ind->location, &stations);
2388 if (stations.Length() == 0) return 0; // No stations found at all => nobody services
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;
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);
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;
2408 if (!c_accepts && !c_produces) continue; // Wrong cargo
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.
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);
2421 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2422 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2424 if (stations.Contains(st)) {
2425 if (v->owner == _local_company) return 2; // Company services industry
2426 result = 1; // Competitor services industry
2431 return result;
2435 * Report news that industry production has changed significantly
2437 * @param ind: Industry with changed production
2438 * @param type: Cargo type that has changed
2439 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
2441 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2443 NewsType nt;
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();
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,
2457 ind->index
2461 static const uint PERCENT_TRANSPORTED_60 = 153;
2462 static const uint PERCENT_TRANSPORTED_80 = 204;
2465 * Change industry production or do closure
2466 * @param i Industry for which changes are performed
2467 * @param monthly true if it's the monthly call, false if it's the random call
2469 static void ChangeIndustryProduction(Industry *i, bool monthly)
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; ///< reinitialize production_rate to match prod_level
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;
2483 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2484 if (callback_enabled) {
2485 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
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
2507 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2508 recalculate_multipliers = true;
2509 break;
2512 } else {
2513 if (monthly != smooth_economy) return;
2514 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
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;
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;
2530 new_prod = old_prod = i->production_rate[j];
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;
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));
2548 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2549 new_prod = Clamp(new_prod, 1, 255);
2551 if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
2552 new_prod = Clamp(new_prod, 0, 16);
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;
2561 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2562 i->production_rate[j] = new_prod;
2564 /* Close the industry when it has the lowest possible production rate */
2565 if (new_prod > 1) closeit = false;
2567 if (abs(percent) >= 10) {
2568 ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
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
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;
2589 /* Increase if needed */
2590 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2591 i->prod_level = min(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2592 recalculate_multipliers = true;
2593 if (str == STR_NULL) str = indspec->production_up_text;
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;
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 {
2612 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2613 recalculate_multipliers = true;
2617 /* Recalculate production_rate
2618 * For non-smooth economy these should always be synchronized with prod_level */
2619 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2621 /* Close if needed and allowed */
2622 if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2623 i->prod_level = PRODLEVEL_CLOSURE;
2624 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2625 str = indspec->closure_text;
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();
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);
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);
2665 * Daily handler for the industry changes
2666 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2667 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2668 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2669 * it would be way more. The daily loop handles those changes.
2671 void IndustryDailyLoop()
2673 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
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;
2680 /* Reset the active part of the counter, just keeping the "fractional part" */
2681 _economy.industry_daily_change_counter &= 0xFFFF;
2683 if (change_loop == 0) {
2684 return; // Nothing to do? get out
2687 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2689 /* perform the required industry changes for the day */
2691 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2692 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
2693 perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2695 for (uint16 j = 0; j < change_loop; j++) {
2696 if (Chance16(perc, 100)) {
2697 _industry_builder.TryBuildNewIndustry();
2698 } else {
2699 Industry *i = Industry::GetRandom();
2700 if (i != NULL) {
2701 ChangeIndustryProduction(i, false);
2702 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2707 cur_company.Restore();
2709 /* production-change */
2710 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2713 void IndustryMonthlyLoop()
2715 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2717 _industry_builder.MonthlyLoop();
2719 Industry *i;
2720 FOR_ALL_INDUSTRIES(i) {
2721 UpdateIndustryStatistics(i);
2722 if (i->prod_level == PRODLEVEL_CLOSURE) {
2723 delete i;
2724 } else {
2725 ChangeIndustryProduction(i, true);
2726 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2730 cur_company.Restore();
2732 /* production-change */
2733 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2737 void InitializeIndustries()
2739 Industry::ResetIndustryCounts();
2740 _industry_sound_tile = 0;
2742 _industry_builder.Reset();
2745 /** Verify whether the generated industries are complete, and warn the user if not. */
2746 void CheckIndustries()
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.
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.
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);
2760 count++;
2761 if (count >= 3) break; // Don't swamp the user with errors.
2766 * Is an industry with the spec a raw industry?
2767 * @return true if it should be handled as a raw industry
2769 bool IndustrySpec::IsRawIndustry() const
2771 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2775 * Is an industry with the spec a processing industry?
2776 * @return true if it should be handled as a processing industry
2778 bool IndustrySpec::IsProcessingIndustry() const
2780 /* Lumber mills are neither raw nor processing */
2781 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2782 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2786 * Get the cost for constructing this industry
2787 * @return the cost (inflation corrected etc)
2789 Money IndustrySpec::GetConstructionCost() const
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;
2797 * Get the cost for removing this industry
2798 * Take note that the cost will always be zero for non-grf industries.
2799 * Only if the grf author did specified a cost will it be applicable.
2800 * @return the cost (inflation corrected etc)
2802 Money IndustrySpec::GetRemovalCost() const
2804 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2808 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2809 * @return true if smooth economy is used.
2811 bool IndustrySpec::UsesSmoothEconomy() const
2813 return _settings_game.economy.smooth_economy &&
2814 !(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
2815 !(HasBit(this->callback_mask, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CHANGE) || HasBit(this->callback_mask, CBM_IND_PROD_CHANGE_BUILD)); // production change callbacks
2818 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
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.
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);
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]);
2844 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
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