45 #include "table/strings.h"
54 void ShowIndustryViewWindow(
int industry);
57 static byte _industry_sound_ctr;
74 memset(&_industry_specs, 0,
sizeof(_industry_specs));
75 memcpy(&_industry_specs, &_origin_industry_specs,
sizeof(_origin_industry_specs));
83 memset(&_industry_tile_specs, 0,
sizeof(_industry_tile_specs));
84 memcpy(&_industry_tile_specs, &_origin_industry_tile_specs,
sizeof(_origin_industry_tile_specs));
119 return &_industry_specs[thistype];
133 return &_industry_tile_specs[gfx];
136 Industry::~Industry()
154 DeleteOilRig(tile_cur);
223 static void IndustryDrawSugarMine(
const TileInfo *ti)
237 _drawtile_proc1[d->
image_3 - 1].x, _drawtile_proc1[d->
image_3 - 1].y);
241 static void IndustryDrawToffeeQuarry(
const TileInfo *ti)
256 static void IndustryDrawBubbleGenerator(
const TileInfo *ti)
264 static void IndustryDrawToyFactory(
const TileInfo *ti)
280 static void IndustryDrawCoalPlantSparks(
const TileInfo *ti)
285 if (image != 0 && image < 7) {
295 typedef void IndustryDrawTileProc(
const TileInfo *ti);
296 static IndustryDrawTileProc *
const _industry_draw_tile_procs[5] = {
297 IndustryDrawSugarMine,
298 IndustryDrawToffeeQuarry,
299 IndustryDrawBubbleGenerator,
300 IndustryDrawToyFactory,
301 IndustryDrawCoalPlantSparks,
304 static void DrawTile_Industry(
TileInfo *ti)
341 DrawWaterClassGround(ti);
350 image = dits->building.
sprite;
353 ti->
x + dits->subtile_x,
354 ti->
y + dits->subtile_y,
365 int proc = dits->draw_proc - 1;
366 if (proc >= 0) _industry_draw_tile_procs[proc](ti);
370 static int GetSlopePixelZ_Industry(
TileIndex tile, uint x, uint y)
393 static void AddAcceptedCargo_Industry(
TileIndex tile,
CargoArray &acceptance, uint32 *always_accepted)
404 const uint8 *cargo_acceptance = itspec->
acceptance;
409 accepts_cargo = raw_accepts_cargo;
417 cargo_acceptance = raw_cargo_acceptance;
425 if (a ==
CT_INVALID || cargo_acceptance[i] == 0)
continue;
428 acceptance[a] += cargo_acceptance[i];
431 if (
HasBit(*always_accepted, a))
continue;
433 bool accepts =
false;
442 if (accepts)
continue;
445 SetBit(*always_accepted, a);
458 td->
str = STR_LAI_TOWN_INDUSTRY_DESCRIPTION_UNDER_CONSTRUCTION;
503 bool moved_cargo =
false;
520 moved_cargo |= (am != 0);
528 static void AnimateTile_Industry(
TileIndex tile)
533 AnimateNewIndustryTile(tile);
538 case GFX_SUGAR_MINE_SIEVE:
544 case 2: SndPlayTileFx(SND_2D_RIP_2, tile);
break;
545 case 6: SndPlayTileFx(SND_29_RIP, tile);
break;
559 case GFX_TOFFEE_QUARY:
564 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
577 case GFX_BUBBLE_CATCHER:
592 case GFX_POWERPLANT_SPARKS:
605 case GFX_TOY_FACTORY:
630 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
631 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
632 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
633 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
637 gfx = (gfx < 155) ? gfx + 1 : 148;
643 case GFX_OILWELL_ANIMATED_1:
644 case GFX_OILWELL_ANIMATED_2:
645 case GFX_OILWELL_ANIMATED_3:
651 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
663 case GFX_COAL_MINE_TOWER_ANIMATED:
664 case GFX_COPPER_MINE_TOWER_ANIMATED:
665 case GFX_GOLD_MINE_TOWER_ANIMATED: {
668 if ((state -= 0x400) < 0)
return;
671 if (state < 0x20 || state >= 0x180) {
677 if (state & 7)
return;
679 if (state & 3)
return;
682 if (m > 0xC2) m = 0xC0;
685 }
else if (state >= 0x200 && state < 0x3A0) {
686 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
687 if (state & i)
return;
690 if (m < 0x80) m = 0x82;
699 static void CreateChimneySmoke(
TileIndex tile)
708 static void MakeIndustryTileBigger(
TileIndex tile)
733 case GFX_POWERPLANT_CHIMNEY:
734 CreateChimneySmoke(tile);
752 case GFX_TOY_FACTORY:
753 case GFX_BUBBLE_CATCHER:
754 case GFX_TOFFEE_QUARY:
759 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
760 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
761 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
762 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
768 static void TileLoopIndustry_BubbleGenerator(
TileIndex tile)
770 static const int8 _bubble_spawn_location[3][4] = {
778 int dir = Random() & 3;
783 _bubble_spawn_location[2][dir],
790 static void TileLoop_Industry(
TileIndex tile)
803 MakeIndustryTileBigger(tile);
807 if (_game_mode == GM_EDITOR)
return;
821 if (StartStopIndustryTileAnimation(tile,
IAT_TILELOOP))
return;
833 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
834 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
835 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
838 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED;
break;
839 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED;
break;
840 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED;
break;
848 case GFX_OILWELL_NOT_ANIMATED:
856 case GFX_COAL_MINE_TOWER_ANIMATED:
857 case GFX_COPPER_MINE_TOWER_ANIMATED:
858 case GFX_GOLD_MINE_TOWER_ANIMATED:
861 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED;
break;
862 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED;
break;
863 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED;
break;
872 case GFX_POWERPLANT_SPARKS:
879 case GFX_COPPER_MINE_CHIMNEY:
884 case GFX_TOY_FACTORY: {
894 case GFX_BUBBLE_GENERATOR:
895 TileLoopIndustry_BubbleGenerator(tile);
898 case GFX_TOFFEE_QUARY:
902 case GFX_SUGAR_MINE_SIEVE:
908 static bool ClickTile_Industry(
TileIndex tile)
950 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
964 default:
return false;
985 if (or_ == 1 &&
Chance16(1, 7)) or_ = 2;
994 static void PlantFarmField(
TileIndex tile, IndustryID industry)
1001 uint32 r = (Random() & 0x303) + 0x404;
1003 uint size_x =
GB(r, 0, 8);
1004 uint size_y =
GB(r, 8, 8);
1009 if (ta.w == 0 || ta.h == 0)
return;
1017 if (count * 2 < ta.w * ta.h)
return;
1021 uint counter =
GB(r, 5, 3);
1022 uint field_type =
GB(r, 8, 8) * 9 >> 8;
1028 MakeField(cur_tile, field_type, industry);
1036 type = _plantfarmfield_type[Random() & 0xF];
1045 void PlantRandomFarmField(
const Industry *i)
1047 int x = i->
location.
w / 2 + Random() % 31 - 16;
1048 int y = i->
location.
h / 2 + Random() % 31 - 16;
1068 _industry_sound_ctr = 1;
1069 _industry_sound_tile = tile;
1099 static void ProduceIndustryGoods(
Industry *i)
1104 if ((i->
counter & 0x3F) == 0) {
1124 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1137 if (plant) PlantRandomFarmField(i);
1160 void OnTick_Industry()
1162 if (_industry_sound_ctr != 0) {
1163 _industry_sound_ctr++;
1165 if (_industry_sound_ctr == 75) {
1167 }
else if (_industry_sound_ctr == 160) {
1168 _industry_sound_ctr = 0;
1173 if (_game_mode == GM_EDITOR)
return;
1176 FOR_ALL_INDUSTRIES(i) {
1177 ProduceIndustryGoods(i);
1213 if (_game_mode == GM_EDITOR)
return CommandCost();
1219 extern bool _ignore_restrictions;
1228 if (_game_mode == GM_EDITOR && _ignore_restrictions)
return CommandCost();
1339 FOR_ALL_INDUSTRIES(i) {
1340 if (i->
type == (byte)type && i->
town == *t) {
1349 bool IsSlopeRefused(
Slope current,
Slope refused)
1380 bool refused_slope =
false;
1381 bool custom_shape =
false;
1398 if (ret.
Failed())
return ret;
1409 custom_shape =
true;
1411 if (ret.
Failed())
return ret;
1428 if (ret.
Failed())
return ret;
1433 if (ret.
Failed())
return ret;
1436 }
while ((++it)->ti.x != -0x80);
1438 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1459 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1469 static bool CheckCanTerraformSurroundingTiles(
TileIndex tile, uint height,
int internal)
1481 if (
internal != 0 &&
Delta(curh, height) > 1)
return false;
1486 if (
internal == 0 && curh != height) {
1487 if (
TileX(tile_walk) == 0 ||
TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk +
TileDiffXY(-1, -1), height,
internal + 1)) {
1502 const int MKEND = -0x80;
1508 if (it->gfx == 0xFF)
continue;
1509 if (it->ti.
x > max_x) max_x = it->ti.
x;
1510 if (it->ti.
y > max_y) max_y = it->ti.
y;
1511 }
while ((++it)->ti.
x != MKEND);
1534 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1547 if (flags & DC_EXEC) {
1556 curh += (curh > h) ? -1 : 1;
1578 static const int dmax = 14;
1580 const int tx =
TileX(tile);
1581 const int ty =
TileY(tile);
1586 if (i == i2)
continue;
1599 FOR_ALL_INDUSTRIES(i) {
1668 uint16 r = Random();
1671 i->
random = initial_random_bits;
1779 }
while ((++it)->ti.
x != -0x80);
1782 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1807 assert(itspec_index < indspec->num_table);
1809 bool custom_shape_check =
false;
1815 _cleared_object_areas = object_areas;
1816 if (ret.
Failed())
return ret;
1821 ret = _check_new_industry_procs[indspec->
check_proc](tile);
1823 if (ret.
Failed())
return ret;
1831 if (ret.
Failed())
return ret;
1835 if (ret.
Failed())
return ret;
1839 if (ret.
Failed())
return ret;
1843 if (flags & DC_EXEC) {
1866 IndustryType it =
GB(p1, 0, 8);
1886 uint16 random_initial_bits =
GB(p2, 0, 16);
1887 uint32 random_var8f = randomizer.
Next();
1894 if (flags & DC_EXEC) {
1901 for (
int i = 0; i < 5000; i++) {
1909 for (
int j = 0; j < num_layouts; j++) {
1910 layout = (layout + 1) % num_layouts;
1920 int layout =
GB(p1, 8, 8);
1921 if (layout >= num_layouts)
return CMD_ERROR;
1924 for (
int i = 0; i < num_layouts; i++) {
1925 layout = (layout + 1) % num_layouts;
1931 if (ret.
Failed())
return ret;
1934 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1953 uint32 seed = Random();
1954 uint32 seed2 = Random();
1956 CommandCost ret =
CreateNewIndustryHelper(tile, type, DC_EXEC, indspec,
RandomRange(indspec->
num_table), seed,
GB(seed2, 0, 16),
OWNER_NONE, creation_type, &i);
1957 assert(i != NULL || ret.
Failed());
1974 *force_at_least_one =
false;
2019 static const uint16 numof_industry_table[] = {
2043 uint tries = try_hard ? 10000u : 2000u;
2044 for (; tries > 0; tries--) {
2046 if (ind != NULL)
return ind;
2101 static const int NEWINDS_PER_MONTH = 0x38000 / (10 * 12);
2122 uint32 total_prob = 0;
2123 uint num_forced = 0;
2127 total_prob += industry_probs[it];
2128 if (force_at_least_one[it]) num_forced++;
2132 if (total_prob == 0 || total_amount < num_forced) {
2134 total_amount = num_forced;
2141 if (force_at_least_one[it]) {
2142 assert(total_amount > 0);
2149 for (uint i = 0; i < total_amount; i++) {
2151 IndustryType it = 0;
2152 while (r >= industry_probs[it]) {
2153 r -= industry_probs[it];
2155 assert(it < NUM_INDUSTRYTYPES);
2157 assert(industry_probs[it] > 0);
2211 bool changed = min_number != this->min_number || probability != this->
probability;
2220 bool changed =
false;
2221 uint num_planned = 0;
2227 changed |= num_planned != total_amount;
2228 if (!changed)
return;
2231 uint force_build = 0;
2232 uint32 total_prob = 0;
2240 if (total_prob == 0)
return;
2243 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2246 while (total_amount > 0) {
2248 IndustryType it = 0;
2249 while (r >= this->
builddata[it].probability) {
2252 assert(it < NUM_INDUSTRYTYPES);
2254 assert(this->
builddata[it].probability > 0);
2269 uint32 total_prob = 0;
2273 missing += difference;
2274 if (this->
builddata[it].wait_count > 0)
continue;
2275 if (difference > 0) {
2278 if (forced_build == NUM_INDUSTRYTYPES ||
2283 total_prob += difference;
2288 if (
EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0;
2294 if (forced_build != NUM_INDUSTRYTYPES) {
2301 if (this->
builddata[it].wait_count > 0)
continue;
2303 if (difference <= 0)
continue;
2304 if (count == 1)
break;
2305 if (r < (uint)difference)
break;
2394 if (stations.
Length() == 0)
return 0;
2403 bool c_accepts =
false;
2404 bool c_produces =
false;
2406 for (
const Vehicle *u = v; u != NULL; u = u->
Next()) {
2414 if (!c_accepts && !c_produces)
continue;
2421 FOR_VEHICLE_ORDERS(v, o) {
2455 default: NOT_REACHED();
2460 AddIndustryNewsItem(
2461 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2467 static const uint PERCENT_TRANSPORTED_60 = 153;
2468 static const uint PERCENT_TRANSPORTED_80 = 204;
2478 bool closeit =
false;
2480 bool standard =
false;
2481 bool suppress_message =
false;
2482 bool recalculate_multipliers =
false;
2490 if (callback_enabled) {
2493 suppress_message =
HasBit(res, 7);
2496 res =
GB(res, 0, 4);
2498 default: NOT_REACHED();
2500 case 0x1: div = 1;
break;
2501 case 0x2: mul = 1;
break;
2502 case 0x3: closeit =
true;
break;
2503 case 0x4: standard =
true;
break;
2504 case 0x5:
case 0x6:
case 0x7:
2505 case 0x8: div = res - 0x3;
break;
2506 case 0x9:
case 0xA:
case 0xB:
2507 case 0xC: mul = res - 0x7;
break;
2510 increment = res == 0x0D ? -1 : 1;
2514 recalculate_multipliers =
true;
2519 if (monthly != smooth_economy)
return;
2527 if (smooth_economy) {
2531 uint32 r = Random();
2532 int old_prod, new_prod, percent;
2540 if (only_decrease) {
2551 new_prod += mult * (
max(((
RandomRange(50) + 10) * old_prod) >> 8, 1U));
2555 new_prod =
Clamp(new_prod, 1, 255);
2558 new_prod =
Clamp(new_prod, 0, 16);
2562 if (new_prod == old_prod && old_prod > 1) {
2567 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2571 if (new_prod > 1) closeit =
false;
2573 if (
abs(percent) >= 10) {
2578 if (only_decrease ||
Chance16(1, 3)) {
2598 recalculate_multipliers =
true;
2603 while (div-- != 0 && !closeit) {
2608 recalculate_multipliers =
true;
2614 if (increment != 0) {
2619 recalculate_multipliers =
true;
2634 if (!suppress_message && str != STR_NULL) {
2646 default: NOT_REACHED();
2650 if (str > STR_LAST_STRINGID) {
2654 }
else if (closeit) {
2665 AddIndustryNewsItem(str, nt, i->
index);
2689 if (change_loop == 0) {
2701 for (uint16 j = 0; j < change_loop; j++) {
2719 void IndustryMonthlyLoop()
2726 FOR_ALL_INDUSTRIES(i) {
2736 cur_company.Restore();
2743 void InitializeIndustries()
2746 _industry_sound_tile = 0;
2758 bool force_at_least_one;
2760 if (chance == 0 || !force_at_least_one)
continue;
2764 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION,
WL_WARNING);
2767 if (count >= 3)
break;
2799 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->
cost_multiplier) >> 8;
2855 GetSlopePixelZ_Industry,
2857 AddAcceptedCargo_Industry,
2858 GetTileDesc_Industry,
2859 GetTileTrackStatus_Industry,
2861 AnimateTile_Industry,
2863 ChangeTileOwner_Industry,
2866 GetFoundation_Industry,
2867 TerraformTile_Industry,