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/>.
10 /** @file industry_cmd.cpp Handling of industry tiles. */
13 #include "map/ground.h"
14 #include "map/bridge.h"
16 #include "station_base.h"
17 #include "landscape.h"
18 #include "viewport_func.h"
19 #include "command_func.h"
21 #include "news_func.h"
22 #include "cheat_type.h"
24 #include "newgrf_cargo.h"
25 #include "newgrf_debug.h"
26 #include "newgrf_industrytiles.h"
27 #include "autoslope.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"
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 "station_func.h"
46 #include "table/strings.h"
47 #include "table/industry_land.h"
48 #include "table/build_industry.h"
50 template<> Industry::Pool
Industry::PoolItem::pool ("Industry");
51 INSTANTIATE_POOL_METHODS(Industry
)
53 void ShowIndustryViewWindow(int industry
);
54 void BuildOilRig(TileIndex tile
);
56 static byte _industry_sound_ctr
;
57 static TileIndex _industry_sound_tile
;
59 uint16
Industry::counts
[NUM_INDUSTRYTYPES
];
61 IndustrySpec _industry_specs
[NUM_INDUSTRYTYPES
];
62 IndustryTileSpec _industry_tile_specs
[NUM_INDUSTRYTILES
];
63 IndustryBuildData _industry_builder
; ///< In-game manager of industries.
66 * This function initialize the spec arrays of both
67 * industry and industry tiles.
68 * It adjusts the enabling of the industry too, based on climate availability.
69 * This will allow for clearer testings
71 void ResetIndustries()
73 memset(&_industry_specs
, 0, sizeof(_industry_specs
));
74 memcpy(&_industry_specs
, &_origin_industry_specs
, sizeof(_origin_industry_specs
));
76 /* once performed, enable only the current climate industries */
77 for (IndustryType i
= 0; i
< NUM_INDUSTRYTYPES
; i
++) {
78 _industry_specs
[i
].enabled
= i
< NEW_INDUSTRYOFFSET
&&
79 HasBit(_origin_industry_specs
[i
].climate_availability
, _settings_game
.game_creation
.landscape
);
82 memset(&_industry_tile_specs
, 0, sizeof(_industry_tile_specs
));
83 memcpy(&_industry_tile_specs
, &_origin_industry_tile_specs
, sizeof(_origin_industry_tile_specs
));
85 /* Reset any overrides that have been set. */
86 _industile_mngr
.ResetOverride();
87 _industry_mngr
.ResetOverride();
91 * Retrieve the type for this industry. Although it is accessed by a tile,
92 * it will return the general type of industry, and not the sprite index
93 * as would do GetIndustryGfx.
94 * @param tile that is queried
95 * @pre IsIndustryTile(tile)
96 * @return general type for this industry, as defined in industry.h
98 IndustryType
GetIndustryType(TileIndex tile
)
100 assert(IsIndustryTile(tile
));
102 const Industry
*ind
= Industry::GetByTile(tile
);
108 * Accessor for array _industry_specs.
109 * This will ensure at once : proper access and
110 * not allowing modifications of it.
111 * @param thistype of industry (which is the index in _industry_specs)
112 * @pre thistype < NUM_INDUSTRYTYPES
113 * @return a pointer to the corresponding industry spec
115 const IndustrySpec
*GetIndustrySpec(IndustryType thistype
)
117 assert(thistype
< NUM_INDUSTRYTYPES
);
118 return &_industry_specs
[thistype
];
122 * Accessor for array _industry_tile_specs.
123 * This will ensure at once : proper access and
124 * not allowing modifications of it.
125 * @param gfx of industrytile (which is the index in _industry_tile_specs)
126 * @pre gfx < INVALID_INDUSTRYTILE
127 * @return a pointer to the corresponding industrytile spec
129 const IndustryTileSpec
*GetIndustryTileSpec(IndustryGfx gfx
)
131 assert(gfx
< INVALID_INDUSTRYTILE
);
132 return &_industry_tile_specs
[gfx
];
135 Industry::~Industry()
137 if (CleaningPool()) return;
139 /* Industry can also be destroyed when not fully initialized.
140 * This means that we do not have to clear tiles either.
141 * Also we must not decrement industry counts in that case. */
142 if (this->location
.w
== 0) return;
144 remove_from_tileset();
146 TILE_AREA_LOOP(tile_cur
, this->location
) {
147 if (IsIndustryTile(tile_cur
)) {
148 if (GetIndustryIndex(tile_cur
) == this->index
) {
149 DeleteNewGRFInspectWindow(GSF_INDUSTRYTILES
, tile_cur
);
151 /* MakeWaterKeepingClass() can also handle 'land' */
152 MakeWaterKeepingClass(tile_cur
, OWNER_NONE
);
154 } else if (IsStationTile(tile_cur
) && IsOilRig(tile_cur
)) {
155 DeleteOilRig(tile_cur
);
159 if (GetIndustrySpec(this->type
)->behaviour
& INDUSTRYBEH_PLANT_FIELDS
) {
160 TileArea
ta (this->location
.tile
);
163 /* Remove the farmland and convert it to regular tiles over time. */
164 TILE_AREA_LOOP(tile_cur
, ta
) {
165 if (IsFieldsTile(tile_cur
) &&
166 GetIndustryIndexOfField(tile_cur
) == this->index
) {
167 SetIndustryIndexOfField(tile_cur
, INVALID_INDUSTRY
);
172 /* don't let any disaster vehicle target invalid industry */
173 ReleaseDisastersTargetingIndustry(this->index
);
175 /* Clear the persistent storage. */
178 DecIndustryTypeCount(this->type
);
180 DeleteIndustryNews(this->index
);
181 DeleteWindowById(WC_INDUSTRY_VIEW
, this->index
);
182 DeleteNewGRFInspectWindow(GSF_INDUSTRIES
, this->index
);
184 DeleteSubsidyWith(ST_INDUSTRY
, this->index
);
185 CargoPacket::InvalidateAllFrom(ST_INDUSTRY
, this->index
);
189 * Invalidating some stuff after removing item from the pool.
190 * @param index index of deleted item
192 void Industry::PostDestructor(size_t index
)
194 InvalidateWindowData(WC_INDUSTRY_DIRECTORY
, 0, 0);
195 Station::RecomputeIndustriesNearForAll();
200 * Return a random valid industry.
201 * @return random industry, NULL if there are no industries
203 /* static */ Industry
*Industry::GetRandom()
205 if (Industry::GetNumItems() == 0) return NULL
;
206 int num
= RandomRange((uint16
)Industry::GetNumItems());
207 size_t index
= MAX_UVALUE(size_t);
213 /* Make sure we have a valid industry */
214 while (!Industry::IsValidID(index
)) {
216 assert(index
< Industry::GetPoolSize());
220 return Industry::Get(index
);
224 static void IndustryDrawSugarMine(const TileInfo
*ti
)
226 if (!IsIndustryCompleted(ti
->tile
)) return;
228 const DrawIndustryAnimationStruct
*d
= &_draw_industry_spec1
[GetAnimationFrame(ti
->tile
)];
230 AddChildSpriteScreen (ti
->vd
, SPR_IT_SUGAR_MINE_SIEVE
+ d
->image_1
, PAL_NONE
, d
->x
, 0);
232 if (d
->image_2
!= 0) {
233 AddChildSpriteScreen (ti
->vd
, SPR_IT_SUGAR_MINE_CLOUDS
+ d
->image_2
- 1, PAL_NONE
, 8, 41);
236 if (d
->image_3
!= 0) {
237 AddChildSpriteScreen (ti
->vd
, SPR_IT_SUGAR_MINE_PILE
+ d
->image_3
- 1, PAL_NONE
,
238 _drawtile_proc1
[d
->image_3
- 1].x
, _drawtile_proc1
[d
->image_3
- 1].y
);
242 static void IndustryDrawToffeeQuarry(const TileInfo
*ti
)
246 if (IsIndustryCompleted(ti
->tile
)) {
247 x
= _industry_anim_offs_toffee
[GetAnimationFrame(ti
->tile
)];
253 AddChildSpriteScreen (ti
->vd
, SPR_IT_TOFFEE_QUARRY_SHOVEL
, PAL_NONE
, 22 - x
, 24 + x
);
254 AddChildSpriteScreen (ti
->vd
, SPR_IT_TOFFEE_QUARRY_TOFFEE
, PAL_NONE
, 6, 14);
257 static void IndustryDrawBubbleGenerator( const TileInfo
*ti
)
259 if (IsIndustryCompleted(ti
->tile
)) {
260 AddChildSpriteScreen (ti
->vd
, SPR_IT_BUBBLE_GENERATOR_BUBBLE
, PAL_NONE
, 5, _industry_anim_offs_bubbles
[GetAnimationFrame(ti
->tile
)]);
262 AddChildSpriteScreen (ti
->vd
, SPR_IT_BUBBLE_GENERATOR_SPRING
, PAL_NONE
, 3, 67);
265 static void IndustryDrawToyFactory(const TileInfo
*ti
)
267 const DrawIndustryAnimationStruct
*d
= &_industry_anim_offs_toys
[GetAnimationFrame(ti
->tile
)];
269 if (d
->image_1
!= 0xFF) {
270 AddChildSpriteScreen (ti
->vd
, SPR_IT_TOY_FACTORY_CLAY
, PAL_NONE
, d
->x
, 96 + d
->image_1
);
273 if (d
->image_2
!= 0xFF) {
274 AddChildSpriteScreen (ti
->vd
, SPR_IT_TOY_FACTORY_ROBOT
, PAL_NONE
, 16 - d
->image_2
* 2, 100 + d
->image_2
);
277 AddChildSpriteScreen (ti
->vd
, SPR_IT_TOY_FACTORY_STAMP
, PAL_NONE
, 7, d
->image_3
);
278 AddChildSpriteScreen (ti
->vd
, SPR_IT_TOY_FACTORY_STAMP_HOLDER
, PAL_NONE
, 0, 42);
281 static void IndustryDrawCoalPlantSparks(const TileInfo
*ti
)
283 if (IsIndustryCompleted(ti
->tile
)) {
284 uint8 image
= GetAnimationFrame(ti
->tile
);
286 if (image
!= 0 && image
< 7) {
287 AddChildSpriteScreen (ti
->vd
, image
+ SPR_IT_POWER_PLANT_TRANSFORMERS
,
289 _coal_plant_sparks
[image
- 1].x
,
290 _coal_plant_sparks
[image
- 1].y
296 typedef void IndustryDrawTileProc(const TileInfo
*ti
);
297 static IndustryDrawTileProc
* const _industry_draw_tile_procs
[5] = {
298 IndustryDrawSugarMine
,
299 IndustryDrawToffeeQuarry
,
300 IndustryDrawBubbleGenerator
,
301 IndustryDrawToyFactory
,
302 IndustryDrawCoalPlantSparks
,
305 static void DrawTile_Industry(TileInfo
*ti
)
307 IndustryGfx gfx
= GetIndustryGfx(ti
->tile
);
308 Industry
*ind
= Industry::GetByTile(ti
->tile
);
309 const IndustryTileSpec
*indts
= GetIndustryTileSpec(gfx
);
311 /* Retrieve pointer to the draw industry tile struct */
312 if (gfx
>= NEW_INDUSTRYTILEOFFSET
) {
313 /* Draw the tile using the specialized method of newgrf industrytile.
314 * DrawNewIndustry will return false if ever the resolver could not
315 * find any sprite to display. So in this case, we will jump on the
316 * substitute gfx instead. */
317 if (indts
->grf_prop
.spritegroup
[0] != NULL
&& DrawNewIndustryTile(ti
, ind
, gfx
, indts
)) {
320 /* No sprite group (or no valid one) found, meaning no graphics associated.
321 * Use the substitute one instead */
322 if (indts
->grf_prop
.subst_id
!= INVALID_INDUSTRYTILE
) {
323 gfx
= indts
->grf_prop
.subst_id
;
324 /* And point the industrytile spec accordingly */
325 indts
= GetIndustryTileSpec(gfx
);
330 const DrawBuildingsTileStruct
*dits
= industry_draw_tile_data
[gfx
][(indts
->anim_state
?
331 GetAnimationFrame(ti
->tile
) & INDUSTRY_COMPLETED
:
332 GetIndustryConstructionStage(ti
->tile
))];
334 SpriteID image
= dits
->ground
.sprite
;
336 /* DrawFoundation() modifies ti->z and ti->tileh */
337 if (ti
->tileh
!= SLOPE_FLAT
) DrawFoundation(ti
, FOUNDATION_LEVELED
);
339 /* If the ground sprite is the default flat water sprite, draw also canal/river borders.
340 * Do not do this if the tile's WaterClass is 'land'. */
341 if (image
== SPR_FLAT_WATER_TILE
&& IsTileOnWater(ti
->tile
)) {
342 DrawWaterClassGround(ti
);
344 DrawGroundSprite (ti
, image
, GroundSpritePaletteTransform(image
, dits
->ground
.pal
, GENERAL_SPRITE_COLOUR(ind
->random_colour
)));
347 /* If industries are transparent and invisible, do not draw the upper part */
348 if (IsInvisibilitySet(TO_INDUSTRIES
)) return;
350 /* Add industry on top of the ground? */
351 image
= dits
->building
.sprite
;
353 AddSortableSpriteToDraw (ti
->vd
, image
, SpriteLayoutPaletteTransform(image
, dits
->building
.pal
, GENERAL_SPRITE_COLOUR(ind
->random_colour
)),
354 ti
->x
+ dits
->subtile_x
,
355 ti
->y
+ dits
->subtile_y
,
360 IsTransparencySet(TO_INDUSTRIES
));
362 if (IsTransparencySet(TO_INDUSTRIES
)) return;
366 int proc
= dits
->draw_proc
- 1;
367 if (proc
>= 0) _industry_draw_tile_procs
[proc
](ti
);
371 static int GetSlopePixelZ_Industry(TileIndex tile
, uint x
, uint y
)
373 return GetTileMaxPixelZ(tile
);
376 static Foundation
GetFoundation_Industry(TileIndex tile
, Slope tileh
)
378 IndustryGfx gfx
= GetIndustryGfx(tile
);
380 /* For NewGRF industry tiles we might not be drawing a foundation. We need to
381 * account for this, as other structures should
382 * draw the wall of the foundation in this case.
384 if (gfx
>= NEW_INDUSTRYTILEOFFSET
) {
385 const IndustryTileSpec
*indts
= GetIndustryTileSpec(gfx
);
386 if (indts
->grf_prop
.spritegroup
[0] != NULL
&& HasBit(indts
->callback_mask
, CBM_INDT_DRAW_FOUNDATIONS
)) {
387 uint32 callback_res
= GetIndustryTileCallback(CBID_INDTILE_DRAW_FOUNDATIONS
, 0, 0, gfx
, Industry::GetByTile(tile
), tile
);
388 if (callback_res
!= CALLBACK_FAILED
&& !ConvertBooleanCallback(indts
->grf_prop
.grffile
, CBID_INDTILE_DRAW_FOUNDATIONS
, callback_res
)) return FOUNDATION_NONE
;
391 return FlatteningFoundation(tileh
);
394 static void AddAcceptedCargo_Industry(TileIndex tile
, CargoArray
&acceptance
, uint32
*always_accepted
)
396 IndustryGfx gfx
= GetIndustryGfx(tile
);
397 const IndustryTileSpec
*itspec
= GetIndustryTileSpec(gfx
);
399 /* When we have to use a callback, we put our data in the next two variables */
400 CargoID raw_accepts_cargo
[lengthof(itspec
->accepts_cargo
)];
401 uint8 raw_cargo_acceptance
[lengthof(itspec
->acceptance
)];
403 /* And then these will always point to a same sized array with the required data */
404 const CargoID
*accepts_cargo
= itspec
->accepts_cargo
;
405 const uint8
*cargo_acceptance
= itspec
->acceptance
;
407 if (HasBit(itspec
->callback_mask
, CBM_INDT_ACCEPT_CARGO
)) {
408 uint16 res
= GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO
, 0, 0, gfx
, Industry::GetByTile(tile
), tile
);
409 if (res
!= CALLBACK_FAILED
) {
410 accepts_cargo
= raw_accepts_cargo
;
411 for (uint i
= 0; i
< lengthof(itspec
->accepts_cargo
); i
++) raw_accepts_cargo
[i
] = GetCargoTranslation(GB(res
, i
* 5, 5), itspec
->grf_prop
.grffile
);
415 if (HasBit(itspec
->callback_mask
, CBM_INDT_CARGO_ACCEPTANCE
)) {
416 uint16 res
= GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE
, 0, 0, gfx
, Industry::GetByTile(tile
), tile
);
417 if (res
!= CALLBACK_FAILED
) {
418 cargo_acceptance
= raw_cargo_acceptance
;
419 for (uint i
= 0; i
< lengthof(itspec
->accepts_cargo
); i
++) raw_cargo_acceptance
[i
] = GB(res
, i
* 4, 4);
423 const Industry
*ind
= Industry::GetByTile(tile
);
424 for (byte i
= 0; i
< lengthof(itspec
->accepts_cargo
); i
++) {
425 CargoID a
= accepts_cargo
[i
];
426 if (a
== CT_INVALID
|| cargo_acceptance
[i
] == 0) continue; // work only with valid cargoes
428 /* Add accepted cargo */
429 acceptance
[a
] += cargo_acceptance
[i
];
431 /* Maybe set 'always accepted' bit (if it's not set already) */
432 if (HasBit(*always_accepted
, a
)) continue;
434 bool accepts
= false;
435 for (uint cargo_index
= 0; cargo_index
< lengthof(ind
->accepts_cargo
); cargo_index
++) {
436 /* Test whether the industry itself accepts the cargo type */
437 if (ind
->accepts_cargo
[cargo_index
] == a
) {
443 if (accepts
) continue;
445 /* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
446 SetBit(*always_accepted
, a
);
450 static void GetTileDesc_Industry(TileIndex tile
, TileDesc
*td
)
452 const Industry
*i
= Industry::GetByTile(tile
);
453 const IndustrySpec
*is
= GetIndustrySpec(i
->type
);
455 td
->owner
[0] = i
->owner
;
457 if (!IsIndustryCompleted(tile
)) {
458 td
->dparam
= td
->str
;
459 td
->str
= STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION
;
462 if (is
->grf_prop
.grffile
!= NULL
) {
463 td
->grf
= GetGRFConfig(is
->grf_prop
.grffile
->grfid
)->GetName();
467 static CommandCost
ClearTile_Industry(TileIndex tile
, DoCommandFlag flags
)
469 Industry
*i
= Industry::GetByTile(tile
);
470 const IndustrySpec
*indspec
= GetIndustrySpec(i
->type
);
472 /* water can destroy industries
473 * in editor you can bulldoze industries
474 * with magic_bulldozer cheat you can destroy industries
475 * (area around OILRIG is water, so water shouldn't flood it
477 if ((_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
&&
478 !_cheats
.magic_bulldozer
.value
) ||
479 ((flags
& DC_AUTO
) != 0) ||
480 (_current_company
== OWNER_WATER
&&
481 ((indspec
->behaviour
& INDUSTRYBEH_BUILT_ONWATER
) ||
482 HasBit(GetIndustryTileSpec(GetIndustryGfx(tile
))->slopes_refused
, 5)))) {
483 SetDParam(1, indspec
->name
);
484 return_cmd_error(flags
& DC_AUTO
? STR_ERROR_GENERIC_OBJECT_IN_THE_WAY
: INVALID_STRING_ID
);
487 if (flags
& DC_EXEC
) {
488 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i
->index
));
489 Game::NewEvent(new ScriptEventIndustryClose(i
->index
));
492 return CommandCost(EXPENSES_CONSTRUCTION
, indspec
->GetRemovalCost());
495 static void TransportIndustryGoods(TileIndex tile
)
497 Industry
*i
= Industry::GetByTile(tile
);
498 const IndustrySpec
*indspec
= GetIndustrySpec(i
->type
);
499 bool moved_cargo
= false;
501 StationFinder
stations(i
->location
);
503 for (uint j
= 0; j
< lengthof(i
->produced_cargo_waiting
); j
++) {
504 uint cw
= min(i
->produced_cargo_waiting
[j
], 255);
505 if (cw
> indspec
->minimal_cargo
&& i
->produced_cargo
[j
] != CT_INVALID
) {
506 i
->produced_cargo_waiting
[j
] -= cw
;
508 /* fluctuating economy? */
509 if (EconomyIsInRecession()) cw
= (cw
+ 1) / 2;
511 i
->this_month_production
[j
] += cw
;
513 uint am
= MoveGoodsToStation(i
->produced_cargo
[j
], cw
, ST_INDUSTRY
, i
->index
, stations
.GetStations());
514 i
->this_month_transported
[j
] += am
;
516 moved_cargo
|= (am
!= 0);
520 if (moved_cargo
&& !StartStopIndustryTileAnimation(i
, IAT_INDUSTRY_DISTRIBUTES_CARGO
)) {
521 uint newgfx
= GetIndustryTileSpec(GetIndustryGfx(tile
))->anim_production
;
523 if (newgfx
!= INDUSTRYTILE_NOANIM
) {
524 ResetIndustryConstructionStage(tile
);
525 SetIndustryCompleted(tile
);
526 SetIndustryGfx(tile
, newgfx
);
527 MarkTileDirtyByTile(tile
);
533 static void AnimateTile_Industry(TileIndex tile
)
535 IndustryGfx gfx
= GetIndustryGfx(tile
);
537 if (GetIndustryTileSpec(gfx
)->animation
.status
!= ANIM_STATUS_NO_ANIMATION
) {
538 AnimateNewIndustryTile(tile
);
543 case GFX_SUGAR_MINE_SIEVE
:
544 if ((_tick_counter
& 1) == 0) {
545 byte m
= GetAnimationFrame(tile
) + 1;
547 if (_settings_client
.sound
.ambient
) {
549 case 2: SndPlayTileFx(SND_2D_RIP_2
, tile
); break;
550 case 6: SndPlayTileFx(SND_29_RIP
, tile
); break;
556 DeleteAnimatedTile(tile
);
558 SetAnimationFrame(tile
, m
);
560 MarkTileDirtyByTile(tile
);
564 case GFX_TOFFEE_QUARY
:
565 if ((_tick_counter
& 3) == 0) {
566 byte m
= GetAnimationFrame(tile
);
568 if (_industry_anim_offs_toffee
[m
] == 0xFF && _settings_client
.sound
.ambient
) {
569 SndPlayTileFx(SND_30_CARTOON_SOUND
, tile
);
574 DeleteAnimatedTile(tile
);
576 SetAnimationFrame(tile
, m
);
578 MarkTileDirtyByTile(tile
);
582 case GFX_BUBBLE_CATCHER
:
583 if ((_tick_counter
& 1) == 0) {
584 byte m
= GetAnimationFrame(tile
);
588 DeleteAnimatedTile(tile
);
590 SetAnimationFrame(tile
, m
);
592 MarkTileDirtyByTile(tile
);
596 /* Sparks on a coal plant */
597 case GFX_POWERPLANT_SPARKS
:
598 if ((_tick_counter
& 3) == 0) {
599 byte m
= GetAnimationFrame(tile
);
601 SetAnimationFrame(tile
, 0);
602 DeleteAnimatedTile(tile
);
604 SetAnimationFrame(tile
, m
+ 1);
605 MarkTileDirtyByTile(tile
);
610 case GFX_TOY_FACTORY
:
611 if ((_tick_counter
& 1) == 0) {
612 byte m
= GetAnimationFrame(tile
) + 1;
615 case 1: if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_2C_MACHINERY
, tile
); break;
616 case 23: if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_2B_COMEDY_HIT
, tile
); break;
617 case 28: if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_2A_EXTRACT_AND_POP
, tile
); break;
620 int n
= GetIndustryAnimationLoop(tile
) + 1;
624 DeleteAnimatedTile(tile
);
626 SetIndustryAnimationLoop(tile
, n
);
630 SetAnimationFrame(tile
, m
);
631 MarkTileDirtyByTile(tile
);
635 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2
:
636 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4
:
637 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6
:
638 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8
:
639 if ((_tick_counter
& 3) == 0) {
640 IndustryGfx gfx
= GetIndustryGfx(tile
);
642 gfx
= (gfx
< 155) ? gfx
+ 1 : 148;
643 SetIndustryGfx(tile
, gfx
);
644 MarkTileDirtyByTile(tile
);
648 case GFX_OILWELL_ANIMATED_1
:
649 case GFX_OILWELL_ANIMATED_2
:
650 case GFX_OILWELL_ANIMATED_3
:
651 if ((_tick_counter
& 7) == 0) {
652 bool b
= Chance16(1, 7);
653 IndustryGfx gfx
= GetIndustryGfx(tile
);
655 byte m
= GetAnimationFrame(tile
) + 1;
656 if (m
== 4 && (m
= 0, ++gfx
) == GFX_OILWELL_ANIMATED_3
+ 1 && (gfx
= GFX_OILWELL_ANIMATED_1
, b
)) {
657 SetIndustryGfx(tile
, GFX_OILWELL_NOT_ANIMATED
);
658 SetIndustryConstructionStage(tile
, 3);
659 DeleteAnimatedTile(tile
);
661 SetAnimationFrame(tile
, m
);
662 SetIndustryGfx(tile
, gfx
);
663 MarkTileDirtyByTile(tile
);
668 case GFX_COAL_MINE_TOWER_ANIMATED
:
669 case GFX_COPPER_MINE_TOWER_ANIMATED
:
670 case GFX_GOLD_MINE_TOWER_ANIMATED
: {
671 int state
= _tick_counter
& 0x7FF;
673 if ((state
-= 0x400) < 0) return;
676 if (state
< 0x20 || state
>= 0x180) {
677 byte m
= GetAnimationFrame(tile
);
679 SetAnimationFrame(tile
, m
| 0x40);
680 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_0B_MINING_MACHINERY
, tile
);
682 if (state
& 7) return;
684 if (state
& 3) return;
686 byte m
= (GetAnimationFrame(tile
) + 1) | 0x40;
687 if (m
> 0xC2) m
= 0xC0;
688 SetAnimationFrame(tile
, m
);
689 MarkTileDirtyByTile(tile
);
690 } else if (state
>= 0x200 && state
< 0x3A0) {
691 int i
= (state
< 0x220 || state
>= 0x380) ? 7 : 3;
692 if (state
& i
) return;
694 byte m
= (GetAnimationFrame(tile
) & 0xBF) - 1;
695 if (m
< 0x80) m
= 0x82;
696 SetAnimationFrame(tile
, m
);
697 MarkTileDirtyByTile(tile
);
704 static void CreateChimneySmoke(TileIndex tile
)
706 uint x
= TileX(tile
) * TILE_SIZE
;
707 uint y
= TileY(tile
) * TILE_SIZE
;
708 int z
= GetTileMaxPixelZ(tile
);
710 CreateEffectVehicle(x
+ 15, y
+ 14, z
+ 59, EV_CHIMNEY_SMOKE
);
713 static void MakeIndustryTileBigger(TileIndex tile
)
715 byte cnt
= GetIndustryConstructionCounter(tile
) + 1;
717 SetIndustryConstructionCounter(tile
, cnt
);
721 byte stage
= GetIndustryConstructionStage(tile
) + 1;
722 SetIndustryConstructionCounter(tile
, 0);
723 SetIndustryConstructionStage(tile
, stage
);
724 StartStopIndustryTileAnimation(tile
, IAT_CONSTRUCTION_STATE_CHANGE
);
725 if (stage
== INDUSTRY_COMPLETED
) SetIndustryCompleted(tile
);
727 MarkTileDirtyByTile(tile
);
729 if (!IsIndustryCompleted(tile
)) return;
731 IndustryGfx gfx
= GetIndustryGfx(tile
);
732 if (gfx
>= NEW_INDUSTRYTILEOFFSET
) {
733 /* New industries are already animated on construction. */
738 case GFX_POWERPLANT_CHIMNEY
:
739 CreateChimneySmoke(tile
);
743 /* Do not require an industry tile to be after the first two GFX_OILRIG_1
744 * tiles (like the default oil rig). Do a proper check to ensure the
745 * tiles belong to the same industry and based on that build the oil rig's
747 TileIndex other
= tile
+ TileDiffXY(0, 1);
749 if (IsIndustryTile(other
) &&
750 GetIndustryGfx(other
) == GFX_OILRIG_1
&&
751 GetIndustryIndex(tile
) == GetIndustryIndex(other
)) {
757 case GFX_TOY_FACTORY
:
758 case GFX_BUBBLE_CATCHER
:
759 case GFX_TOFFEE_QUARY
:
760 SetAnimationFrame(tile
, 0);
761 SetIndustryAnimationLoop(tile
, 0);
764 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_2
:
765 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_4
:
766 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_6
:
767 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7
: case GFX_PLASTIC_FOUNTAIN_ANIMATED_8
:
768 AddAnimatedTile(tile
);
773 static void TileLoopIndustry_BubbleGenerator(TileIndex tile
)
775 static const int8 _bubble_spawn_location
[3][4] = {
781 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_2E_EXTRACT_AND_POP
, tile
);
783 int dir
= Random() & 3;
785 EffectVehicle
*v
= CreateEffectVehicleAbove(
786 TileX(tile
) * TILE_SIZE
+ _bubble_spawn_location
[0][dir
],
787 TileY(tile
) * TILE_SIZE
+ _bubble_spawn_location
[1][dir
],
788 _bubble_spawn_location
[2][dir
],
792 if (v
!= NULL
) v
->animation_substate
= dir
;
795 static void TileLoop_Industry(TileIndex tile
)
797 if (IsTileOnWater(tile
)) TileLoop_Water(tile
);
799 /* Normally this doesn't happen, but if an industry NewGRF is removed
800 * an industry that was previously build on water can now be flooded.
801 * If this happens the tile is no longer an industry tile after
802 * returning from TileLoop_Water. */
803 if (!IsIndustryTile(tile
)) return;
805 TriggerIndustryTile(tile
, INDTILE_TRIGGER_TILE_LOOP
);
807 if (!IsIndustryCompleted(tile
)) {
808 MakeIndustryTileBigger(tile
);
812 if (_game_mode
== GM_EDITOR
) return;
814 TransportIndustryGoods(tile
);
816 if (StartStopIndustryTileAnimation(tile
, IAT_TILELOOP
)) return;
818 IndustryGfx newgfx
= GetIndustryTileSpec(GetIndustryGfx(tile
))->anim_next
;
819 if (newgfx
!= INDUSTRYTILE_NOANIM
) {
820 ResetIndustryConstructionStage(tile
);
821 SetIndustryGfx(tile
, newgfx
);
822 MarkTileDirtyByTile(tile
);
826 IndustryGfx gfx
= GetIndustryGfx(tile
);
828 case GFX_COAL_MINE_TOWER_NOT_ANIMATED
:
829 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED
:
830 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED
:
831 if (!(_tick_counter
& 0x400) && Chance16(1, 2)) {
833 case GFX_COAL_MINE_TOWER_NOT_ANIMATED
: gfx
= GFX_COAL_MINE_TOWER_ANIMATED
; break;
834 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED
: gfx
= GFX_COPPER_MINE_TOWER_ANIMATED
; break;
835 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED
: gfx
= GFX_GOLD_MINE_TOWER_ANIMATED
; break;
837 SetIndustryGfx(tile
, gfx
);
838 SetAnimationFrame(tile
, 0x80);
839 AddAnimatedTile(tile
);
843 case GFX_OILWELL_NOT_ANIMATED
:
844 if (Chance16(1, 6)) {
845 SetIndustryGfx(tile
, GFX_OILWELL_ANIMATED_1
);
846 SetAnimationFrame(tile
, 0);
847 AddAnimatedTile(tile
);
851 case GFX_COAL_MINE_TOWER_ANIMATED
:
852 case GFX_COPPER_MINE_TOWER_ANIMATED
:
853 case GFX_GOLD_MINE_TOWER_ANIMATED
:
854 if (!(_tick_counter
& 0x400)) {
856 case GFX_COAL_MINE_TOWER_ANIMATED
: gfx
= GFX_COAL_MINE_TOWER_NOT_ANIMATED
; break;
857 case GFX_COPPER_MINE_TOWER_ANIMATED
: gfx
= GFX_COPPER_MINE_TOWER_NOT_ANIMATED
; break;
858 case GFX_GOLD_MINE_TOWER_ANIMATED
: gfx
= GFX_GOLD_MINE_TOWER_NOT_ANIMATED
; break;
860 SetIndustryGfx(tile
, gfx
);
861 SetIndustryCompleted(tile
);
862 SetIndustryConstructionStage(tile
, 3);
863 DeleteAnimatedTile(tile
);
867 case GFX_POWERPLANT_SPARKS
:
868 if (Chance16(1, 3)) {
869 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_0C_ELECTRIC_SPARK
, tile
);
870 AddAnimatedTile(tile
);
874 case GFX_COPPER_MINE_CHIMNEY
:
875 CreateEffectVehicleAbove(TileX(tile
) * TILE_SIZE
+ 6, TileY(tile
) * TILE_SIZE
+ 6, 43, EV_COPPER_MINE_SMOKE
);
879 case GFX_TOY_FACTORY
: {
880 Industry
*i
= Industry::GetByTile(tile
);
881 if (i
->was_cargo_delivered
) {
882 i
->was_cargo_delivered
= false;
883 SetIndustryAnimationLoop(tile
, 0);
884 AddAnimatedTile(tile
);
889 case GFX_BUBBLE_GENERATOR
:
890 TileLoopIndustry_BubbleGenerator(tile
);
893 case GFX_TOFFEE_QUARY
:
894 AddAnimatedTile(tile
);
897 case GFX_SUGAR_MINE_SIEVE
:
898 if (Chance16(1, 3)) AddAnimatedTile(tile
);
903 static bool ClickTile_Industry(TileIndex tile
)
905 ShowIndustryViewWindow(GetIndustryIndex(tile
));
909 static void ChangeTileOwner_Industry(TileIndex tile
, Owner old_owner
, Owner new_owner
)
911 /* If the founder merges, the industry was created by the merged company */
912 Industry
*i
= Industry::GetByTile(tile
);
913 if (i
->founder
== old_owner
) i
->founder
= (new_owner
== INVALID_OWNER
) ? OWNER_NONE
: new_owner
;
917 * Check whether the tile is a forest.
918 * @param tile the tile to investigate.
919 * @return true if and only if the tile is a forest
921 bool IsTileForestIndustry(TileIndex tile
)
923 /* Check for industry tile */
924 if (!IsIndustryTile(tile
)) return false;
926 const Industry
*ind
= Industry::GetByTile(tile
);
928 /* Check for organic industry (i.e. not processing or extractive) */
929 if ((GetIndustrySpec(ind
->type
)->life_type
& INDUSTRYLIFE_ORGANIC
) == 0) return false;
931 /* Check for wood production */
932 for (uint i
= 0; i
< lengthof(ind
->produced_cargo
); i
++) {
933 /* The industry produces wood. */
934 if (ind
->produced_cargo
[i
] != CT_INVALID
&& CargoSpec::Get(ind
->produced_cargo
[i
])->label
== 'WOOD') return true;
940 static const byte _plantfarmfield_type
[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
942 static bool IsValidFarmFieldTile(TileIndex tile
, bool allow_fields
)
944 if (!IsGroundTile(tile
)) return false;
946 return IsFieldsTile(tile
) ? allow_fields
:
947 !IsSnowTile(tile
) && !IsClearGround(tile
, GROUND_DESERT
) && !IsClearGround(tile
, GROUND_SHORE
);
950 static void SetupFarmFieldFence(TileIndex tile
, int size
, byte type
, DiagDirection side
)
952 TileIndexDiff diff
= (DiagDirToAxis(side
) == AXIS_Y
? TileDiffXY(1, 0) : TileDiffXY(0, 1));
955 tile
= TILE_MASK(tile
);
957 if (IsFieldsTile(tile
)) {
960 if (or_
== 1 && Chance16(1, 7)) or_
= 2;
962 SetFence(tile
, side
, or_
);
969 static void PlantFarmField(TileIndex tile
, IndustryID industry
)
971 if (_settings_game
.game_creation
.landscape
== LT_ARCTIC
) {
972 if (GetTileZ(tile
) + 2 >= GetSnowLine()) return;
975 /* determine field size */
976 uint32 r
= (Random() & 0x303) + 0x404;
977 if (_settings_game
.game_creation
.landscape
== LT_ARCTIC
) r
+= 0x404;
978 uint size_x
= GB(r
, 0, 8);
979 uint size_y
= GB(r
, 8, 8);
982 ta
.expand (size_x
/ 2, size_y
/ 2, size_x
- (size_x
/ 2), size_y
- (size_y
/ 2));
984 if (ta
.w
== 0 || ta
.h
== 0) return;
986 /* check the amount of bad tiles */
988 TILE_AREA_LOOP(cur_tile
, ta
) {
989 assert(cur_tile
< MapSize());
990 count
+= IsValidFarmFieldTile(cur_tile
, false);
992 if (count
* 2 < ta
.w
* ta
.h
) return;
994 /* determine type of field */
996 uint counter
= GB(r
, 5, 3);
997 uint field_type
= GB(r
, 8, 8) * 9 >> 8;
1000 TILE_AREA_LOOP(cur_tile
, ta
) {
1001 assert(cur_tile
< MapSize());
1002 if (IsValidFarmFieldTile(cur_tile
, true)) {
1003 MakeField(cur_tile
, field_type
, industry
);
1004 SetClearCounter(cur_tile
, counter
);
1005 MarkTileDirtyByTile(cur_tile
);
1010 if (_settings_game
.game_creation
.landscape
!= LT_ARCTIC
&& _settings_game
.game_creation
.landscape
!= LT_TROPIC
) {
1011 type
= _plantfarmfield_type
[Random() & 0xF];
1014 SetupFarmFieldFence(ta
.tile
, ta
.h
, type
, DIAGDIR_NE
);
1015 SetupFarmFieldFence(ta
.tile
, ta
.w
, type
, DIAGDIR_NW
);
1016 SetupFarmFieldFence(ta
.tile
+ TileDiffXY(ta
.w
- 1, 0), ta
.h
, type
, DIAGDIR_SW
);
1017 SetupFarmFieldFence(ta
.tile
+ TileDiffXY(0, ta
.h
- 1), ta
.w
, type
, DIAGDIR_SE
);
1020 void PlantRandomFarmField(const Industry
*i
)
1022 int x
= i
->location
.w
/ 2 + Random() % 31 - 16;
1023 int y
= i
->location
.h
/ 2 + Random() % 31 - 16;
1025 TileIndex tile
= TileAddWrap(i
->location
.tile
, x
, y
);
1027 if (tile
!= INVALID_TILE
) PlantFarmField(tile
, i
->index
);
1031 * Perform a circular search around the Lumber Mill in order to find trees to cut
1034 static void ChopLumberMillTrees(Industry
*i
)
1036 /* We only want to cut trees if all tiles are completed. */
1037 TILE_AREA_LOOP(tile_cur
, i
->location
) {
1038 if (i
->TileBelongsToIndustry(tile_cur
)) {
1039 if (!IsIndustryCompleted(tile_cur
)) return;
1043 TileIndex tile
= i
->location
.tile
;
1044 CircularTileIterator
iter (tile
, 40); // 40x40 tiles to search
1045 for (tile
= iter
; tile
!= INVALID_TILE
; tile
= ++iter
) {
1046 if (IsTreeTile(tile
) && GetTreeGrowth(tile
) > 2) { ///< 3 and up means all fully grown trees
1049 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_NONE
, FILE_LINE
);
1051 _industry_sound_ctr
= 1;
1052 _industry_sound_tile
= tile
;
1053 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_38_CHAINSAW
, tile
);
1055 DoCommand(tile
, 0, 0, DC_EXEC
, CMD_LANDSCAPE_CLEAR
);
1057 cur_company
.Restore();
1058 i
->produced_cargo_waiting
[0] = min(0xffff, i
->produced_cargo_waiting
[0] + 45); // Found a tree, add according value to waiting cargo.
1064 static void ProduceIndustryGoods(Industry
*i
)
1066 const IndustrySpec
*indsp
= GetIndustrySpec(i
->type
);
1069 if ((i
->counter
& 0x3F) == 0) {
1072 if (Chance16R(1, 14, r
) && (num
= indsp
->number_of_sounds
) != 0 && _settings_client
.sound
.ambient
) {
1074 (SoundFx
)(indsp
->random_sounds
[((r
>> 16) * num
) >> 16]),
1081 /* produce some cargo */
1082 if ((i
->counter
% INDUSTRY_PRODUCE_TICKS
) == 0) {
1083 if (HasBit(indsp
->callback_mask
, CBM_IND_PRODUCTION_256_TICKS
)) IndustryProductionCallback(i
, 1);
1085 IndustryBehaviour indbehav
= indsp
->behaviour
;
1086 i
->produced_cargo_waiting
[0] = min(0xffff, i
->produced_cargo_waiting
[0] + i
->production_rate
[0]);
1087 i
->produced_cargo_waiting
[1] = min(0xffff, i
->produced_cargo_waiting
[1] + i
->production_rate
[1]);
1089 if ((indbehav
& INDUSTRYBEH_PLANT_FIELDS
) != 0) {
1090 uint16 cb_res
= CALLBACK_FAILED
;
1091 if (HasBit(indsp
->callback_mask
, CBM_IND_SPECIAL_EFFECT
)) {
1092 cb_res
= GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT
, Random(), 0, i
, i
->type
, i
->location
.tile
);
1096 if (cb_res
!= CALLBACK_FAILED
) {
1097 plant
= ConvertBooleanCallback(indsp
->grf_prop
.grffile
, CBID_INDUSTRY_SPECIAL_EFFECT
, cb_res
);
1099 plant
= Chance16(1, 8);
1102 if (plant
) PlantRandomFarmField(i
);
1104 if ((indbehav
& INDUSTRYBEH_CUT_TREES
) != 0) {
1105 uint16 cb_res
= CALLBACK_FAILED
;
1106 if (HasBit(indsp
->callback_mask
, CBM_IND_SPECIAL_EFFECT
)) {
1107 cb_res
= GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT
, Random(), 1, i
, i
->type
, i
->location
.tile
);
1111 if (cb_res
!= CALLBACK_FAILED
) {
1112 cut
= ConvertBooleanCallback(indsp
->grf_prop
.grffile
, CBID_INDUSTRY_SPECIAL_EFFECT
, cb_res
);
1114 cut
= ((i
->counter
% INDUSTRY_CUT_TREE_TICKS
) == 0);
1117 if (cut
) ChopLumberMillTrees(i
);
1120 TriggerIndustry(i
, INDUSTRY_TRIGGER_INDUSTRY_TICK
);
1121 StartStopIndustryTileAnimation(i
, IAT_INDUSTRY_TICK
);
1125 void OnTick_Industry()
1127 if (_industry_sound_ctr
!= 0) {
1128 _industry_sound_ctr
++;
1130 if (_industry_sound_ctr
== 75) {
1131 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_37_BALLOON_SQUEAK
, _industry_sound_tile
);
1132 } else if (_industry_sound_ctr
== 160) {
1133 _industry_sound_ctr
= 0;
1134 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_36_CARTOON_CRASH
, _industry_sound_tile
);
1138 if (_game_mode
== GM_EDITOR
) return;
1141 FOR_ALL_INDUSTRIES(i
) {
1142 ProduceIndustryGoods(i
);
1147 * Check the conditions of #CHECK_NOTHING (Always succeeds).
1148 * @param tile %Tile to perform the checking.
1149 * @return Succeeded or failed command.
1151 static CommandCost
CheckNewIndustry_NULL(TileIndex tile
)
1153 return CommandCost();
1157 * Check the conditions of #CHECK_FOREST (Industry should be build above snow-line in arctic climate).
1158 * @param tile %Tile to perform the checking.
1159 * @return Succeeded or failed command.
1161 static CommandCost
CheckNewIndustry_Forest(TileIndex tile
)
1163 if (_settings_game
.game_creation
.landscape
== LT_ARCTIC
) {
1164 if (GetTileZ(tile
) < HighestSnowLine() + 2) {
1165 return_cmd_error(STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED
);
1168 return CommandCost();
1172 * Check the conditions of #CHECK_REFINERY (Industry should be positioned near edge of the map).
1173 * @param tile %Tile to perform the checking.
1174 * @return Succeeded or failed command.
1176 static CommandCost
CheckNewIndustry_OilRefinery(TileIndex tile
)
1178 if (_game_mode
== GM_EDITOR
) return CommandCost();
1179 if (DistanceFromEdge(TILE_ADDXY(tile
, 1, 1)) < _settings_game
.game_creation
.oil_refinery_limit
) return CommandCost();
1181 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED
);
1184 extern bool _ignore_restrictions
;
1187 * Check the conditions of #CHECK_OIL_RIG (Industries at sea should be positioned near edge of the map).
1188 * @param tile %Tile to perform the checking.
1189 * @return Succeeded or failed command.
1191 static CommandCost
CheckNewIndustry_OilRig(TileIndex tile
)
1193 if (_game_mode
== GM_EDITOR
&& _ignore_restrictions
) return CommandCost();
1194 if (TileHeight(tile
) == 0 &&
1195 DistanceFromEdge(TILE_ADDXY(tile
, 1, 1)) < _settings_game
.game_creation
.oil_refinery_limit
) return CommandCost();
1197 return_cmd_error(STR_ERROR_CAN_ONLY_BE_POSITIONED
);
1201 * Check the conditions of #CHECK_FARM (Industry should be below snow-line in arctic).
1202 * @param tile %Tile to perform the checking.
1203 * @return Succeeded or failed command.
1205 static CommandCost
CheckNewIndustry_Farm(TileIndex tile
)
1207 if (_settings_game
.game_creation
.landscape
== LT_ARCTIC
) {
1208 if (GetTileZ(tile
) + 2 >= HighestSnowLine()) {
1209 return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1212 return CommandCost();
1216 * Check the conditions of #CHECK_PLANTATION (Industry should NOT be in the desert).
1217 * @param tile %Tile to perform the checking.
1218 * @return Succeeded or failed command.
1220 static CommandCost
CheckNewIndustry_Plantation(TileIndex tile
)
1222 if (GetTropicZone(tile
) == TROPICZONE_DESERT
) {
1223 return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1225 return CommandCost();
1229 * Check the conditions of #CHECK_WATER (Industry should be in the desert).
1230 * @param tile %Tile to perform the checking.
1231 * @return Succeeded or failed command.
1233 static CommandCost
CheckNewIndustry_Water(TileIndex tile
)
1235 if (GetTropicZone(tile
) != TROPICZONE_DESERT
) {
1236 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT
);
1238 return CommandCost();
1242 * Check the conditions of #CHECK_LUMBERMILL (Industry should be in the rain forest).
1243 * @param tile %Tile to perform the checking.
1244 * @return Succeeded or failed command.
1246 static CommandCost
CheckNewIndustry_Lumbermill(TileIndex tile
)
1248 if (GetTropicZone(tile
) != TROPICZONE_RAINFOREST
) {
1249 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST
);
1251 return CommandCost();
1255 * Check the conditions of #CHECK_BUBBLEGEN (Industry should be in low land).
1256 * @param tile %Tile to perform the checking.
1257 * @return Succeeded or failed command.
1259 static CommandCost
CheckNewIndustry_BubbleGen(TileIndex tile
)
1261 if (GetTileZ(tile
) > 4) {
1262 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_LOW_AREAS
);
1264 return CommandCost();
1268 * Industrytype check function signature.
1269 * @param tile %Tile to check.
1270 * @return Succeeded or failed command.
1272 typedef CommandCost
CheckNewIndustryProc(TileIndex tile
);
1274 /** Check functions for different types of industry. */
1275 static CheckNewIndustryProc
* const _check_new_industry_procs
[CHECK_END
] = {
1276 CheckNewIndustry_NULL
, ///< CHECK_NOTHING
1277 CheckNewIndustry_Forest
, ///< CHECK_FOREST
1278 CheckNewIndustry_OilRefinery
, ///< CHECK_REFINERY
1279 CheckNewIndustry_Farm
, ///< CHECK_FARM
1280 CheckNewIndustry_Plantation
, ///< CHECK_PLANTATION
1281 CheckNewIndustry_Water
, ///< CHECK_WATER
1282 CheckNewIndustry_Lumbermill
, ///< CHECK_LUMBERMILL
1283 CheckNewIndustry_BubbleGen
, ///< CHECK_BUBBLEGEN
1284 CheckNewIndustry_OilRig
, ///< CHECK_OIL_RIG
1288 * Find a town for the industry, while checking for multiple industries in the same town.
1289 * @param tile Position of the industry to build.
1290 * @param type Industry type.
1291 * @param [out] town Pointer to return town for the new industry, \c NULL is written if no good town can be found.
1292 * @return Succeeded or failed command.
1294 * @pre \c *t != NULL
1295 * @post \c *t points to a town on success, and \c NULL on failure.
1297 static CommandCost
FindTownForIndustry(TileIndex tile
, int type
, Town
**t
)
1299 *t
= ClosestTownFromTile(tile
);
1301 if (_settings_game
.economy
.multiple_industry_per_town
) return CommandCost();
1304 FOR_ALL_INDUSTRIES(i
) {
1305 if (i
->type
== (byte
)type
&& i
->town
== *t
) {
1307 return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN
);
1311 return CommandCost();
1314 bool IsSlopeRefused(Slope current
, Slope refused
)
1316 if (IsSteepSlope(current
)) return true;
1317 if (current
!= SLOPE_FLAT
) {
1318 if (IsSteepSlope(refused
)) return true;
1320 Slope t
= ComplementSlope(current
);
1322 if ((refused
& SLOPE_W
) && (t
& SLOPE_NW
)) return true;
1323 if ((refused
& SLOPE_S
) && (t
& SLOPE_NE
)) return true;
1324 if ((refused
& SLOPE_E
) && (t
& SLOPE_SW
)) return true;
1325 if ((refused
& SLOPE_N
) && (t
& SLOPE_SE
)) return true;
1332 * Are the tiles of the industry free?
1333 * @param tile Position to check.
1334 * @param it Industry tiles table.
1335 * @param itspec_index The index of the itsepc to build/fund
1336 * @param type Type of the industry.
1337 * @param initial_random_bits The random bits the industry is going to have after construction.
1338 * @param founder Industry founder
1339 * @param creation_type The circumstances the industry is created under.
1340 * @param [out] custom_shape_check Perform custom check for the site.
1341 * @return Failed or succeeded command.
1343 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
)
1345 bool refused_slope
= false;
1346 bool custom_shape
= false;
1349 IndustryGfx gfx
= GetTranslatedIndustryTileID(it
->gfx
);
1350 TileIndex cur_tile
= TileAddWrap(tile
, it
->ti
.x
, it
->ti
.y
);
1352 if (!IsValidTile(cur_tile
)) {
1353 return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1356 if (gfx
== GFX_WATERTILE_SPECIALCHECK
) {
1357 if (!IsPlainWaterTile(cur_tile
) ||
1358 !IsTileFlat(cur_tile
)) {
1359 return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1362 CommandCost ret
= EnsureNoVehicleOnGround(cur_tile
);
1363 if (ret
.Failed()) return ret
;
1364 if (HasBridgeAbove(cur_tile
)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1366 const IndustryTileSpec
*its
= GetIndustryTileSpec(gfx
);
1368 IndustryBehaviour ind_behav
= GetIndustrySpec(type
)->behaviour
;
1370 /* Perform land/water check if not disabled */
1371 if (!HasBit(its
->slopes_refused
, 5) && ((HasTileWaterClass(cur_tile
) && IsTileOnWater(cur_tile
)) == !(ind_behav
& INDUSTRYBEH_BUILT_ONWATER
))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1373 if (HasBit(its
->callback_mask
, CBM_INDT_SHAPE_CHECK
)) {
1374 custom_shape
= true;
1375 CommandCost ret
= PerformIndustryTileSlopeCheck(tile
, cur_tile
, its
, type
, gfx
, itspec_index
, initial_random_bits
, founder
, creation_type
);
1376 if (ret
.Failed()) return ret
;
1378 Slope tileh
= GetTileSlope(cur_tile
);
1379 refused_slope
|= IsSlopeRefused(tileh
, its
->slopes_refused
);
1382 if ((ind_behav
& (INDUSTRYBEH_ONLY_INTOWN
| INDUSTRYBEH_TOWN1200_MORE
)) || // Tile must be a house
1383 ((ind_behav
& INDUSTRYBEH_ONLY_NEARTOWN
) && IsHouseTile(cur_tile
))) { // Tile is allowed to be a house (and it is a house)
1384 if (!IsHouseTile(cur_tile
)) {
1385 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS
);
1388 /* Clear the tiles as OWNER_TOWN to not affect town rating, and to not clear protected buildings */
1389 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_TOWN
, FILE_LINE
);
1390 CommandCost ret
= DoCommand(cur_tile
, 0, 0, DC_NONE
, CMD_LANDSCAPE_CLEAR
);
1391 cur_company
.Restore();
1393 if (ret
.Failed()) return ret
;
1395 /* Clear the tiles, but do not affect town ratings */
1396 CommandCost ret
= DoCommand(cur_tile
, 0, 0, DC_AUTO
| DC_NO_TEST_TOWN_RATING
| DC_NO_MODIFY_TOWN_RATING
, CMD_LANDSCAPE_CLEAR
);
1398 if (ret
.Failed()) return ret
;
1401 } while ((++it
)->ti
.x
!= -0x80);
1403 if (custom_shape_check
!= NULL
) *custom_shape_check
= custom_shape
;
1405 /* It is almost impossible to have a fully flat land in TG, so what we
1406 * do is that we check if we can make the land flat later on. See
1407 * CheckIfCanLevelIndustryPlatform(). */
1408 if (!refused_slope
|| (_settings_game
.game_creation
.land_generator
== LG_TERRAGENESIS
&& _generating_world
&& !custom_shape
&& !_ignore_restrictions
)) {
1409 return CommandCost();
1411 return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1415 * Is the industry allowed to be built at this place for the town?
1416 * @param tile Tile to construct the industry.
1417 * @param type Type of the industry.
1418 * @param t Town authority that the industry belongs to.
1419 * @return Succeeded or failed command.
1421 static CommandCost
CheckIfIndustryIsAllowed(TileIndex tile
, int type
, const Town
*t
)
1423 if ((GetIndustrySpec(type
)->behaviour
& INDUSTRYBEH_TOWN1200_MORE
) && t
->cache
.population
< 1200) {
1424 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200
);
1427 if ((GetIndustrySpec(type
)->behaviour
& INDUSTRYBEH_ONLY_NEARTOWN
) && DistanceMax(t
->xy
, tile
) > 9) {
1428 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_NEAR_TOWN_CENTER
);
1431 return CommandCost();
1434 static bool CheckCanTerraformSurroundingTiles(TileIndex tile
, uint height
, int internal
)
1436 /* Check if we don't leave the map */
1437 if (TileX(tile
) == 0 || TileY(tile
) == 0 || IsVoidTile(tile
)) return false;
1439 TileArea
ta(tile
- TileDiffXY(1, 1), 2, 2);
1440 TILE_AREA_LOOP(tile_walk
, ta
) {
1441 uint curh
= TileHeight(tile_walk
);
1442 /* Is the tile clear? */
1443 if (!IsGroundTile(tile_walk
)) return false;
1445 /* Don't allow too big of a change if this is the sub-tile check */
1446 if (internal
!= 0 && Delta(curh
, height
) > 1) return false;
1448 /* Different height, so the surrounding tiles of this tile
1449 * has to be correct too (in level, or almost in level)
1450 * else you get a chain-reaction of terraforming. */
1451 if (internal
== 0 && curh
!= height
) {
1452 if (TileX(tile_walk
) == 0 || TileY(tile_walk
) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk
+ TileDiffXY(-1, -1), height
, internal
+ 1)) {
1462 * This function tries to flatten out the land below an industry, without
1463 * damaging the surroundings too much.
1465 static bool CheckIfCanLevelIndustryPlatform(TileIndex tile
, DoCommandFlag flags
, const IndustryTileTable
*it
, int type
)
1467 const int MKEND
= -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
1471 /* Finds dimensions of largest variant of this industry */
1473 if (it
->gfx
== 0xFF) continue; // FF been a marquer for a check on clear water, skip it
1474 if (it
->ti
.x
> max_x
) max_x
= it
->ti
.x
;
1475 if (it
->ti
.y
> max_y
) max_y
= it
->ti
.y
;
1476 } while ((++it
)->ti
.x
!= MKEND
);
1478 /* Remember level height */
1479 uint h
= TileHeight(tile
);
1481 if (TileX(tile
) <= _settings_game
.construction
.industry_platform
+ 1U || TileY(tile
) <= _settings_game
.construction
.industry_platform
+ 1U) return false;
1482 /* Check that all tiles in area and surrounding are clear
1483 * this determines that there are no obstructing items */
1485 TileArea
ta(tile
+ TileDiffXY(-_settings_game
.construction
.industry_platform
, -_settings_game
.construction
.industry_platform
),
1486 max_x
+ 2 + 2 * _settings_game
.construction
.industry_platform
, max_y
+ 2 + 2 * _settings_game
.construction
.industry_platform
);
1488 if (TileX(ta
.tile
) + ta
.w
>= MapMaxX() || TileY(ta
.tile
) + ta
.h
>= MapMaxY()) return false;
1490 /* _current_company is OWNER_NONE for randomly generated industries and in editor, or the company who funded or prospected the industry.
1491 * Perform terraforming as OWNER_TOWN to disable autoslope and town ratings. */
1492 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_TOWN
, FILE_LINE
);
1494 TILE_AREA_LOOP(tile_walk
, ta
) {
1495 uint curh
= TileHeight(tile_walk
);
1497 /* This tile needs terraforming. Check if we can do that without
1498 * damaging the surroundings too much. */
1499 if (!CheckCanTerraformSurroundingTiles(tile_walk
, h
, 0)) {
1500 cur_company
.Restore();
1503 /* This is not 100% correct check, but the best we can do without modifying the map.
1504 * What is missing, is if the difference in height is more than 1.. */
1505 if (DoCommand(tile_walk
, SLOPE_N
, (curh
> h
) ? 0 : 1, flags
& ~DC_EXEC
, CMD_TERRAFORM_LAND
).Failed()) {
1506 cur_company
.Restore();
1512 if (flags
& DC_EXEC
) {
1513 /* Terraform the land under the industry */
1514 TILE_AREA_LOOP(tile_walk
, ta
) {
1515 uint curh
= TileHeight(tile_walk
);
1517 /* We give the terraforming for free here, because we can't calculate
1518 * exact cost in the test-round, and as we all know, that will cause
1519 * a nice assert if they don't match ;) */
1520 DoCommand(tile_walk
, SLOPE_N
, (curh
> h
) ? 0 : 1, flags
, CMD_TERRAFORM_LAND
);
1521 curh
+= (curh
> h
) ? -1 : 1;
1526 cur_company
.Restore();
1532 * Check that the new industry is far enough from conflicting industries.
1533 * @param tile Tile to construct the industry.
1534 * @param type Type of the new industry.
1535 * @return Succeeded or failed command.
1537 static CommandCost
CheckIfFarEnoughFromConflictingIndustry(TileIndex tile
, int type
)
1539 const IndustrySpec
*indspec
= GetIndustrySpec(type
);
1541 for (Industry::TileSet::Iterator
iter (&Industry::set
, tile
, 14); iter
.get_item() != NULL
; iter
.next()) {
1542 const Industry
*i
= iter
.get_item();
1544 /* Within 14 tiles from another industry is considered close */
1545 if (DistanceMax(tile
, i
->location
.tile
) > 14) continue;
1547 /* check if there are any conflicting industry types around */
1548 if (i
->type
== indspec
->conflicting
[0] ||
1549 i
->type
== indspec
->conflicting
[1] ||
1550 i
->type
== indspec
->conflicting
[2]) {
1551 return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE
);
1554 return CommandCost();
1558 * Advertise about a new industry opening.
1559 * @param ind Industry being opened.
1561 static void AdvertiseIndustryOpening(const Industry
*ind
)
1563 const IndustrySpec
*ind_spc
= GetIndustrySpec(ind
->type
);
1564 AddNewsItem
<IndustryNewsItem
> (ind_spc
->new_industry_text
,
1565 NT_INDUSTRY_OPEN
, ind
->index
,
1567 ind_spc
->new_industry_text
> STR_LAST_STRINGID
?
1568 STR_TOWN_NAME
: ind
->town
->index
,
1570 AI::BroadcastNewEvent(new ScriptEventIndustryOpen(ind
->index
));
1571 Game::NewEvent(new ScriptEventIndustryOpen(ind
->index
));
1575 * Put an industry on the map.
1576 * @param i Just allocated poolitem, mostly empty.
1577 * @param tile North tile of the industry.
1578 * @param type Type of the industry.
1579 * @param it Industrylayout to build.
1580 * @param layout Number of the layout.
1581 * @param t Nearest town.
1582 * @param founder Founder of the industry; OWNER_NONE in case of random construction.
1583 * @param initial_random_bits Random bits for the industry.
1585 static void DoCreateNewIndustry(Industry
*i
, TileIndex tile
, IndustryType type
, const IndustryTileTable
*it
, byte layout
, Town
*t
, Owner founder
, uint16 initial_random_bits
)
1587 const IndustrySpec
*indspec
= GetIndustrySpec(type
);
1589 i
->location
= TileArea(tile
, 1, 1);
1591 Industry::IncIndustryTypeCount(type
);
1593 i
->produced_cargo
[0] = indspec
->produced_cargo
[0];
1594 i
->produced_cargo
[1] = indspec
->produced_cargo
[1];
1595 i
->accepts_cargo
[0] = indspec
->accepts_cargo
[0];
1596 i
->accepts_cargo
[1] = indspec
->accepts_cargo
[1];
1597 i
->accepts_cargo
[2] = indspec
->accepts_cargo
[2];
1598 i
->production_rate
[0] = indspec
->production_rate
[0];
1599 i
->production_rate
[1] = indspec
->production_rate
[1];
1601 /* don't use smooth economy for industries using production related callbacks */
1602 if (indspec
->UsesSmoothEconomy()) {
1603 i
->production_rate
[0] = min((RandomRange(256) + 128) * i
->production_rate
[0] >> 8, 255);
1604 i
->production_rate
[1] = min((RandomRange(256) + 128) * i
->production_rate
[1] >> 8, 255);
1608 i
->owner
= OWNER_NONE
;
1610 uint16 r
= Random();
1611 i
->random_colour
= GB(r
, 0, 4);
1612 i
->counter
= GB(r
, 4, 12);
1613 i
->random
= initial_random_bits
;
1614 i
->produced_cargo_waiting
[0] = 0;
1615 i
->produced_cargo_waiting
[1] = 0;
1616 i
->incoming_cargo_waiting
[0] = 0;
1617 i
->incoming_cargo_waiting
[1] = 0;
1618 i
->incoming_cargo_waiting
[2] = 0;
1619 i
->this_month_production
[0] = 0;
1620 i
->this_month_production
[1] = 0;
1621 i
->this_month_transported
[0] = 0;
1622 i
->this_month_transported
[1] = 0;
1623 i
->last_month_pct_transported
[0] = 0;
1624 i
->last_month_pct_transported
[1] = 0;
1625 i
->last_month_transported
[0] = 0;
1626 i
->last_month_transported
[1] = 0;
1627 i
->was_cargo_delivered
= false;
1628 i
->last_prod_year
= _cur_year
;
1629 i
->founder
= founder
;
1631 i
->construction_date
= _date
;
1632 i
->construction_type
= (_game_mode
== GM_EDITOR
) ? ICT_SCENARIO_EDITOR
:
1633 (_generating_world
? ICT_MAP_GENERATION
: ICT_NORMAL_GAMEPLAY
);
1635 /* Adding 1 here makes it conform to specs of var44 of varaction2 for industries
1636 * 0 = created prior of newindustries
1637 * else, chosen layout + 1 */
1638 i
->selected_layout
= layout
+ 1;
1640 i
->prod_level
= PRODLEVEL_DEFAULT
;
1642 /* Call callbacks after the regular fields got initialised. */
1644 if (HasBit(indspec
->callback_mask
, CBM_IND_PROD_CHANGE_BUILD
)) {
1645 uint16 res
= GetIndustryCallback(CBID_INDUSTRY_PROD_CHANGE_BUILD
, 0, Random(), i
, type
, INVALID_TILE
);
1646 if (res
!= CALLBACK_FAILED
) {
1647 if (res
< PRODLEVEL_MINIMUM
|| res
> PRODLEVEL_MAXIMUM
) {
1648 ErrorUnknownCallbackResult(indspec
->grf_prop
.grffile
->grfid
, CBID_INDUSTRY_PROD_CHANGE_BUILD
, res
);
1650 i
->prod_level
= res
;
1651 i
->RecomputeProductionMultipliers();
1656 if (_generating_world
) {
1657 i
->last_month_production
[0] = i
->production_rate
[0] * 8;
1658 i
->last_month_production
[1] = i
->production_rate
[1] * 8;
1660 i
->last_month_production
[0] = i
->last_month_production
[1] = 0;
1663 if (HasBit(indspec
->callback_mask
, CBM_IND_DECIDE_COLOUR
)) {
1664 uint16 res
= GetIndustryCallback(CBID_INDUSTRY_DECIDE_COLOUR
, 0, 0, i
, type
, INVALID_TILE
);
1665 if (res
!= CALLBACK_FAILED
) {
1666 if (GB(res
, 4, 11) != 0) ErrorUnknownCallbackResult(indspec
->grf_prop
.grffile
->grfid
, CBID_INDUSTRY_DECIDE_COLOUR
, res
);
1667 i
->random_colour
= GB(res
, 0, 4);
1671 if (HasBit(indspec
->callback_mask
, CBM_IND_INPUT_CARGO_TYPES
)) {
1672 for (uint j
= 0; j
< lengthof(i
->accepts_cargo
); j
++) i
->accepts_cargo
[j
] = CT_INVALID
;
1673 for (uint j
= 0; j
< lengthof(i
->accepts_cargo
); j
++) {
1674 uint16 res
= GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES
, j
, 0, i
, type
, INVALID_TILE
);
1675 if (res
== CALLBACK_FAILED
|| GB(res
, 0, 8) == CT_INVALID
) break;
1676 if (indspec
->grf_prop
.grffile
->grf_version
>= 8 && res
>= 0x100) {
1677 ErrorUnknownCallbackResult(indspec
->grf_prop
.grffile
->grfid
, CBID_INDUSTRY_INPUT_CARGO_TYPES
, res
);
1680 i
->accepts_cargo
[j
] = GetCargoTranslation(GB(res
, 0, 8), indspec
->grf_prop
.grffile
);
1684 if (HasBit(indspec
->callback_mask
, CBM_IND_OUTPUT_CARGO_TYPES
)) {
1685 for (uint j
= 0; j
< lengthof(i
->produced_cargo
); j
++) i
->produced_cargo
[j
] = CT_INVALID
;
1686 for (uint j
= 0; j
< lengthof(i
->produced_cargo
); j
++) {
1687 uint16 res
= GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES
, j
, 0, i
, type
, INVALID_TILE
);
1688 if (res
== CALLBACK_FAILED
|| GB(res
, 0, 8) == CT_INVALID
) break;
1689 if (indspec
->grf_prop
.grffile
->grf_version
>= 8 && res
>= 0x100) {
1690 ErrorUnknownCallbackResult(indspec
->grf_prop
.grffile
->grfid
, CBID_INDUSTRY_OUTPUT_CARGO_TYPES
, res
);
1693 i
->produced_cargo
[j
] = GetCargoTranslation(GB(res
, 0, 8), indspec
->grf_prop
.grffile
);
1697 /* Plant the tiles */
1700 TileIndex cur_tile
= tile
+ ToTileIndexDiff(it
->ti
);
1702 if (it
->gfx
!= GFX_WATERTILE_SPECIALCHECK
) {
1703 i
->location
.Add(cur_tile
);
1705 WaterClass wc
= (IsPlainWaterTile(cur_tile
) ? GetWaterClass(cur_tile
) : WATER_CLASS_INVALID
);
1707 DoCommand(cur_tile
, 0, 0, DC_EXEC
| DC_NO_TEST_TOWN_RATING
| DC_NO_MODIFY_TOWN_RATING
, CMD_LANDSCAPE_CLEAR
);
1709 MakeIndustry(cur_tile
, i
->index
, it
->gfx
, Random(), wc
);
1711 if (_generating_world
) {
1712 SetIndustryConstructionCounter(cur_tile
, 3);
1713 SetIndustryConstructionStage(cur_tile
, 2);
1716 /* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
1717 IndustryGfx cur_gfx
= GetTranslatedIndustryTileID(it
->gfx
);
1718 const IndustryTileSpec
*its
= GetIndustryTileSpec(cur_gfx
);
1719 if (its
->animation
.status
!= ANIM_STATUS_NO_ANIMATION
) AddAnimatedTile(cur_tile
);
1721 } while ((++it
)->ti
.x
!= -0x80);
1723 if (GetIndustrySpec(i
->type
)->behaviour
& INDUSTRYBEH_PLANT_ON_BUILT
) {
1724 for (uint j
= 0; j
!= 50; j
++) PlantRandomFarmField(i
);
1726 InvalidateWindowData(WC_INDUSTRY_DIRECTORY
, 0, 0);
1728 Station::RecomputeIndustriesNearForAll();
1732 * Helper function for Build/Fund an industry
1733 * @param tile tile where industry is built
1734 * @param type of industry to build
1735 * @param flags of operations to conduct
1736 * @param indspec pointer to industry specifications
1737 * @param itspec_index the index of the itsepc to build/fund
1738 * @param seed random seed (possibly) used by industries
1739 * @param initial_random_bits The random bits the industry is going to have after construction.
1740 * @param founder Founder of the industry
1741 * @param creation_type The circumstances the industry is created under.
1742 * @param [out] ip Pointer to store newly created industry.
1743 * @return Succeeded or failed command.
1745 * @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.
1747 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
)
1749 assert(itspec_index
< indspec
->num_table
);
1750 const IndustryTileTable
*it
= indspec
->table
[itspec_index
];
1751 bool custom_shape_check
= false;
1755 SmallVector
<ClearedObjectArea
, 1> object_areas(_cleared_object_areas
);
1756 CommandCost ret
= CheckIfIndustryTilesAreFree(tile
, it
, itspec_index
, type
, random_initial_bits
, founder
, creation_type
, &custom_shape_check
);
1757 _cleared_object_areas
= object_areas
;
1758 if (ret
.Failed()) return ret
;
1760 if (HasBit(GetIndustrySpec(type
)->callback_mask
, CBM_IND_LOCATION
)) {
1761 ret
= CheckIfCallBackAllowsCreation(tile
, type
, itspec_index
, random_var8f
, random_initial_bits
, founder
, creation_type
);
1763 ret
= _check_new_industry_procs
[indspec
->check_proc
](tile
);
1765 if (ret
.Failed()) return ret
;
1767 if (!custom_shape_check
&& _settings_game
.game_creation
.land_generator
== LG_TERRAGENESIS
&& _generating_world
&&
1768 !_ignore_restrictions
&& !CheckIfCanLevelIndustryPlatform(tile
, DC_NO_WATER
, it
, type
)) {
1769 return_cmd_error(STR_ERROR_SITE_UNSUITABLE
);
1772 ret
= CheckIfFarEnoughFromConflictingIndustry(tile
, type
);
1773 if (ret
.Failed()) return ret
;
1776 ret
= FindTownForIndustry(tile
, type
, &t
);
1777 if (ret
.Failed()) return ret
;
1780 ret
= CheckIfIndustryIsAllowed(tile
, type
, t
);
1781 if (ret
.Failed()) return ret
;
1783 if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES
);
1785 if (flags
& DC_EXEC
) {
1786 *ip
= new Industry(tile
);
1787 if (!custom_shape_check
) CheckIfCanLevelIndustryPlatform(tile
, DC_NO_WATER
| DC_EXEC
, it
, type
);
1788 DoCreateNewIndustry(*ip
, tile
, type
, it
, itspec_index
, t
, founder
, random_initial_bits
);
1791 return CommandCost();
1795 * Build/Fund an industry
1796 * @param tile tile where industry is built
1797 * @param flags of operations to conduct
1798 * @param p1 various bitstuffed elements
1799 * - p1 = (bit 0 - 7) - industry type see build_industry.h and see industry.h
1800 * - p1 = (bit 8 - 15) - first layout to try
1801 * - p1 = (bit 16 ) - 0 = prospect, 1 = fund (only valid if current company is DEITY)
1802 * @param p2 seed to use for desyncfree randomisations
1803 * @param text unused
1804 * @return the cost of this operation or an error
1806 CommandCost
CmdBuildIndustry(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1808 IndustryType it
= GB(p1
, 0, 8);
1809 if (it
>= NUM_INDUSTRYTYPES
) return CMD_ERROR
;
1811 const IndustrySpec
*indspec
= GetIndustrySpec(it
);
1813 /* Check if the to-be built/founded industry is available for this climate. */
1814 if (!indspec
->enabled
|| indspec
->num_table
== 0) return CMD_ERROR
;
1816 /* If the setting for raw-material industries is not on, you cannot build raw-material industries.
1817 * Raw material industries are industries that do not accept cargo (at least for now) */
1818 if (_game_mode
!= GM_EDITOR
&& _current_company
!= OWNER_DEITY
&& _settings_game
.construction
.raw_industry_construction
== 0 && indspec
->IsRawIndustry()) {
1822 if (_game_mode
!= GM_EDITOR
&& GetIndustryProbabilityCallback(it
, _current_company
== OWNER_DEITY
? IACT_RANDOMCREATION
: IACT_USERCREATION
, 1) == 0) {
1826 Randomizer randomizer
;
1827 randomizer
.SetSeed(p2
);
1828 uint16 random_initial_bits
= GB(p2
, 0, 16);
1829 uint32 random_var8f
= randomizer
.Next();
1830 int num_layouts
= indspec
->num_table
;
1831 CommandCost ret
= CommandCost(STR_ERROR_SITE_UNSUITABLE
);
1832 const bool deity_prospect
= _current_company
== OWNER_DEITY
&& !HasBit(p1
, 16);
1834 Industry
*ind
= NULL
;
1835 if (deity_prospect
|| (_game_mode
!= GM_EDITOR
&& _current_company
!= OWNER_DEITY
&& _settings_game
.construction
.raw_industry_construction
== 2 && indspec
->IsRawIndustry())) {
1836 if (flags
& DC_EXEC
) {
1837 /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */
1838 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_TOWN
, FILE_LINE
);
1839 /* Prospecting has a chance to fail, however we cannot guarantee that something can
1840 * be built on the map, so the chance gets lower when the map is fuller, but there
1841 * is nothing we can really do about that. */
1842 if (deity_prospect
|| Random() <= indspec
->prospecting_chance
) {
1843 for (int i
= 0; i
< 5000; i
++) {
1844 /* We should not have more than one Random() in a function call
1845 * because parameter evaluation order is not guaranteed in the c++ standard
1847 tile
= RandomTile();
1848 /* Start with a random layout */
1849 int layout
= RandomRange(num_layouts
);
1850 /* Check now each layout, starting with the random one */
1851 for (int j
= 0; j
< num_layouts
; j
++) {
1852 layout
= (layout
+ 1) % num_layouts
;
1853 ret
= CreateNewIndustryHelper(tile
, it
, flags
, indspec
, layout
, random_var8f
, random_initial_bits
, cur_company
.GetOriginalValue(), _current_company
== OWNER_DEITY
? IACT_RANDOMCREATION
: IACT_PROSPECTCREATION
, &ind
);
1854 if (ret
.Succeeded()) break;
1856 if (ret
.Succeeded()) break;
1859 cur_company
.Restore();
1862 int layout
= GB(p1
, 8, 8);
1863 if (layout
>= num_layouts
) return CMD_ERROR
;
1865 /* Check subsequently each layout, starting with the given layout in p1 */
1866 for (int i
= 0; i
< num_layouts
; i
++) {
1867 layout
= (layout
+ 1) % num_layouts
;
1868 ret
= CreateNewIndustryHelper(tile
, it
, flags
, indspec
, layout
, random_var8f
, random_initial_bits
, _current_company
, _current_company
== OWNER_DEITY
? IACT_RANDOMCREATION
: IACT_USERCREATION
, &ind
);
1869 if (ret
.Succeeded()) break;
1872 /* If it still failed, there's no suitable layout to build here, return the error */
1873 if (ret
.Failed()) return ret
;
1876 if ((flags
& DC_EXEC
) && ind
!= NULL
&& _game_mode
!= GM_EDITOR
) {
1877 AdvertiseIndustryOpening(ind
);
1880 return CommandCost(EXPENSES_OTHER
, indspec
->GetConstructionCost());
1885 * Create a new industry of random layout.
1886 * @param tile The location to build the industry.
1887 * @param type The industry type to build.
1888 * @param creation_type The circumstances the industry is created under.
1889 * @return the created industry or NULL if it failed.
1891 static Industry
*CreateNewIndustry(TileIndex tile
, IndustryType type
, IndustryAvailabilityCallType creation_type
)
1893 const IndustrySpec
*indspec
= GetIndustrySpec(type
);
1895 uint32 seed
= Random();
1896 uint32 seed2
= Random();
1898 CommandCost ret
= CreateNewIndustryHelper(tile
, type
, DC_EXEC
, indspec
, RandomRange(indspec
->num_table
), seed
, GB(seed2
, 0, 16), OWNER_NONE
, creation_type
, &i
);
1899 assert(i
!= NULL
|| ret
.Failed());
1904 * Compute the appearance probability for an industry during map creation.
1905 * @param it Industry type to compute.
1906 * @param [out] force_at_least_one Returns whether at least one instance should be forced on map creation.
1907 * @return Relative probability for the industry to appear.
1909 static uint32
GetScaledIndustryGenerationProbability(IndustryType it
, bool *force_at_least_one
)
1911 const IndustrySpec
*ind_spc
= GetIndustrySpec(it
);
1912 uint32 chance
= ind_spc
->appear_creation
[_settings_game
.game_creation
.landscape
] * 16; // * 16 to increase precision
1913 if (!ind_spc
->enabled
|| ind_spc
->num_table
== 0 ||
1914 (_game_mode
!= GM_EDITOR
&& _settings_game
.difficulty
.industry_density
== ID_FUND_ONLY
) ||
1915 (chance
= GetIndustryProbabilityCallback(it
, IACT_MAPGENERATION
, chance
)) == 0) {
1916 *force_at_least_one
= false;
1919 /* We want industries appearing at coast to appear less often on bigger maps, as length of coast increases slower than map area.
1920 * For simplicity we scale in both cases, though scaling the probabilities of all industries has no effect. */
1921 chance
= (ind_spc
->check_proc
== CHECK_REFINERY
|| ind_spc
->check_proc
== CHECK_OIL_RIG
) ? ScaleByMapPerimeter(chance
) : ScaleByMapSize(chance
);
1923 *force_at_least_one
= (chance
> 0) && !(ind_spc
->behaviour
& INDUSTRYBEH_NOBUILT_MAPCREATION
) && (_game_mode
!= GM_EDITOR
);
1929 * Compute the probability for constructing a new industry during game play.
1930 * @param it Industry type to compute.
1931 * @param [out] min_number Minimal number of industries that should exist at the map.
1932 * @return Relative probability for the industry to appear.
1934 static uint16
GetIndustryGamePlayProbability(IndustryType it
, byte
*min_number
)
1936 if (_settings_game
.difficulty
.industry_density
== ID_FUND_ONLY
) {
1941 const IndustrySpec
*ind_spc
= GetIndustrySpec(it
);
1942 byte chance
= ind_spc
->appear_ingame
[_settings_game
.game_creation
.landscape
];
1943 if (!ind_spc
->enabled
|| ind_spc
->num_table
== 0 ||
1944 ((ind_spc
->behaviour
& INDUSTRYBEH_BEFORE_1950
) && _cur_year
> 1950) ||
1945 ((ind_spc
->behaviour
& INDUSTRYBEH_AFTER_1960
) && _cur_year
< 1960) ||
1946 (chance
= GetIndustryProbabilityCallback(it
, IACT_RANDOMCREATION
, chance
)) == 0) {
1950 *min_number
= (ind_spc
->behaviour
& INDUSTRYBEH_CANCLOSE_LASTINSTANCE
) ? 1 : 0;
1955 * Get wanted number of industries on the map.
1956 * @return Wanted number of industries at the map.
1958 static uint
GetNumberOfIndustries()
1960 /* Number of industries on a 256x256 map. */
1961 static const uint16 numof_industry_table
[] = {
1970 assert(lengthof(numof_industry_table
) == ID_END
);
1971 uint difficulty
= (_game_mode
!= GM_EDITOR
) ? _settings_game
.difficulty
.industry_density
: (uint
)ID_VERY_LOW
;
1972 return min(Industry::Pool::MAX_SIZE
, ScaleByMapSize(numof_industry_table
[difficulty
]));
1976 * Try to place the industry in the game.
1977 * Since there is no feedback why placement fails, there is no other option
1978 * than to try a few times before concluding it does not work.
1979 * @param type Industry type of the desired industry.
1980 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type.)
1981 * @return Pointer to created industry, or \c NULL if creation failed.
1983 static Industry
*PlaceIndustry(IndustryType type
, IndustryAvailabilityCallType creation_type
, bool try_hard
)
1985 uint tries
= try_hard
? 10000u : 2000u;
1986 for (; tries
> 0; tries
--) {
1987 Industry
*ind
= CreateNewIndustry(RandomTile(), type
, creation_type
);
1988 if (ind
!= NULL
) return ind
;
1994 * Try to build a industry on the map.
1995 * @param type IndustryType of the desired industry
1996 * @param try_hard Try very hard to find a place. (Used to place at least one industry per type)
1998 static void PlaceInitialIndustry(IndustryType type
, bool try_hard
)
2000 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_NONE
, FILE_LINE
);
2002 IncreaseGeneratingWorldProgress(GWP_INDUSTRY
);
2003 PlaceIndustry(type
, IACT_MAPGENERATION
, try_hard
);
2005 cur_company
.Restore();
2009 * Get total number of industries existing in the game.
2010 * @return Number of industries currently in the game.
2012 static uint
GetCurrentTotalNumberOfIndustries()
2015 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) total
+= Industry::GetIndustryTypeCount(it
);
2020 /** Reset the entry. */
2021 void IndustryTypeBuildData::Reset()
2023 this->probability
= 0;
2024 this->min_number
= 0;
2025 this->target_count
= 0;
2027 this->wait_count
= 0;
2030 /** Completely reset the industry build data. */
2031 void IndustryBuildData::Reset()
2033 this->wanted_inds
= GetCurrentTotalNumberOfIndustries() << 16;
2035 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2036 this->builddata
[it
].Reset();
2040 /** Monthly update of industry build data. */
2041 void IndustryBuildData::MonthlyLoop()
2043 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.
2044 if (_settings_game
.difficulty
.industry_density
== ID_FUND_ONLY
) return; // 'no industries' setting.
2046 /* To prevent running out of unused industries for the player to connect,
2047 * add a fraction of new industries each month, but only if the manager can keep up. */
2048 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).
2049 if (GetCurrentTotalNumberOfIndustries() + max_behind
>= (this->wanted_inds
>> 16)) {
2050 this->wanted_inds
+= ScaleByMapSize(NEWINDS_PER_MONTH
);
2055 * This function will create random industries during game creation.
2056 * It will scale the amount of industries by mapsize and difficulty level.
2058 void GenerateIndustries()
2060 if (_game_mode
!= GM_EDITOR
&& _settings_game
.difficulty
.industry_density
== ID_FUND_ONLY
) return; // No industries in the game.
2062 uint32 industry_probs
[NUM_INDUSTRYTYPES
];
2063 bool force_at_least_one
[NUM_INDUSTRYTYPES
];
2064 uint32 total_prob
= 0;
2065 uint num_forced
= 0;
2067 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2068 industry_probs
[it
] = GetScaledIndustryGenerationProbability(it
, force_at_least_one
+ it
);
2069 total_prob
+= industry_probs
[it
];
2070 if (force_at_least_one
[it
]) num_forced
++;
2073 uint total_amount
= GetNumberOfIndustries();
2074 if (total_prob
== 0 || total_amount
< num_forced
) {
2075 /* Only place the forced ones */
2076 total_amount
= num_forced
;
2079 SetGeneratingWorldProgress(GWP_INDUSTRY
, total_amount
);
2081 /* Try to build one industry per type independent of any probabilities */
2082 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2083 if (force_at_least_one
[it
]) {
2084 assert(total_amount
> 0);
2086 PlaceInitialIndustry(it
, true);
2090 /* Add the remaining industries according to their probabilities */
2091 for (uint i
= 0; i
< total_amount
; i
++) {
2092 uint32 r
= RandomRange(total_prob
);
2093 IndustryType it
= 0;
2094 while (r
>= industry_probs
[it
]) {
2095 r
-= industry_probs
[it
];
2097 assert(it
< NUM_INDUSTRYTYPES
);
2099 assert(industry_probs
[it
] > 0);
2100 PlaceInitialIndustry(it
, false);
2102 _industry_builder
.Reset();
2106 * Monthly update of industry statistics.
2107 * @param i Industry to update.
2109 static void UpdateIndustryStatistics(Industry
*i
)
2111 for (byte j
= 0; j
< lengthof(i
->produced_cargo
); j
++) {
2112 if (i
->produced_cargo
[j
] != CT_INVALID
) {
2114 if (i
->this_month_production
[j
] != 0) {
2115 i
->last_prod_year
= _cur_year
;
2116 pct
= min(i
->this_month_transported
[j
] * 256 / i
->this_month_production
[j
], 255);
2118 i
->last_month_pct_transported
[j
] = pct
;
2120 i
->last_month_production
[j
] = i
->this_month_production
[j
];
2121 i
->this_month_production
[j
] = 0;
2123 i
->last_month_transported
[j
] = i
->this_month_transported
[j
];
2124 i
->this_month_transported
[j
] = 0;
2130 * Recompute #production_rate for current #prod_level.
2131 * This function is only valid when not using smooth economy.
2133 void Industry::RecomputeProductionMultipliers()
2135 const IndustrySpec
*indspec
= GetIndustrySpec(this->type
);
2136 assert(!indspec
->UsesSmoothEconomy());
2138 /* Rates are rounded up, so e.g. oilrig always produces some passengers */
2139 this->production_rate
[0] = min(CeilDiv(indspec
->production_rate
[0] * this->prod_level
, PRODLEVEL_DEFAULT
), 0xFF);
2140 this->production_rate
[1] = min(CeilDiv(indspec
->production_rate
[1] * this->prod_level
, PRODLEVEL_DEFAULT
), 0xFF);
2145 * Set the #probability and #min_number fields for the industry type \a it for a running game.
2146 * @param it Industry type.
2147 * @return At least one of the fields has changed value.
2149 bool IndustryTypeBuildData::GetIndustryTypeData(IndustryType it
)
2152 uint32 probability
= GetIndustryGamePlayProbability(it
, &min_number
);
2153 bool changed
= min_number
!= this->min_number
|| probability
!= this->probability
;
2154 this->min_number
= min_number
;
2155 this->probability
= probability
;
2159 /** Decide how many industries of each type are needed. */
2160 void IndustryBuildData::SetupTargetCount()
2162 bool changed
= false;
2163 uint num_planned
= 0; // Number of industries planned in the industry build data.
2164 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2165 changed
|= this->builddata
[it
].GetIndustryTypeData(it
);
2166 num_planned
+= this->builddata
[it
].target_count
;
2168 uint total_amount
= this->wanted_inds
>> 16; // Desired total number of industries.
2169 changed
|= num_planned
!= total_amount
;
2170 if (!changed
) return; // All industries are still the same, no need to re-randomize.
2172 /* Initialize the target counts. */
2173 uint force_build
= 0; // Number of industries that should always be available.
2174 uint32 total_prob
= 0; // Sum of probabilities.
2175 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2176 IndustryTypeBuildData
*ibd
= this->builddata
+ it
;
2177 force_build
+= ibd
->min_number
;
2178 ibd
->target_count
= ibd
->min_number
;
2179 total_prob
+= ibd
->probability
;
2182 if (total_prob
== 0) return; // No buildable industries.
2184 /* Subtract forced industries from the number of industries available for construction. */
2185 total_amount
= (total_amount
<= force_build
) ? 0 : total_amount
- force_build
;
2187 /* Assign number of industries that should be aimed for, by using the probability as a weight. */
2188 while (total_amount
> 0) {
2189 uint32 r
= RandomRange(total_prob
);
2190 IndustryType it
= 0;
2191 while (r
>= this->builddata
[it
].probability
) {
2192 r
-= this->builddata
[it
].probability
;
2194 assert(it
< NUM_INDUSTRYTYPES
);
2196 assert(this->builddata
[it
].probability
> 0);
2197 this->builddata
[it
].target_count
++;
2203 * Try to create a random industry, during gameplay
2205 void IndustryBuildData::TryBuildNewIndustry()
2207 this->SetupTargetCount();
2209 int missing
= 0; // Number of industries that need to be build.
2210 uint count
= 0; // Number of industry types eligible for build.
2211 uint32 total_prob
= 0; // Sum of probabilities.
2212 IndustryType forced_build
= NUM_INDUSTRYTYPES
; // Industry type that should be forcibly build.
2213 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2214 int difference
= this->builddata
[it
].target_count
- Industry::GetIndustryTypeCount(it
);
2215 missing
+= difference
;
2216 if (this->builddata
[it
].wait_count
> 0) continue; // This type may not be built now.
2217 if (difference
> 0) {
2218 if (Industry::GetIndustryTypeCount(it
) == 0 && this->builddata
[it
].min_number
> 0) {
2219 /* An industry that should exist at least once, is not available. Force it, trying the most needed one first. */
2220 if (forced_build
== NUM_INDUSTRYTYPES
||
2221 difference
> this->builddata
[forced_build
].target_count
- Industry::GetIndustryTypeCount(forced_build
)) {
2225 total_prob
+= difference
;
2230 if (EconomyIsInRecession() || (forced_build
== NUM_INDUSTRYTYPES
&& (missing
<= 0 || total_prob
== 0))) count
= 0; // Skip creation of an industry.
2233 /* If not forced, pick a weighted random industry to build.
2234 * For the case that count == 1, there is no need to draw a random number. */
2236 if (forced_build
!= NUM_INDUSTRYTYPES
) {
2239 /* Non-forced, select an industry type to build (weighted random). */
2240 uint32 r
= 0; // Initialized to silence the compiler.
2241 if (count
> 1) r
= RandomRange(total_prob
);
2242 for (it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2243 if (this->builddata
[it
].wait_count
> 0) continue; // Type may not be built now.
2244 int difference
= this->builddata
[it
].target_count
- Industry::GetIndustryTypeCount(it
);
2245 if (difference
<= 0) continue; // Too many of this kind.
2246 if (count
== 1) break;
2247 if (r
< (uint
)difference
) break;
2250 assert(it
< NUM_INDUSTRYTYPES
&& this->builddata
[it
].target_count
> Industry::GetIndustryTypeCount(it
));
2253 /* Try to create the industry. */
2254 const Industry
*ind
= PlaceIndustry(it
, IACT_RANDOMCREATION
, false);
2256 this->builddata
[it
].wait_count
= this->builddata
[it
].max_wait
+ 1; // Compensate for decrementing below.
2257 this->builddata
[it
].max_wait
= min(1000, this->builddata
[it
].max_wait
+ 2);
2259 AdvertiseIndustryOpening(ind
);
2260 this->builddata
[it
].max_wait
= max(this->builddata
[it
].max_wait
/ 2, 1); // Reduce waiting time of the industry type.
2264 /* Decrement wait counters. */
2265 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2266 if (this->builddata
[it
].wait_count
> 0) this->builddata
[it
].wait_count
--;
2271 * Protects an industry from closure if the appropriate flags and conditions are met
2272 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the
2273 * count of industries of this type must one (or lower) in order to be protected
2275 * @param type IndustryType been queried
2276 * @result true if protection is on, false otherwise (except for oil wells)
2278 static bool CheckIndustryCloseDownProtection(IndustryType type
)
2280 const IndustrySpec
*indspec
= GetIndustrySpec(type
);
2282 /* oil wells (or the industries with that flag set) are always allowed to closedown */
2283 if ((indspec
->behaviour
& INDUSTRYBEH_DONT_INCR_PROD
) && _settings_game
.game_creation
.landscape
== LT_TEMPERATE
) return false;
2284 return (indspec
->behaviour
& INDUSTRYBEH_CANCLOSE_LASTINSTANCE
) == 0 && Industry::GetIndustryTypeCount(type
) <= 1;
2288 * Can given cargo type be accepted or produced by the industry?
2289 * @param cargo: Cargo type
2290 * @param ind: Industry
2291 * @param *c_accepts: Pointer to boolean for acceptance of cargo
2292 * @param *c_produces: Pointer to boolean for production of cargo
2293 * @return: \c *c_accepts is set when industry accepts the cargo type,
2294 * \c *c_produces is set when the industry produces the cargo type
2296 static void CanCargoServiceIndustry(CargoID cargo
, Industry
*ind
, bool *c_accepts
, bool *c_produces
)
2298 if (cargo
== CT_INVALID
) return;
2300 /* Check for acceptance of cargo */
2301 for (byte j
= 0; j
< lengthof(ind
->accepts_cargo
); j
++) {
2302 if (cargo
== ind
->accepts_cargo
[j
] && !IndustryTemporarilyRefusesCargo(ind
, cargo
)) {
2308 /* Check for produced cargo */
2309 for (byte j
= 0; j
< lengthof(ind
->produced_cargo
); j
++) {
2310 if (cargo
== ind
->produced_cargo
[j
]) {
2318 * Compute who can service the industry.
2320 * Here, 'can service' means that he/she has trains and stations close enough
2321 * to the industry with the right cargo type and the right orders (ie has the
2324 * @param ind: Industry being investigated.
2326 * @return The NewsType to use for a production change in this industry.
2328 static NewsType
IndustryServiceNewsType (Industry
*ind
)
2330 /* Find all stations within reach of the industry */
2331 StationList stations
;
2332 FindStationsAroundTiles(ind
->location
, &stations
);
2334 if (stations
.Length() == 0) return NT_INDUSTRY_NOBODY
; // No stations found at all
2338 FOR_ALL_VEHICLES(v
) {
2339 /* Is it worthwhile to try this vehicle? */
2340 if (v
->owner
!= _local_company
&& result
!= 0) continue;
2342 /* Check whether it accepts the right kind of cargo */
2343 bool c_accepts
= false;
2344 bool c_produces
= false;
2345 if (v
->type
== VEH_TRAIN
&& v
->IsFrontEngine()) {
2346 for (const Vehicle
*u
= v
; u
!= NULL
; u
= u
->Next()) {
2347 CanCargoServiceIndustry(u
->cargo_type
, ind
, &c_accepts
, &c_produces
);
2349 } else if (v
->type
== VEH_ROAD
|| v
->type
== VEH_SHIP
|| v
->type
== VEH_AIRCRAFT
) {
2350 CanCargoServiceIndustry(v
->cargo_type
, ind
, &c_accepts
, &c_produces
);
2354 if (!c_accepts
&& !c_produces
) continue; // Wrong cargo
2356 /* Check orders of the vehicle.
2357 * We cannot check the first of shared orders only, since the first vehicle in such a chain
2358 * may have a different cargo type.
2361 FOR_VEHICLE_ORDERS(v
, o
) {
2362 if (o
->IsType(OT_GOTO_STATION
) && !(o
->GetUnloadType() & OUFB_TRANSFER
)) {
2363 /* Vehicle visits a station to load or unload */
2364 Station
*st
= Station::Get(o
->GetDestination());
2367 /* Same cargo produced by industry is dropped here => not serviced by vehicle v */
2368 if ((o
->GetUnloadType() & OUFB_UNLOAD
) && !c_accepts
) break;
2370 if (stations
.Contains(st
)) {
2371 if (v
->owner
== _local_company
) return NT_INDUSTRY_COMPANY
; // Company services industry
2372 result
= 1; // Competitor services industry
2377 return result
? NT_INDUSTRY_OTHER
: NT_INDUSTRY_NOBODY
;
2380 static const uint PERCENT_TRANSPORTED_60
= 153;
2381 static const uint PERCENT_TRANSPORTED_80
= 204;
2384 * Change industry production smoothly for standard industries.
2385 * @param i Industry for which changes are performed.
2386 * @param only_decrease Whether production can only decrease (temperate oil wells).
2387 * @param on_water Whether the industry is built on water (oil rigs).
2388 * @return Whether the industry should be closed.
2390 static bool ChangeIndustryProductionSmooth (Industry
*i
,
2391 bool only_decrease
, bool on_water
)
2395 for (byte j
= 0; j
< lengthof(i
->produced_cargo
); j
++) {
2396 if (i
->produced_cargo
[j
] == CT_INVALID
) continue;
2398 uint32 r
= Random();
2400 assert_compile (PERCENT_TRANSPORTED_80
> PERCENT_TRANSPORTED_60
);
2403 if (only_decrease
) {
2404 /* For industries with only_decrease flags (temperate
2405 * terrain Oil Wells), the multiplier will always be
2406 * -1 so they will only decrease. */
2408 } else if (i
->last_month_pct_transported
[j
] > PERCENT_TRANSPORTED_80
) {
2409 /* Bonus for very high station ratings:
2410 * 16% chance for decrease. */
2411 mult
= Chance16I (1, 6, r
) ? -1 : 1;
2413 /* For normal industries, if over 60% is transported,
2414 * 33% chance for decrease, else 67% chance for decrease. */
2415 mult
= ((i
->last_month_pct_transported
[j
] > PERCENT_TRANSPORTED_60
) == Chance16I (1, 3, r
)) ? -1 : 1;
2418 /* 4.5% chance for 3-23% (or 1 unit for very low productions) production change,
2419 * determined by mult value. If mult = 1 prod. increases, else (-1) it decreases. */
2420 int old_prod
, new_prod
;
2421 new_prod
= old_prod
= i
->production_rate
[j
];
2422 if (Chance16I (1, 22, r
>> 16)) {
2423 new_prod
+= mult
* max (((RandomRange(50) + 10) * old_prod
) >> 8, 1U);
2426 /* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
2427 new_prod
= Clamp (new_prod
, 1, 255);
2429 if (on_water
&& j
== 1) {
2430 new_prod
= Clamp(new_prod
, 0, 16);
2433 /* Do not stop closing the industry when it has the lowest possible production rate */
2434 if (new_prod
== old_prod
&& old_prod
> 1) {
2439 int percent
= (old_prod
== 0) ? 100 : (new_prod
* 100 / old_prod
- 100);
2440 i
->production_rate
[j
] = new_prod
;
2442 /* Close the industry when it has the lowest possible production rate */
2443 if (new_prod
> 1) close
= false;
2445 int percent_abs
= abs (percent
);
2446 if (percent_abs
>= 10) {
2447 AddNewsItem
<IndustryNewsItem
> (percent
>= 0 ?
2448 STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH
:
2449 STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH
,
2450 IndustryServiceNewsType (i
), i
->index
,
2451 CargoSpec::Get(i
->produced_cargo
[j
])->name
,
2452 i
->index
, percent_abs
);
2460 * Change industry production or do closure
2461 * @param i Industry for which changes are performed
2462 * @param monthly true if it's the monthly call, false if it's the random call
2464 static void ChangeIndustryProduction(Industry
*i
, bool monthly
)
2466 StringID str
= STR_NULL
;
2467 bool closeit
= false;
2468 const IndustrySpec
*indspec
= GetIndustrySpec(i
->type
);
2469 bool standard
= false;
2470 bool suppress_message
= false;
2471 bool recalculate_multipliers
= false; ///< reinitialize production_rate to match prod_level
2472 /* don't use smooth economy for industries using production related callbacks */
2473 bool smooth_economy
= indspec
->UsesSmoothEconomy();
2478 bool callback_enabled
= HasBit(indspec
->callback_mask
, monthly
? CBM_IND_MONTHLYPROD_CHANGE
: CBM_IND_PRODUCTION_CHANGE
);
2479 if (callback_enabled
) {
2480 uint16 res
= GetIndustryCallback(monthly
? CBID_INDUSTRY_MONTHLYPROD_CHANGE
: CBID_INDUSTRY_PRODUCTION_CHANGE
, 0, Random(), i
, i
->type
, i
->location
.tile
);
2481 if (res
!= CALLBACK_FAILED
) { // failed callback means "do nothing"
2482 suppress_message
= HasBit(res
, 7);
2483 /* Get the custom message if any */
2484 if (HasBit(res
, 8)) str
= MapGRFStringID(indspec
->grf_prop
.grffile
->grfid
, GB(GetRegister(0x100), 0, 16));
2485 res
= GB(res
, 0, 4);
2487 default: NOT_REACHED();
2488 case 0x0: break; // Do nothing, but show the custom message if any
2489 case 0x1: div
= 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
2490 case 0x2: mul
= 1; break; // Double industry production if it hasn't reached eight times of the original yet.
2491 case 0x3: closeit
= true; break; // The industry announces imminent closure, and is physically removed from the map next month.
2492 case 0x4: standard
= true; break; // Do the standard random production change as if this industry was a primary one.
2493 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16
2494 case 0x8: div
= res
- 0x3; break; // Divide production by 32
2495 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16
2496 case 0xC: mul
= res
- 0x7; break; // Multiply production by 32
2497 case 0xD: // decrement production
2498 case 0xE: // increment production
2499 increment
= res
== 0x0D ? -1 : 1;
2501 case 0xF: // Set production to third byte of register 0x100
2502 i
->prod_level
= Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM
, PRODLEVEL_MAXIMUM
);
2503 recalculate_multipliers
= true;
2508 if (monthly
!= smooth_economy
) return;
2509 if (indspec
->life_type
== INDUSTRYLIFE_BLACK_HOLE
) return;
2512 if (standard
|| (!callback_enabled
&& (indspec
->life_type
& (INDUSTRYLIFE_ORGANIC
| INDUSTRYLIFE_EXTRACTIVE
)) != 0)) {
2513 /* decrease or increase */
2514 bool only_decrease
= (indspec
->behaviour
& INDUSTRYBEH_DONT_INCR_PROD
) && _settings_game
.game_creation
.landscape
== LT_TEMPERATE
;
2516 if (smooth_economy
) {
2517 closeit
= ChangeIndustryProductionSmooth (i
, only_decrease
,
2518 (indspec
->behaviour
& INDUSTRYBEH_BUILT_ONWATER
) != 0);
2520 if (only_decrease
|| Chance16(1, 3)) {
2521 /* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
2522 if (!only_decrease
&& (i
->last_month_pct_transported
[0] > PERCENT_TRANSPORTED_60
) != Chance16(1, 3)) {
2523 mul
= 1; // Increase production
2525 div
= 1; // Decrease production
2531 if (!callback_enabled
&& (indspec
->life_type
& INDUSTRYLIFE_PROCESSING
)) {
2532 if ( (byte
)(_cur_year
- i
->last_prod_year
) >= 5 && Chance16(1, smooth_economy
? 180 : 2)) {
2537 /* Increase if needed */
2538 while (mul
-- != 0 && i
->prod_level
< PRODLEVEL_MAXIMUM
) {
2539 i
->prod_level
= min(i
->prod_level
* 2, PRODLEVEL_MAXIMUM
);
2540 recalculate_multipliers
= true;
2541 if (str
== STR_NULL
) str
= indspec
->production_up_text
;
2544 /* Decrease if needed */
2545 while (div
-- != 0 && !closeit
) {
2546 if (i
->prod_level
== PRODLEVEL_MINIMUM
) {
2549 i
->prod_level
= max(i
->prod_level
/ 2, (int)PRODLEVEL_MINIMUM
); // typecast to int required to please MSVC
2550 recalculate_multipliers
= true;
2551 if (str
== STR_NULL
) str
= indspec
->production_down_text
;
2555 /* Increase or Decreasing the production level if needed */
2556 if (increment
!= 0) {
2557 if (increment
< 0 && i
->prod_level
== PRODLEVEL_MINIMUM
) {
2560 i
->prod_level
= ClampU(i
->prod_level
+ increment
, PRODLEVEL_MINIMUM
, PRODLEVEL_MAXIMUM
);
2561 recalculate_multipliers
= true;
2565 /* Recalculate production_rate
2566 * For non-smooth economy these should always be synchronized with prod_level */
2567 if (recalculate_multipliers
) i
->RecomputeProductionMultipliers();
2569 /* Close if needed and allowed */
2570 if (closeit
&& !CheckIndustryCloseDownProtection(i
->type
)) {
2571 i
->prod_level
= PRODLEVEL_CLOSURE
;
2572 SetWindowDirty(WC_INDUSTRY_VIEW
, i
->index
);
2573 str
= indspec
->closure_text
;
2576 if (!suppress_message
&& str
!= STR_NULL
) {
2578 /* Compute news category */
2580 nt
= NT_INDUSTRY_CLOSE
;
2581 AI::BroadcastNewEvent(new ScriptEventIndustryClose(i
->index
));
2582 Game::NewEvent(new ScriptEventIndustryClose(i
->index
));
2584 nt
= IndustryServiceNewsType (i
);
2586 /* Report the news to the user. */
2587 uint p0
= (str
> STR_LAST_STRINGID
) ? STR_TOWN_NAME
:
2588 closeit
? STR_FORMAT_INDUSTRY_NAME
: i
->index
;
2590 AddNewsItem
<TileNewsItem
> (str
, nt
,
2591 i
->location
.tile
+ TileDiffXY(1, 1),
2592 p0
, i
->town
->index
, indspec
->name
);
2594 AddNewsItem
<IndustryNewsItem
> (str
, nt
, i
->index
,
2595 p0
, i
->town
->index
, indspec
->name
);
2601 * Daily handler for the industry changes
2602 * Taking the original map size of 256*256, the number of random changes was always of just one unit.
2603 * But it cannot be the same on smaller or bigger maps. That number has to be scaled up or down.
2604 * For small maps, it implies that less than one change per month is required, while on bigger maps,
2605 * it would be way more. The daily loop handles those changes.
2607 void IndustryDailyLoop()
2609 _economy
.industry_daily_change_counter
+= _economy
.industry_daily_increment
;
2611 /* Bits 16-31 of industry_construction_counter contain the number of industries to change/create today,
2612 * the lower 16 bit are a fractional part that might accumulate over several days until it
2613 * is sufficient for an industry. */
2614 uint16 change_loop
= _economy
.industry_daily_change_counter
>> 16;
2616 /* Reset the active part of the counter, just keeping the "fractional part" */
2617 _economy
.industry_daily_change_counter
&= 0xFFFF;
2619 if (change_loop
== 0) {
2620 return; // Nothing to do? get out
2623 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_NONE
, FILE_LINE
);
2625 /* perform the required industry changes for the day */
2627 uint perc
= 3; // Between 3% and 9% chance of creating a new industry.
2628 if ((_industry_builder
.wanted_inds
>> 16) > GetCurrentTotalNumberOfIndustries()) {
2629 perc
= min(9u, perc
+ (_industry_builder
.wanted_inds
>> 16) - GetCurrentTotalNumberOfIndustries());
2631 for (uint16 j
= 0; j
< change_loop
; j
++) {
2632 if (Chance16(perc
, 100)) {
2633 _industry_builder
.TryBuildNewIndustry();
2635 Industry
*i
= Industry::GetRandom();
2637 ChangeIndustryProduction(i
, false);
2638 SetWindowDirty(WC_INDUSTRY_VIEW
, i
->index
);
2643 cur_company
.Restore();
2645 /* production-change */
2646 InvalidateWindowData(WC_INDUSTRY_DIRECTORY
, 0, 1);
2649 void IndustryMonthlyLoop()
2651 Backup
<CompanyByte
> cur_company(_current_company
, OWNER_NONE
, FILE_LINE
);
2653 _industry_builder
.MonthlyLoop();
2656 FOR_ALL_INDUSTRIES(i
) {
2657 UpdateIndustryStatistics(i
);
2658 if (i
->prod_level
== PRODLEVEL_CLOSURE
) {
2661 ChangeIndustryProduction(i
, true);
2662 SetWindowDirty(WC_INDUSTRY_VIEW
, i
->index
);
2666 cur_company
.Restore();
2668 /* production-change */
2669 InvalidateWindowData(WC_INDUSTRY_DIRECTORY
, 0, 1);
2673 void InitializeIndustries()
2675 Industry::ResetIndustryCounts();
2676 _industry_sound_tile
= 0;
2678 _industry_builder
.Reset();
2681 /** Verify whether the generated industries are complete, and warn the user if not. */
2682 void CheckIndustries()
2685 for (IndustryType it
= 0; it
< NUM_INDUSTRYTYPES
; it
++) {
2686 if (Industry::GetIndustryTypeCount(it
) > 0) continue; // Types of existing industries can be skipped.
2688 bool force_at_least_one
;
2689 uint32 chance
= GetScaledIndustryGenerationProbability(it
, &force_at_least_one
);
2690 if (chance
== 0 || !force_at_least_one
) continue; // Types that are not available can be skipped.
2692 const IndustrySpec
*is
= GetIndustrySpec(it
);
2693 SetDParam(0, is
->name
);
2694 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES
, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION
, WL_WARNING
);
2697 if (count
>= 3) break; // Don't swamp the user with errors.
2702 * Is an industry with the spec a raw industry?
2703 * @return true if it should be handled as a raw industry
2705 bool IndustrySpec::IsRawIndustry() const
2707 return (this->life_type
& (INDUSTRYLIFE_EXTRACTIVE
| INDUSTRYLIFE_ORGANIC
)) != 0;
2711 * Is an industry with the spec a processing industry?
2712 * @return true if it should be handled as a processing industry
2714 bool IndustrySpec::IsProcessingIndustry() const
2716 /* Lumber mills are neither raw nor processing */
2717 return (this->life_type
& INDUSTRYLIFE_PROCESSING
) != 0 &&
2718 (this->behaviour
& INDUSTRYBEH_CUT_TREES
) == 0;
2722 * Get the cost for constructing this industry
2723 * @return the cost (inflation corrected etc)
2725 Money
IndustrySpec::GetConstructionCost() const
2727 /* Building raw industries like secondary uses different price base */
2728 return (_price
[(_settings_game
.construction
.raw_industry_construction
== 1 && this->IsRawIndustry()) ?
2729 PR_BUILD_INDUSTRY_RAW
: PR_BUILD_INDUSTRY
] * this->cost_multiplier
) >> 8;
2733 * Get the cost for removing this industry
2734 * Take note that the cost will always be zero for non-grf industries.
2735 * Only if the grf author did specified a cost will it be applicable.
2736 * @return the cost (inflation corrected etc)
2738 Money
IndustrySpec::GetRemovalCost() const
2740 return (_price
[PR_CLEAR_INDUSTRY
] * this->removal_cost_multiplier
) >> 8;
2744 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
2745 * @return true if smooth economy is used.
2747 bool IndustrySpec::UsesSmoothEconomy() const
2749 return _settings_game
.economy
.smooth_economy
&&
2750 !(HasBit(this->callback_mask
, CBM_IND_PRODUCTION_256_TICKS
) || HasBit(this->callback_mask
, CBM_IND_PRODUCTION_CARGO_ARRIVAL
)) && // production callbacks
2751 !(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
2754 static CommandCost
TerraformTile_Industry(TileIndex tile
, DoCommandFlag flags
, int z_new
, Slope tileh_new
)
2756 if (AutoslopeEnabled()) {
2757 /* We imitate here TTDP's behaviour:
2758 * - Both new and old slope must not be steep.
2759 * - TileMaxZ must not be changed.
2760 * - Allow autoslope by default.
2761 * - Disallow autoslope if callback succeeds and returns non-zero.
2763 Slope tileh_old
= GetTileSlope(tile
);
2764 /* TileMaxZ must not be changed. Slopes must not be steep. */
2765 if (!IsSteepSlope(tileh_old
) && !IsSteepSlope(tileh_new
) && (GetTileMaxZ(tile
) == z_new
+ GetSlopeMaxZ(tileh_new
))) {
2766 const IndustryGfx gfx
= GetIndustryGfx(tile
);
2767 const IndustryTileSpec
*itspec
= GetIndustryTileSpec(gfx
);
2769 /* Call callback 3C 'disable autosloping for industry tiles'. */
2770 if (HasBit(itspec
->callback_mask
, CBM_INDT_AUTOSLOPE
)) {
2771 /* If the callback fails, allow autoslope. */
2772 uint16 res
= GetIndustryTileCallback(CBID_INDTILE_AUTOSLOPE
, 0, 0, gfx
, Industry::GetByTile(tile
), tile
);
2773 if (res
== CALLBACK_FAILED
|| !ConvertBooleanCallback(itspec
->grf_prop
.grffile
, CBID_INDTILE_AUTOSLOPE
, res
)) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2775 /* allow autoslope */
2776 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2780 return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
2783 extern const TileTypeProcs _tile_type_industry_procs
= {
2784 DrawTile_Industry
, // draw_tile_proc
2785 GetSlopePixelZ_Industry
, // get_slope_z_proc
2786 ClearTile_Industry
, // clear_tile_proc
2787 AddAcceptedCargo_Industry
, // add_accepted_cargo_proc
2788 GetTileDesc_Industry
, // get_tile_desc_proc
2789 NULL
, // get_tile_railway_status_proc
2790 NULL
, // get_tile_road_status_proc
2791 NULL
, // get_tile_waterway_status_proc
2792 ClickTile_Industry
, // click_tile_proc
2793 AnimateTile_Industry
, // animate_tile_proc
2794 TileLoop_Industry
, // tile_loop_proc
2795 ChangeTileOwner_Industry
, // change_tile_owner_proc
2796 NULL
, // add_produced_cargo_proc
2797 GetFoundation_Industry
, // get_foundation_proc
2798 TerraformTile_Industry
, // terraform_tile_proc