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;
494 static void TransportIndustryGoods(
TileIndex tile)
498 bool moved_cargo =
false;
515 moved_cargo |= (am != 0);
532 static void AnimateTile_Industry(
TileIndex tile)
537 AnimateNewIndustryTile(tile);
542 case GFX_SUGAR_MINE_SIEVE:
548 case 2: SndPlayTileFx(SND_2D_RIP_2, tile);
break;
549 case 6: SndPlayTileFx(SND_29_RIP, tile);
break;
563 case GFX_TOFFEE_QUARY:
568 SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
581 case GFX_BUBBLE_CATCHER:
596 case GFX_POWERPLANT_SPARKS:
609 case GFX_TOY_FACTORY:
634 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
635 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
636 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
637 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
641 gfx = (gfx < 155) ? gfx + 1 : 148;
647 case GFX_OILWELL_ANIMATED_1:
648 case GFX_OILWELL_ANIMATED_2:
649 case GFX_OILWELL_ANIMATED_3:
655 if (m == 4 && (m = 0, ++gfx) == GFX_OILWELL_ANIMATED_3 + 1 && (gfx = GFX_OILWELL_ANIMATED_1, b)) {
667 case GFX_COAL_MINE_TOWER_ANIMATED:
668 case GFX_COPPER_MINE_TOWER_ANIMATED:
669 case GFX_GOLD_MINE_TOWER_ANIMATED: {
672 if ((state -= 0x400) < 0)
return;
675 if (state < 0x20 || state >= 0x180) {
681 if (state & 7)
return;
683 if (state & 3)
return;
686 if (m > 0xC2) m = 0xC0;
689 }
else if (state >= 0x200 && state < 0x3A0) {
690 int i = (state < 0x220 || state >= 0x380) ? 7 : 3;
691 if (state & i)
return;
694 if (m < 0x80) m = 0x82;
703 static void CreateChimneySmoke(
TileIndex tile)
712 static void MakeIndustryTileBigger(
TileIndex tile)
737 case GFX_POWERPLANT_CHIMNEY:
738 CreateChimneySmoke(tile);
756 case GFX_TOY_FACTORY:
757 case GFX_BUBBLE_CATCHER:
758 case GFX_TOFFEE_QUARY:
763 case GFX_PLASTIC_FOUNTAIN_ANIMATED_1:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_2:
764 case GFX_PLASTIC_FOUNTAIN_ANIMATED_3:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_4:
765 case GFX_PLASTIC_FOUNTAIN_ANIMATED_5:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_6:
766 case GFX_PLASTIC_FOUNTAIN_ANIMATED_7:
case GFX_PLASTIC_FOUNTAIN_ANIMATED_8:
772 static void TileLoopIndustry_BubbleGenerator(
TileIndex tile)
774 static const int8 _bubble_spawn_location[3][4] = {
782 int dir = Random() & 3;
787 _bubble_spawn_location[2][dir],
794 static void TileLoop_Industry(
TileIndex tile)
807 MakeIndustryTileBigger(tile);
811 if (_game_mode == GM_EDITOR)
return;
813 TransportIndustryGoods(tile);
815 if (StartStopIndustryTileAnimation(tile,
IAT_TILELOOP))
return;
827 case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
828 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
829 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
832 case GFX_COAL_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COAL_MINE_TOWER_ANIMATED;
break;
833 case GFX_COPPER_MINE_TOWER_NOT_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_ANIMATED;
break;
834 case GFX_GOLD_MINE_TOWER_NOT_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_ANIMATED;
break;
842 case GFX_OILWELL_NOT_ANIMATED:
850 case GFX_COAL_MINE_TOWER_ANIMATED:
851 case GFX_COPPER_MINE_TOWER_ANIMATED:
852 case GFX_GOLD_MINE_TOWER_ANIMATED:
855 case GFX_COAL_MINE_TOWER_ANIMATED: gfx = GFX_COAL_MINE_TOWER_NOT_ANIMATED;
break;
856 case GFX_COPPER_MINE_TOWER_ANIMATED: gfx = GFX_COPPER_MINE_TOWER_NOT_ANIMATED;
break;
857 case GFX_GOLD_MINE_TOWER_ANIMATED: gfx = GFX_GOLD_MINE_TOWER_NOT_ANIMATED;
break;
866 case GFX_POWERPLANT_SPARKS:
873 case GFX_COPPER_MINE_CHIMNEY:
878 case GFX_TOY_FACTORY: {
888 case GFX_BUBBLE_GENERATOR:
889 TileLoopIndustry_BubbleGenerator(tile);
892 case GFX_TOFFEE_QUARY:
896 case GFX_SUGAR_MINE_SIEVE:
902 static bool ClickTile_Industry(
TileIndex tile)
944 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
958 default:
return false;
979 if (or_ == 1 &&
Chance16(1, 7)) or_ = 2;
988 static void PlantFarmField(
TileIndex tile, IndustryID industry)
995 uint32 r = (Random() & 0x303) + 0x404;
997 uint size_x =
GB(r, 0, 8);
998 uint size_y =
GB(r, 8, 8);
1003 if (ta.w == 0 || ta.h == 0)
return;
1011 if (count * 2 < ta.w * ta.h)
return;
1015 uint counter =
GB(r, 5, 3);
1016 uint field_type =
GB(r, 8, 8) * 9 >> 8;
1022 MakeField(cur_tile, field_type, industry);
1030 type = _plantfarmfield_type[Random() & 0xF];
1039 void PlantRandomFarmField(
const Industry *i)
1041 int x = i->
location.
w / 2 + Random() % 31 - 16;
1042 int y = i->
location.
h / 2 + Random() % 31 - 16;
1062 _industry_sound_ctr = 1;
1063 _industry_sound_tile = tile;
1093 static void ProduceIndustryGoods(
Industry *i)
1098 if ((i->
counter & 0x3F) == 0) {
1118 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
1131 if (plant) PlantRandomFarmField(i);
1154 void OnTick_Industry()
1156 if (_industry_sound_ctr != 0) {
1157 _industry_sound_ctr++;
1159 if (_industry_sound_ctr == 75) {
1161 }
else if (_industry_sound_ctr == 160) {
1162 _industry_sound_ctr = 0;
1167 if (_game_mode == GM_EDITOR)
return;
1170 FOR_ALL_INDUSTRIES(i) {
1171 ProduceIndustryGoods(i);
1207 if (_game_mode == GM_EDITOR)
return CommandCost();
1213 extern bool _ignore_restrictions;
1222 if (_game_mode == GM_EDITOR && _ignore_restrictions)
return CommandCost();
1333 FOR_ALL_INDUSTRIES(i) {
1334 if (i->
type == (byte)type && i->
town == *t) {
1343 bool IsSlopeRefused(
Slope current,
Slope refused)
1374 bool refused_slope =
false;
1375 bool custom_shape =
false;
1392 if (ret.
Failed())
return ret;
1403 custom_shape =
true;
1405 if (ret.
Failed())
return ret;
1422 if (ret.
Failed())
return ret;
1427 if (ret.
Failed())
return ret;
1430 }
while ((++it)->ti.x != -0x80);
1432 if (custom_shape_check != NULL) *custom_shape_check = custom_shape;
1453 return_cmd_error(STR_ERROR_CAN_ONLY_BE_BUILT_IN_TOWNS_WITH_POPULATION_OF_1200);
1463 static bool CheckCanTerraformSurroundingTiles(
TileIndex tile, uint height,
int internal)
1475 if (
internal != 0 &&
Delta(curh, height) > 1)
return false;
1480 if (
internal == 0 && curh != height) {
1481 if (
TileX(tile_walk) == 0 ||
TileY(tile_walk) == 0 || !CheckCanTerraformSurroundingTiles(tile_walk +
TileDiffXY(-1, -1), height,
internal + 1)) {
1496 const int MKEND = -0x80;
1502 if (it->gfx == 0xFF)
continue;
1503 if (it->ti.
x > max_x) max_x = it->ti.
x;
1504 if (it->ti.
y > max_y) max_y = it->ti.
y;
1505 }
while ((++it)->ti.
x != MKEND);
1528 if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) {
1541 if (flags & DC_EXEC) {
1550 curh += (curh > h) ? -1 : 1;
1572 static const int dmax = 14;
1574 const int tx =
TileX(tile);
1575 const int ty =
TileY(tile);
1580 if (i == i2)
continue;
1593 FOR_ALL_INDUSTRIES(i) {
1662 uint16 r = Random();
1665 i->
random = initial_random_bits;
1773 }
while ((++it)->ti.
x != -0x80);
1776 for (uint j = 0; j != 50; j++) PlantRandomFarmField(i);
1801 assert(itspec_index < indspec->num_table);
1803 bool custom_shape_check =
false;
1809 _cleared_object_areas = object_areas;
1810 if (ret.
Failed())
return ret;
1815 ret = _check_new_industry_procs[indspec->
check_proc](tile);
1817 if (ret.
Failed())
return ret;
1825 if (ret.
Failed())
return ret;
1829 if (ret.
Failed())
return ret;
1833 if (ret.
Failed())
return ret;
1837 if (flags & DC_EXEC) {
1860 IndustryType it =
GB(p1, 0, 8);
1880 uint16 random_initial_bits =
GB(p2, 0, 16);
1881 uint32 random_var8f = randomizer.
Next();
1888 if (flags & DC_EXEC) {
1895 for (
int i = 0; i < 5000; i++) {
1903 for (
int j = 0; j < num_layouts; j++) {
1904 layout = (layout + 1) % num_layouts;
1914 int layout =
GB(p1, 8, 8);
1915 if (layout >= num_layouts)
return CMD_ERROR;
1918 for (
int i = 0; i < num_layouts; i++) {
1919 layout = (layout + 1) % num_layouts;
1925 if (ret.
Failed())
return ret;
1928 if ((flags & DC_EXEC) && ind != NULL && _game_mode != GM_EDITOR) {
1947 uint32 seed = Random();
1948 uint32 seed2 = Random();
1950 CommandCost ret =
CreateNewIndustryHelper(tile, type, DC_EXEC, indspec,
RandomRange(indspec->
num_table), seed,
GB(seed2, 0, 16),
OWNER_NONE, creation_type, &i);
1951 assert(i != NULL || ret.
Failed());
1968 *force_at_least_one =
false;
2013 static const uint16 numof_industry_table[] = {
2037 uint tries = try_hard ? 10000u : 2000u;
2038 for (; tries > 0; tries--) {
2040 if (ind != NULL)
return ind;
2095 static const int NEWINDS_PER_MONTH = 0x38000 / (10 * 12);
2116 uint32 total_prob = 0;
2117 uint num_forced = 0;
2121 total_prob += industry_probs[it];
2122 if (force_at_least_one[it]) num_forced++;
2126 if (total_prob == 0 || total_amount < num_forced) {
2128 total_amount = num_forced;
2135 if (force_at_least_one[it]) {
2136 assert(total_amount > 0);
2143 for (uint i = 0; i < total_amount; i++) {
2145 IndustryType it = 0;
2146 while (r >= industry_probs[it]) {
2147 r -= industry_probs[it];
2149 assert(it < NUM_INDUSTRYTYPES);
2151 assert(industry_probs[it] > 0);
2205 bool changed = min_number != this->min_number || probability != this->
probability;
2214 bool changed =
false;
2215 uint num_planned = 0;
2221 changed |= num_planned != total_amount;
2222 if (!changed)
return;
2225 uint force_build = 0;
2226 uint32 total_prob = 0;
2234 if (total_prob == 0)
return;
2237 total_amount = (total_amount <= force_build) ? 0 : total_amount - force_build;
2240 while (total_amount > 0) {
2242 IndustryType it = 0;
2243 while (r >= this->
builddata[it].probability) {
2246 assert(it < NUM_INDUSTRYTYPES);
2248 assert(this->
builddata[it].probability > 0);
2263 uint32 total_prob = 0;
2267 missing += difference;
2268 if (this->
builddata[it].wait_count > 0)
continue;
2269 if (difference > 0) {
2272 if (forced_build == NUM_INDUSTRYTYPES ||
2277 total_prob += difference;
2282 if (
EconomyIsInRecession() || (forced_build == NUM_INDUSTRYTYPES && (missing <= 0 || total_prob == 0))) count = 0;
2288 if (forced_build != NUM_INDUSTRYTYPES) {
2295 if (this->
builddata[it].wait_count > 0)
continue;
2297 if (difference <= 0)
continue;
2298 if (count == 1)
break;
2299 if (r < (uint)difference)
break;
2388 if (stations.
Length() == 0)
return 0;
2397 bool c_accepts =
false;
2398 bool c_produces =
false;
2400 for (
const Vehicle *u = v; u != NULL; u = u->
Next()) {
2408 if (!c_accepts && !c_produces)
continue;
2415 FOR_VEHICLE_ORDERS(v, o) {
2449 default: NOT_REACHED();
2454 AddIndustryNewsItem(
2455 percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
2461 static const uint PERCENT_TRANSPORTED_60 = 153;
2462 static const uint PERCENT_TRANSPORTED_80 = 204;
2472 bool closeit =
false;
2474 bool standard =
false;
2475 bool suppress_message =
false;
2476 bool recalculate_multipliers =
false;
2484 if (callback_enabled) {
2487 suppress_message =
HasBit(res, 7);
2490 res =
GB(res, 0, 4);
2492 default: NOT_REACHED();
2494 case 0x1: div = 1;
break;
2495 case 0x2: mul = 1;
break;
2496 case 0x3: closeit =
true;
break;
2497 case 0x4: standard =
true;
break;
2498 case 0x5:
case 0x6:
case 0x7:
2499 case 0x8: div = res - 0x3;
break;
2500 case 0x9:
case 0xA:
case 0xB:
2501 case 0xC: mul = res - 0x7;
break;
2504 increment = res == 0x0D ? -1 : 1;
2508 recalculate_multipliers =
true;
2513 if (monthly != smooth_economy)
return;
2521 if (smooth_economy) {
2525 uint32 r = Random();
2526 int old_prod, new_prod, percent;
2534 if (only_decrease) {
2545 new_prod += mult * (
max(((
RandomRange(50) + 10) * old_prod) >> 8, 1U));
2549 new_prod =
Clamp(new_prod, 1, 255);
2552 new_prod =
Clamp(new_prod, 0, 16);
2556 if (new_prod == old_prod && old_prod > 1) {
2561 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
2565 if (new_prod > 1) closeit =
false;
2567 if (
abs(percent) >= 10) {
2572 if (only_decrease ||
Chance16(1, 3)) {
2592 recalculate_multipliers =
true;
2597 while (div-- != 0 && !closeit) {
2602 recalculate_multipliers =
true;
2608 if (increment != 0) {
2613 recalculate_multipliers =
true;
2628 if (!suppress_message && str != STR_NULL) {
2640 default: NOT_REACHED();
2644 if (str > STR_LAST_STRINGID) {
2648 }
else if (closeit) {
2659 AddIndustryNewsItem(str, nt, i->
index);
2683 if (change_loop == 0) {
2695 for (uint16 j = 0; j < change_loop; j++) {
2713 void IndustryMonthlyLoop()
2720 FOR_ALL_INDUSTRIES(i) {
2730 cur_company.Restore();
2737 void InitializeIndustries()
2740 _industry_sound_tile = 0;
2752 bool force_at_least_one;
2754 if (chance == 0 || !force_at_least_one)
continue;
2758 ShowErrorMessage(STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES, STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION,
WL_WARNING);
2761 if (count >= 3)
break;
2793 PR_BUILD_INDUSTRY_RAW : PR_BUILD_INDUSTRY] * this->
cost_multiplier) >> 8;
2849 GetSlopePixelZ_Industry,
2851 AddAcceptedCargo_Industry,
2852 GetTileDesc_Industry,
2853 GetTileTrackStatus_Industry,
2855 AnimateTile_Industry,
2857 ChangeTileOwner_Industry,
2860 GetFoundation_Industry,
2861 TerraformTile_Industry,