Fix compiler warnings.
[openttd-joker.git] / src / industry_cmd.cpp
blobbd4cef1051bf92b37f6cbc573a4e14272fd226b4
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 "tunnel_map.h"
25 #include "newgrf_cargo.h"
26 #include "newgrf_debug.h"
27 #include "newgrf_industrytiles.h"
28 #include "autoslope.h"
29 #include "water.h"
30 #include "strings_func.h"
31 #include "window_func.h"
32 #include "date_func.h"
33 #include "vehicle_func.h"
34 #include "sound_func.h"
35 #include "animated_tile_func.h"
36 #include "effectvehicle_func.h"
37 #include "effectvehicle_base.h"
38 #include "ai/ai.hpp"
39 #include "core/pool_func.hpp"
40 #include "subsidy_func.h"
41 #include "core/backup_type.hpp"
42 #include "object_base.h"
43 #include "game/game.hpp"
44 #include "error.h"
46 #include "table/strings.h"
47 #include "table/industry_land.h"
48 #include "table/build_industry.h"
50 #include "safeguards.h"
52 IndustryPool _industry_pool("Industry");
53 INSTANTIATE_POOL_METHODS(Industry)
55 void ShowIndustryViewWindow(int industry);
56 void BuildOilRig(TileIndex tile);
58 static byte _industry_sound_ctr;
59 static TileIndex _industry_sound_tile;
61 uint16 Industry::counts[NUM_INDUSTRYTYPES];
63 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
64 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
65 IndustryBuildData _industry_builder; ///< In-game manager of industries.
67 /**
68 * This function initialize the spec arrays of both
69 * industry and industry tiles.
70 * It adjusts the enabling of the industry too, based on climate availability.
71 * This will allow for clearer testings
73 void ResetIndustries()
75 memset(&_industry_specs, 0, sizeof(_industry_specs));
76 memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
78 /* once performed, enable only the current climate industries */
79 for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
80 _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
81 HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
84 memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
85 memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
87 /* Reset any overrides that have been set. */
88 _industile_mngr.ResetOverride();
89 _industry_mngr.ResetOverride();
92 /**
93 * Retrieve the type for this industry. Although it is accessed by a tile,
94 * it will return the general type of industry, and not the sprite index
95 * as would do GetIndustryGfx.
96 * @param tile that is queried
97 * @pre IsTileType(tile, MP_INDUSTRY)
98 * @return general type for this industry, as defined in industry.h
100 IndustryType GetIndustryType(TileIndex tile)
102 assert(IsTileType(tile, MP_INDUSTRY));
104 const Industry *ind = Industry::GetByTile(tile);
105 assert(ind != NULL);
106 return ind->type;
110 * Accessor for array _industry_specs.
111 * This will ensure at once : proper access and
112 * not allowing modifications of it.
113 * @param thistype of industry (which is the index in _industry_specs)
114 * @pre thistype < NUM_INDUSTRYTYPES
115 * @return a pointer to the corresponding industry spec
117 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
119 assert(thistype < NUM_INDUSTRYTYPES);
120 return &_industry_specs[thistype];
124 * Accessor for array _industry_tile_specs.
125 * This will ensure at once : proper access and
126 * not allowing modifications of it.
127 * @param gfx of industrytile (which is the index in _industry_tile_specs)
128 * @pre gfx < INVALID_INDUSTRYTILE
129 * @return a pointer to the corresponding industrytile spec
131 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
133 assert(gfx < INVALID_INDUSTRYTILE);
134 return &_industry_tile_specs[gfx];
137 Industry::~Industry()
139 if (CleaningPool()) return;
141 /* Industry can also be destroyed when not fully initialized.
142 * This means that we do not have to clear tiles either.
143 * Also we must not decrement industry counts in that case. */
144 if (this->location.w == 0) return;
146 TILE_AREA_LOOP(tile_cur, this->location) {
147 if (IsTileType(tile_cur, MP_INDUSTRY)) {
148 if (GetIndustryIndex(tile_cur) == this->index) {
149 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur);
151 /* MakeWaterKeepingClass() can also handle 'land' */
152 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
154 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
155 DeleteOilRig(tile_cur);
159 if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
160 TileArea ta(this->location.tile - TileDiffXY(min(TileX(this->location.tile), 21), min(TileY(this->location.tile), 21)), 42, 42);
161 ta.ClampToMap();
163 /* Remove the farmland and convert it to regular tiles over time. */
164 TILE_AREA_LOOP(tile_cur, ta) {
165 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
166 GetIndustryIndexOfField(tile_cur) == this->index) {
167 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
172 /* don't let any disaster vehicle target invalid industry */
173 ReleaseDisastersTargetingIndustry(this->index);
175 /* Clear the persistent storage. */
176 delete this->psa;
178 DecIndustryTypeCount(this->type);
180 DeleteIndustryNews(this->index);
181 DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
182 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
184 DeleteSubsidyWith(ST_INDUSTRY, this->index);
185 CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
189 * Invalidating some stuff after removing item from the pool.
190 * @param index index of deleted item
192 void Industry::PostDestructor(size_t index)
194 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
195 Station::RecomputeIndustriesNearForAll();
200 * Return a random valid industry.
201 * @return random industry, NULL if there are no industries
203 /* static */ Industry *Industry::GetRandom()
205 if (Industry::GetNumItems() == 0) return NULL;
206 int num = RandomRange((uint16)Industry::GetNumItems());
207 size_t index = MAX_UVALUE(size_t);
209 while (num >= 0) {
210 num--;
211 index++;
213 /* Make sure we have a valid industry */
214 while (!Industry::IsValidID(index)) {
215 index++;
216 assert(index < Industry::GetPoolSize());
220 return Industry::Get(index);
224 static void IndustryDrawSugarMine(const TileInfo *ti)
226 if (!IsIndustryCompleted(ti->tile)) return;
228 const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
230 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
232 if (d->image_2 != 0) {
233 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
236 if (d->image_3 != 0) {
237 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
238 _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
242 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
244 uint8 x = 0;
246 if (IsIndustryCompleted(ti->tile)) {
247 x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
248 if (x == 0xFF) {
249 x = 0;
253 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
254 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
257 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
259 if (IsIndustryCompleted(ti->tile)) {
260 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
262 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
265 static void IndustryDrawToyFactory(const TileInfo *ti)
267 const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
269 if (d->image_1 != 0xFF) {
270 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
273 if (d->image_2 != 0xFF) {
274 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
277 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
278 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
281 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
283 if (IsIndustryCompleted(ti->tile)) {
284 uint8 image = GetAnimationFrame(ti->tile);
286 if (image != 0 && image < 7) {
287 AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
288 PAL_NONE,
289 _coal_plant_sparks[image - 1].x,
290 _coal_plant_sparks[image - 1].y
296 typedef void IndustryDrawTileProc(const TileInfo *ti);
297 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
298 IndustryDrawSugarMine,
299 IndustryDrawToffeeQuarry,
300 IndustryDrawBubbleGenerator,
301 IndustryDrawToyFactory,
302 IndustryDrawCoalPlantSparks,
305 static void DrawTile_Industry(TileInfo *ti)
307 IndustryGfx gfx = GetIndustryGfx(ti->tile);
308 Industry *ind = Industry::GetByTile(ti->tile);
309 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
311 /* Retrieve pointer to the draw industry tile struct */
312 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
313 /* Draw the tile using the specialized method of newgrf industrytile.
314 * DrawNewIndustry will return false if ever the resolver could not
315 * find any sprite to display. So in this case, we will jump on the
316 * substitute gfx instead. */
317 if (indts->grf_prop.spritegroup[0] != NULL && DrawNewIndustryTile(ti, ind, gfx, indts)) {
318 return;
319 } else {
320 /* No sprite group (or no valid one) found, meaning no graphics associated.
321 * Use the substitute one instead */
322 if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
323 gfx = indts->grf_prop.subst_id;
324 /* And point the industrytile spec accordingly */
325 indts = GetIndustryTileSpec(gfx);
330 const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
331 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
332 GetIndustryConstructionStage(ti->tile))];
334 SpriteID image = dits->ground.sprite;
336 /* DrawFoundation() modifies ti->z and ti->tileh */
337 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
339 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
340 * Do not do this if the tile's WaterClass is 'land'. */
341 if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
342 DrawWaterClassGround(ti);
343 } else {
344 DrawGroundSprite(image, GroundSpritePaletteTransform(image, dits->ground.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)));
347 DrawOverlay(ti, MP_INDUSTRY);
349 /* If industries are transparent and invisible, do not draw the upper part */
350 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
352 /* Add industry on top of the ground? */
353 image = dits->building.sprite;
354 if (image != 0) {
355 AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)),
356 ti->x + dits->subtile_x,
357 ti->y + dits->subtile_y,
358 dits->width,
359 dits->height,
360 dits->dz,
361 ti->z,
362 IsTransparencySet(TO_INDUSTRIES));
364 if (IsTransparencySet(TO_INDUSTRIES)) return;
368 int proc = dits->draw_proc - 1;
369 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
373 static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
375 return GetTileMaxPixelZ(tile);
378 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
380 IndustryGfx gfx = GetIndustryGfx(tile);
382 /* For NewGRF industry tiles we might not be drawing a foundation. We need to
383 * account for this, as other structures should
384 * draw the wall of the foundation in this case.
386 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
387 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
388 if (indts->grf_prop.spritegroup[0] != NULL && HasBit(indts->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
389 uint32 callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, Industry::GetByTile(tile), tile);
390 if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(indts->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
393 return FlatteningFoundation(tileh);
396 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted)
398 IndustryGfx gfx = GetIndustryGfx(tile);
399 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
401 /* When we have to use a callback, we put our data in the next two variables */
402 CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)];
403 uint8 raw_cargo_acceptance[lengthof(itspec->acceptance)];
405 /* And then these will always point to a same sized array with the required data */
406 const CargoID *accepts_cargo = itspec->accepts_cargo;
407 const uint8 *cargo_acceptance = itspec->acceptance;
409 if (HasBit(itspec->callback_mask, CBM_INDT_ACCEPT_CARGO)) {
410 uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
411 if (res != CALLBACK_FAILED) {
412 accepts_cargo = raw_accepts_cargo;
413 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
417 if (HasBit(itspec->callback_mask, CBM_INDT_CARGO_ACCEPTANCE)) {
418 uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
419 if (res != CALLBACK_FAILED) {
420 cargo_acceptance = raw_cargo_acceptance;
421 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_cargo_acceptance[i] = GB(res, i * 4, 4);
425 const Industry *ind = Industry::GetByTile(tile);
426 for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
427 CargoID a = accepts_cargo[i];
428 if (a == CT_INVALID || cargo_acceptance[i] == 0) continue; // work only with valid cargoes
430 /* Add accepted cargo */
431 acceptance[a] += cargo_acceptance[i];
433 /* Maybe set 'always accepted' bit (if it's not set already) */
434 if (HasBit(*always_accepted, a)) continue;
436 bool accepts = false;
437 for (uint cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
438 /* Test whether the industry itself accepts the cargo type */
439 if (ind->accepts_cargo[cargo_index] == a) {
440 accepts = true;
441 break;
445 if (accepts) continue;
447 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
448 SetBit(*always_accepted, a);
452 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
454 const Industry *i = Industry::GetByTile(tile);
455 const IndustrySpec *is = GetIndustrySpec(i->type);
457 td->owner[0] = i->owner;
458 td->str = is->name;
459 if (!IsIndustryCompleted(tile)) {
460 SetDParamX(td->dparam, 0, td->str);
461 td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
464 if (is->grf_prop.grffile != NULL) {
465 td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
469 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
471 Industry *i = Industry::GetByTile(tile);
472 const IndustrySpec *indspec = GetIndustrySpec(i->type);
474 /* water can destroy industries
475 * in editor you can bulldoze industries
476 * with magic_bulldozer cheat you can destroy industries
477 * (area around OILRIG is water, so water shouldn't flood it
479 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
480 !_cheats.magic_bulldozer.value) ||
481 ((flags & DC_AUTO) != 0) ||
482 (_current_company == OWNER_WATER &&
483 ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
484 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
485 SetDParam(1, indspec->name);
486 return_cmd_error(flags & DC_AUTO ? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY : INVALID_STRING_ID);
489 if (flags & DC_EXEC) {
490 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
491 Game::NewEvent(new ScriptEventIndustryClose(i->index));
492 delete i;
494 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
498 * Move produced cargo from industry to nearby stations.
499 * @param tile Industry tile
500 * @return true if any cargo was moved.
502 static bool TransportIndustryGoods(TileIndex tile)
504 Industry *i = Industry::GetByTile(tile);
505 const IndustrySpec *indspec = GetIndustrySpec(i->type);
506 bool moved_cargo = false;
508 StationFinder stations(i->location);
510 for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
511 uint cw = min(i->produced_cargo_waiting[j], 255);
512 if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
513 i->produced_cargo_waiting[j] -= cw;
515 /* fluctuating economy? */
516 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
518 i->this_month_production[j] += cw;
520 uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
521 i->this_month_transported[j] += am;
523 moved_cargo |= (am != 0);
527 return moved_cargo;
531 static void AnimateTile_Industry(TileIndex tile)
533 IndustryGfx gfx = GetIndustryGfx(tile);
535 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
536 AnimateNewIndustryTile(tile);
537 return;
540 switch (gfx) {
541 case GFX_SUGAR_MINE_SIEVE:
542 if ((_tick_counter & 1) == 0) {
543 byte m = GetAnimationFrame(tile) + 1;
545 if (_settings_client.sound.ambient) {
546 switch (m & 7) {
547 case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
548 case 6: SndPlayTileFx(SND_29_RIP, tile); break;
552 if (m >= 96) {
553 m = 0;
554 DeleteAnimatedTile(tile);
556 SetAnimationFrame(tile, m);
558 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
560 break;
562 case GFX_TOFFEE_QUARY:
563 if ((_tick_counter & 3) == 0) {
564 byte m = GetAnimationFrame(tile);
566 if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
567 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
570 if (++m >= 70) {
571 m = 0;
572 DeleteAnimatedTile(tile);
574 SetAnimationFrame(tile, m);
576 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
578 break;
580 case GFX_BUBBLE_CATCHER:
581 if ((_tick_counter & 1) == 0) {
582 byte m = GetAnimationFrame(tile);
584 if (++m >= 40) {
585 m = 0;
586 DeleteAnimatedTile(tile);
588 SetAnimationFrame(tile, m);
590 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
592 break;
594 /* Sparks on a coal plant */
595 case GFX_POWERPLANT_SPARKS:
596 if ((_tick_counter & 3) == 0) {
597 byte m = GetAnimationFrame(tile);
598 if (m == 6) {
599 SetAnimationFrame(tile, 0);
600 DeleteAnimatedTile(tile);
601 } else {
602 SetAnimationFrame(tile, m + 1);
603 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
606 break;
608 case GFX_TOY_FACTORY:
609 if ((_tick_counter & 1) == 0) {
610 byte m = GetAnimationFrame(tile) + 1;
612 switch (m) {
613 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
614 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
615 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
616 default:
617 if (m >= 50) {
618 int n = GetIndustryAnimationLoop(tile) + 1;
619 m = 0;
620 if (n >= 8) {
621 n = 0;
622 DeleteAnimatedTile(tile);
624 SetIndustryAnimationLoop(tile, n);
628 SetAnimationFrame(tile, m);
629 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
631 break;
633 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
634 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
635 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
636 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
637 if ((_tick_counter & 3) == 0) {
638 IndustryGfx gfx = GetIndustryGfx(tile);
640 gfx = (gfx < 155) ? gfx + 1 : 148;
641 SetIndustryGfx(tile, gfx);
642 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
644 break;
646 case GFX_OILWELL_ANIMATED_1:
647 case GFX_OILWELL_ANIMATED_2:
648 case GFX_OILWELL_ANIMATED_3:
649 if ((_tick_counter & 7) == 0) {
650 bool b = Chance16(1, 7);
651 IndustryGfx gfx = GetIndustryGfx(tile);
653 byte m = GetAnimationFrame(tile) + 1;
654 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
655 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
656 SetIndustryConstructionStage(tile, 3);
657 DeleteAnimatedTile(tile);
658 } else {
659 SetAnimationFrame(tile, m);
660 SetIndustryGfx(tile, gfx);
661 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
664 break;
666 case GFX_COAL_MINE_TOWER_ANIMATED:
667 case GFX_COPPER_MINE_TOWER_ANIMATED:
668 case GFX_GOLD_MINE_TOWER_ANIMATED: {
669 int state = _tick_counter & 0x7FF;
671 if ((state -= 0x400) < 0) return;
673 if (state < 0x1A0) {
674 if (state < 0x20 || state >= 0x180) {
675 byte m = GetAnimationFrame(tile);
676 if (!(m & 0x40)) {
677 SetAnimationFrame(tile, m | 0x40);
678 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
680 if (state & 7) return;
681 } else {
682 if (state & 3) return;
684 byte m = (GetAnimationFrame(tile) + 1) | 0x40;
685 if (m > 0xC2) m = 0xC0;
686 SetAnimationFrame(tile, m);
687 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
688 } else if (state >= 0x200 && state < 0x3A0) {
689 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
690 if (state & i) return;
692 byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
693 if (m < 0x80) m = 0x82;
694 SetAnimationFrame(tile, m);
695 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
697 break;
702 static void CreateChimneySmoke(TileIndex tile)
704 uint x = TileX(tile) * TILE_SIZE;
705 uint y = TileY(tile) * TILE_SIZE;
706 int z = GetTileMaxPixelZ(tile);
708 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
711 static void MakeIndustryTileBigger(TileIndex tile)
713 byte cnt = GetIndustryConstructionCounter(tile) + 1;
714 if (cnt != 4) {
715 SetIndustryConstructionCounter(tile, cnt);
716 return;
719 byte stage = GetIndustryConstructionStage(tile) + 1;
720 SetIndustryConstructionCounter(tile, 0);
721 SetIndustryConstructionStage(tile, stage);
722 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
723 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
725 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
727 if (!IsIndustryCompleted(tile)) return;
729 IndustryGfx gfx = GetIndustryGfx(tile);
730 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
731 /* New industries are already animated on construction. */
732 return;
735 switch (gfx) {
736 case GFX_POWERPLANT_CHIMNEY:
737 CreateChimneySmoke(tile);
738 break;
740 case GFX_OILRIG_1: {
741 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
742 * tiles (like the default oil rig). Do a proper check to ensure the
743 * tiles belong to the same industry and based on that build the oil rig's
744 * station. */
745 TileIndex other = tile + TileDiffXY(0, 1);
747 if (IsTileType(other, MP_INDUSTRY) &&
748 GetIndustryGfx(other) == GFX_OILRIG_1 &&
749 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
750 BuildOilRig(tile);
752 break;
755 case GFX_TOY_FACTORY:
756 case GFX_BUBBLE_CATCHER:
757 case GFX_TOFFEE_QUARY:
758 SetAnimationFrame(tile, 0);
759 SetIndustryAnimationLoop(tile, 0);
760 break;
762 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
763 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
764 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
765 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
766 AddAnimatedTile(tile);
767 break;
771 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
773 static const int8 _bubble_spawn_location[3][4] = {
774 { 11, 0, -4, -14 },
775 { -4, -10, -4, 1 },
776 { 49, 59, 60, 65 },
779 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
781 int dir = Random() & 3;
783 EffectVehicle *v = CreateEffectVehicleAbove(
784 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
785 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
786 _bubble_spawn_location[2][dir],
787 EV_BUBBLE
790 if (v != NULL) v->animation_substate = dir;
793 static void TileLoop_Industry(TileIndex tile)
795 if (IsTileOnWater(tile)) TileLoop_Water(tile);
797 /* Normally this doesn't happen, but if an industry NewGRF is removed
798 * an industry that was previously build on water can now be flooded.
799 * If this happens the tile is no longer an industry tile after
800 * returning from TileLoop_Water. */
801 if (!IsTileType(tile, MP_INDUSTRY)) return;
803 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
805 if (!IsIndustryCompleted(tile)) {
806 MakeIndustryTileBigger(tile);
807 return;
810 if (_game_mode == GM_EDITOR) return;
812 if (TransportIndustryGoods(tile) && !StartStopIndustryTileAnimation(Industry::GetByTile(tile), IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
813 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
815 if (newgfx != INDUSTRYTILE_NOANIM) {
816 ResetIndustryConstructionStage(tile);
817 SetIndustryCompleted(tile);
818 SetIndustryGfx(tile, newgfx);
819 MarkTileDirtyByTile(tile);
820 return;
824 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
826 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
827 if (newgfx != INDUSTRYTILE_NOANIM) {
828 ResetIndustryConstructionStage(tile);
829 SetIndustryGfx(tile, newgfx);
830 MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
831 return;
834 IndustryGfx gfx = GetIndustryGfx(tile);
835 switch (gfx) {
836 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
837 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
838 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
839 if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
840 switch (gfx) {
841 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
842 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
843 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
845 SetIndustryGfx(tile, gfx);
846 SetAnimationFrame(tile, 0x80);
847 AddAnimatedTile(tile);
849 break;
851 case GFX_OILWELL_NOT_ANIMATED:
852 if (Chance16(1, 6)) {
853 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
854 SetAnimationFrame(tile, 0);
855 AddAnimatedTile(tile);
857 break;
859 case GFX_COAL_MINE_TOWER_ANIMATED:
860 case GFX_COPPER_MINE_TOWER_ANIMATED:
861 case GFX_GOLD_MINE_TOWER_ANIMATED:
862 if (!(_tick_counter & 0x400)) {
863 switch (gfx) {
864 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
865 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
866 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
868 SetIndustryGfx(tile, gfx);
869 SetIndustryCompleted(tile);
870 SetIndustryConstructionStage(tile, 3);
871 DeleteAnimatedTile(tile);
873 break;
875 case GFX_POWERPLANT_SPARKS:
876 if (Chance16(1, 3)) {
877 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
878 AddAnimatedTile(tile);
880 break;
882 case GFX_COPPER_MINE_CHIMNEY:
883 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
884 break;
887 case GFX_TOY_FACTORY: {
888 Industry *i = Industry::GetByTile(tile);
889 if (i->was_cargo_delivered) {
890 i->was_cargo_delivered = false;
891 SetIndustryAnimationLoop(tile, 0);
892 AddAnimatedTile(tile);
895 break;
897 case GFX_BUBBLE_GENERATOR:
898 TileLoopIndustry_BubbleGenerator(tile);
899 break;
901 case GFX_TOFFEE_QUARY:
902 AddAnimatedTile(tile);
903 break;
905 case GFX_SUGAR_MINE_SIEVE:
906 if (Chance16(1, 3)) AddAnimatedTile(tile);
907 break;
911 static bool ClickTile_Industry(TileIndex tile)
913 ShowIndustryViewWindow(GetIndustryIndex(tile));
914 return true;
917 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
919 return 0;
922 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
924 /* If the founder merges, the industry was created by the merged company */
925 Industry *i = Industry::GetByTile(tile);
926 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
930 * Check whether the tile is a forest.
931 * @param tile the tile to investigate.
932 * @return true if and only if the tile is a forest
934 bool IsTileForestIndustry(TileIndex tile)
936 /* Check for industry tile */
937 if (!IsTileType(tile, MP_INDUSTRY)) return false;
939 const Industry *ind = Industry::GetByTile(tile);
941 /* Check for organic industry (i.e. not processing or extractive) */
942 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
944 /* Check for wood production */
945 for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
946 /* The industry produces wood. */
947 if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
950 return false;
953 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
956 * Check whether the tile can be replaced by a farm field.
957 * @param tile the tile to investigate.
958 * @param allow_fields if true, the method will return true even if
959 * the tile is a farm tile, otherwise the tile may not be a farm tile
960 * @return true if the tile can become a farm field
962 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
964 switch (GetTileType(tile)) {
965 case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
966 case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
967 default: return false;
972 * Build farm field fence
973 * @param tile the tile to position the fence on
974 * @param size the size of the field being planted in tiles
975 * @param type type of fence to set
976 * @param side the side of the tile to attempt placement
978 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
980 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
982 do {
983 tile = TILE_MASK(tile);
985 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
986 byte or_ = type;
988 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
990 SetFence(tile, side, or_);
993 tile += diff;
994 } while (--size);
997 static void PlantFarmField(TileIndex tile, IndustryID industry)
999 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1000 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1003 /* determine field size */
1004 uint32 r = (Random() & 0x303) + 0x404;
1005 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1006 uint size_x = GB(r, 0, 8);
1007 uint size_y = GB(r, 8, 8);
1009 TileArea ta(tile - TileDiffXY(min(TileX(tile), size_x / 2), min(TileY(tile), size_y / 2)), size_x, size_y);
1010 ta.ClampToMap();
1012 if (ta.w == 0 || ta.h == 0) return;
1014 /* check the amount of bad tiles */
1015 int count = 0;
1016 TILE_AREA_LOOP(cur_tile, ta) {
1017 assert(cur_tile < MapSize());
1018 count += IsSuitableForFarmField(cur_tile, false);
1020 if (count * 2 < ta.w * ta.h) return;
1022 /* determine type of field */
1023 r = Random();
1024 uint counter = GB(r, 5, 3);
1025 uint field_type = GB(r, 8, 8) * 9 >> 8;
1027 /* make field */
1028 TILE_AREA_LOOP(cur_tile, ta) {
1029 assert(cur_tile < MapSize());
1030 if (IsSuitableForFarmField(cur_tile, true)) {
1031 MakeField(cur_tile, field_type, industry);
1032 SetClearCounter(cur_tile, counter);
1033 MarkTileDirtyByTile(cur_tile, ZOOM_LVL_DRAW_MAP);
1037 int type = 3;
1038 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1039 type = _plantfarmfield_type[Random() & 0xF];
1042 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1043 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1044 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1045 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1048 void PlantRandomFarmField(const Industry *i)
1050 int x = i->location.w / 2 + Random() % 31 - 16;
1051 int y = i->location.h / 2 + Random() % 31 - 16;
1053 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1055 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1059 * Search callback function for ChopLumberMillTrees
1060 * @param tile to test
1061 * @param user_data that is passed by the caller. In this case, nothing
1062 * @return the result of the test
1064 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
1066 if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1067 /* found a tree */
1069 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1071 _industry_sound_ctr = 1;
1072 _industry_sound_tile = tile;
1073 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1075 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1077 cur_company.Restore();
1078 return true;
1080 return false;
1084 * Perform a circular search around the Lumber Mill in order to find trees to cut
1085 * @param i industry
1087 static void ChopLumberMillTrees(Industry *i)
1089 /* We only want to cut trees if all tiles are completed. */
1090 TILE_AREA_LOOP(tile_cur, i->location) {
1091 if (i->TileBelongsToIndustry(tile_cur)) {
1092 if (!IsIndustryCompleted(tile_cur)) return;
1096 TileIndex tile = i->location.tile;
1097 if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, NULL)) { // 40x40 tiles to search.
1098 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1102 static void ProduceIndustryGoods(Industry *i)
1104 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1106 /* play a sound? */
1107 if ((i->counter & 0x3F) == 0) {
1108 uint32 r;
1109 uint num;
1110 if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
1111 SndPlayTileFx(
1112 (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
1113 i->location.tile);
1117 i->counter--;
1119 /* produce some cargo */
1120 if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1121 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
1123 IndustryBehaviour indbehav = indsp->behaviour;
1124 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
1125 i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
1127 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1128 uint16 cb_res = CALLBACK_FAILED;
1129 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1130 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1133 bool plant;
1134 if (cb_res != CALLBACK_FAILED) {
1135 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1136 } else {
1137 plant = Chance16(1, 8);
1140 if (plant) PlantRandomFarmField(i);
1142 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1143 uint16 cb_res = CALLBACK_FAILED;
1144 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1145 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1148 bool cut;
1149 if (cb_res != CALLBACK_FAILED) {
1150 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1151 } else {
1152 cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1155 if (cut) ChopLumberMillTrees(i);
1158 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1159 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1163 void OnTick_Industry()
1165 if (_industry_sound_ctr != 0) {
1166 _industry_sound_ctr++;
1168 if (_industry_sound_ctr == 75) {
1169 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1170 } else if (_industry_sound_ctr == 160) {
1171 _industry_sound_ctr = 0;
1172 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1176 if (_game_mode == GM_EDITOR) return;
1178 Industry *i;
1179 FOR_ALL_INDUSTRIES(i) {
1180 ProduceIndustryGoods(i);
1185 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1186 * @param tile %Tile to perform the checking.
1187 * @return Succeeded or failed command.
1189 static CommandCost CheckNewIndustry_NULL(TileIndex tile)
1191 return CommandCost();
1195 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1196 * @param tile %Tile to perform the checking.
1197 * @return Succeeded or failed command.
1199 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1201 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1202 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1203 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1206 return CommandCost();
1210 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1211 * @param tile %Tile to perform the checking.
1212 * @return Succeeded or failed command.
1214 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1216 if (_game_mode == GM_EDITOR) return CommandCost();
1217 if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1219 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1222 extern bool _ignore_restrictions;
1225 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1226 * @param tile %Tile to perform the checking.
1227 * @return Succeeded or failed command.
1229 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1231 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1232 if (TileHeight(tile) == 0 &&
1233 DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1235 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1239 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1240 * @param tile %Tile to perform the checking.
1241 * @return Succeeded or failed command.
1243 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1245 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1246 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1247 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1250 return CommandCost();
1254 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1255 * @param tile %Tile to perform the checking.
1256 * @return Succeeded or failed command.
1258 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1260 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1261 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1263 return CommandCost();
1267 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1268 * @param tile %Tile to perform the checking.
1269 * @return Succeeded or failed command.
1271 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1273 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1274 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1276 return CommandCost();
1280 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1281 * @param tile %Tile to perform the checking.
1282 * @return Succeeded or failed command.
1284 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1286 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1287 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1289 return CommandCost();
1293 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1294 * @param tile %Tile to perform the checking.
1295 * @return Succeeded or failed command.
1297 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1299 if (GetTileZ(tile) > 4) {
1300 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1302 return CommandCost();
1306 * Industrytype check function signature.
1307 * @param tile %Tile to check.
1308 * @return Succeeded or failed command.
1310 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1312 /** Check functions for different types of industry. */
1313 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1314 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1315 CheckNewIndustry_Forest, ///< CHECK_FOREST
1316 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1317 CheckNewIndustry_Farm, ///< CHECK_FARM
1318 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1319 CheckNewIndustry_Water, ///< CHECK_WATER
1320 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1321 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1322 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1326 * Find a town for the industry, while checking for multiple industries in the same town.
1327 * @param tile Position of the industry to build.
1328 * @param type Industry type.
1329 * @param [out] town Pointer to return town for the new industry, \c NULL is written if no good town can be found.
1330 * @return Succeeded or failed command.
1332 * @pre \c *t != NULL
1333 * @post \c *t points to a town on success, and \c NULL on failure.
1335 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1337 *t = ClosestTownFromTile(tile, UINT_MAX);
1339 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1341 const Industry *i;
1342 FOR_ALL_INDUSTRIES(i) {
1343 if (i->type == (byte)type && i->town == *t) {
1344 *t = NULL;
1345 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1349 return CommandCost();
1352 bool IsSlopeRefused(Slope current, Slope refused)
1354 if (IsSteepSlope(current)) return true;
1355 if (current != SLOPE_FLAT) {
1356 if (IsSteepSlope(refused)) return true;
1358 Slope t = ComplementSlope(current);
1360 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1361 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1362 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1363 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1366 return false;
1370 * Are the tiles of the industry free?
1371 * @param tile Position to check.
1372 * @param it Industry tiles table.
1373 * @param itspec_index The index of the itsepc to build/fund
1374 * @param type Type of the industry.
1375 * @param initial_random_bits The random bits the industry is going to have after construction.
1376 * @param founder Industry founder
1377 * @param creation_type The circumstances the industry is created under.
1378 * @param [out] custom_shape_check Perform custom check for the site.
1379 * @return Failed or succeeded command.
1381 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)
1383 bool refused_slope = false;
1384 bool custom_shape = false;
1386 do {
1387 IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1388 TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1390 if (!IsValidTile(cur_tile)) {
1391 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1394 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1395 if (!IsWaterTile(cur_tile) ||
1396 !IsTileFlat(cur_tile)) {
1397 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1399 } else {
1400 CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1401 if (ret.Failed()) return ret;
1402 if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1404 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1406 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1408 /* Perform land/water check if not disabled */
1409 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1411 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1412 custom_shape = true;
1413 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
1414 if (ret.Failed()) return ret;
1415 } else {
1416 Slope tileh = GetTileSlope(cur_tile);
1417 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1420 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1421 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1422 if (!IsTileType(cur_tile, MP_HOUSE)) {
1423 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1426 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1427 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1428 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1429 cur_company.Restore();
1431 if (ret.Failed()) return ret;
1432 } else {
1433 /* Clear the tiles, but do not affect town ratings */
1434 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1436 if (ret.Failed()) return ret;
1439 } while ((++it)->ti.x != -0x80);
1441 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1443 /* It is almost impossible to have a fully flat land in TG, so what we
1444 * do is that we check if we can make the land flat later on. See
1445 * CheckIfCanLevelIndustryPlatform(). */
1446 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1447 return CommandCost();
1449 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1453 * Is the industry allowed to be built at this place for the town?
1454 * @param tile Tile to construct the industry.
1455 * @param type Type of the industry.
1456 * @param t Town authority that the industry belongs to.
1457 * @return Succeeded or failed command.
1459 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1461 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1462 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1465 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1466 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1469 if (type == IT_OIL_RIG &&
1470 (IsTunnelInWay(tile, 0) ||
1471 IsTunnelInWay(tile + TileDiffXY(0, 1), 0) ||
1472 IsTunnelInWay(tile + TileDiffXY(1, 2), 0))) return_cmd_error(STR_ERROR_NO_DRILLING_ABOVE_CHUNNEL);
1474 return CommandCost();
1477 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1479 /* Check if we don't leave the map */
1480 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1482 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1483 TILE_AREA_LOOP(tile_walk, ta) {
1484 uint curh = TileHeight(tile_walk);
1485 /* Is the tile clear? */
1486 if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1488 /* Don't allow too big of a change if this is the sub-tile check */
1489 if (internal != 0 && Delta(curh, height) > 1) return false;
1491 /* Different height, so the surrounding tiles of this tile
1492 * has to be correct too (in level, or almost in level)
1493 * else you get a chain-reaction of terraforming. */
1494 if (internal == 0 && curh != height) {
1495 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1496 return false;
1501 return true;
1505 * This function tries to flatten out the land below an industry, without
1506 * damaging the surroundings too much.
1508 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
1510 const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1511 int max_x = 0;
1512 int max_y = 0;
1514 /* Finds dimensions of largest variant of this industry */
1515 do {
1516 if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1517 if (it->ti.x > max_x) max_x = it->ti.x;
1518 if (it->ti.y > max_y) max_y = it->ti.y;
1519 } while ((++it)->ti.x != MKEND);
1521 /* Remember level height */
1522 uint h = TileHeight(tile);
1524 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1525 /* Check that all tiles in area and surrounding are clear
1526 * this determines that there are no obstructing items */
1528 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1529 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1531 if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1533 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1534 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1535 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1537 TILE_AREA_LOOP(tile_walk, ta) {
1538 uint curh = TileHeight(tile_walk);
1539 if (curh != h) {
1540 /* This tile needs terraforming. Check if we can do that without
1541 * damaging the surroundings too much. */
1542 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1543 cur_company.Restore();
1544 return false;
1546 /* This is not 100% correct check, but the best we can do without modifying the map.
1547 * What is missing, is if the difference in height is more than 1.. */
1548 if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1549 cur_company.Restore();
1550 return false;
1555 if (flags & DC_EXEC) {
1556 /* Terraform the land under the industry */
1557 TILE_AREA_LOOP(tile_walk, ta) {
1558 uint curh = TileHeight(tile_walk);
1559 while (curh != h) {
1560 /* We give the terraforming for free here, because we can't calculate
1561 * exact cost in the test-round, and as we all know, that will cause
1562 * a nice assert if they don't match ;) */
1563 DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1564 curh += (curh > h) ? -1 : 1;
1569 cur_company.Restore();
1570 return true;
1575 * Check that the new industry is far enough from conflicting industries.
1576 * @param tile Tile to construct the industry.
1577 * @param type Type of the new industry.
1578 * @return Succeeded or failed command.
1580 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1582 const IndustrySpec *indspec = GetIndustrySpec(type);
1583 const Industry *i = NULL;
1585 /* On a large map with many industries, it may be faster to check an area. */
1586 static const int dmax = 14;
1587 if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
1588 const int tx = TileX(tile);
1589 const int ty = TileY(tile);
1590 TileArea tile_area = TileArea(TileXY(max(0, tx - dmax), max(0, ty - dmax)), TileXY(min(MapMaxX(), tx + dmax), min(MapMaxY(), ty + dmax)));
1591 TILE_AREA_LOOP(atile, tile_area) {
1592 if (GetTileType(atile) == MP_INDUSTRY) {
1593 const Industry *i2 = Industry::GetByTile(atile);
1594 if (i == i2) continue;
1595 i = i2;
1596 if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1597 if (i->type == indspec->conflicting[0] ||
1598 i->type == indspec->conflicting[1] ||
1599 i->type == indspec->conflicting[2]) {
1600 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1604 return CommandCost();
1607 FOR_ALL_INDUSTRIES(i) {
1608 /* Within 14 tiles from another industry is considered close */
1609 if (DistanceMax(tile, i->location.tile) > 14) continue;
1611 /* check if there are any conflicting industry types around */
1612 if (i->type == indspec->conflicting[0] ||
1613 i->type == indspec->conflicting[1] ||
1614 i->type == indspec->conflicting[2]) {
1615 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1618 return CommandCost();
1622 * Advertise about a new industry opening.
1623 * @param ind Industry being opened.
1625 static void AdvertiseIndustryOpening(const Industry *ind)
1627 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1628 SetDParam(0, ind_spc->name);
1629 if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1630 SetDParam(1, STR_TOWN_NAME);
1631 SetDParam(2, ind->town->index);
1632 } else {
1633 SetDParam(1, ind->town->index);
1635 AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1636 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1637 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1641 * Put an industry on the map.
1642 * @param i Just allocated poolitem, mostly empty.
1643 * @param tile North tile of the industry.
1644 * @param type Type of the industry.
1645 * @param it Industrylayout to build.
1646 * @param layout Number of the layout.
1647 * @param t Nearest town.
1648 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1649 * @param initial_random_bits Random bits for the industry.
1651 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1653 const IndustrySpec *indspec = GetIndustrySpec(type);
1655 i->location = TileArea(tile, 1, 1);
1656 i->type = type;
1657 Industry::IncIndustryTypeCount(type);
1659 i->produced_cargo[0] = indspec->produced_cargo[0];
1660 i->produced_cargo[1] = indspec->produced_cargo[1];
1661 i->accepts_cargo[0] = indspec->accepts_cargo[0];
1662 i->accepts_cargo[1] = indspec->accepts_cargo[1];
1663 i->accepts_cargo[2] = indspec->accepts_cargo[2];
1664 i->production_rate[0] = indspec->production_rate[0];
1665 i->production_rate[1] = indspec->production_rate[1];
1667 /* don't use smooth economy for industries using production related callbacks */
1668 if (indspec->UsesSmoothEconomy()) {
1669 i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8, 255);
1670 i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8, 255);
1673 i->town = t;
1674 i->owner = OWNER_NONE;
1676 uint16 r = Random();
1677 i->random_colour = GB(r, 0, 4);
1678 i->counter = GB(r, 4, 12);
1679 i->random = initial_random_bits;
1680 i->produced_cargo_waiting[0] = 0;
1681 i->produced_cargo_waiting[1] = 0;
1682 i->incoming_cargo_waiting[0] = 0;
1683 i->incoming_cargo_waiting[1] = 0;
1684 i->incoming_cargo_waiting[2] = 0;
1685 i->this_month_production[0] = 0;
1686 i->this_month_production[1] = 0;
1687 i->this_month_transported[0] = 0;
1688 i->this_month_transported[1] = 0;
1689 i->last_month_pct_transported[0] = 0;
1690 i->last_month_pct_transported[1] = 0;
1691 i->last_month_transported[0] = 0;
1692 i->last_month_transported[1] = 0;
1693 i->was_cargo_delivered = false;
1694 i->last_prod_year = _cur_year;
1695 i->founder = founder;
1697 i->construction_date = _date;
1698 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1699 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1701 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1702 * 0 = created prior of newindustries
1703 * else, chosen layout + 1 */
1704 i->selected_layout = layout + 1;
1706 i->prod_level = PRODLEVEL_DEFAULT;
1708 /* Call callbacks after the regular fields got initialised. */
1710 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1711 uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1712 if (res != CALLBACK_FAILED) {
1713 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1714 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1715 } else {
1716 i->prod_level = res;
1717 i->RecomputeProductionMultipliers();
1722 if (_generating_world) {
1723 i->last_month_production[0] = i->production_rate[0] * 8;
1724 i->last_month_production[1] = i->production_rate[1] * 8;
1725 } else {
1726 i->last_month_production[0] = i->last_month_production[1] = 0;
1729 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1730 uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1731 if (res != CALLBACK_FAILED) {
1732 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1733 i->random_colour = GB(res, 0, 4);
1737 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1738 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1739 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) {
1740 uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1741 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1742 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1743 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1744 break;
1746 i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1750 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1751 for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1752 for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
1753 uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1754 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1755 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1756 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1757 break;
1759 i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1763 /* Plant the tiles */
1765 do {
1766 TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1768 if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1769 i->location.Add(cur_tile);
1771 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1773 DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1775 MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1777 if (_generating_world) {
1778 SetIndustryConstructionCounter(cur_tile, 3);
1779 SetIndustryConstructionStage(cur_tile, 2);
1782 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1783 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
1784 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1785 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1787 } while ((++it)->ti.x != -0x80);
1789 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1790 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1792 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
1794 Station::RecomputeIndustriesNearForAll();
1798 * Helper function for Build/Fund an industry
1799 * @param tile tile where industry is built
1800 * @param type of industry to build
1801 * @param flags of operations to conduct
1802 * @param indspec pointer to industry specifications
1803 * @param itspec_index the index of the itsepc to build/fund
1804 * @param seed random seed (possibly) used by industries
1805 * @param initial_random_bits The random bits the industry is going to have after construction.
1806 * @param founder Founder of the industry
1807 * @param creation_type The circumstances the industry is created under.
1808 * @param [out] ip Pointer to store newly created industry.
1809 * @return Succeeded or failed command.
1811 * @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.
1813 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)
1815 assert(itspec_index < indspec->num_table);
1816 const IndustryTileTable *it = indspec->table[itspec_index];
1817 bool custom_shape_check = false;
1819 *ip = NULL;
1821 SmallVector<ClearedObjectArea, 1> object_areas(_cleared_object_areas);
1822 CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1823 _cleared_object_areas = object_areas;
1824 if (ret.Failed()) return ret;
1826 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1827 ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
1828 } else {
1829 ret = _check_new_industry_procs[indspec->check_proc](tile);
1831 if (ret.Failed()) return ret;
1833 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
1834 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1835 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1838 ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1839 if (ret.Failed()) return ret;
1841 Town *t = NULL;
1842 ret = FindTownForIndustry(tile, type, &t);
1843 if (ret.Failed()) return ret;
1844 assert(t != NULL);
1846 ret = CheckIfIndustryIsAllowed(tile, type, t);
1847 if (ret.Failed()) return ret;
1849 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1851 if (flags & DC_EXEC) {
1852 *ip = new Industry(tile);
1853 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
1854 DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
1857 return CommandCost();
1861 * Build/Fund an industry
1862 * @param tile tile where industry is built
1863 * @param flags of operations to conduct
1864 * @param p1 various bitstuffed elements
1865 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1866 * - p1 = (bit 8 - 15) - first layout to try
1867 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1868 * @param p2 seed to use for desyncfree randomisations
1869 * @param text unused
1870 * @return the cost of this operation or an error
1872 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1874 IndustryType it = GB(p1, 0, 8);
1875 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1877 const IndustrySpec *indspec = GetIndustrySpec(it);
1879 /* Check if the to-be built/founded industry is available for this climate. */
1880 if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
1882 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1883 * Raw material industries are industries that do not accept cargo (at least for now) */
1884 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1885 return CMD_ERROR;
1888 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1889 return CMD_ERROR;
1892 Randomizer randomizer;
1893 randomizer.SetSeed(p2);
1894 uint16 random_initial_bits = GB(p2, 0, 16);
1895 uint32 random_var8f = randomizer.Next();
1896 int num_layouts = indspec->num_table;
1897 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
1898 const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
1900 Industry *ind = NULL;
1901 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
1902 if (flags & DC_EXEC) {
1903 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1904 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1905 /* Prospecting has a chance to fail, however we cannot guarantee that something can
1906 * be built on the map, so the chance gets lower when the map is fuller, but there
1907 * is nothing we can really do about that. */
1908 if (deity_prospect || Random() <= indspec->prospecting_chance) {
1909 for (int i = 0; i < 5000; i++) {
1910 /* We should not have more than one Random() in a function call
1911 * because parameter evaluation order is not guaranteed in the c++ standard
1913 tile = RandomTile();
1914 /* Start with a random layout */
1915 int layout = RandomRange(num_layouts);
1916 /* Check now each layout, starting with the random one */
1917 for (int j = 0; j < num_layouts; j++) {
1918 layout = (layout + 1) % num_layouts;
1919 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
1920 if (ret.Succeeded()) break;
1922 if (ret.Succeeded()) break;
1925 cur_company.Restore();
1927 } else {
1928 int layout = GB(p1, 8, 8);
1929 if (layout >= num_layouts) return CMD_ERROR;
1931 /* Check subsequently each layout, starting with the given layout in p1 */
1932 for (int i = 0; i < num_layouts; i++) {
1933 layout = (layout + 1) % num_layouts;
1934 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
1935 if (ret.Succeeded()) break;
1938 /* If it still failed, there's no suitable layout to build here, return the error */
1939 if (ret.Failed()) return ret;
1942 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1943 AdvertiseIndustryOpening(ind);
1946 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1951 * Create a new industry of random layout.
1952 * @param tile The location to build the industry.
1953 * @param type The industry type to build.
1954 * @param creation_type The circumstances the industry is created under.
1955 * @return the created industry or NULL if it failed.
1957 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1959 const IndustrySpec *indspec = GetIndustrySpec(type);
1961 uint32 seed = Random();
1962 uint32 seed2 = Random();
1963 Industry *ind = NULL;
1964 CommandCost ret;
1966 int layout = RandomRange(indspec->num_table);
1968 /* Check subsequently each layout, starting with the given layout in p1 */
1969 for (int i = 0; i < indspec->num_table; i++) {
1970 layout = (layout + 1) % indspec->num_table;
1971 ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, layout, seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &ind);
1972 if (ret.Succeeded()) break;
1975 assert(ind != NULL || ret.Failed());
1976 return ind;
1980 * Compute the appearance probability for an industry during map creation.
1981 * @param it Industry type to compute.
1982 * @param [out] force_at_least_one Returns whether at least one instance should be forced on map creation.
1983 * @return Relative probability for the industry to appear.
1985 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
1987 const IndustrySpec *ind_spc = GetIndustrySpec(it);
1988 uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
1989 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1990 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
1991 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
1992 *force_at_least_one = false;
1993 return 0;
1994 } else {
1995 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1996 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1997 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(chance) : ScaleByMapSize(chance);
1999 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
2000 return chance;
2005 * Compute the probability for constructing a new industry during game play.
2006 * @param it Industry type to compute.
2007 * @param [out] min_number Minimal number of industries that should exist at the map.
2008 * @return Relative probability for the industry to appear.
2010 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
2012 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
2013 *min_number = 0;
2014 return 0;
2017 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2018 byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2019 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
2020 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
2021 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
2022 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2023 *min_number = 0;
2024 return 0;
2026 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2027 return chance;
2031 * Get wanted number of industries on the map.
2032 * @return Wanted number of industries at the map.
2034 static uint GetNumberOfIndustries()
2036 /* Number of industries on a 256x256 map. */
2037 static const uint16 numof_industry_table[] = {
2038 0, // none
2039 0, // minimal
2040 10, // very low
2041 25, // low
2042 55, // normal
2043 80, // high
2046 assert(lengthof(numof_industry_table) == ID_END);
2047 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2048 return min(IndustryPool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2052 * Try to place the industry in the game.
2053 * Since there is no feedback why placement fails, there is no other option
2054 * than to try a few times before concluding it does not work.
2055 * @param type Industry type of the desired industry.
2056 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2057 * @return Pointer to created industry, or \c NULL if creation failed.
2059 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2061 uint tries = try_hard ? 10000u : 2000u;
2062 for (; tries > 0; tries--) {
2063 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2064 if (ind != NULL) return ind;
2066 return NULL;
2070 * Try to build a industry on the map.
2071 * @param type IndustryType of the desired industry
2072 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2074 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2076 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2078 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2079 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2081 cur_company.Restore();
2085 * Get total number of industries existing in the game.
2086 * @return Number of industries currently in the game.
2088 static uint GetCurrentTotalNumberOfIndustries()
2090 int total = 0;
2091 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2092 return total;
2096 /** Reset the entry. */
2097 void IndustryTypeBuildData::Reset()
2099 this->probability = 0;
2100 this->min_number = 0;
2101 this->target_count = 0;
2102 this->max_wait = 1;
2103 this->wait_count = 0;
2106 /** Completely reset the industry build data. */
2107 void IndustryBuildData::Reset()
2109 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2111 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2112 this->builddata[it].Reset();
2116 /** Monthly update of industry build data. */
2117 void IndustryBuildData::MonthlyLoop()
2119 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.
2120 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2122 /* To prevent running out of unused industries for the player to connect,
2123 * add a fraction of new industries each month, but only if the manager can keep up. */
2124 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).
2125 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2126 this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2131 * This function will create random industries during game creation.
2132 * It will scale the amount of industries by mapsize and difficulty level.
2134 void GenerateIndustries()
2136 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2138 uint32 industry_probs[NUM_INDUSTRYTYPES];
2139 bool force_at_least_one[NUM_INDUSTRYTYPES];
2140 uint32 total_prob = 0;
2141 uint num_forced = 0;
2143 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2144 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2145 total_prob += industry_probs[it];
2146 if (force_at_least_one[it]) num_forced++;
2149 uint total_amount = GetNumberOfIndustries();
2150 if (total_prob == 0 || total_amount < num_forced) {
2151 /* Only place the forced ones */
2152 total_amount = num_forced;
2155 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2157 /* Try to build one industry per type independent of any probabilities */
2158 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2159 if (force_at_least_one[it]) {
2160 assert(total_amount > 0);
2161 total_amount--;
2162 PlaceInitialIndustry(it, true);
2166 /* Add the remaining industries according to their probabilities */
2167 for (uint i = 0; i < total_amount; i++) {
2168 uint32 r = RandomRange(total_prob);
2169 IndustryType it = 0;
2170 while (r >= industry_probs[it]) {
2171 r -= industry_probs[it];
2172 it++;
2173 assert(it < NUM_INDUSTRYTYPES);
2175 assert(industry_probs[it] > 0);
2176 PlaceInitialIndustry(it, false);
2178 _industry_builder.Reset();
2182 * Monthly update of industry statistics.
2183 * @param i Industry to update.
2185 static void UpdateIndustryStatistics(Industry *i)
2187 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2188 if (i->produced_cargo[j] != CT_INVALID) {
2189 byte pct = 0;
2190 if (i->this_month_production[j] != 0) {
2191 i->last_prod_year = _cur_year;
2192 pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2194 i->last_month_pct_transported[j] = pct;
2196 i->last_month_production[j] = i->this_month_production[j];
2197 i->this_month_production[j] = 0;
2199 i->last_month_transported[j] = i->this_month_transported[j];
2200 i->this_month_transported[j] = 0;
2206 * Recompute #production_rate for current #prod_level.
2207 * This function is only valid when not using smooth economy.
2209 void Industry::RecomputeProductionMultipliers()
2211 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2212 assert(!indspec->UsesSmoothEconomy());
2214 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2215 this->production_rate[0] = min(CeilDiv(indspec->production_rate[0] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2216 this->production_rate[1] = min(CeilDiv(indspec->production_rate[1] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2221 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2222 * @param it Industry type.
2223 * @return At least one of the fields has changed value.
2225 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2227 byte min_number;
2228 uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2229 bool changed = min_number != this->min_number || probability != this->probability;
2230 this->min_number = min_number;
2231 this->probability = probability;
2232 return changed;
2235 /** Decide how many industries of each type are needed. */
2236 void IndustryBuildData::SetupTargetCount()
2238 bool changed = false;
2239 uint num_planned = 0; // Number of industries planned in the industry build data.
2240 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2241 changed |= this->builddata[it].GetIndustryTypeData(it);
2242 num_planned += this->builddata[it].target_count;
2244 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2245 changed |= num_planned != total_amount;
2246 if (!changed) return; // All industries are still the same, no need to re-randomize.
2248 /* Initialize the target counts. */
2249 uint force_build = 0; // Number of industries that should always be available.
2250 uint32 total_prob = 0; // Sum of probabilities.
2251 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2252 IndustryTypeBuildData *ibd = this->builddata + it;
2253 force_build += ibd->min_number;
2254 ibd->target_count = ibd->min_number;
2255 total_prob += ibd->probability;
2258 if (total_prob == 0) return; // No buildable industries.
2260 /* Subtract forced industries from the number of industries available for construction. */
2261 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2263 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2264 while (total_amount > 0) {
2265 uint32 r = RandomRange(total_prob);
2266 IndustryType it = 0;
2267 while (r >= this->builddata[it].probability) {
2268 r -= this->builddata[it].probability;
2269 it++;
2270 assert(it < NUM_INDUSTRYTYPES);
2272 assert(this->builddata[it].probability > 0);
2273 this->builddata[it].target_count++;
2274 total_amount--;
2279 * Try to create a random industry, during gameplay
2281 void IndustryBuildData::TryBuildNewIndustry()
2283 this->SetupTargetCount();
2285 int missing = 0; // Number of industries that need to be build.
2286 uint count = 0; // Number of industry types eligible for build.
2287 uint32 total_prob = 0; // Sum of probabilities.
2288 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2289 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2290 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2291 missing += difference;
2292 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2293 if (difference > 0) {
2294 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2295 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2296 if (forced_build == NUM_INDUSTRYTYPES ||
2297 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2298 forced_build = it;
2301 total_prob += difference;
2302 count++;
2306 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2308 if (count >= 1) {
2309 /* If not forced, pick a weighted random industry to build.
2310 * For the case that count == 1, there is no need to draw a random number. */
2311 IndustryType it;
2312 if (forced_build != NUM_INDUSTRYTYPES) {
2313 it = forced_build;
2314 } else {
2315 /* Non-forced, select an industry type to build (weighted random). */
2316 uint32 r = 0; // Initialized to silence the compiler.
2317 if (count > 1) r = RandomRange(total_prob);
2318 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2319 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2320 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2321 if (difference <= 0) continue; // Too many of this kind.
2322 if (count == 1) break;
2323 if (r < (uint)difference) break;
2324 r -= difference;
2326 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2329 /* Try to create the industry. */
2330 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, forced_build != NUM_INDUSTRYTYPES);
2331 if (ind == NULL) {
2332 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2333 this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2334 } else {
2335 AdvertiseIndustryOpening(ind);
2336 this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2340 /* Decrement wait counters. */
2341 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2342 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2347 * Protects an industry from closure if the appropriate flags and conditions are met
2348 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2349 * count of industries of this type must one (or lower) in order to be protected
2350 * against closure.
2351 * @param type IndustryType been queried
2352 * @result true if protection is on, false otherwise (except for oil wells)
2354 static bool CheckIndustryCloseDownProtection(IndustryType type)
2356 const IndustrySpec *indspec = GetIndustrySpec(type);
2358 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2359 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2360 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2364 * Can given cargo type be accepted or produced by the industry?
2365 * @param cargo: Cargo type
2366 * @param ind: Industry
2367 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2368 * @param *c_produces: Pointer to boolean for production of cargo
2369 * @return: \c *c_accepts is set when industry accepts the cargo type,
2370 * \c *c_produces is set when the industry produces the cargo type
2372 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2374 if (cargo == CT_INVALID) return;
2376 /* Check for acceptance of cargo */
2377 for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2378 if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2379 *c_accepts = true;
2380 break;
2384 /* Check for produced cargo */
2385 for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2386 if (cargo == ind->produced_cargo[j]) {
2387 *c_produces = true;
2388 break;
2394 * Compute who can service the industry.
2396 * Here, 'can service' means that he/she has trains and stations close enough
2397 * to the industry with the right cargo type and the right orders (ie has the
2398 * technical means).
2400 * @param ind: Industry being investigated.
2402 * @return: 0 if nobody can service the industry, 2 if the local company can
2403 * service the industry, and 1 otherwise (only competitors can service the
2404 * industry)
2406 static int WhoCanServiceIndustry(Industry *ind)
2408 /* Find all stations within reach of the industry */
2409 StationList stations;
2410 FindStationsAroundTiles(ind->location, &stations);
2412 if (stations.Length() == 0) return 0; // No stations found at all => nobody services
2414 const Vehicle *v;
2415 int result = 0;
2416 FOR_ALL_VEHICLES(v) {
2417 /* Is it worthwhile to try this vehicle? */
2418 if (v->owner != _local_company && result != 0) continue;
2420 /* Check whether it accepts the right kind of cargo */
2421 bool c_accepts = false;
2422 bool c_produces = false;
2423 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2424 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2425 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2427 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2428 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2429 } else {
2430 continue;
2432 if (!c_accepts && !c_produces) continue; // Wrong cargo
2434 /* Check orders of the vehicle.
2435 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2436 * may have a different cargo type.
2438 const Order *o;
2439 FOR_VEHICLE_ORDERS(v, o) {
2440 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2441 /* Vehicle visits a station to load or unload */
2442 Station *st = Station::Get(o->GetDestination());
2443 assert(st != NULL);
2445 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2446 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2448 if (stations.Contains(st)) {
2449 if (v->owner == _local_company) return 2; // Company services industry
2450 result = 1; // Competitor services industry
2455 return result;
2459 * Report news that industry production has changed significantly
2461 * @param ind: Industry with changed production
2462 * @param type: Cargo type that has changed
2463 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
2465 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2467 NewsType nt;
2469 switch (WhoCanServiceIndustry(ind)) {
2470 case 0: nt = NT_INDUSTRY_NOBODY; break;
2471 case 1: nt = NT_INDUSTRY_OTHER; break;
2472 case 2: nt = NT_INDUSTRY_COMPANY; break;
2473 default: NOT_REACHED();
2475 SetDParam(2, abs(percent));
2476 SetDParam(0, CargoSpec::Get(type)->name);
2477 SetDParam(1, ind->index);
2478 AddIndustryNewsItem(
2479 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2481 ind->index
2485 static const uint PERCENT_TRANSPORTED_60 = 153;
2486 static const uint PERCENT_TRANSPORTED_80 = 204;
2489 * Change industry production or do closure
2490 * @param i Industry for which changes are performed
2491 * @param monthly true if it's the monthly call, false if it's the random call
2493 static void ChangeIndustryProduction(Industry *i, bool monthly)
2495 StringID str = STR_NULL;
2496 bool closeit = false;
2497 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2498 bool standard = false;
2499 bool suppress_message = false;
2500 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2501 /* don't use smooth economy for industries using production related callbacks */
2502 bool smooth_economy = indspec->UsesSmoothEconomy();
2503 byte div = 0;
2504 byte mul = 0;
2505 int8 increment = 0;
2507 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2508 if (callback_enabled) {
2509 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2510 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2511 suppress_message = HasBit(res, 7);
2512 /* Get the custom message if any */
2513 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2514 res = GB(res, 0, 4);
2515 switch (res) {
2516 default: NOT_REACHED();
2517 case 0x0: break; // Do nothing, but show the custom message if any
2518 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2519 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2520 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2521 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2522 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2523 case 0x8: div = res - 0x3; break; // Divide production by 32
2524 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2525 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2526 case 0xD: // decrement production
2527 case 0xE: // increment production
2528 increment = res == 0x0D ? -1 : 1;
2529 break;
2530 case 0xF: // Set production to third byte of register 0x100
2531 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2532 recalculate_multipliers = true;
2533 break;
2536 } else {
2537 if (monthly != smooth_economy) return;
2538 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2541 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2542 /* decrease or increase */
2543 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2545 if (smooth_economy) {
2546 closeit = true;
2547 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2548 if (i->produced_cargo[j] == CT_INVALID) continue;
2549 uint32 r = Random();
2550 int old_prod, new_prod, percent;
2551 /* If over 60% is transported, mult is 1, else mult is -1. */
2552 int mult = (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) ? 1 : -1;
2554 new_prod = old_prod = i->production_rate[j];
2556 /* For industries with only_decrease flags (temperate terrain Oil Wells),
2557 * the multiplier will always be -1 so they will only decrease. */
2558 if (only_decrease) {
2559 mult = -1;
2560 /* For normal industries, if over 60% is transported, 33% chance for decrease.
2561 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2562 } else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2563 mult *= -1;
2566 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2567 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2568 if (Chance16I(1, 22, r >> 16)) {
2569 new_prod += mult * (max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2572 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2573 new_prod = Clamp(new_prod, 1, 255);
2575 if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
2576 new_prod = Clamp(new_prod, 0, 16);
2579 /* Do not stop closing the industry when it has the lowest possible production rate */
2580 if (new_prod == old_prod && old_prod > 1) {
2581 closeit = false;
2582 continue;
2585 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2586 i->production_rate[j] = new_prod;
2588 /* Close the industry when it has the lowest possible production rate */
2589 if (new_prod > 1) closeit = false;
2591 if (abs(percent) >= 10) {
2592 ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
2595 } else {
2596 if (only_decrease || Chance16(1, 3)) {
2597 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2598 if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2599 mul = 1; // Increase production
2600 } else {
2601 div = 1; // Decrease production
2607 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2608 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2609 closeit = true;
2613 /* Increase if needed */
2614 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2615 i->prod_level = min(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2616 recalculate_multipliers = true;
2617 if (str == STR_NULL) str = indspec->production_up_text;
2620 /* Decrease if needed */
2621 while (div-- != 0 && !closeit) {
2622 if (i->prod_level == PRODLEVEL_MINIMUM) {
2623 closeit = true;
2624 } else {
2625 i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2626 recalculate_multipliers = true;
2627 if (str == STR_NULL) str = indspec->production_down_text;
2631 /* Increase or Decreasing the production level if needed */
2632 if (increment != 0) {
2633 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2634 closeit = true;
2635 } else {
2636 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2637 recalculate_multipliers = true;
2641 /* Recalculate production_rate
2642 * For non-smooth economy these should always be synchronized with prod_level */
2643 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2645 /* Close if needed and allowed */
2646 if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2647 i->prod_level = PRODLEVEL_CLOSURE;
2648 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2649 str = indspec->closure_text;
2652 if (!suppress_message && str != STR_NULL) {
2653 NewsType nt;
2654 /* Compute news category */
2655 if (closeit) {
2656 nt = NT_INDUSTRY_CLOSE;
2657 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2658 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2659 } else {
2660 switch (WhoCanServiceIndustry(i)) {
2661 case 0: nt = NT_INDUSTRY_NOBODY; break;
2662 case 1: nt = NT_INDUSTRY_OTHER; break;
2663 case 2: nt = NT_INDUSTRY_COMPANY; break;
2664 default: NOT_REACHED();
2667 /* Set parameters of news string */
2668 if (str > STR_LAST_STRINGID) {
2669 SetDParam(0, STR_TOWN_NAME);
2670 SetDParam(1, i->town->index);
2671 SetDParam(2, indspec->name);
2672 } else if (closeit) {
2673 SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
2674 SetDParam(1, i->town->index);
2675 SetDParam(2, indspec->name);
2676 } else {
2677 SetDParam(0, i->index);
2679 /* and report the news to the user */
2680 if (closeit) {
2681 AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
2682 } else {
2683 AddIndustryNewsItem(str, nt, i->index);
2689 * Daily handler for the industry changes
2690 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2691 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2692 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2693 * it would be way more. The daily loop handles those changes.
2695 void IndustryDailyLoop()
2697 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
2699 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2700 * the lower 16 bit are a fractional part that might accumulate over several days until it
2701 * is sufficient for an industry. */
2702 uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2704 /* Reset the active part of the counter, just keeping the "fractional part" */
2705 _economy.industry_daily_change_counter &= 0xFFFF;
2707 if (change_loop == 0) {
2708 return; // Nothing to do? get out
2711 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2713 /* perform the required industry changes for the day */
2715 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2716 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
2717 perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2719 for (uint16 j = 0; j < change_loop; j++) {
2720 /* industry for taxes */
2721 if (_economy.industry_helper > _price[PR_BUILD_INDUSTRY] << 3) {
2722 _economy.industry_helper -= _price[PR_BUILD_INDUSTRY] << 3;
2723 _industry_builder.TryBuildNewIndustry();
2724 } else if (Chance16(3, 100)) {
2725 _industry_builder.TryBuildNewIndustry();
2726 } else {
2727 Industry *i = Industry::GetRandom();
2728 if (i != NULL) {
2729 ChangeIndustryProduction(i, false);
2730 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2735 cur_company.Restore();
2737 /* production-change */
2738 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2741 void IndustryMonthlyLoop()
2743 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2745 _industry_builder.MonthlyLoop();
2747 Industry *i;
2748 FOR_ALL_INDUSTRIES(i) {
2749 UpdateIndustryStatistics(i);
2750 if (i->prod_level == PRODLEVEL_CLOSURE) {
2751 delete i;
2752 } else {
2753 ChangeIndustryProduction(i, true);
2754 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2758 cur_company.Restore();
2760 /* production-change */
2761 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2765 void InitializeIndustries()
2767 Industry::ResetIndustryCounts();
2768 _industry_sound_tile = 0;
2770 _industry_builder.Reset();
2773 /** Verify whether the generated industries are complete, and warn the user if not. */
2774 void CheckIndustries()
2776 int count = 0;
2777 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2778 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2780 bool force_at_least_one;
2781 uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2782 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2784 const IndustrySpec *is = GetIndustrySpec(it);
2785 SetDParam(0, is->name);
2786 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2788 count++;
2789 if (count >= 3) break; // Don't swamp the user with errors.
2794 * Is an industry with the spec a raw industry?
2795 * @return true if it should be handled as a raw industry
2797 bool IndustrySpec::IsRawIndustry() const
2799 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2803 * Is an industry with the spec a processing industry?
2804 * @return true if it should be handled as a processing industry
2806 bool IndustrySpec::IsProcessingIndustry() const
2808 /* Lumber mills are neither raw nor processing */
2809 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2810 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2814 * Get the cost for constructing this industry
2815 * @return the cost (inflation corrected etc)
2817 Money IndustrySpec::GetConstructionCost() const
2819 /* Building raw industries like secondary uses different price base */
2820 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2821 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2825 * Get the cost for removing this industry
2826 * Take note that the cost will always be zero for non-grf industries.
2827 * Only if the grf author did specified a cost will it be applicable.
2828 * @return the cost (inflation corrected etc)
2830 Money IndustrySpec::GetRemovalCost() const
2832 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2836 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2837 * @return true if smooth economy is used.
2839 bool IndustrySpec::UsesSmoothEconomy() const
2841 return _settings_game.economy.smooth_economy &&
2842 !(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
2843 !(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
2846 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2848 if (AutoslopeEnabled()) {
2849 /* We imitate here TTDP's behaviour:
2850 * - Both new and old slope must not be steep.
2851 * - TileMaxZ must not be changed.
2852 * - Allow autoslope by default.
2853 * - Disallow autoslope if callback succeeds and returns non-zero.
2855 Slope tileh_old = GetTileSlope(tile);
2856 /* TileMaxZ must not be changed. Slopes must not be steep. */
2857 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2858 const IndustryGfx gfx = GetIndustryGfx(tile);
2859 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2861 /* Call callback 3C 'disable autosloping for industry tiles'. */
2862 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2863 /* If the callback fails, allow autoslope. */
2864 uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2865 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2866 } else {
2867 /* allow autoslope */
2868 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2872 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2875 extern const TileTypeProcs _tile_type_industry_procs = {
2876 DrawTile_Industry, // draw_tile_proc
2877 GetSlopePixelZ_Industry, // get_slope_z_proc
2878 ClearTile_Industry, // clear_tile_proc
2879 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2880 GetTileDesc_Industry, // get_tile_desc_proc
2881 GetTileTrackStatus_Industry, // get_tile_track_status_proc
2882 ClickTile_Industry, // click_tile_proc
2883 AnimateTile_Industry, // animate_tile_proc
2884 TileLoop_Industry, // tile_loop_proc
2885 ChangeTileOwner_Industry, // change_tile_owner_proc
2886 NULL, // add_produced_cargo_proc
2887 NULL, // vehicle_enter_tile_proc
2888 GetFoundation_Industry, // get_foundation_proc
2889 TerraformTile_Industry, // terraform_tile_proc