1690 } |
1693 } |
1691 } |
1694 } |
1692 } |
1695 } |
1693 } |
1696 } |
1694 |
1697 |
1695 /** Change industry production or do closure |
|
1696 * @param i Industry for which changes are performed |
|
1697 */ |
|
1698 static void ExtChangeIndustryProduction(Industry *i) |
|
1699 { |
|
1700 bool closeit = true; |
|
1701 int j; |
|
1702 const IndustrySpec *indspec = GetIndustrySpec(i->type); |
|
1703 |
|
1704 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return; |
|
1705 |
|
1706 if ((indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) { |
|
1707 for (j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){ |
|
1708 uint32 r = Random(); |
|
1709 int old_prod, new_prod, percent; |
|
1710 int mag; |
|
1711 |
|
1712 new_prod = old_prod = i->production_rate[j]; |
|
1713 |
|
1714 if (CHANCE16I(20, 1024, r)) new_prod -= max(((RandomRange(50) + 10) * old_prod) >> 8, 1U); |
|
1715 /* Chance of increasing becomes better when more is transported */ |
|
1716 if (CHANCE16I(20 + (i->last_month_pct_transported[j] * 20 >> 8), 1024, r >> 16) && |
|
1717 ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) == 0 || _opt.landscape != LT_TEMPERATE)) { |
|
1718 new_prod += max(((RandomRange(50) + 10) * old_prod) >> 8, 1U); |
|
1719 } |
|
1720 |
|
1721 new_prod = clamp(new_prod, 1, 255); |
|
1722 /* Do not stop closing the industry when it has the lowest possible production rate */ |
|
1723 if (new_prod == old_prod && old_prod > 1) { |
|
1724 closeit = false; |
|
1725 continue; |
|
1726 } |
|
1727 |
|
1728 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100); |
|
1729 i->production_rate[j] = new_prod; |
|
1730 |
|
1731 /* Close the industry when it has the lowest possible production rate */ |
|
1732 if (new_prod > 1) closeit = false; |
|
1733 |
|
1734 mag = abs(percent); |
|
1735 if (mag >= 10) { |
|
1736 SetDParam(2, mag); |
|
1737 SetDParam(0, GetCargo(indspec->produced_cargo[j])->name); |
|
1738 SetDParam(1, i->index); |
|
1739 AddNewsItem( |
|
1740 percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN, |
|
1741 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_ECONOMY, 0), |
|
1742 i->xy + TileDiffXY(1, 1), 0 |
|
1743 ); |
|
1744 } |
|
1745 } |
|
1746 } |
|
1747 |
|
1748 if ((indspec->life_type & INDUSTRYLIFE_PROCESSING) != 0) { |
|
1749 if ((byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1, 180)) closeit = false; |
|
1750 } |
|
1751 |
|
1752 /* If industry will be closed down, show this */ |
|
1753 if (closeit) { |
|
1754 i->prod_level = 0; |
|
1755 SetDParam(0, i->index); |
|
1756 AddNewsItem( |
|
1757 indspec->closure_text, |
|
1758 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), |
|
1759 i->xy + TileDiffXY(1, 1), 0 |
|
1760 ); |
|
1761 } |
|
1762 } |
|
1763 |
|
1764 |
|
1765 static void UpdateIndustryStatistics(Industry *i) |
1698 static void UpdateIndustryStatistics(Industry *i) |
1766 { |
1699 { |
1767 byte pct; |
1700 byte pct; |
1768 bool refresh = false; |
1701 bool refresh = false; |
1769 const IndustrySpec *indsp = GetIndustrySpec(i->type); |
1702 const IndustrySpec *indsp = GetIndustrySpec(i->type); |
1852 SetDParam(1, ind->town->index); |
1778 SetDParam(1, ind->town->index); |
1853 AddNewsItem(ind_spc->new_industry_text, |
1779 AddNewsItem(ind_spc->new_industry_text, |
1854 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0); |
1780 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0); |
1855 } |
1781 } |
1856 |
1782 |
1857 static void ChangeIndustryProduction(Industry *i) |
1783 /** |
1858 { |
1784 * Protects an industry from closure if the appropriate flags and conditions are met |
|
1785 * INDUSTRYBEH_CANCLOSE_LASTINSTANCE must be set (which, by default, it is not) and the |
|
1786 * count of industries of this type must one (or lower) in order to be protected |
|
1787 * against closure. |
|
1788 * @param type IndustryType been queried |
|
1789 * @result true if protection is on, false otherwise (except for oil wells) |
|
1790 */ |
|
1791 static bool CheckIndustryCloseDownProtection(IndustryType type) |
|
1792 { |
|
1793 const IndustrySpec *indspec = GetIndustrySpec(type); |
|
1794 |
|
1795 /* oil wells (or the industries with that flag set) are always allowed to closedown */ |
|
1796 if (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD && _opt.landscape == LT_TEMPERATE) return false; |
|
1797 return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE && GetIndustryTypeCount(type) <= 1); |
|
1798 } |
|
1799 |
|
1800 /** Change industry production or do closure |
|
1801 * @param i Industry for which changes are performed |
|
1802 * @param monthly true if it's the monthly call, false if it's the random call |
|
1803 */ |
|
1804 static void ChangeIndustryProduction(Industry *i, bool monthly) |
|
1805 { |
|
1806 extern StringID MapGRFStringID(uint32 grfid, StringID str); |
1859 StringID str = STR_NULL; |
1807 StringID str = STR_NULL; |
1860 int type = i->type; |
1808 bool closeit = false; |
1861 const IndustrySpec *indspec = GetIndustrySpec(type); |
1809 const IndustrySpec *indspec = GetIndustrySpec(i->type); |
1862 |
1810 bool standard = true; |
1863 if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return; |
1811 bool suppress_message = false; |
1864 |
1812 byte div = 0; |
1865 if ((indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) { |
1813 byte mul = 0; |
1866 bool only_decrease = false; |
1814 |
1867 |
1815 if (HASBIT(indspec->callback_flags, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE)) { |
|
1816 uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->xy); |
|
1817 if (res != CALLBACK_FAILED) { |
|
1818 standard = false; |
|
1819 suppress_message = HASBIT(res, 7); |
|
1820 /* Get the custom message if any */ |
|
1821 if (HASBIT(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16)); |
|
1822 res = GB(res, 0, 4); |
|
1823 switch(res) { |
|
1824 default: NOT_REACHED(); |
|
1825 case 0x0: break; // Do nothing, but show the custom message if any |
|
1826 case 0x1: div = 1; break; // Halve industry production. If production reaches the quarter of the default, the industry is closed instead. |
|
1827 case 0x2: mul = 1; break; // Double industry production if it hasn't reached eight times of the original yet. |
|
1828 case 0x3: closeit = true; break; // The industry announces imminent closure, and is physically removed from the map next month. |
|
1829 case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one. |
|
1830 case 0x5: case 0x6: case 0x7: // Divide production by 4, 8, 16 |
|
1831 case 0x8: div = res - 0x5; break; // Divide production by 32 |
|
1832 case 0x9: case 0xA: case 0xB: // Multiply production by 4, 8, 16 |
|
1833 case 0xC: mul = res - 0x9; break; // Multiply production by 32 |
|
1834 } |
|
1835 } |
|
1836 } |
|
1837 |
|
1838 if (standard && monthly != _patches.smooth_economy) return; |
|
1839 |
|
1840 if (standard && indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return; |
|
1841 |
|
1842 if (standard && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) { |
1868 /* decrease or increase */ |
1843 /* decrease or increase */ |
1869 if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE) |
1844 bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE; |
1870 only_decrease = true; |
1845 |
1871 |
1846 if (_patches.smooth_economy) { |
1872 if (only_decrease || CHANCE16(1, 3)) { |
1847 closeit = true; |
1873 /* If you transport > 60%, 66% chance we increase, else 33% chance we increase */ |
1848 for (byte j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){ |
1874 if (!only_decrease && (i->last_month_pct_transported[0] > 153) != CHANCE16(1, 3)) { |
1849 uint32 r = Random(); |
1875 /* Increase production */ |
1850 int old_prod, new_prod, percent; |
1876 if (i->prod_level != 0x80) { |
1851 int mag; |
1877 byte b; |
1852 |
1878 |
1853 new_prod = old_prod = i->production_rate[j]; |
1879 i->prod_level <<= 1; |
1854 |
1880 |
1855 if (CHANCE16I(20, 1024, r)) new_prod -= max(((RandomRange(50) + 10) * old_prod) >> 8, 1U); |
1881 b = i->production_rate[0] * 2; |
1856 /* Chance of increasing becomes better when more is transported */ |
1882 if (i->production_rate[0] >= 128) |
1857 if (CHANCE16I(20 + (i->last_month_pct_transported[j] * 20 >> 8), 1024, r >> 16) && !only_decrease) { |
1883 b = 0xFF; |
1858 new_prod += max(((RandomRange(50) + 10) * old_prod) >> 8, 1U); |
1884 i->production_rate[0] = b; |
|
1885 |
|
1886 b = i->production_rate[1] * 2; |
|
1887 if (i->production_rate[1] >= 128) |
|
1888 b = 0xFF; |
|
1889 i->production_rate[1] = b; |
|
1890 |
|
1891 str = indspec->production_up_text; |
|
1892 } |
1859 } |
1893 } else { |
1860 |
1894 /* Decrease production */ |
1861 new_prod = clamp(new_prod, 1, 255); |
1895 if (i->prod_level == 4) { |
1862 /* Do not stop closing the industry when it has the lowest possible production rate */ |
1896 i->prod_level = 0; |
1863 if (new_prod == old_prod && old_prod > 1) { |
1897 str = indspec->closure_text; |
1864 closeit = false; |
|
1865 continue; |
|
1866 } |
|
1867 |
|
1868 percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100); |
|
1869 i->production_rate[j] = new_prod; |
|
1870 |
|
1871 /* Close the industry when it has the lowest possible production rate */ |
|
1872 if (new_prod > 1) closeit = false; |
|
1873 |
|
1874 mag = abs(percent); |
|
1875 if (mag >= 10) { |
|
1876 SetDParam(2, mag); |
|
1877 SetDParam(0, GetCargo(indspec->produced_cargo[j])->name); |
|
1878 SetDParam(1, i->index); |
|
1879 AddNewsItem( |
|
1880 percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN, |
|
1881 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_ECONOMY, 0), |
|
1882 i->xy + TileDiffXY(1, 1), 0 |
|
1883 ); |
|
1884 } |
|
1885 } |
|
1886 } else { |
|
1887 if (only_decrease || CHANCE16(1, 3)) { |
|
1888 /* If you transport > 60%, 66% chance we increase, else 33% chance we increase */ |
|
1889 if (!only_decrease && (i->last_month_pct_transported[0] > 153) != CHANCE16(1, 3)) { |
|
1890 mul = 1; // Increase production |
1898 } else { |
1891 } else { |
1899 i->prod_level >>= 1; |
1892 div = 1; // Decrease production |
1900 i->production_rate[0] = (i->production_rate[0] + 1) >> 1; |
|
1901 i->production_rate[1] = (i->production_rate[1] + 1) >> 1; |
|
1902 |
|
1903 str = indspec->production_down_text; |
|
1904 } |
1893 } |
1905 } |
1894 } |
1906 } |
1895 } |
1907 } |
1896 } |
1908 if (indspec->life_type & INDUSTRYLIFE_PROCESSING) { |
1897 |
1909 /* maybe close */ |
1898 if (standard && indspec->life_type & INDUSTRYLIFE_PROCESSING) { |
1910 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, 2)) { |
1899 if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, _patches.smooth_economy ? 180 : 2)) { |
1911 i->prod_level = 0; |
1900 closeit = true; |
1912 str = indspec->closure_text; |
1901 } |
1913 } |
1902 } |
1914 } |
1903 |
1915 |
1904 /* Increase if needed */ |
1916 if (str != STR_NULL) { |
1905 while (mul-- != 0 && i->prod_level < 0x80) { |
|
1906 i->prod_level <<= 1; |
|
1907 i->production_rate[0] = min(i->production_rate[0] * 2, 0xFF); |
|
1908 i->production_rate[1] = min(i->production_rate[1] * 2, 0xFF); |
|
1909 if (str == STR_NULL) str = indspec->production_up_text; |
|
1910 } |
|
1911 |
|
1912 /* Decrease if needed */ |
|
1913 while (div-- != 0 && !closeit) { |
|
1914 if (i->prod_level == 4) { |
|
1915 closeit = true; |
|
1916 } else { |
|
1917 i->prod_level >>= 1; |
|
1918 i->production_rate[0] = (i->production_rate[0] + 1) >> 1; |
|
1919 i->production_rate[1] = (i->production_rate[1] + 1) >> 1; |
|
1920 if (str == STR_NULL) str = indspec->production_down_text; |
|
1921 } |
|
1922 } |
|
1923 |
|
1924 /* Close if needed and allowed */ |
|
1925 if (closeit && !CheckIndustryCloseDownProtection(i->type)) { |
|
1926 i->prod_level = 0; |
|
1927 str = indspec->closure_text; |
|
1928 } |
|
1929 |
|
1930 if (!suppress_message && str != STR_NULL) { |
1917 SetDParam(0, i->index); |
1931 SetDParam(0, i->index); |
1918 AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, str == indspec->closure_text ? NT_OPENCLOSE : NT_ECONOMY, 0), i->xy + TileDiffXY(1, 1), 0); |
1932 AddNewsItem(str, |
|
1933 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, closeit ? NT_OPENCLOSE : NT_ECONOMY, 0), |
|
1934 i->xy + TileDiffXY(1, 1), 0); |
1919 } |
1935 } |
1920 } |
1936 } |
1921 |
1937 |
1922 void IndustryMonthlyLoop() |
1938 void IndustryMonthlyLoop() |
1923 { |
1939 { |
1971 )) >> 8; |
1992 )) >> 8; |
1972 } |
1993 } |
1973 |
1994 |
1974 static CommandCost TerraformTile_Industry(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1995 static CommandCost TerraformTile_Industry(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1975 { |
1996 { |
|
1997 if (AutoslopeEnabled()) { |
|
1998 /* We imitate here TTDP's behaviour: |
|
1999 * - Both new and old slope must not be steep. |
|
2000 * - TileMaxZ must not be changed. |
|
2001 * - Allow autoslope by default. |
|
2002 * - Disallow autoslope if callback succeeds and returns non-zero. |
|
2003 */ |
|
2004 Slope tileh_old = GetTileSlope(tile, NULL); |
|
2005 /* TileMaxZ must not be changed. Slopes must not be steep. */ |
|
2006 if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) { |
|
2007 const IndustryGfx gfx = GetIndustryGfx(tile); |
|
2008 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); |
|
2009 |
|
2010 /* Call callback 3C 'disable autosloping for industry tiles'. */ |
|
2011 if (HASBIT(itspec->callback_flags, CBM_INDT_AUTOSLOPE)) { |
|
2012 /* If the callback fails, allow autoslope. */ |
|
2013 uint16 res = GetIndustryTileCallback(CBID_INDUSTRY_AUTOSLOPE, 0, 0, gfx, GetIndustryByTile(tile), tile); |
|
2014 if ((res == 0) || (res == CALLBACK_FAILED)) return _price.terraform; |
|
2015 } else { |
|
2016 // allow autoslope |
|
2017 return _price.terraform; |
|
2018 } |
|
2019 } |
|
2020 } |
1976 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); // funny magic bulldozer |
2021 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); // funny magic bulldozer |
1977 } |
2022 } |
1978 |
2023 |
1979 extern const TileTypeProcs _tile_type_industry_procs = { |
2024 extern const TileTypeProcs _tile_type_industry_procs = { |
1980 DrawTile_Industry, /* draw_tile_proc */ |
2025 DrawTile_Industry, /* draw_tile_proc */ |
2018 SLE_VAR(Industry, random_color, SLE_UINT8), |
2063 SLE_VAR(Industry, random_color, SLE_UINT8), |
2019 SLE_CONDVAR(Industry, last_prod_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30), |
2064 SLE_CONDVAR(Industry, last_prod_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30), |
2020 SLE_CONDVAR(Industry, last_prod_year, SLE_INT32, 31, SL_MAX_VERSION), |
2065 SLE_CONDVAR(Industry, last_prod_year, SLE_INT32, 31, SL_MAX_VERSION), |
2021 SLE_VAR(Industry, was_cargo_delivered, SLE_UINT8), |
2066 SLE_VAR(Industry, was_cargo_delivered, SLE_UINT8), |
2022 |
2067 |
2023 SLE_CONDVAR(Industry, owner, SLE_UINT8, 70, SL_MAX_VERSION), |
2068 SLE_CONDVAR(Industry, founder, SLE_UINT8, 70, SL_MAX_VERSION), |
2024 SLE_CONDVAR(Industry, construction_date, SLE_INT32, 70, SL_MAX_VERSION), |
2069 SLE_CONDVAR(Industry, construction_date, SLE_INT32, 70, SL_MAX_VERSION), |
2025 SLE_CONDVAR(Industry, construction_type, SLE_UINT8, 70, SL_MAX_VERSION), |
2070 SLE_CONDVAR(Industry, construction_type, SLE_UINT8, 70, SL_MAX_VERSION), |
2026 SLE_CONDVAR(Industry, last_cargo_accepted_at, SLE_INT32, 70, SL_MAX_VERSION), |
2071 SLE_CONDVAR(Industry, last_cargo_accepted_at, SLE_INT32, 70, SL_MAX_VERSION), |
2027 SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, 73, SL_MAX_VERSION), |
2072 SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, 73, SL_MAX_VERSION), |
|
2073 |
|
2074 SLE_CONDARRX(cpp_offsetof(Industry, psa) + cpp_offsetof(Industry::PersistentStorage, storage), SLE_UINT32, 16, 76, SL_MAX_VERSION), |
2028 |
2075 |
2029 /* reserve extra space in savegame here. (currently 32 bytes) */ |
2076 /* reserve extra space in savegame here. (currently 32 bytes) */ |
2030 SLE_CONDNULL(32, 2, SL_MAX_VERSION), |
2077 SLE_CONDNULL(32, 2, SL_MAX_VERSION), |
2031 |
2078 |
2032 SLE_END() |
2079 SLE_END() |