(svn r27985) -Codechange: Convert VA2 switches into ones with non-overlapping ranges...
[openttd.git] / src / industry_cmd.cpp
blob9c98b120c61a997fbe14e0bcbd1e73c041b6d4d9
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file industry_cmd.cpp Handling of industry tiles. */
12 #include "stdafx.h"
13 #include "clear_map.h"
14 #include "industry.h"
15 #include "station_base.h"
16 #include "landscape.h"
17 #include "viewport_func.h"
18 #include "command_func.h"
19 #include "town.h"
20 #include "news_func.h"
21 #include "cheat_type.h"
22 #include "genworld.h"
23 #include "tree_map.h"
24 #include "newgrf_cargo.h"
25 #include "newgrf_debug.h"
26 #include "newgrf_industrytiles.h"
27 #include "autoslope.h"
28 #include "water.h"
29 #include "strings_func.h"
30 #include "window_func.h"
31 #include "date_func.h"
32 #include "vehicle_func.h"
33 #include "sound_func.h"
34 #include "animated_tile_func.h"
35 #include "effectvehicle_func.h"
36 #include "effectvehicle_base.h"
37 #include "ai/ai.hpp"
38 #include "core/pool_func.hpp"
39 #include "subsidy_func.h"
40 #include "core/backup_type.hpp"
41 #include "object_base.h"
42 #include "game/game.hpp"
43 #include "error.h"
45 #include "table/strings.h"
46 #include "table/industry_land.h"
47 #include "table/build_industry.h"
49 #include "safeguards.h"
51 IndustryPool _industry_pool("Industry");
52 INSTANTIATE_POOL_METHODS(Industry)
54 void ShowIndustryViewWindow(int industry);
55 void BuildOilRig(TileIndex tile);
57 static byte _industry_sound_ctr;
58 static TileIndex _industry_sound_tile;
60 uint16 Industry::counts[NUM_INDUSTRYTYPES];
62 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
63 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
64 IndustryBuildData _industry_builder; ///< In-game manager of industries.
66 /**
67 * This function initialize the spec arrays of both
68 * industry and industry tiles.
69 * It adjusts the enabling of the industry too, based on climate availability.
70 * This will allow for clearer testings
72 void ResetIndustries()
74 memset(&_industry_specs, 0, sizeof(_industry_specs));
75 memcpy(&_industry_specs, &_origin_industry_specs, sizeof(_origin_industry_specs));
77 /* once performed, enable only the current climate industries */
78 for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) {
79 _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET &&
80 HasBit(_origin_industry_specs[i].climate_availability, _settings_game.game_creation.landscape);
83 memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs));
84 memcpy(&_industry_tile_specs, &_origin_industry_tile_specs, sizeof(_origin_industry_tile_specs));
86 /* Reset any overrides that have been set. */
87 _industile_mngr.ResetOverride();
88 _industry_mngr.ResetOverride();
91 /**
92 * Retrieve the type for this industry. Although it is accessed by a tile,
93 * it will return the general type of industry, and not the sprite index
94 * as would do GetIndustryGfx.
95 * @param tile that is queried
96 * @pre IsTileType(tile, MP_INDUSTRY)
97 * @return general type for this industry, as defined in industry.h
99 IndustryType GetIndustryType(TileIndex tile)
101 assert(IsTileType(tile, MP_INDUSTRY));
103 const Industry *ind = Industry::GetByTile(tile);
104 assert(ind != NULL);
105 return ind->type;
109 * Accessor for array _industry_specs.
110 * This will ensure at once : proper access and
111 * not allowing modifications of it.
112 * @param thistype of industry (which is the index in _industry_specs)
113 * @pre thistype < NUM_INDUSTRYTYPES
114 * @return a pointer to the corresponding industry spec
116 const IndustrySpec *GetIndustrySpec(IndustryType thistype)
118 assert(thistype < NUM_INDUSTRYTYPES);
119 return &_industry_specs[thistype];
123 * Accessor for array _industry_tile_specs.
124 * This will ensure at once : proper access and
125 * not allowing modifications of it.
126 * @param gfx of industrytile (which is the index in _industry_tile_specs)
127 * @pre gfx < INVALID_INDUSTRYTILE
128 * @return a pointer to the corresponding industrytile spec
130 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx)
132 assert(gfx < INVALID_INDUSTRYTILE);
133 return &_industry_tile_specs[gfx];
136 Industry::~Industry()
138 if (CleaningPool()) return;
140 /* Industry can also be destroyed when not fully initialized.
141 * This means that we do not have to clear tiles either.
142 * Also we must not decrement industry counts in that case. */
143 if (this->location.w == 0) return;
145 TILE_AREA_LOOP(tile_cur, this->location) {
146 if (IsTileType(tile_cur, MP_INDUSTRY)) {
147 if (GetIndustryIndex(tile_cur) == this->index) {
148 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES, tile_cur);
150 /* MakeWaterKeepingClass() can also handle 'land' */
151 MakeWaterKeepingClass(tile_cur, OWNER_NONE);
153 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
154 DeleteOilRig(tile_cur);
158 if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) {
159 TileArea ta(this->location.tile - TileDiffXY(min(TileX(this->location.tile), 21), min(TileY(this->location.tile), 21)), 42, 42);
160 ta.ClampToMap();
162 /* Remove the farmland and convert it to regular tiles over time. */
163 TILE_AREA_LOOP(tile_cur, ta) {
164 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) &&
165 GetIndustryIndexOfField(tile_cur) == this->index) {
166 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY);
171 /* don't let any disaster vehicle target invalid industry */
172 ReleaseDisastersTargetingIndustry(this->index);
174 /* Clear the persistent storage. */
175 delete this->psa;
177 DecIndustryTypeCount(this->type);
179 DeleteIndustryNews(this->index);
180 DeleteWindowById(WC_INDUSTRY_VIEW, this->index);
181 DeleteNewGRFInspectWindow(GSF_INDUSTRIES, this->index);
183 DeleteSubsidyWith(ST_INDUSTRY, this->index);
184 CargoPacket::InvalidateAllFrom(ST_INDUSTRY, this->index);
188 * Invalidating some stuff after removing item from the pool.
189 * @param index index of deleted item
191 void Industry::PostDestructor(size_t index)
193 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
194 Station::RecomputeIndustriesNearForAll();
199 * Return a random valid industry.
200 * @return random industry, NULL if there are no industries
202 /* static */ Industry *Industry::GetRandom()
204 if (Industry::GetNumItems() == 0) return NULL;
205 int num = RandomRange((uint16)Industry::GetNumItems());
206 size_t index = MAX_UVALUE(size_t);
208 while (num >= 0) {
209 num--;
210 index++;
212 /* Make sure we have a valid industry */
213 while (!Industry::IsValidID(index)) {
214 index++;
215 assert(index < Industry::GetPoolSize());
219 return Industry::Get(index);
223 static void IndustryDrawSugarMine(const TileInfo *ti)
225 if (!IsIndustryCompleted(ti->tile)) return;
227 const DrawIndustryAnimationStruct *d = &_draw_industry_spec1[GetAnimationFrame(ti->tile)];
229 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_SIEVE + d->image_1, PAL_NONE, d->x, 0);
231 if (d->image_2 != 0) {
232 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_CLOUDS + d->image_2 - 1, PAL_NONE, 8, 41);
235 if (d->image_3 != 0) {
236 AddChildSpriteScreen(SPR_IT_SUGAR_MINE_PILE + d->image_3 - 1, PAL_NONE,
237 _drawtile_proc1[d->image_3 - 1].x, _drawtile_proc1[d->image_3 - 1].y);
241 static void IndustryDrawToffeeQuarry(const TileInfo *ti)
243 uint8 x = 0;
245 if (IsIndustryCompleted(ti->tile)) {
246 x = _industry_anim_offs_toffee[GetAnimationFrame(ti->tile)];
247 if (x == 0xFF) {
248 x = 0;
252 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_SHOVEL, PAL_NONE, 22 - x, 24 + x);
253 AddChildSpriteScreen(SPR_IT_TOFFEE_QUARRY_TOFFEE, PAL_NONE, 6, 14);
256 static void IndustryDrawBubbleGenerator( const TileInfo *ti)
258 if (IsIndustryCompleted(ti->tile)) {
259 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_BUBBLE, PAL_NONE, 5, _industry_anim_offs_bubbles[GetAnimationFrame(ti->tile)]);
261 AddChildSpriteScreen(SPR_IT_BUBBLE_GENERATOR_SPRING, PAL_NONE, 3, 67);
264 static void IndustryDrawToyFactory(const TileInfo *ti)
266 const DrawIndustryAnimationStruct *d = &_industry_anim_offs_toys[GetAnimationFrame(ti->tile)];
268 if (d->image_1 != 0xFF) {
269 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_CLAY, PAL_NONE, d->x, 96 + d->image_1);
272 if (d->image_2 != 0xFF) {
273 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_ROBOT, PAL_NONE, 16 - d->image_2 * 2, 100 + d->image_2);
276 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP, PAL_NONE, 7, d->image_3);
277 AddChildSpriteScreen(SPR_IT_TOY_FACTORY_STAMP_HOLDER, PAL_NONE, 0, 42);
280 static void IndustryDrawCoalPlantSparks(const TileInfo *ti)
282 if (IsIndustryCompleted(ti->tile)) {
283 uint8 image = GetAnimationFrame(ti->tile);
285 if (image != 0 && image < 7) {
286 AddChildSpriteScreen(image + SPR_IT_POWER_PLANT_TRANSFORMERS,
287 PAL_NONE,
288 _coal_plant_sparks[image - 1].x,
289 _coal_plant_sparks[image - 1].y
295 typedef void IndustryDrawTileProc(const TileInfo *ti);
296 static IndustryDrawTileProc * const _industry_draw_tile_procs[5] = {
297 IndustryDrawSugarMine,
298 IndustryDrawToffeeQuarry,
299 IndustryDrawBubbleGenerator,
300 IndustryDrawToyFactory,
301 IndustryDrawCoalPlantSparks,
304 static void DrawTile_Industry(TileInfo *ti)
306 IndustryGfx gfx = GetIndustryGfx(ti->tile);
307 Industry *ind = Industry::GetByTile(ti->tile);
308 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
310 /* Retrieve pointer to the draw industry tile struct */
311 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
312 /* Draw the tile using the specialized method of newgrf industrytile.
313 * DrawNewIndustry will return false if ever the resolver could not
314 * find any sprite to display. So in this case, we will jump on the
315 * substitute gfx instead. */
316 if (indts->grf_prop.spritegroup[0] != NULL && DrawNewIndustryTile(ti, ind, gfx, indts)) {
317 return;
318 } else {
319 /* No sprite group (or no valid one) found, meaning no graphics associated.
320 * Use the substitute one instead */
321 if (indts->grf_prop.subst_id != INVALID_INDUSTRYTILE) {
322 gfx = indts->grf_prop.subst_id;
323 /* And point the industrytile spec accordingly */
324 indts = GetIndustryTileSpec(gfx);
329 const DrawBuildingsTileStruct *dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
330 GetAnimationFrame(ti->tile) & INDUSTRY_COMPLETED :
331 GetIndustryConstructionStage(ti->tile))];
333 SpriteID image = dits->ground.sprite;
335 /* DrawFoundation() modifies ti->z and ti->tileh */
336 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
338 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
339 * Do not do this if the tile's WaterClass is 'land'. */
340 if (image == SPR_FLAT_WATER_TILE && IsTileOnWater(ti->tile)) {
341 DrawWaterClassGround(ti);
342 } else {
343 DrawGroundSprite(image, GroundSpritePaletteTransform(image, dits->ground.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)));
346 /* If industries are transparent and invisible, do not draw the upper part */
347 if (IsInvisibilitySet(TO_INDUSTRIES)) return;
349 /* Add industry on top of the ground? */
350 image = dits->building.sprite;
351 if (image != 0) {
352 AddSortableSpriteToDraw(image, SpriteLayoutPaletteTransform(image, dits->building.pal, GENERAL_SPRITE_COLOUR(ind->random_colour)),
353 ti->x + dits->subtile_x,
354 ti->y + dits->subtile_y,
355 dits->width,
356 dits->height,
357 dits->dz,
358 ti->z,
359 IsTransparencySet(TO_INDUSTRIES));
361 if (IsTransparencySet(TO_INDUSTRIES)) return;
365 int proc = dits->draw_proc - 1;
366 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
370 static int GetSlopePixelZ_Industry(TileIndex tile, uint x, uint y)
372 return GetTileMaxPixelZ(tile);
375 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
377 IndustryGfx gfx = GetIndustryGfx(tile);
379 /* For NewGRF industry tiles we might not be drawing a foundation. We need to
380 * account for this, as other structures should
381 * draw the wall of the foundation in this case.
383 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
384 const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
385 if (indts->grf_prop.spritegroup[0] != NULL && HasBit(indts->callback_mask, CBM_INDT_DRAW_FOUNDATIONS)) {
386 uint32 callback_res = GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS, 0, 0, gfx, Industry::GetByTile(tile), tile);
387 if (callback_res != CALLBACK_FAILED && !ConvertBooleanCallback(indts->grf_prop.grffile, CBID_INDTILE_DRAW_FOUNDATIONS, callback_res)) return FOUNDATION_NONE;
390 return FlatteningFoundation(tileh);
393 static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *always_accepted)
395 IndustryGfx gfx = GetIndustryGfx(tile);
396 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
398 /* When we have to use a callback, we put our data in the next two variables */
399 CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)];
400 uint8 raw_cargo_acceptance[lengthof(itspec->acceptance)];
402 /* And then these will always point to a same sized array with the required data */
403 const CargoID *accepts_cargo = itspec->accepts_cargo;
404 const uint8 *cargo_acceptance = itspec->acceptance;
406 if (HasBit(itspec->callback_mask, CBM_INDT_ACCEPT_CARGO)) {
407 uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, Industry::GetByTile(tile), tile);
408 if (res != CALLBACK_FAILED) {
409 accepts_cargo = raw_accepts_cargo;
410 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
414 if (HasBit(itspec->callback_mask, CBM_INDT_CARGO_ACCEPTANCE)) {
415 uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, Industry::GetByTile(tile), tile);
416 if (res != CALLBACK_FAILED) {
417 cargo_acceptance = raw_cargo_acceptance;
418 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_cargo_acceptance[i] = GB(res, i * 4, 4);
422 const Industry *ind = Industry::GetByTile(tile);
423 for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
424 CargoID a = accepts_cargo[i];
425 if (a == CT_INVALID || cargo_acceptance[i] == 0) continue; // work only with valid cargoes
427 /* Add accepted cargo */
428 acceptance[a] += cargo_acceptance[i];
430 /* Maybe set 'always accepted' bit (if it's not set already) */
431 if (HasBit(*always_accepted, a)) continue;
433 bool accepts = false;
434 for (uint cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
435 /* Test whether the industry itself accepts the cargo type */
436 if (ind->accepts_cargo[cargo_index] == a) {
437 accepts = true;
438 break;
442 if (accepts) continue;
444 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
445 SetBit(*always_accepted, a);
449 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
451 const Industry *i = Industry::GetByTile(tile);
452 const IndustrySpec *is = GetIndustrySpec(i->type);
454 td->owner[0] = i->owner;
455 td->str = is->name;
456 if (!IsIndustryCompleted(tile)) {
457 SetDParamX(td->dparam, 0, td->str);
458 td->str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
461 if (is->grf_prop.grffile != NULL) {
462 td->grf = GetGRFConfig(is->grf_prop.grffile->grfid)->GetName();
466 static CommandCost ClearTile_Industry(TileIndex tile, DoCommandFlag flags)
468 Industry *i = Industry::GetByTile(tile);
469 const IndustrySpec *indspec = GetIndustrySpec(i->type);
471 /* water can destroy industries
472 * in editor you can bulldoze industries
473 * with magic_bulldozer cheat you can destroy industries
474 * (area around OILRIG is water, so water shouldn't flood it
476 if ((_current_company != OWNER_WATER && _game_mode != GM_EDITOR &&
477 !_cheats.magic_bulldozer.value) ||
478 ((flags & DC_AUTO) != 0) ||
479 (_current_company == OWNER_WATER &&
480 ((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) ||
481 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile))->slopes_refused, 5)))) {
482 SetDParam(1, indspec->name);
483 return_cmd_error(flags & DC_AUTO ? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY : INVALID_STRING_ID);
486 if (flags & DC_EXEC) {
487 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
488 Game::NewEvent(new ScriptEventIndustryClose(i->index));
489 delete i;
491 return CommandCost(EXPENSES_CONSTRUCTION, indspec->GetRemovalCost());
495 * Move produced cargo from industry to nearby stations.
496 * @param tile Industry tile
497 * @return true if any cargo was moved.
499 static bool TransportIndustryGoods(TileIndex tile)
501 Industry *i = Industry::GetByTile(tile);
502 const IndustrySpec *indspec = GetIndustrySpec(i->type);
503 bool moved_cargo = false;
505 StationFinder stations(i->location);
507 for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) {
508 uint cw = min(i->produced_cargo_waiting[j], 255);
509 if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) {
510 i->produced_cargo_waiting[j] -= cw;
512 /* fluctuating economy? */
513 if (EconomyIsInRecession()) cw = (cw + 1) / 2;
515 i->this_month_production[j] += cw;
517 uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations());
518 i->this_month_transported[j] += am;
520 moved_cargo |= (am != 0);
524 return moved_cargo;
528 static void AnimateTile_Industry(TileIndex tile)
530 IndustryGfx gfx = GetIndustryGfx(tile);
532 if (GetIndustryTileSpec(gfx)->animation.status != ANIM_STATUS_NO_ANIMATION) {
533 AnimateNewIndustryTile(tile);
534 return;
537 switch (gfx) {
538 case GFX_SUGAR_MINE_SIEVE:
539 if ((_tick_counter & 1) == 0) {
540 byte m = GetAnimationFrame(tile) + 1;
542 if (_settings_client.sound.ambient) {
543 switch (m & 7) {
544 case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
545 case 6: SndPlayTileFx(SND_29_RIP, tile); break;
549 if (m >= 96) {
550 m = 0;
551 DeleteAnimatedTile(tile);
553 SetAnimationFrame(tile, m);
555 MarkTileDirtyByTile(tile);
557 break;
559 case GFX_TOFFEE_QUARY:
560 if ((_tick_counter & 3) == 0) {
561 byte m = GetAnimationFrame(tile);
563 if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
564 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
567 if (++m >= 70) {
568 m = 0;
569 DeleteAnimatedTile(tile);
571 SetAnimationFrame(tile, m);
573 MarkTileDirtyByTile(tile);
575 break;
577 case GFX_BUBBLE_CATCHER:
578 if ((_tick_counter & 1) == 0) {
579 byte m = GetAnimationFrame(tile);
581 if (++m >= 40) {
582 m = 0;
583 DeleteAnimatedTile(tile);
585 SetAnimationFrame(tile, m);
587 MarkTileDirtyByTile(tile);
589 break;
591 /* Sparks on a coal plant */
592 case GFX_POWERPLANT_SPARKS:
593 if ((_tick_counter & 3) == 0) {
594 byte m = GetAnimationFrame(tile);
595 if (m == 6) {
596 SetAnimationFrame(tile, 0);
597 DeleteAnimatedTile(tile);
598 } else {
599 SetAnimationFrame(tile, m + 1);
600 MarkTileDirtyByTile(tile);
603 break;
605 case GFX_TOY_FACTORY:
606 if ((_tick_counter & 1) == 0) {
607 byte m = GetAnimationFrame(tile) + 1;
609 switch (m) {
610 case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
611 case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
612 case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
613 default:
614 if (m >= 50) {
615 int n = GetIndustryAnimationLoop(tile) + 1;
616 m = 0;
617 if (n >= 8) {
618 n = 0;
619 DeleteAnimatedTile(tile);
621 SetIndustryAnimationLoop(tile, n);
625 SetAnimationFrame(tile, m);
626 MarkTileDirtyByTile(tile);
628 break;
630 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
631 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
632 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
633 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
634 if ((_tick_counter & 3) == 0) {
635 IndustryGfx gfx = GetIndustryGfx(tile);
637 gfx = (gfx < 155) ? gfx + 1 : 148;
638 SetIndustryGfx(tile, gfx);
639 MarkTileDirtyByTile(tile);
641 break;
643 case GFX_OILWELL_ANIMATED_1:
644 case GFX_OILWELL_ANIMATED_2:
645 case GFX_OILWELL_ANIMATED_3:
646 if ((_tick_counter & 7) == 0) {
647 bool b = Chance16(1, 7);
648 IndustryGfx gfx = GetIndustryGfx(tile);
650 byte m = GetAnimationFrame(tile) + 1;
651 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
652 SetIndustryGfx(tile, GFX_OILWELL_NOT_ANIMATED);
653 SetIndustryConstructionStage(tile, 3);
654 DeleteAnimatedTile(tile);
655 } else {
656 SetAnimationFrame(tile, m);
657 SetIndustryGfx(tile, gfx);
658 MarkTileDirtyByTile(tile);
661 break;
663 case GFX_COAL_MINE_TOWER_ANIMATED:
664 case GFX_COPPER_MINE_TOWER_ANIMATED:
665 case GFX_GOLD_MINE_TOWER_ANIMATED: {
666 int state = _tick_counter & 0x7FF;
668 if ((state -= 0x400) < 0) return;
670 if (state < 0x1A0) {
671 if (state < 0x20 || state >= 0x180) {
672 byte m = GetAnimationFrame(tile);
673 if (!(m & 0x40)) {
674 SetAnimationFrame(tile, m | 0x40);
675 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
677 if (state & 7) return;
678 } else {
679 if (state & 3) return;
681 byte m = (GetAnimationFrame(tile) + 1) | 0x40;
682 if (m > 0xC2) m = 0xC0;
683 SetAnimationFrame(tile, m);
684 MarkTileDirtyByTile(tile);
685 } else if (state >= 0x200 && state < 0x3A0) {
686 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
687 if (state & i) return;
689 byte m = (GetAnimationFrame(tile) & 0xBF) - 1;
690 if (m < 0x80) m = 0x82;
691 SetAnimationFrame(tile, m);
692 MarkTileDirtyByTile(tile);
694 break;
699 static void CreateChimneySmoke(TileIndex tile)
701 uint x = TileX(tile) * TILE_SIZE;
702 uint y = TileY(tile) * TILE_SIZE;
703 int z = GetTileMaxPixelZ(tile);
705 CreateEffectVehicle(x + 15, y + 14, z + 59, EV_CHIMNEY_SMOKE);
708 static void MakeIndustryTileBigger(TileIndex tile)
710 byte cnt = GetIndustryConstructionCounter(tile) + 1;
711 if (cnt != 4) {
712 SetIndustryConstructionCounter(tile, cnt);
713 return;
716 byte stage = GetIndustryConstructionStage(tile) + 1;
717 SetIndustryConstructionCounter(tile, 0);
718 SetIndustryConstructionStage(tile, stage);
719 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
720 if (stage == INDUSTRY_COMPLETED) SetIndustryCompleted(tile);
722 MarkTileDirtyByTile(tile);
724 if (!IsIndustryCompleted(tile)) return;
726 IndustryGfx gfx = GetIndustryGfx(tile);
727 if (gfx >= NEW_INDUSTRYTILEOFFSET) {
728 /* New industries are already animated on construction. */
729 return;
732 switch (gfx) {
733 case GFX_POWERPLANT_CHIMNEY:
734 CreateChimneySmoke(tile);
735 break;
737 case GFX_OILRIG_1: {
738 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
739 * tiles (like the default oil rig). Do a proper check to ensure the
740 * tiles belong to the same industry and based on that build the oil rig's
741 * station. */
742 TileIndex other = tile + TileDiffXY(0, 1);
744 if (IsTileType(other, MP_INDUSTRY) &&
745 GetIndustryGfx(other) == GFX_OILRIG_1 &&
746 GetIndustryIndex(tile) == GetIndustryIndex(other)) {
747 BuildOilRig(tile);
749 break;
752 case GFX_TOY_FACTORY:
753 case GFX_BUBBLE_CATCHER:
754 case GFX_TOFFEE_QUARY:
755 SetAnimationFrame(tile, 0);
756 SetIndustryAnimationLoop(tile, 0);
757 break;
759 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
760 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
761 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
762 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
763 AddAnimatedTile(tile);
764 break;
768 static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
770 static const int8 _bubble_spawn_location[3][4] = {
771 { 11, 0, -4, -14 },
772 { -4, -10, -4, 1 },
773 { 49, 59, 60, 65 },
776 if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
778 int dir = Random() & 3;
780 EffectVehicle *v = CreateEffectVehicleAbove(
781 TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir],
782 TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir],
783 _bubble_spawn_location[2][dir],
784 EV_BUBBLE
787 if (v != NULL) v->animation_substate = dir;
790 static void TileLoop_Industry(TileIndex tile)
792 if (IsTileOnWater(tile)) TileLoop_Water(tile);
794 /* Normally this doesn't happen, but if an industry NewGRF is removed
795 * an industry that was previously build on water can now be flooded.
796 * If this happens the tile is no longer an industry tile after
797 * returning from TileLoop_Water. */
798 if (!IsTileType(tile, MP_INDUSTRY)) return;
800 TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
802 if (!IsIndustryCompleted(tile)) {
803 MakeIndustryTileBigger(tile);
804 return;
807 if (_game_mode == GM_EDITOR) return;
809 if (TransportIndustryGoods(tile) && !StartStopIndustryTileAnimation(Industry::GetByTile(tile), IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
810 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
812 if (newgfx != INDUSTRYTILE_NOANIM) {
813 ResetIndustryConstructionStage(tile);
814 SetIndustryCompleted(tile);
815 SetIndustryGfx(tile, newgfx);
816 MarkTileDirtyByTile(tile);
817 return;
821 if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
823 IndustryGfx newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
824 if (newgfx != INDUSTRYTILE_NOANIM) {
825 ResetIndustryConstructionStage(tile);
826 SetIndustryGfx(tile, newgfx);
827 MarkTileDirtyByTile(tile);
828 return;
831 IndustryGfx gfx = GetIndustryGfx(tile);
832 switch (gfx) {
833 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
834 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
835 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
836 if (!(_tick_counter & 0x400) && Chance16(1, 2)) {
837 switch (gfx) {
838 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED; break;
839 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED; break;
840 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED; break;
842 SetIndustryGfx(tile, gfx);
843 SetAnimationFrame(tile, 0x80);
844 AddAnimatedTile(tile);
846 break;
848 case GFX_OILWELL_NOT_ANIMATED:
849 if (Chance16(1, 6)) {
850 SetIndustryGfx(tile, GFX_OILWELL_ANIMATED_1);
851 SetAnimationFrame(tile, 0);
852 AddAnimatedTile(tile);
854 break;
856 case GFX_COAL_MINE_TOWER_ANIMATED:
857 case GFX_COPPER_MINE_TOWER_ANIMATED:
858 case GFX_GOLD_MINE_TOWER_ANIMATED:
859 if (!(_tick_counter & 0x400)) {
860 switch (gfx) {
861 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED; break;
862 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED; break;
863 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED; break;
865 SetIndustryGfx(tile, gfx);
866 SetIndustryCompleted(tile);
867 SetIndustryConstructionStage(tile, 3);
868 DeleteAnimatedTile(tile);
870 break;
872 case GFX_POWERPLANT_SPARKS:
873 if (Chance16(1, 3)) {
874 if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
875 AddAnimatedTile(tile);
877 break;
879 case GFX_COPPER_MINE_CHIMNEY:
880 CreateEffectVehicleAbove(TileX(tile) * TILE_SIZE + 6, TileY(tile) * TILE_SIZE + 6, 43, EV_COPPER_MINE_SMOKE);
881 break;
884 case GFX_TOY_FACTORY: {
885 Industry *i = Industry::GetByTile(tile);
886 if (i->was_cargo_delivered) {
887 i->was_cargo_delivered = false;
888 SetIndustryAnimationLoop(tile, 0);
889 AddAnimatedTile(tile);
892 break;
894 case GFX_BUBBLE_GENERATOR:
895 TileLoopIndustry_BubbleGenerator(tile);
896 break;
898 case GFX_TOFFEE_QUARY:
899 AddAnimatedTile(tile);
900 break;
902 case GFX_SUGAR_MINE_SIEVE:
903 if (Chance16(1, 3)) AddAnimatedTile(tile);
904 break;
908 static bool ClickTile_Industry(TileIndex tile)
910 ShowIndustryViewWindow(GetIndustryIndex(tile));
911 return true;
914 static TrackStatus GetTileTrackStatus_Industry(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
916 return 0;
919 static void ChangeTileOwner_Industry(TileIndex tile, Owner old_owner, Owner new_owner)
921 /* If the founder merges, the industry was created by the merged company */
922 Industry *i = Industry::GetByTile(tile);
923 if (i->founder == old_owner) i->founder = (new_owner == INVALID_OWNER) ? OWNER_NONE : new_owner;
927 * Check whether the tile is a forest.
928 * @param tile the tile to investigate.
929 * @return true if and only if the tile is a forest
931 bool IsTileForestIndustry(TileIndex tile)
933 /* Check for industry tile */
934 if (!IsTileType(tile, MP_INDUSTRY)) return false;
936 const Industry *ind = Industry::GetByTile(tile);
938 /* Check for organic industry (i.e. not processing or extractive) */
939 if ((GetIndustrySpec(ind->type)->life_type & INDUSTRYLIFE_ORGANIC) == 0) return false;
941 /* Check for wood production */
942 for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
943 /* The industry produces wood. */
944 if (ind->produced_cargo[i] != CT_INVALID && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
947 return false;
950 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
953 * Check whether the tile can be replaced by a farm field.
954 * @param tile the tile to investigate.
955 * @param allow_fields if true, the method will return true even if
956 * the tile is a farm tile, otherwise the tile may not be a farm tile
957 * @return true if the tile can become a farm field
959 static bool IsSuitableForFarmField(TileIndex tile, bool allow_fields)
961 switch (GetTileType(tile)) {
962 case MP_CLEAR: return !IsClearGround(tile, CLEAR_SNOW) && !IsClearGround(tile, CLEAR_DESERT) && (allow_fields || !IsClearGround(tile, CLEAR_FIELDS));
963 case MP_TREES: return GetTreeGround(tile) != TREE_GROUND_SHORE;
964 default: return false;
969 * Build farm field fence
970 * @param tile the tile to position the fence on
971 * @param size the size of the field being planted in tiles
972 * @param type type of fence to set
973 * @param side the side of the tile to attempt placement
975 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, DiagDirection side)
977 TileIndexDiff diff = (DiagDirToAxis(side) == AXIS_Y ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
979 do {
980 tile = TILE_MASK(tile);
982 if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) {
983 byte or_ = type;
985 if (or_ == 1 && Chance16(1, 7)) or_ = 2;
987 SetFence(tile, side, or_);
990 tile += diff;
991 } while (--size);
994 static void PlantFarmField(TileIndex tile, IndustryID industry)
996 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
997 if (GetTileZ(tile) + 2 >= GetSnowLine()) return;
1000 /* determine field size */
1001 uint32 r = (Random() & 0x303) + 0x404;
1002 if (_settings_game.game_creation.landscape == LT_ARCTIC) r += 0x404;
1003 uint size_x = GB(r, 0, 8);
1004 uint size_y = GB(r, 8, 8);
1006 TileArea ta(tile - TileDiffXY(min(TileX(tile), size_x / 2), min(TileY(tile), size_y / 2)), size_x, size_y);
1007 ta.ClampToMap();
1009 if (ta.w == 0 || ta.h == 0) return;
1011 /* check the amount of bad tiles */
1012 int count = 0;
1013 TILE_AREA_LOOP(cur_tile, ta) {
1014 assert(cur_tile < MapSize());
1015 count += IsSuitableForFarmField(cur_tile, false);
1017 if (count * 2 < ta.w * ta.h) return;
1019 /* determine type of field */
1020 r = Random();
1021 uint counter = GB(r, 5, 3);
1022 uint field_type = GB(r, 8, 8) * 9 >> 8;
1024 /* make field */
1025 TILE_AREA_LOOP(cur_tile, ta) {
1026 assert(cur_tile < MapSize());
1027 if (IsSuitableForFarmField(cur_tile, true)) {
1028 MakeField(cur_tile, field_type, industry);
1029 SetClearCounter(cur_tile, counter);
1030 MarkTileDirtyByTile(cur_tile);
1034 int type = 3;
1035 if (_settings_game.game_creation.landscape != LT_ARCTIC && _settings_game.game_creation.landscape != LT_TROPIC) {
1036 type = _plantfarmfield_type[Random() & 0xF];
1039 SetupFarmFieldFence(ta.tile, ta.h, type, DIAGDIR_NE);
1040 SetupFarmFieldFence(ta.tile, ta.w, type, DIAGDIR_NW);
1041 SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, DIAGDIR_SW);
1042 SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, DIAGDIR_SE);
1045 void PlantRandomFarmField(const Industry *i)
1047 int x = i->location.w / 2 + Random() % 31 - 16;
1048 int y = i->location.h / 2 + Random() % 31 - 16;
1050 TileIndex tile = TileAddWrap(i->location.tile, x, y);
1052 if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
1056 * Search callback function for ChopLumberMillTrees
1057 * @param tile to test
1058 * @param user_data that is passed by the caller. In this case, nothing
1059 * @return the result of the test
1061 static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
1063 if (IsTileType(tile, MP_TREES) && GetTreeGrowth(tile) > 2) { ///< 3 and up means all fully grown trees
1064 /* found a tree */
1066 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
1068 _industry_sound_ctr = 1;
1069 _industry_sound_tile = tile;
1070 if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
1072 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1074 cur_company.Restore();
1075 return true;
1077 return false;
1081 * Perform a circular search around the Lumber Mill in order to find trees to cut
1082 * @param i industry
1084 static void ChopLumberMillTrees(Industry *i)
1086 /* We only want to cut trees if all tiles are completed. */
1087 TILE_AREA_LOOP(tile_cur, i->location) {
1088 if (i->TileBelongsToIndustry(tile_cur)) {
1089 if (!IsIndustryCompleted(tile_cur)) return;
1093 TileIndex tile = i->location.tile;
1094 if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, NULL)) { // 40x40 tiles to search.
1095 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); // Found a tree, add according value to waiting cargo.
1099 static void ProduceIndustryGoods(Industry *i)
1101 const IndustrySpec *indsp = GetIndustrySpec(i->type);
1103 /* play a sound? */
1104 if ((i->counter & 0x3F) == 0) {
1105 uint32 r;
1106 uint num;
1107 if (Chance16R(1, 14, r) && (num = indsp->number_of_sounds) != 0 && _settings_client.sound.ambient) {
1108 SndPlayTileFx(
1109 (SoundFx)(indsp->random_sounds[((r >> 16) * num) >> 16]),
1110 i->location.tile);
1114 i->counter--;
1116 /* produce some cargo */
1117 if ((i->counter % INDUSTRY_PRODUCE_TICKS) == 0) {
1118 if (HasBit(indsp->callback_mask, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
1120 IndustryBehaviour indbehav = indsp->behaviour;
1121 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
1122 i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
1124 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1125 uint16 cb_res = CALLBACK_FAILED;
1126 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1127 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->location.tile);
1130 bool plant;
1131 if (cb_res != CALLBACK_FAILED) {
1132 plant = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1133 } else {
1134 plant = Chance16(1, 8);
1137 if (plant) PlantRandomFarmField(i);
1139 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
1140 uint16 cb_res = CALLBACK_FAILED;
1141 if (HasBit(indsp->callback_mask, CBM_IND_SPECIAL_EFFECT)) {
1142 cb_res = GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 1, i, i->type, i->location.tile);
1145 bool cut;
1146 if (cb_res != CALLBACK_FAILED) {
1147 cut = ConvertBooleanCallback(indsp->grf_prop.grffile, CBID_INDUSTRY_SPECIAL_EFFECT, cb_res);
1148 } else {
1149 cut = ((i->counter % INDUSTRY_CUT_TREE_TICKS) == 0);
1152 if (cut) ChopLumberMillTrees(i);
1155 TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
1156 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
1160 void OnTick_Industry()
1162 if (_industry_sound_ctr != 0) {
1163 _industry_sound_ctr++;
1165 if (_industry_sound_ctr == 75) {
1166 if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
1167 } else if (_industry_sound_ctr == 160) {
1168 _industry_sound_ctr = 0;
1169 if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
1173 if (_game_mode == GM_EDITOR) return;
1175 Industry *i;
1176 FOR_ALL_INDUSTRIES(i) {
1177 ProduceIndustryGoods(i);
1182 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1183 * @param tile %Tile to perform the checking.
1184 * @return Succeeded or failed command.
1186 static CommandCost CheckNewIndustry_NULL(TileIndex tile)
1188 return CommandCost();
1192 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1193 * @param tile %Tile to perform the checking.
1194 * @return Succeeded or failed command.
1196 static CommandCost CheckNewIndustry_Forest(TileIndex tile)
1198 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1199 if (GetTileZ(tile) < HighestSnowLine() + 2) {
1200 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED);
1203 return CommandCost();
1207 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1208 * @param tile %Tile to perform the checking.
1209 * @return Succeeded or failed command.
1211 static CommandCost CheckNewIndustry_OilRefinery(TileIndex tile)
1213 if (_game_mode == GM_EDITOR) return CommandCost();
1214 if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1216 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1219 extern bool _ignore_restrictions;
1222 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1223 * @param tile %Tile to perform the checking.
1224 * @return Succeeded or failed command.
1226 static CommandCost CheckNewIndustry_OilRig(TileIndex tile)
1228 if (_game_mode == GM_EDITOR && _ignore_restrictions) return CommandCost();
1229 if (TileHeight(tile) == 0 &&
1230 DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings_game.game_creation.oil_refinery_limit) return CommandCost();
1232 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED);
1236 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1237 * @param tile %Tile to perform the checking.
1238 * @return Succeeded or failed command.
1240 static CommandCost CheckNewIndustry_Farm(TileIndex tile)
1242 if (_settings_game.game_creation.landscape == LT_ARCTIC) {
1243 if (GetTileZ(tile) + 2 >= HighestSnowLine()) {
1244 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1247 return CommandCost();
1251 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1252 * @param tile %Tile to perform the checking.
1253 * @return Succeeded or failed command.
1255 static CommandCost CheckNewIndustry_Plantation(TileIndex tile)
1257 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
1258 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1260 return CommandCost();
1264 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1265 * @param tile %Tile to perform the checking.
1266 * @return Succeeded or failed command.
1268 static CommandCost CheckNewIndustry_Water(TileIndex tile)
1270 if (GetTropicZone(tile) != TROPICZONE_DESERT) {
1271 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT);
1273 return CommandCost();
1277 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1278 * @param tile %Tile to perform the checking.
1279 * @return Succeeded or failed command.
1281 static CommandCost CheckNewIndustry_Lumbermill(TileIndex tile)
1283 if (GetTropicZone(tile) != TROPICZONE_RAINFOREST) {
1284 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST);
1286 return CommandCost();
1290 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1291 * @param tile %Tile to perform the checking.
1292 * @return Succeeded or failed command.
1294 static CommandCost CheckNewIndustry_BubbleGen(TileIndex tile)
1296 if (GetTileZ(tile) > 4) {
1297 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS);
1299 return CommandCost();
1303 * Industrytype check function signature.
1304 * @param tile %Tile to check.
1305 * @return Succeeded or failed command.
1307 typedef CommandCost CheckNewIndustryProc(TileIndex tile);
1309 /** Check functions for different types of industry. */
1310 static CheckNewIndustryProc * const _check_new_industry_procs[CHECK_END] = {
1311 CheckNewIndustry_NULL, ///< CHECK_NOTHING
1312 CheckNewIndustry_Forest, ///< CHECK_FOREST
1313 CheckNewIndustry_OilRefinery, ///< CHECK_REFINERY
1314 CheckNewIndustry_Farm, ///< CHECK_FARM
1315 CheckNewIndustry_Plantation, ///< CHECK_PLANTATION
1316 CheckNewIndustry_Water, ///< CHECK_WATER
1317 CheckNewIndustry_Lumbermill, ///< CHECK_LUMBERMILL
1318 CheckNewIndustry_BubbleGen, ///< CHECK_BUBBLEGEN
1319 CheckNewIndustry_OilRig, ///< CHECK_OIL_RIG
1323 * Find a town for the industry, while checking for multiple industries in the same town.
1324 * @param tile Position of the industry to build.
1325 * @param type Industry type.
1326 * @param [out] town Pointer to return town for the new industry, \c NULL is written if no good town can be found.
1327 * @return Succeeded or failed command.
1329 * @pre \c *t != NULL
1330 * @post \c *t points to a town on success, and \c NULL on failure.
1332 static CommandCost FindTownForIndustry(TileIndex tile, int type, Town **t)
1334 *t = ClosestTownFromTile(tile, UINT_MAX);
1336 if (_settings_game.economy.multiple_industry_per_town) return CommandCost();
1338 const Industry *i;
1339 FOR_ALL_INDUSTRIES(i) {
1340 if (i->type == (byte)type && i->town == *t) {
1341 *t = NULL;
1342 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN);
1346 return CommandCost();
1349 bool IsSlopeRefused(Slope current, Slope refused)
1351 if (IsSteepSlope(current)) return true;
1352 if (current != SLOPE_FLAT) {
1353 if (IsSteepSlope(refused)) return true;
1355 Slope t = ComplementSlope(current);
1357 if ((refused & SLOPE_W) && (t & SLOPE_NW)) return true;
1358 if ((refused & SLOPE_S) && (t & SLOPE_NE)) return true;
1359 if ((refused & SLOPE_E) && (t & SLOPE_SW)) return true;
1360 if ((refused & SLOPE_N) && (t & SLOPE_SE)) return true;
1363 return false;
1367 * Are the tiles of the industry free?
1368 * @param tile Position to check.
1369 * @param it Industry tiles table.
1370 * @param itspec_index The index of the itsepc to build/fund
1371 * @param type Type of the industry.
1372 * @param initial_random_bits The random bits the industry is going to have after construction.
1373 * @param founder Industry founder
1374 * @param creation_type The circumstances the industry is created under.
1375 * @param [out] custom_shape_check Perform custom check for the site.
1376 * @return Failed or succeeded command.
1378 static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, uint itspec_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = NULL)
1380 bool refused_slope = false;
1381 bool custom_shape = false;
1383 do {
1384 IndustryGfx gfx = GetTranslatedIndustryTileID(it->gfx);
1385 TileIndex cur_tile = TileAddWrap(tile, it->ti.x, it->ti.y);
1387 if (!IsValidTile(cur_tile)) {
1388 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1391 if (gfx == GFX_WATERTILE_SPECIALCHECK) {
1392 if (!IsWaterTile(cur_tile) ||
1393 !IsTileFlat(cur_tile)) {
1394 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1396 } else {
1397 CommandCost ret = EnsureNoVehicleOnGround(cur_tile);
1398 if (ret.Failed()) return ret;
1399 if (IsBridgeAbove(cur_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1401 const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
1403 IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
1405 /* Perform land/water check if not disabled */
1406 if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1408 if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
1409 custom_shape = true;
1410 CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index, initial_random_bits, founder, creation_type);
1411 if (ret.Failed()) return ret;
1412 } else {
1413 Slope tileh = GetTileSlope(cur_tile);
1414 refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
1417 if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
1418 ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
1419 if (!IsTileType(cur_tile, MP_HOUSE)) {
1420 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS);
1423 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1424 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1425 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
1426 cur_company.Restore();
1428 if (ret.Failed()) return ret;
1429 } else {
1430 /* Clear the tiles, but do not affect town ratings */
1431 CommandCost ret = DoCommand(cur_tile, 0, 0, DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1433 if (ret.Failed()) return ret;
1436 } while ((++it)->ti.x != -0x80);
1438 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1440 /* It is almost impossible to have a fully flat land in TG, so what we
1441 * do is that we check if we can make the land flat later on. See
1442 * CheckIfCanLevelIndustryPlatform(). */
1443 if (!refused_slope || (_settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions)) {
1444 return CommandCost();
1446 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1450 * Is the industry allowed to be built at this place for the town?
1451 * @param tile Tile to construct the industry.
1452 * @param type Type of the industry.
1453 * @param t Town authority that the industry belongs to.
1454 * @return Succeeded or failed command.
1456 static CommandCost CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
1458 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_TOWN1200_MORE) && t->cache.population < 1200) {
1459 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1462 if ((GetIndustrySpec(type)->behaviour & INDUSTRYBEH_ONLY_NEARTOWN) && DistanceMax(t->xy, tile) > 9) {
1463 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER);
1466 return CommandCost();
1469 static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
1471 /* Check if we don't leave the map */
1472 if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
1474 TileArea ta(tile - TileDiffXY(1, 1), 2, 2);
1475 TILE_AREA_LOOP(tile_walk, ta) {
1476 uint curh = TileHeight(tile_walk);
1477 /* Is the tile clear? */
1478 if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES)) return false;
1480 /* Don't allow too big of a change if this is the sub-tile check */
1481 if (internal != 0 && Delta(curh, height) > 1) return false;
1483 /* Different height, so the surrounding tiles of this tile
1484 * has to be correct too (in level, or almost in level)
1485 * else you get a chain-reaction of terraforming. */
1486 if (internal == 0 && curh != height) {
1487 if (TileX(tile_walk) == 0 || TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1)) {
1488 return false;
1493 return true;
1497 * This function tries to flatten out the land below an industry, without
1498 * damaging the surroundings too much.
1500 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, DoCommandFlag flags, const IndustryTileTable *it, int type)
1502 const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1503 int max_x = 0;
1504 int max_y = 0;
1506 /* Finds dimensions of largest variant of this industry */
1507 do {
1508 if (it->gfx == 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1509 if (it->ti.x > max_x) max_x = it->ti.x;
1510 if (it->ti.y > max_y) max_y = it->ti.y;
1511 } while ((++it)->ti.x != MKEND);
1513 /* Remember level height */
1514 uint h = TileHeight(tile);
1516 if (TileX(tile) <= _settings_game.construction.industry_platform + 1U || TileY(tile) <= _settings_game.construction.industry_platform + 1U) return false;
1517 /* Check that all tiles in area and surrounding are clear
1518 * this determines that there are no obstructing items */
1520 TileArea ta(tile + TileDiffXY(-_settings_game.construction.industry_platform, -_settings_game.construction.industry_platform),
1521 max_x + 2 + 2 * _settings_game.construction.industry_platform, max_y + 2 + 2 * _settings_game.construction.industry_platform);
1523 if (TileX(ta.tile) + ta.w >= MapMaxX() || TileY(ta.tile) + ta.h >= MapMaxY()) return false;
1525 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1526 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1527 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1529 TILE_AREA_LOOP(tile_walk, ta) {
1530 uint curh = TileHeight(tile_walk);
1531 if (curh != h) {
1532 /* This tile needs terraforming. Check if we can do that without
1533 * damaging the surroundings too much. */
1534 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1535 cur_company.Restore();
1536 return false;
1538 /* This is not 100% correct check, but the best we can do without modifying the map.
1539 * What is missing, is if the difference in height is more than 1.. */
1540 if (DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND).Failed()) {
1541 cur_company.Restore();
1542 return false;
1547 if (flags & DC_EXEC) {
1548 /* Terraform the land under the industry */
1549 TILE_AREA_LOOP(tile_walk, ta) {
1550 uint curh = TileHeight(tile_walk);
1551 while (curh != h) {
1552 /* We give the terraforming for free here, because we can't calculate
1553 * exact cost in the test-round, and as we all know, that will cause
1554 * a nice assert if they don't match ;) */
1555 DoCommand(tile_walk, SLOPE_N, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
1556 curh += (curh > h) ? -1 : 1;
1561 cur_company.Restore();
1562 return true;
1567 * Check that the new industry is far enough from conflicting industries.
1568 * @param tile Tile to construct the industry.
1569 * @param type Type of the new industry.
1570 * @return Succeeded or failed command.
1572 static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, int type)
1574 const IndustrySpec *indspec = GetIndustrySpec(type);
1575 const Industry *i = NULL;
1577 /* On a large map with many industries, it may be faster to check an area. */
1578 static const int dmax = 14;
1579 if (Industry::GetNumItems() > (size_t) (dmax * dmax * 2)) {
1580 const int tx = TileX(tile);
1581 const int ty = TileY(tile);
1582 TileArea tile_area = TileArea(TileXY(max(0, tx - dmax), max(0, ty - dmax)), TileXY(min(MapMaxX(), tx + dmax), min(MapMaxY(), ty + dmax)));
1583 TILE_AREA_LOOP(atile, tile_area) {
1584 if (GetTileType(atile) == MP_INDUSTRY) {
1585 const Industry *i2 = Industry::GetByTile(atile);
1586 if (i == i2) continue;
1587 i = i2;
1588 if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue;
1589 if (i->type == indspec->conflicting[0] ||
1590 i->type == indspec->conflicting[1] ||
1591 i->type == indspec->conflicting[2]) {
1592 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1596 return CommandCost();
1599 FOR_ALL_INDUSTRIES(i) {
1600 /* Within 14 tiles from another industry is considered close */
1601 if (DistanceMax(tile, i->location.tile) > 14) continue;
1603 /* check if there are any conflicting industry types around */
1604 if (i->type == indspec->conflicting[0] ||
1605 i->type == indspec->conflicting[1] ||
1606 i->type == indspec->conflicting[2]) {
1607 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE);
1610 return CommandCost();
1614 * Advertise about a new industry opening.
1615 * @param ind Industry being opened.
1617 static void AdvertiseIndustryOpening(const Industry *ind)
1619 const IndustrySpec *ind_spc = GetIndustrySpec(ind->type);
1620 SetDParam(0, ind_spc->name);
1621 if (ind_spc->new_industry_text > STR_LAST_STRINGID) {
1622 SetDParam(1, STR_TOWN_NAME);
1623 SetDParam(2, ind->town->index);
1624 } else {
1625 SetDParam(1, ind->town->index);
1627 AddIndustryNewsItem(ind_spc->new_industry_text, NT_INDUSTRY_OPEN, ind->index);
1628 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind->index));
1629 Game::NewEvent(new ScriptEventIndustryOpen(ind->index));
1633 * Put an industry on the map.
1634 * @param i Just allocated poolitem, mostly empty.
1635 * @param tile North tile of the industry.
1636 * @param type Type of the industry.
1637 * @param it Industrylayout to build.
1638 * @param layout Number of the layout.
1639 * @param t Nearest town.
1640 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1641 * @param initial_random_bits Random bits for the industry.
1643 static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, const IndustryTileTable *it, byte layout, Town *t, Owner founder, uint16 initial_random_bits)
1645 const IndustrySpec *indspec = GetIndustrySpec(type);
1647 i->location = TileArea(tile, 1, 1);
1648 i->type = type;
1649 Industry::IncIndustryTypeCount(type);
1651 i->produced_cargo[0] = indspec->produced_cargo[0];
1652 i->produced_cargo[1] = indspec->produced_cargo[1];
1653 i->accepts_cargo[0] = indspec->accepts_cargo[0];
1654 i->accepts_cargo[1] = indspec->accepts_cargo[1];
1655 i->accepts_cargo[2] = indspec->accepts_cargo[2];
1656 i->production_rate[0] = indspec->production_rate[0];
1657 i->production_rate[1] = indspec->production_rate[1];
1659 /* don't use smooth economy for industries using production related callbacks */
1660 if (indspec->UsesSmoothEconomy()) {
1661 i->production_rate[0] = min((RandomRange(256) + 128) * i->production_rate[0] >> 8, 255);
1662 i->production_rate[1] = min((RandomRange(256) + 128) * i->production_rate[1] >> 8, 255);
1665 i->town = t;
1666 i->owner = OWNER_NONE;
1668 uint16 r = Random();
1669 i->random_colour = GB(r, 0, 4);
1670 i->counter = GB(r, 4, 12);
1671 i->random = initial_random_bits;
1672 i->produced_cargo_waiting[0] = 0;
1673 i->produced_cargo_waiting[1] = 0;
1674 i->incoming_cargo_waiting[0] = 0;
1675 i->incoming_cargo_waiting[1] = 0;
1676 i->incoming_cargo_waiting[2] = 0;
1677 i->this_month_production[0] = 0;
1678 i->this_month_production[1] = 0;
1679 i->this_month_transported[0] = 0;
1680 i->this_month_transported[1] = 0;
1681 i->last_month_pct_transported[0] = 0;
1682 i->last_month_pct_transported[1] = 0;
1683 i->last_month_transported[0] = 0;
1684 i->last_month_transported[1] = 0;
1685 i->was_cargo_delivered = false;
1686 i->last_prod_year = _cur_year;
1687 i->founder = founder;
1689 i->construction_date = _date;
1690 i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
1691 (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
1693 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1694 * 0 = created prior of newindustries
1695 * else, chosen layout + 1 */
1696 i->selected_layout = layout + 1;
1698 i->prod_level = PRODLEVEL_DEFAULT;
1700 /* Call callbacks after the regular fields got initialised. */
1702 if (HasBit(indspec->callback_mask, CBM_IND_PROD_CHANGE_BUILD)) {
1703 uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD, 0, Random(), i, type, INVALID_TILE);
1704 if (res != CALLBACK_FAILED) {
1705 if (res < PRODLEVEL_MINIMUM || res > PRODLEVEL_MAXIMUM) {
1706 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROD_CHANGE_BUILD, res);
1707 } else {
1708 i->prod_level = res;
1709 i->RecomputeProductionMultipliers();
1714 if (_generating_world) {
1715 i->last_month_production[0] = i->production_rate[0] * 8;
1716 i->last_month_production[1] = i->production_rate[1] * 8;
1717 } else {
1718 i->last_month_production[0] = i->last_month_production[1] = 0;
1721 if (HasBit(indspec->callback_mask, CBM_IND_DECIDE_COLOUR)) {
1722 uint16 res = GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR, 0, 0, i, type, INVALID_TILE);
1723 if (res != CALLBACK_FAILED) {
1724 if (GB(res, 4, 11) != 0) ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_DECIDE_COLOUR, res);
1725 i->random_colour = GB(res, 0, 4);
1729 if (HasBit(indspec->callback_mask, CBM_IND_INPUT_CARGO_TYPES)) {
1730 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) i->accepts_cargo[j] = CT_INVALID;
1731 for (uint j = 0; j < lengthof(i->accepts_cargo); j++) {
1732 uint16 res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1733 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1734 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1735 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
1736 break;
1738 i->accepts_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1742 if (HasBit(indspec->callback_mask, CBM_IND_OUTPUT_CARGO_TYPES)) {
1743 for (uint j = 0; j < lengthof(i->produced_cargo); j++) i->produced_cargo[j] = CT_INVALID;
1744 for (uint j = 0; j < lengthof(i->produced_cargo); j++) {
1745 uint16 res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
1746 if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
1747 if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
1748 ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
1749 break;
1751 i->produced_cargo[j] = GetCargoTranslation(GB(res, 0, 8), indspec->grf_prop.grffile);
1755 /* Plant the tiles */
1757 do {
1758 TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
1760 if (it->gfx != GFX_WATERTILE_SPECIALCHECK) {
1761 i->location.Add(cur_tile);
1763 WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
1765 DoCommand(cur_tile, 0, 0, DC_EXEC | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, CMD_LANDSCAPE_CLEAR);
1767 MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
1769 if (_generating_world) {
1770 SetIndustryConstructionCounter(cur_tile, 3);
1771 SetIndustryConstructionStage(cur_tile, 2);
1774 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1775 IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
1776 const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
1777 if (its->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
1779 } while ((++it)->ti.x != -0x80);
1781 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) {
1782 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1784 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0);
1786 Station::RecomputeIndustriesNearForAll();
1790 * Helper function for Build/Fund an industry
1791 * @param tile tile where industry is built
1792 * @param type of industry to build
1793 * @param flags of operations to conduct
1794 * @param indspec pointer to industry specifications
1795 * @param itspec_index the index of the itsepc to build/fund
1796 * @param seed random seed (possibly) used by industries
1797 * @param initial_random_bits The random bits the industry is going to have after construction.
1798 * @param founder Founder of the industry
1799 * @param creation_type The circumstances the industry is created under.
1800 * @param [out] ip Pointer to store newly created industry.
1801 * @return Succeeded or failed command.
1803 * @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.
1805 static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, DoCommandFlag flags, const IndustrySpec *indspec, uint itspec_index, uint32 random_var8f, uint16 random_initial_bits, Owner founder, IndustryAvailabilityCallType creation_type, Industry **ip)
1807 assert(itspec_index < indspec->num_table);
1808 const IndustryTileTable *it = indspec->table[itspec_index];
1809 bool custom_shape_check = false;
1811 *ip = NULL;
1813 SmallVector<ClearedObjectArea, 1> object_areas(_cleared_object_areas);
1814 CommandCost ret = CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
1815 _cleared_object_areas = object_areas;
1816 if (ret.Failed()) return ret;
1818 if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
1819 ret = CheckIfCallBackAllowsCreation(tile, type, itspec_index, random_var8f, random_initial_bits, founder, creation_type);
1820 } else {
1821 ret = _check_new_industry_procs[indspec->check_proc](tile);
1823 if (ret.Failed()) return ret;
1825 if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
1826 !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, it, type)) {
1827 return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
1830 ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
1831 if (ret.Failed()) return ret;
1833 Town *t = NULL;
1834 ret = FindTownForIndustry(tile, type, &t);
1835 if (ret.Failed()) return ret;
1836 assert(t != NULL);
1838 ret = CheckIfIndustryIsAllowed(tile, type, t);
1839 if (ret.Failed()) return ret;
1841 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
1843 if (flags & DC_EXEC) {
1844 *ip = new Industry(tile);
1845 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER | DC_EXEC, it, type);
1846 DoCreateNewIndustry(*ip, tile, type, it, itspec_index, t, founder, random_initial_bits);
1849 return CommandCost();
1853 * Build/Fund an industry
1854 * @param tile tile where industry is built
1855 * @param flags of operations to conduct
1856 * @param p1 various bitstuffed elements
1857 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1858 * - p1 = (bit 8 - 15) - first layout to try
1859 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1860 * @param p2 seed to use for desyncfree randomisations
1861 * @param text unused
1862 * @return the cost of this operation or an error
1864 CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1866 IndustryType it = GB(p1, 0, 8);
1867 if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR;
1869 const IndustrySpec *indspec = GetIndustrySpec(it);
1871 /* Check if the to-be built/founded industry is available for this climate. */
1872 if (!indspec->enabled || indspec->num_table == 0) return CMD_ERROR;
1874 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1875 * Raw material industries are industries that do not accept cargo (at least for now) */
1876 if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
1877 return CMD_ERROR;
1880 if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) {
1881 return CMD_ERROR;
1884 Randomizer randomizer;
1885 randomizer.SetSeed(p2);
1886 uint16 random_initial_bits = GB(p2, 0, 16);
1887 uint32 random_var8f = randomizer.Next();
1888 int num_layouts = indspec->num_table;
1889 CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE);
1890 const bool deity_prospect = _current_company == OWNER_DEITY && !HasBit(p1, 16);
1892 Industry *ind = NULL;
1893 if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) {
1894 if (flags & DC_EXEC) {
1895 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1896 Backup<CompanyByte> cur_company(_current_company, OWNER_TOWN, FILE_LINE);
1897 /* Prospecting has a chance to fail, however we cannot guarantee that something can
1898 * be built on the map, so the chance gets lower when the map is fuller, but there
1899 * is nothing we can really do about that. */
1900 if (deity_prospect || Random() <= indspec->prospecting_chance) {
1901 for (int i = 0; i < 5000; i++) {
1902 /* We should not have more than one Random() in a function call
1903 * because parameter evaluation order is not guaranteed in the c++ standard
1905 tile = RandomTile();
1906 /* Start with a random layout */
1907 int layout = RandomRange(num_layouts);
1908 /* Check now each layout, starting with the random one */
1909 for (int j = 0; j < num_layouts; j++) {
1910 layout = (layout + 1) % num_layouts;
1911 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION, &ind);
1912 if (ret.Succeeded()) break;
1914 if (ret.Succeeded()) break;
1917 cur_company.Restore();
1919 } else {
1920 int layout = GB(p1, 8, 8);
1921 if (layout >= num_layouts) return CMD_ERROR;
1923 /* Check subsequently each layout, starting with the given layout in p1 */
1924 for (int i = 0; i < num_layouts; i++) {
1925 layout = (layout + 1) % num_layouts;
1926 ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, _current_company, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, &ind);
1927 if (ret.Succeeded()) break;
1930 /* If it still failed, there's no suitable layout to build here, return the error */
1931 if (ret.Failed()) return ret;
1934 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1935 AdvertiseIndustryOpening(ind);
1938 return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
1943 * Create a new industry of random layout.
1944 * @param tile The location to build the industry.
1945 * @param type The industry type to build.
1946 * @param creation_type The circumstances the industry is created under.
1947 * @return the created industry or NULL if it failed.
1949 static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAvailabilityCallType creation_type)
1951 const IndustrySpec *indspec = GetIndustrySpec(type);
1953 uint32 seed = Random();
1954 uint32 seed2 = Random();
1955 Industry *i = NULL;
1956 CommandCost ret = CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed, GB(seed2, 0, 16), OWNER_NONE, creation_type, &i);
1957 assert(i != NULL || ret.Failed());
1958 return i;
1962 * Compute the appearance probability for an industry during map creation.
1963 * @param it Industry type to compute.
1964 * @param [out] force_at_least_one Returns whether at least one instance should be forced on map creation.
1965 * @return Relative probability for the industry to appear.
1967 static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one)
1969 const IndustrySpec *ind_spc = GetIndustrySpec(it);
1970 uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision
1971 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
1972 (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) ||
1973 (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) {
1974 *force_at_least_one = false;
1975 return 0;
1976 } else {
1977 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1978 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1979 chance = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(chance) : ScaleByMapSize(chance);
1981 *force_at_least_one = (chance > 0) && !(ind_spc->behaviour & INDUSTRYBEH_NOBUILT_MAPCREATION) && (_game_mode != GM_EDITOR);
1982 return chance;
1987 * Compute the probability for constructing a new industry during game play.
1988 * @param it Industry type to compute.
1989 * @param [out] min_number Minimal number of industries that should exist at the map.
1990 * @return Relative probability for the industry to appear.
1992 static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number)
1994 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) {
1995 *min_number = 0;
1996 return 0;
1999 const IndustrySpec *ind_spc = GetIndustrySpec(it);
2000 byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
2001 if (!ind_spc->enabled || ind_spc->num_table == 0 ||
2002 ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) ||
2003 ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) ||
2004 (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
2005 *min_number = 0;
2006 return 0;
2008 *min_number = (ind_spc->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) ? 1 : 0;
2009 return chance;
2013 * Get wanted number of industries on the map.
2014 * @return Wanted number of industries at the map.
2016 static uint GetNumberOfIndustries()
2018 /* Number of industries on a 256x256 map. */
2019 static const uint16 numof_industry_table[] = {
2020 0, // none
2021 0, // minimal
2022 10, // very low
2023 25, // low
2024 55, // normal
2025 80, // high
2028 assert(lengthof(numof_industry_table) == ID_END);
2029 uint difficulty = (_game_mode != GM_EDITOR) ? _settings_game.difficulty.industry_density : (uint)ID_VERY_LOW;
2030 return min(IndustryPool::MAX_SIZE, ScaleByMapSize(numof_industry_table[difficulty]));
2034 * Try to place the industry in the game.
2035 * Since there is no feedback why placement fails, there is no other option
2036 * than to try a few times before concluding it does not work.
2037 * @param type Industry type of the desired industry.
2038 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
2039 * @return Pointer to created industry, or \c NULL if creation failed.
2041 static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType creation_type, bool try_hard)
2043 uint tries = try_hard ? 10000u : 2000u;
2044 for (; tries > 0; tries--) {
2045 Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
2046 if (ind != NULL) return ind;
2048 return NULL;
2052 * Try to build a industry on the map.
2053 * @param type IndustryType of the desired industry
2054 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
2056 static void PlaceInitialIndustry(IndustryType type, bool try_hard)
2058 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2060 IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
2061 PlaceIndustry(type, IACT_MAPGENERATION, try_hard);
2063 cur_company.Restore();
2067 * Get total number of industries existing in the game.
2068 * @return Number of industries currently in the game.
2070 static uint GetCurrentTotalNumberOfIndustries()
2072 int total = 0;
2073 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it);
2074 return total;
2078 /** Reset the entry. */
2079 void IndustryTypeBuildData::Reset()
2081 this->probability = 0;
2082 this->min_number = 0;
2083 this->target_count = 0;
2084 this->max_wait = 1;
2085 this->wait_count = 0;
2088 /** Completely reset the industry build data. */
2089 void IndustryBuildData::Reset()
2091 this->wanted_inds = GetCurrentTotalNumberOfIndustries() << 16;
2093 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2094 this->builddata[it].Reset();
2098 /** Monthly update of industry build data. */
2099 void IndustryBuildData::MonthlyLoop()
2101 static const int NEWINDS_PER_MONTH = 0x38000 / (10 * 12); // lower 16 bits is a float fraction, 3.5 industries per decade, divided by 10 * 12 months.
2102 if (_settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // 'no industries' setting.
2104 /* To prevent running out of unused industries for the player to connect,
2105 * add a fraction of new industries each month, but only if the manager can keep up. */
2106 uint max_behind = 1 + min(99u, ScaleByMapSize(3)); // At most 2 industries for small maps, and 100 at the biggest map (about 6 months industry build attempts).
2107 if (GetCurrentTotalNumberOfIndustries() + max_behind >= (this->wanted_inds >> 16)) {
2108 this->wanted_inds += ScaleByMapSize(NEWINDS_PER_MONTH);
2113 * This function will create random industries during game creation.
2114 * It will scale the amount of industries by mapsize and difficulty level.
2116 void GenerateIndustries()
2118 if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game.
2120 uint32 industry_probs[NUM_INDUSTRYTYPES];
2121 bool force_at_least_one[NUM_INDUSTRYTYPES];
2122 uint32 total_prob = 0;
2123 uint num_forced = 0;
2125 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2126 industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it);
2127 total_prob += industry_probs[it];
2128 if (force_at_least_one[it]) num_forced++;
2131 uint total_amount = GetNumberOfIndustries();
2132 if (total_prob == 0 || total_amount < num_forced) {
2133 /* Only place the forced ones */
2134 total_amount = num_forced;
2137 SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount);
2139 /* Try to build one industry per type independent of any probabilities */
2140 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2141 if (force_at_least_one[it]) {
2142 assert(total_amount > 0);
2143 total_amount--;
2144 PlaceInitialIndustry(it, true);
2148 /* Add the remaining industries according to their probabilities */
2149 for (uint i = 0; i < total_amount; i++) {
2150 uint32 r = RandomRange(total_prob);
2151 IndustryType it = 0;
2152 while (r >= industry_probs[it]) {
2153 r -= industry_probs[it];
2154 it++;
2155 assert(it < NUM_INDUSTRYTYPES);
2157 assert(industry_probs[it] > 0);
2158 PlaceInitialIndustry(it, false);
2160 _industry_builder.Reset();
2164 * Monthly update of industry statistics.
2165 * @param i Industry to update.
2167 static void UpdateIndustryStatistics(Industry *i)
2169 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2170 if (i->produced_cargo[j] != CT_INVALID) {
2171 byte pct = 0;
2172 if (i->this_month_production[j] != 0) {
2173 i->last_prod_year = _cur_year;
2174 pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
2176 i->last_month_pct_transported[j] = pct;
2178 i->last_month_production[j] = i->this_month_production[j];
2179 i->this_month_production[j] = 0;
2181 i->last_month_transported[j] = i->this_month_transported[j];
2182 i->this_month_transported[j] = 0;
2188 * Recompute #production_rate for current #prod_level.
2189 * This function is only valid when not using smooth economy.
2191 void Industry::RecomputeProductionMultipliers()
2193 const IndustrySpec *indspec = GetIndustrySpec(this->type);
2194 assert(!indspec->UsesSmoothEconomy());
2196 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2197 this->production_rate[0] = min(CeilDiv(indspec->production_rate[0] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2198 this->production_rate[1] = min(CeilDiv(indspec->production_rate[1] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
2203 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2204 * @param it Industry type.
2205 * @return At least one of the fields has changed value.
2207 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it)
2209 byte min_number;
2210 uint32 probability = GetIndustryGamePlayProbability(it, &min_number);
2211 bool changed = min_number != this->min_number || probability != this->probability;
2212 this->min_number = min_number;
2213 this->probability = probability;
2214 return changed;
2217 /** Decide how many industries of each type are needed. */
2218 void IndustryBuildData::SetupTargetCount()
2220 bool changed = false;
2221 uint num_planned = 0; // Number of industries planned in the industry build data.
2222 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2223 changed |= this->builddata[it].GetIndustryTypeData(it);
2224 num_planned += this->builddata[it].target_count;
2226 uint total_amount = this->wanted_inds >> 16; // Desired total number of industries.
2227 changed |= num_planned != total_amount;
2228 if (!changed) return; // All industries are still the same, no need to re-randomize.
2230 /* Initialize the target counts. */
2231 uint force_build = 0; // Number of industries that should always be available.
2232 uint32 total_prob = 0; // Sum of probabilities.
2233 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2234 IndustryTypeBuildData *ibd = this->builddata + it;
2235 force_build += ibd->min_number;
2236 ibd->target_count = ibd->min_number;
2237 total_prob += ibd->probability;
2240 if (total_prob == 0) return; // No buildable industries.
2242 /* Subtract forced industries from the number of industries available for construction. */
2243 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2245 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2246 while (total_amount > 0) {
2247 uint32 r = RandomRange(total_prob);
2248 IndustryType it = 0;
2249 while (r >= this->builddata[it].probability) {
2250 r -= this->builddata[it].probability;
2251 it++;
2252 assert(it < NUM_INDUSTRYTYPES);
2254 assert(this->builddata[it].probability > 0);
2255 this->builddata[it].target_count++;
2256 total_amount--;
2261 * Try to create a random industry, during gameplay
2263 void IndustryBuildData::TryBuildNewIndustry()
2265 this->SetupTargetCount();
2267 int missing = 0; // Number of industries that need to be build.
2268 uint count = 0; // Number of industry types eligible for build.
2269 uint32 total_prob = 0; // Sum of probabilities.
2270 IndustryType forced_build = NUM_INDUSTRYTYPES; // Industry type that should be forcibly build.
2271 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2272 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2273 missing += difference;
2274 if (this->builddata[it].wait_count > 0) continue; // This type may not be built now.
2275 if (difference > 0) {
2276 if (Industry::GetIndustryTypeCount(it) == 0 && this->builddata[it].min_number > 0) {
2277 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2278 if (forced_build == NUM_INDUSTRYTYPES ||
2279 difference > this->builddata[forced_build].target_count - Industry::GetIndustryTypeCount(forced_build)) {
2280 forced_build = it;
2283 total_prob += difference;
2284 count++;
2288 if (EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0; // Skip creation of an industry.
2290 if (count >= 1) {
2291 /* If not forced, pick a weighted random industry to build.
2292 * For the case that count == 1, there is no need to draw a random number. */
2293 IndustryType it;
2294 if (forced_build != NUM_INDUSTRYTYPES) {
2295 it = forced_build;
2296 } else {
2297 /* Non-forced, select an industry type to build (weighted random). */
2298 uint32 r = 0; // Initialized to silence the compiler.
2299 if (count > 1) r = RandomRange(total_prob);
2300 for (it = 0; it < NUM_INDUSTRYTYPES; it++) {
2301 if (this->builddata[it].wait_count > 0) continue; // Type may not be built now.
2302 int difference = this->builddata[it].target_count - Industry::GetIndustryTypeCount(it);
2303 if (difference <= 0) continue; // Too many of this kind.
2304 if (count == 1) break;
2305 if (r < (uint)difference) break;
2306 r -= difference;
2308 assert(it < NUM_INDUSTRYTYPES && this->builddata[it].target_count > Industry::GetIndustryTypeCount(it));
2311 /* Try to create the industry. */
2312 const Industry *ind = PlaceIndustry(it, IACT_RANDOMCREATION, false);
2313 if (ind == NULL) {
2314 this->builddata[it].wait_count = this->builddata[it].max_wait + 1; // Compensate for decrementing below.
2315 this->builddata[it].max_wait = min(1000, this->builddata[it].max_wait + 2);
2316 } else {
2317 AdvertiseIndustryOpening(ind);
2318 this->builddata[it].max_wait = max(this->builddata[it].max_wait / 2, 1); // Reduce waiting time of the industry type.
2322 /* Decrement wait counters. */
2323 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2324 if (this->builddata[it].wait_count > 0) this->builddata[it].wait_count--;
2329 * Protects an industry from closure if the appropriate flags and conditions are met
2330 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2331 * count of industries of this type must one (or lower) in order to be protected
2332 * against closure.
2333 * @param type IndustryType been queried
2334 * @result true if protection is on, false otherwise (except for oil wells)
2336 static bool CheckIndustryCloseDownProtection(IndustryType type)
2338 const IndustrySpec *indspec = GetIndustrySpec(type);
2340 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2341 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE) return false;
2342 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && Industry::GetIndustryTypeCount(type) <= 1;
2346 * Can given cargo type be accepted or produced by the industry?
2347 * @param cargo: Cargo type
2348 * @param ind: Industry
2349 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2350 * @param *c_produces: Pointer to boolean for production of cargo
2351 * @return: \c *c_accepts is set when industry accepts the cargo type,
2352 * \c *c_produces is set when the industry produces the cargo type
2354 static void CanCargoServiceIndustry(CargoID cargo, Industry *ind, bool *c_accepts, bool *c_produces)
2356 if (cargo == CT_INVALID) return;
2358 /* Check for acceptance of cargo */
2359 for (byte j = 0; j < lengthof(ind->accepts_cargo); j++) {
2360 if (cargo == ind->accepts_cargo[j] && !IndustryTemporarilyRefusesCargo(ind, cargo)) {
2361 *c_accepts = true;
2362 break;
2366 /* Check for produced cargo */
2367 for (byte j = 0; j < lengthof(ind->produced_cargo); j++) {
2368 if (cargo == ind->produced_cargo[j]) {
2369 *c_produces = true;
2370 break;
2376 * Compute who can service the industry.
2378 * Here, 'can service' means that he/she has trains and stations close enough
2379 * to the industry with the right cargo type and the right orders (ie has the
2380 * technical means).
2382 * @param ind: Industry being investigated.
2384 * @return: 0 if nobody can service the industry, 2 if the local company can
2385 * service the industry, and 1 otherwise (only competitors can service the
2386 * industry)
2388 static int WhoCanServiceIndustry(Industry *ind)
2390 /* Find all stations within reach of the industry */
2391 StationList stations;
2392 FindStationsAroundTiles(ind->location, &stations);
2394 if (stations.Length() == 0) return 0; // No stations found at all => nobody services
2396 const Vehicle *v;
2397 int result = 0;
2398 FOR_ALL_VEHICLES(v) {
2399 /* Is it worthwhile to try this vehicle? */
2400 if (v->owner != _local_company && result != 0) continue;
2402 /* Check whether it accepts the right kind of cargo */
2403 bool c_accepts = false;
2404 bool c_produces = false;
2405 if (v->type == VEH_TRAIN && v->IsFrontEngine()) {
2406 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
2407 CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
2409 } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) {
2410 CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces);
2411 } else {
2412 continue;
2414 if (!c_accepts && !c_produces) continue; // Wrong cargo
2416 /* Check orders of the vehicle.
2417 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2418 * may have a different cargo type.
2420 const Order *o;
2421 FOR_VEHICLE_ORDERS(v, o) {
2422 if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
2423 /* Vehicle visits a station to load or unload */
2424 Station *st = Station::Get(o->GetDestination());
2425 assert(st != NULL);
2427 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2428 if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
2430 if (stations.Contains(st)) {
2431 if (v->owner == _local_company) return 2; // Company services industry
2432 result = 1; // Competitor services industry
2437 return result;
2441 * Report news that industry production has changed significantly
2443 * @param ind: Industry with changed production
2444 * @param type: Cargo type that has changed
2445 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
2447 static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
2449 NewsType nt;
2451 switch (WhoCanServiceIndustry(ind)) {
2452 case 0: nt = NT_INDUSTRY_NOBODY; break;
2453 case 1: nt = NT_INDUSTRY_OTHER; break;
2454 case 2: nt = NT_INDUSTRY_COMPANY; break;
2455 default: NOT_REACHED();
2457 SetDParam(2, abs(percent));
2458 SetDParam(0, CargoSpec::Get(type)->name);
2459 SetDParam(1, ind->index);
2460 AddIndustryNewsItem(
2461 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2463 ind->index
2467 static const uint PERCENT_TRANSPORTED_60 = 153;
2468 static const uint PERCENT_TRANSPORTED_80 = 204;
2471 * Change industry production or do closure
2472 * @param i Industry for which changes are performed
2473 * @param monthly true if it's the monthly call, false if it's the random call
2475 static void ChangeIndustryProduction(Industry *i, bool monthly)
2477 StringID str = STR_NULL;
2478 bool closeit = false;
2479 const IndustrySpec *indspec = GetIndustrySpec(i->type);
2480 bool standard = false;
2481 bool suppress_message = false;
2482 bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
2483 /* don't use smooth economy for industries using production related callbacks */
2484 bool smooth_economy = indspec->UsesSmoothEconomy();
2485 byte div = 0;
2486 byte mul = 0;
2487 int8 increment = 0;
2489 bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
2490 if (callback_enabled) {
2491 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
2492 if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
2493 suppress_message = HasBit(res, 7);
2494 /* Get the custom message if any */
2495 if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
2496 res = GB(res, 0, 4);
2497 switch (res) {
2498 default: NOT_REACHED();
2499 case 0x0: break; // Do nothing, but show the custom message if any
2500 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2501 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2502 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2503 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
2504 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2505 case 0x8: div = res - 0x3; break; // Divide production by 32
2506 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2507 case 0xC: mul = res - 0x7; break; // Multiply production by 32
2508 case 0xD: // decrement production
2509 case 0xE: // increment production
2510 increment = res == 0x0D ? -1 : 1;
2511 break;
2512 case 0xF: // Set production to third byte of register 0x100
2513 i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2514 recalculate_multipliers = true;
2515 break;
2518 } else {
2519 if (monthly != smooth_economy) return;
2520 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
2523 if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
2524 /* decrease or increase */
2525 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
2527 if (smooth_economy) {
2528 closeit = true;
2529 for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
2530 if (i->produced_cargo[j] == CT_INVALID) continue;
2531 uint32 r = Random();
2532 int old_prod, new_prod, percent;
2533 /* If over 60% is transported, mult is 1, else mult is -1. */
2534 int mult = (i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_60) ? 1 : -1;
2536 new_prod = old_prod = i->production_rate[j];
2538 /* For industries with only_decrease flags (temperate terrain Oil Wells),
2539 * the multiplier will always be -1 so they will only decrease. */
2540 if (only_decrease) {
2541 mult = -1;
2542 /* For normal industries, if over 60% is transported, 33% chance for decrease.
2543 * Bonus for very high station ratings (over 80%): 16% chance for decrease. */
2544 } else if (Chance16I(1, ((i->last_month_pct_transported[j] > PERCENT_TRANSPORTED_80) ? 6 : 3), r)) {
2545 mult *= -1;
2548 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2549 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2550 if (Chance16I(1, 22, r >> 16)) {
2551 new_prod += mult * (max(((RandomRange(50) + 10) * old_prod) >> 8, 1U));
2554 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2555 new_prod = Clamp(new_prod, 1, 255);
2557 if (((indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) && j == 1) {
2558 new_prod = Clamp(new_prod, 0, 16);
2561 /* Do not stop closing the industry when it has the lowest possible production rate */
2562 if (new_prod == old_prod && old_prod > 1) {
2563 closeit = false;
2564 continue;
2567 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2568 i->production_rate[j] = new_prod;
2570 /* Close the industry when it has the lowest possible production rate */
2571 if (new_prod > 1) closeit = false;
2573 if (abs(percent) >= 10) {
2574 ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
2577 } else {
2578 if (only_decrease || Chance16(1, 3)) {
2579 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2580 if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
2581 mul = 1; // Increase production
2582 } else {
2583 div = 1; // Decrease production
2589 if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
2590 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
2591 closeit = true;
2595 /* Increase if needed */
2596 while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
2597 i->prod_level = min(i->prod_level * 2, PRODLEVEL_MAXIMUM);
2598 recalculate_multipliers = true;
2599 if (str == STR_NULL) str = indspec->production_up_text;
2602 /* Decrease if needed */
2603 while (div-- != 0 && !closeit) {
2604 if (i->prod_level == PRODLEVEL_MINIMUM) {
2605 closeit = true;
2606 } else {
2607 i->prod_level = max(i->prod_level / 2, (int)PRODLEVEL_MINIMUM); // typecast to int required to please MSVC
2608 recalculate_multipliers = true;
2609 if (str == STR_NULL) str = indspec->production_down_text;
2613 /* Increase or Decreasing the production level if needed */
2614 if (increment != 0) {
2615 if (increment < 0 && i->prod_level == PRODLEVEL_MINIMUM) {
2616 closeit = true;
2617 } else {
2618 i->prod_level = ClampU(i->prod_level + increment, PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
2619 recalculate_multipliers = true;
2623 /* Recalculate production_rate
2624 * For non-smooth economy these should always be synchronized with prod_level */
2625 if (recalculate_multipliers) i->RecomputeProductionMultipliers();
2627 /* Close if needed and allowed */
2628 if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
2629 i->prod_level = PRODLEVEL_CLOSURE;
2630 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2631 str = indspec->closure_text;
2634 if (!suppress_message && str != STR_NULL) {
2635 NewsType nt;
2636 /* Compute news category */
2637 if (closeit) {
2638 nt = NT_INDUSTRY_CLOSE;
2639 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i->index));
2640 Game::NewEvent(new ScriptEventIndustryClose(i->index));
2641 } else {
2642 switch (WhoCanServiceIndustry(i)) {
2643 case 0: nt = NT_INDUSTRY_NOBODY; break;
2644 case 1: nt = NT_INDUSTRY_OTHER; break;
2645 case 2: nt = NT_INDUSTRY_COMPANY; break;
2646 default: NOT_REACHED();
2649 /* Set parameters of news string */
2650 if (str > STR_LAST_STRINGID) {
2651 SetDParam(0, STR_TOWN_NAME);
2652 SetDParam(1, i->town->index);
2653 SetDParam(2, indspec->name);
2654 } else if (closeit) {
2655 SetDParam(0, STR_FORMAT_INDUSTRY_NAME);
2656 SetDParam(1, i->town->index);
2657 SetDParam(2, indspec->name);
2658 } else {
2659 SetDParam(0, i->index);
2661 /* and report the news to the user */
2662 if (closeit) {
2663 AddTileNewsItem(str, nt, i->location.tile + TileDiffXY(1, 1));
2664 } else {
2665 AddIndustryNewsItem(str, nt, i->index);
2671 * Daily handler for the industry changes
2672 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2673 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2674 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2675 * it would be way more. The daily loop handles those changes.
2677 void IndustryDailyLoop()
2679 _economy.industry_daily_change_counter += _economy.industry_daily_increment;
2681 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2682 * the lower 16 bit are a fractional part that might accumulate over several days until it
2683 * is sufficient for an industry. */
2684 uint16 change_loop = _economy.industry_daily_change_counter >> 16;
2686 /* Reset the active part of the counter, just keeping the "fractional part" */
2687 _economy.industry_daily_change_counter &= 0xFFFF;
2689 if (change_loop == 0) {
2690 return; // Nothing to do? get out
2693 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2695 /* perform the required industry changes for the day */
2697 uint perc = 3; // Between 3% and 9% chance of creating a new industry.
2698 if ((_industry_builder.wanted_inds >> 16) > GetCurrentTotalNumberOfIndustries()) {
2699 perc = min(9u, perc + (_industry_builder.wanted_inds >> 16) - GetCurrentTotalNumberOfIndustries());
2701 for (uint16 j = 0; j < change_loop; j++) {
2702 if (Chance16(perc, 100)) {
2703 _industry_builder.TryBuildNewIndustry();
2704 } else {
2705 Industry *i = Industry::GetRandom();
2706 if (i != NULL) {
2707 ChangeIndustryProduction(i, false);
2708 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2713 cur_company.Restore();
2715 /* production-change */
2716 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2719 void IndustryMonthlyLoop()
2721 Backup<CompanyByte> cur_company(_current_company, OWNER_NONE, FILE_LINE);
2723 _industry_builder.MonthlyLoop();
2725 Industry *i;
2726 FOR_ALL_INDUSTRIES(i) {
2727 UpdateIndustryStatistics(i);
2728 if (i->prod_level == PRODLEVEL_CLOSURE) {
2729 delete i;
2730 } else {
2731 ChangeIndustryProduction(i, true);
2732 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
2736 cur_company.Restore();
2738 /* production-change */
2739 InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1);
2743 void InitializeIndustries()
2745 Industry::ResetIndustryCounts();
2746 _industry_sound_tile = 0;
2748 _industry_builder.Reset();
2751 /** Verify whether the generated industries are complete, and warn the user if not. */
2752 void CheckIndustries()
2754 int count = 0;
2755 for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) {
2756 if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped.
2758 bool force_at_least_one;
2759 uint32 chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one);
2760 if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped.
2762 const IndustrySpec *is = GetIndustrySpec(it);
2763 SetDParam(0, is->name);
2764 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION, WL_WARNING);
2766 count++;
2767 if (count >= 3) break; // Don't swamp the user with errors.
2772 * Is an industry with the spec a raw industry?
2773 * @return true if it should be handled as a raw industry
2775 bool IndustrySpec::IsRawIndustry() const
2777 return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0;
2781 * Is an industry with the spec a processing industry?
2782 * @return true if it should be handled as a processing industry
2784 bool IndustrySpec::IsProcessingIndustry() const
2786 /* Lumber mills are neither raw nor processing */
2787 return (this->life_type & INDUSTRYLIFE_PROCESSING) != 0 &&
2788 (this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
2792 * Get the cost for constructing this industry
2793 * @return the cost (inflation corrected etc)
2795 Money IndustrySpec::GetConstructionCost() const
2797 /* Building raw industries like secondary uses different price base */
2798 return (_price[(_settings_game.construction.raw_industry_construction == 1 && this->IsRawIndustry()) ?
2799 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->cost_multiplier) >> 8;
2803 * Get the cost for removing this industry
2804 * Take note that the cost will always be zero for non-grf industries.
2805 * Only if the grf author did specified a cost will it be applicable.
2806 * @return the cost (inflation corrected etc)
2808 Money IndustrySpec::GetRemovalCost() const
2810 return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
2814 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2815 * @return true if smooth economy is used.
2817 bool IndustrySpec::UsesSmoothEconomy() const
2819 return _settings_game.economy.smooth_economy &&
2820 !(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
2821 !(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
2824 static CommandCost TerraformTile_Industry(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2826 if (AutoslopeEnabled()) {
2827 /* We imitate here TTDP's behaviour:
2828 * - Both new and old slope must not be steep.
2829 * - TileMaxZ must not be changed.
2830 * - Allow autoslope by default.
2831 * - Disallow autoslope if callback succeeds and returns non-zero.
2833 Slope tileh_old = GetTileSlope(tile);
2834 /* TileMaxZ must not be changed. Slopes must not be steep. */
2835 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
2836 const IndustryGfx gfx = GetIndustryGfx(tile);
2837 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
2839 /* Call callback 3C 'disable autosloping for industry tiles'. */
2840 if (HasBit(itspec->callback_mask, CBM_INDT_AUTOSLOPE)) {
2841 /* If the callback fails, allow autoslope. */
2842 uint16 res = GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE, 0, 0, gfx, Industry::GetByTile(tile), tile);
2843 if (res == CALLBACK_FAILED || !ConvertBooleanCallback(itspec->grf_prop.grffile, CBID_INDTILE_AUTOSLOPE, res)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2844 } else {
2845 /* allow autoslope */
2846 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2850 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2853 extern const TileTypeProcs _tile_type_industry_procs = {
2854 DrawTile_Industry, // draw_tile_proc
2855 GetSlopePixelZ_Industry, // get_slope_z_proc
2856 ClearTile_Industry, // clear_tile_proc
2857 AddAcceptedCargo_Industry, // add_accepted_cargo_proc
2858 GetTileDesc_Industry, // get_tile_desc_proc
2859 GetTileTrackStatus_Industry, // get_tile_track_status_proc
2860 ClickTile_Industry, // click_tile_proc
2861 AnimateTile_Industry, // animate_tile_proc
2862 TileLoop_Industry, // tile_loop_proc
2863 ChangeTileOwner_Industry, // change_tile_owner_proc
2864 NULL, // add_produced_cargo_proc
2865 NULL, // vehicle_enter_tile_proc
2866 GetFoundation_Industry, // get_foundation_proc
2867 TerraformTile_Industry, // terraform_tile_proc