src/industry_cmd.cpp
branchnoai
changeset 9724 b39bc69bb2f2
parent 9723 eee46cb39750
child 9732 f8eb3e208514
equal deleted inserted replaced
9723:eee46cb39750 9724:b39bc69bb2f2
     5 #include "stdafx.h"
     5 #include "stdafx.h"
     6 #include "openttd.h"
     6 #include "openttd.h"
     7 #include "clear_map.h"
     7 #include "clear_map.h"
     8 #include "industry_map.h"
     8 #include "industry_map.h"
     9 #include "station_map.h"
     9 #include "station_map.h"
    10 #include "table/strings.h"
       
    11 #include "table/sprites.h"
       
    12 #include "train.h"
    10 #include "train.h"
    13 #include "landscape.h"
    11 #include "landscape.h"
    14 #include "viewport_func.h"
    12 #include "viewport_func.h"
    15 #include "command_func.h"
    13 #include "command_func.h"
    16 #include "industry.h"
    14 #include "industry.h"
    17 #include "town.h"
    15 #include "town.h"
    18 #include "news.h"
    16 #include "news.h"
    19 #include "saveload.h"
    17 #include "saveload.h"
    20 #include "variables.h"
    18 #include "variables.h"
    21 #include "table/industry_land.h"
       
    22 #include "table/build_industry.h"
       
    23 #include "genworld.h"
    19 #include "genworld.h"
    24 #include "water_map.h"
    20 #include "water_map.h"
    25 #include "tree_map.h"
    21 #include "tree_map.h"
    26 #include "cargotype.h"
    22 #include "cargotype.h"
    27 #include "newgrf.h"
    23 #include "newgrf.h"
    38 #include "functions.h"
    34 #include "functions.h"
    39 #include "window_func.h"
    35 #include "window_func.h"
    40 #include "date_func.h"
    36 #include "date_func.h"
    41 #include "vehicle_func.h"
    37 #include "vehicle_func.h"
    42 #include "sound_func.h"
    38 #include "sound_func.h"
       
    39 
       
    40 #include "table/strings.h"
       
    41 #include "table/sprites.h"
       
    42 #include "table/industry_land.h"
       
    43 #include "table/build_industry.h"
    43 
    44 
    44 void ShowIndustryViewWindow(int industry);
    45 void ShowIndustryViewWindow(int industry);
    45 void BuildOilRig(TileIndex tile);
    46 void BuildOilRig(TileIndex tile);
    46 
    47 
    47 static byte _industry_sound_ctr;
    48 static byte _industry_sound_ctr;
   838 
   839 
   839 static bool IsBadFarmFieldTile(TileIndex tile)
   840 static bool IsBadFarmFieldTile(TileIndex tile)
   840 {
   841 {
   841 	switch (GetTileType(tile)) {
   842 	switch (GetTileType(tile)) {
   842 		case MP_CLEAR: return IsClearGround(tile, CLEAR_FIELDS) || IsClearGround(tile, CLEAR_SNOW) || IsClearGround(tile, CLEAR_DESERT);
   843 		case MP_CLEAR: return IsClearGround(tile, CLEAR_FIELDS) || IsClearGround(tile, CLEAR_SNOW) || IsClearGround(tile, CLEAR_DESERT);
   843 		case MP_TREES: return false;
   844 		case MP_TREES: return (GetTreeGround(tile) == TREE_GROUND_SHORE);
   844 		default:       return true;
   845 		default:       return true;
   845 	}
   846 	}
   846 }
   847 }
   847 
   848 
   848 static bool IsBadFarmFieldTile2(TileIndex tile)
   849 static bool IsBadFarmFieldTile2(TileIndex tile)
   849 {
   850 {
   850 	switch (GetTileType(tile)) {
   851 	switch (GetTileType(tile)) {
   851 		case MP_CLEAR: return IsClearGround(tile, CLEAR_SNOW) || IsClearGround(tile, CLEAR_DESERT);
   852 		case MP_CLEAR: return IsClearGround(tile, CLEAR_SNOW) || IsClearGround(tile, CLEAR_DESERT);
   852 		case MP_TREES: return false;
   853 		case MP_TREES: return (GetTreeGround(tile) == TREE_GROUND_SHORE);
   853 		default:       return true;
   854 		default:       return true;
   854 	}
   855 	}
   855 }
   856 }
   856 
   857 
   857 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction)
   858 static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction)
  1375 	_current_player = old_player;
  1376 	_current_player = old_player;
  1376 	return true;
  1377 	return true;
  1377 }
  1378 }
  1378 
  1379 
  1379 
  1380 
  1380 static bool CheckIfTooCloseToIndustry(TileIndex tile, int type)
  1381 static bool CheckIfFarEnoughFromIndustry(TileIndex tile, int type)
  1381 {
  1382 {
  1382 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1383 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1383 	const Industry *i;
  1384 	const Industry *i;
  1384 
  1385 
  1385 	/* accepting industries won't be close, not even with patch */
       
  1386 	if (_patches.same_industry_close && indspec->accepts_cargo[0] == CT_INVALID)
  1386 	if (_patches.same_industry_close && indspec->accepts_cargo[0] == CT_INVALID)
       
  1387 		/* Allow primary industries to be placed close to any other industry */
  1387 		return true;
  1388 		return true;
  1388 
  1389 
  1389 	FOR_ALL_INDUSTRIES(i) {
  1390 	FOR_ALL_INDUSTRIES(i) {
       
  1391 		/* Within 14 tiles from another industry is considered close */
       
  1392 		bool in_low_distance = DistanceMax(tile, i->xy) <= 14;
       
  1393 
  1390 		/* check if an industry that accepts the same goods is nearby */
  1394 		/* check if an industry that accepts the same goods is nearby */
  1391 		if (DistanceMax(tile, i->xy) <= 14 &&
  1395 		if (in_low_distance &&
  1392 				indspec->accepts_cargo[0] != CT_INVALID &&
  1396 				indspec->accepts_cargo[0] != CT_INVALID && // not a primary industry?
  1393 				indspec->accepts_cargo[0] == i->accepts_cargo[0] && (
  1397 				indspec->accepts_cargo[0] == i->accepts_cargo[0] && (
  1394 					_game_mode != GM_EDITOR ||
  1398 				/* at least one of those options must be true */
  1395 					!_patches.same_industry_close ||
  1399 				_game_mode != GM_EDITOR || // editor must not be stopped
  1396 					!_patches.multiple_industry_per_town
  1400 				!_patches.same_industry_close ||
  1397 				)) {
  1401 				!_patches.multiple_industry_per_town)) {
  1398 			_error_message = STR_INDUSTRY_TOO_CLOSE;
  1402 			_error_message = STR_INDUSTRY_TOO_CLOSE;
  1399 			return false;
  1403 			return false;
  1400 		}
  1404 		}
  1401 
  1405 
  1402 		/* check "not close to" field. */
  1406 		/* check if there are any conflicting industry types around */
  1403 		if ((i->type == indspec->conflicting[0] || i->type == indspec->conflicting[1] || i->type == indspec->conflicting[2]) &&
  1407 		if ((i->type == indspec->conflicting[0] ||
  1404 				DistanceMax(tile, i->xy) <= 14) {
  1408 				i->type == indspec->conflicting[1] ||
       
  1409 				i->type == indspec->conflicting[2]) &&
       
  1410 				in_low_distance) {
  1405 			_error_message = STR_INDUSTRY_TOO_CLOSE;
  1411 			_error_message = STR_INDUSTRY_TOO_CLOSE;
  1406 			return false;
  1412 			return false;
  1407 		}
  1413 		}
  1408 	}
  1414 	}
  1409 	return true;
  1415 	return true;
  1516 
  1522 
  1517 			if (_generating_world) {
  1523 			if (_generating_world) {
  1518 				SetIndustryConstructionCounter(cur_tile, 3);
  1524 				SetIndustryConstructionCounter(cur_tile, 3);
  1519 				SetIndustryConstructionStage(cur_tile, 2);
  1525 				SetIndustryConstructionStage(cur_tile, 2);
  1520 			}
  1526 			}
  1521 			if (it->gfx >= NEW_INDUSTRYTILEOFFSET) {
  1527 
  1522 				/* New industry */
  1528 			/* it->gfx is stored in the map. But the translated ID cur_gfx is the interesting one */
  1523 				const IndustryTileSpec *its = GetIndustryTileSpec(it->gfx);
  1529 			IndustryGfx cur_gfx = GetTranslatedIndustryTileID(it->gfx);
  1524 				if (its->animation_info != 0xFFFF) AddAnimatedTile(cur_tile);
  1530 			const IndustryTileSpec *its = GetIndustryTileSpec(cur_gfx);
  1525 			}
  1531 			if (its->animation_info != 0xFFFF) AddAnimatedTile(cur_tile);
  1526 		}
  1532 		}
  1527 	} while ((++it)->ti.x != -0x80);
  1533 	} while ((++it)->ti.x != -0x80);
  1528 
  1534 
  1529 	i->width++;
  1535 	i->width++;
  1530 	i->height++;
  1536 	i->height++;
  1540  * @param tile tile where industry is built
  1546  * @param tile tile where industry is built
  1541  * @param type of industry to build
  1547  * @param type of industry to build
  1542  * @param flags of operations to conduct
  1548  * @param flags of operations to conduct
  1543  * @param indspec pointer to industry specifications
  1549  * @param indspec pointer to industry specifications
  1544  * @param itspec_index the index of the itsepc to build/fund
  1550  * @param itspec_index the index of the itsepc to build/fund
       
  1551  * @param seed random seed (possibly) used by industries
  1545  * @return the pointer of the newly created industry, or NULL if it failed
  1552  * @return the pointer of the newly created industry, or NULL if it failed
  1546  */
  1553  */
  1547 static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, uint itspec_index)
  1554 static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, uint itspec_index, uint32 seed)
  1548 {
  1555 {
  1549 	const IndustryTileTable *it = indspec->table[itspec_index];
  1556 	const IndustryTileTable *it = indspec->table[itspec_index];
  1550 	bool custom_shape_check = false;
  1557 	bool custom_shape_check = false;
  1551 
  1558 
  1552 	if (!CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, &custom_shape_check)) return NULL;
  1559 	if (!CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, &custom_shape_check)) return NULL;
  1553 
  1560 
  1554 	if (HasBit(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) {
  1561 	if (HasBit(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) {
  1555 		if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index)) return NULL;
  1562 		if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index, seed)) return NULL;
  1556 	} else {
  1563 	} else {
  1557 		if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
  1564 		if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
  1558 	}
  1565 	}
  1559 
  1566 
  1560 	if (!custom_shape_check && _patches.land_generator == LG_TERRAGENESIS && _generating_world && !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
  1567 	if (!custom_shape_check && _patches.land_generator == LG_TERRAGENESIS && _generating_world && !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
  1561 	if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
  1568 	if (!CheckIfFarEnoughFromIndustry(tile, type)) return NULL;
  1562 
  1569 
  1563 	const Town *t = CheckMultipleIndustryInTown(tile, type);
  1570 	const Town *t = CheckMultipleIndustryInTown(tile, type);
  1564 	if (t == NULL) return NULL;
  1571 	if (t == NULL) return NULL;
  1565 
  1572 
  1566 	if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
  1573 	if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
  1580 }
  1587 }
  1581 
  1588 
  1582 /** Build/Fund an industry
  1589 /** Build/Fund an industry
  1583  * @param tile tile where industry is built
  1590  * @param tile tile where industry is built
  1584  * @param flags of operations to conduct
  1591  * @param flags of operations to conduct
  1585  * @param p1 industry type see build_industry.h and see industry.h
  1592  * @param p1 various bitstuffed elements
  1586  * @param p2 first layout to try
  1593  * - p1 = (bit  0 - 15) - industry type see build_industry.h and see industry.h
       
  1594  * - p1 = (bit 16 - 31) - first layout to try
       
  1595  * @param p2 seed to use for variable 8F
  1587  * @return index of the newly create industry, or CMD_ERROR if it failed
  1596  * @return index of the newly create industry, or CMD_ERROR if it failed
  1588  */
  1597  */
  1589 CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1598 CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1590 {
  1599 {
  1591 	const IndustrySpec *indspec;
  1600 	const IndustrySpec *indspec = GetIndustrySpec(GB(p1, 0, 16));
  1592 
       
  1593 	indspec = GetIndustrySpec(p1);
       
  1594 
  1601 
  1595 	/* Check if the to-be built/founded industry is available for this climate. */
  1602 	/* Check if the to-be built/founded industry is available for this climate. */
  1596 	if (!indspec->enabled) {
  1603 	if (!indspec->enabled) {
  1597 		return CMD_ERROR;
  1604 		return CMD_ERROR;
  1598 	}
  1605 	}
  1612 				for (int i = 0; i < 5000; i++) {
  1619 				for (int i = 0; i < 5000; i++) {
  1613 					/* We should not have more than one Random() in a function call
  1620 					/* We should not have more than one Random() in a function call
  1614 					 * because parameter evaluation order is not guaranteed in the c++ standard
  1621 					 * because parameter evaluation order is not guaranteed in the c++ standard
  1615 					 */
  1622 					 */
  1616 					tile = RandomTile();
  1623 					tile = RandomTile();
  1617 					const Industry *ind = CreateNewIndustryHelper(tile, p1, flags, indspec, RandomRange(indspec->num_table));
  1624 					const Industry *ind = CreateNewIndustryHelper(tile, p1, flags, indspec, RandomRange(indspec->num_table), p2);
  1618 					if (ind != NULL) {
  1625 					if (ind != NULL) {
  1619 						SetDParam(0, indspec->name);
  1626 						SetDParam(0, indspec->name);
  1620 						if (indspec->new_industry_text > STR_LAST_STRINGID) {
  1627 						if (indspec->new_industry_text > STR_LAST_STRINGID) {
  1621 							SetDParam(1, STR_TOWN);
  1628 							SetDParam(1, STR_TOWN);
  1622 							SetDParam(2, ind->town->index);
  1629 							SetDParam(2, ind->town->index);
  1631 			}
  1638 			}
  1632 		}
  1639 		}
  1633 	} else {
  1640 	} else {
  1634 		int count = indspec->num_table;
  1641 		int count = indspec->num_table;
  1635 		const IndustryTileTable * const *itt = indspec->table;
  1642 		const IndustryTileTable * const *itt = indspec->table;
  1636 		int num = Clamp(p2, 0, count - 1);
  1643 		int num = Clamp(GB(p1, 16, 16), 0, count - 1);
  1637 
  1644 
  1638 		_error_message = STR_0239_SITE_UNSUITABLE;
  1645 		_error_message = STR_0239_SITE_UNSUITABLE;
  1639 		do {
  1646 		do {
  1640 			if (--count < 0) return CMD_ERROR;
  1647 			if (--count < 0) return CMD_ERROR;
  1641 			if (--num < 0) num = indspec->num_table - 1;
  1648 			if (--num < 0) num = indspec->num_table - 1;
  1642 		} while (!CheckIfIndustryTilesAreFree(tile, itt[num], num, p1));
  1649 		} while (!CheckIfIndustryTilesAreFree(tile, itt[num], num, p1));
  1643 
  1650 
  1644 		if (CreateNewIndustryHelper(tile, p1, flags, indspec, num) == NULL) return CMD_ERROR;
  1651 		if (CreateNewIndustryHelper(tile, p1, flags, indspec, num, p2) == NULL) return CMD_ERROR;
  1645 	}
  1652 	}
  1646 
  1653 
  1647 	return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
  1654 	return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
  1648 }
  1655 }
  1649 
  1656 
  1650 
  1657 
  1651 Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
  1658 Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
  1652 {
  1659 {
  1653 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1660 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1654 
  1661 
  1655 	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table));
  1662 	uint32 seed = Random();
       
  1663 	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed);
  1656 }
  1664 }
  1657 
  1665 
  1658 enum {
  1666 enum {
  1659 	NB_NUMOFINDUSTRY = 11,
  1667 	NB_NUMOFINDUSTRY = 11,
  1660 	NB_DIFFICULTY_LEVEL = 5,
  1668 	NB_DIFFICULTY_LEVEL = 5,
  1943 		 * We cannot check the first of shared orders only, since the first vehicle in such a chain
  1951 		 * We cannot check the first of shared orders only, since the first vehicle in such a chain
  1944 		 * may have a different cargo type.
  1952 		 * may have a different cargo type.
  1945 		 */
  1953 		 */
  1946 		const Order *o;
  1954 		const Order *o;
  1947 		FOR_VEHICLE_ORDERS(v, o) {
  1955 		FOR_VEHICLE_ORDERS(v, o) {
  1948 			if (o->type == OT_GOTO_STATION && !HasBit(o->flags, OFB_TRANSFER)) {
  1956 			if (o->type == OT_GOTO_STATION && !HasBit(o->flags, OF_TRANSFER)) {
  1949 				/* Vehicle visits a station to load or unload */
  1957 				/* Vehicle visits a station to load or unload */
  1950 				Station *st = GetStation(o->dest);
  1958 				Station *st = GetStation(o->dest);
  1951 				if (!st->IsValid()) continue;
  1959 				if (!st->IsValid()) continue;
  1952 
  1960 
  1953 				/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
  1961 				/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
  1954 				if (HasBit(o->flags, OFB_UNLOAD) && !c_accepts) break;
  1962 				if (HasBit(o->flags, OF_UNLOAD) && !c_accepts) break;
  1955 
  1963 
  1956 				if (stations.find(st) != stations.end()) {
  1964 				if (stations.find(st) != stations.end()) {
  1957 					if (v->owner == _local_player) return 2; // Player services industry
  1965 					if (v->owner == _local_player) return 2; // Player services industry
  1958 					result = 1; // Competitor services industry
  1966 					result = 1; // Competitor services industry
  1959 				}
  1967 				}
  2135 			i->production_rate[1] = (i->production_rate[1] + 1) >> 1;
  2143 			i->production_rate[1] = (i->production_rate[1] + 1) >> 1;
  2136 			if (str == STR_NULL) str = indspec->production_down_text;
  2144 			if (str == STR_NULL) str = indspec->production_down_text;
  2137 		}
  2145 		}
  2138 	}
  2146 	}
  2139 
  2147 
       
  2148 	/* Increase or Decreasing the production level if needed */
  2140 	if (increment != 0) {
  2149 	if (increment != 0) {
  2141 		i->prod_level = ClampU(i->prod_level + increment, 4, 0x80);
  2150 		if (increment < 0 && i->prod_level == 4) {
  2142 		if (i->prod_level == 4) closeit = true;
  2151 			closeit = true;
       
  2152 		} else {
       
  2153 			i->prod_level = ClampU(i->prod_level + increment, 4, 0x80);
       
  2154 		}
  2143 	}
  2155 	}
  2144 
  2156 
  2145 	/* Close if needed and allowed */
  2157 	/* Close if needed and allowed */
  2146 	if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
  2158 	if (closeit && !CheckIndustryCloseDownProtection(i->type)) {
  2147 		i->prod_level = 0;
  2159 		i->prod_level = 0;
  2292 	SLE_CONDVAR(Industry, xy,                         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
  2304 	SLE_CONDVAR(Industry, xy,                         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
  2293 	SLE_CONDVAR(Industry, xy,                         SLE_UINT32,                  6, SL_MAX_VERSION),
  2305 	SLE_CONDVAR(Industry, xy,                         SLE_UINT32,                  6, SL_MAX_VERSION),
  2294 	    SLE_VAR(Industry, width,                      SLE_UINT8),
  2306 	    SLE_VAR(Industry, width,                      SLE_UINT8),
  2295 	    SLE_VAR(Industry, height,                     SLE_UINT8),
  2307 	    SLE_VAR(Industry, height,                     SLE_UINT8),
  2296 	    SLE_REF(Industry, town,                       REF_TOWN),
  2308 	    SLE_REF(Industry, town,                       REF_TOWN),
  2297 	SLE_CONDNULL( 2, 2, 60),       ///< used to be industry's produced_cargo
  2309 	SLE_CONDNULL( 2, 0, 60),       ///< used to be industry's produced_cargo
  2298 	SLE_CONDARR(Industry, produced_cargo,             SLE_UINT8,  2,              78, SL_MAX_VERSION),
  2310 	SLE_CONDARR(Industry, produced_cargo,             SLE_UINT8,  2,              78, SL_MAX_VERSION),
  2299 	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16, 3,              70, SL_MAX_VERSION),
  2311 	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16, 3,              70, SL_MAX_VERSION),
  2300 	    SLE_ARR(Industry, produced_cargo_waiting,     SLE_UINT16, 2),
  2312 	    SLE_ARR(Industry, produced_cargo_waiting,     SLE_UINT16, 2),
  2301 	    SLE_ARR(Industry, production_rate,            SLE_UINT8,  2),
  2313 	    SLE_ARR(Industry, production_rate,            SLE_UINT8,  2),
  2302 	SLE_CONDNULL( 3, 2, 60),       ///< used to be industry's accepts_cargo
  2314 	SLE_CONDNULL( 3, 0, 60),       ///< used to be industry's accepts_cargo
  2303 	SLE_CONDARR(Industry, accepts_cargo,              SLE_UINT8,  3,              78, SL_MAX_VERSION),
  2315 	SLE_CONDARR(Industry, accepts_cargo,              SLE_UINT8,  3,              78, SL_MAX_VERSION),
  2304 	    SLE_VAR(Industry, prod_level,                 SLE_UINT8),
  2316 	    SLE_VAR(Industry, prod_level,                 SLE_UINT8),
  2305 	    SLE_ARR(Industry, this_month_production,      SLE_UINT16, 2),
  2317 	    SLE_ARR(Industry, this_month_production,      SLE_UINT16, 2),
  2306 	    SLE_ARR(Industry, this_month_transported,     SLE_UINT16, 2),
  2318 	    SLE_ARR(Industry, this_month_transported,     SLE_UINT16, 2),
  2307 	    SLE_ARR(Industry, last_month_pct_transported, SLE_UINT8,  2),
  2319 	    SLE_ARR(Industry, last_month_pct_transported, SLE_UINT8,  2),