328 return SLOPE_FLAT; |
328 return SLOPE_FLAT; |
329 } |
329 } |
330 |
330 |
331 static void GetAcceptedCargo_Industry(TileIndex tile, AcceptedCargo ac) |
331 static void GetAcceptedCargo_Industry(TileIndex tile, AcceptedCargo ac) |
332 { |
332 { |
333 const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile)); |
333 IndustryGfx gfx = GetIndustryGfx(tile); |
334 CargoID a; |
334 const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); |
|
335 |
|
336 /* When we have to use a callback, we put our data in the next two variables */ |
|
337 CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)]; |
|
338 uint8 raw_acceptance[lengthof(itspec->acceptance)]; |
|
339 |
|
340 /* And then these will always point to a same sized array with the required data */ |
|
341 const CargoID *accepts_cargo = itspec->accepts_cargo; |
|
342 const uint8 *acceptance = itspec->acceptance; |
|
343 |
|
344 if (HASBIT(itspec->callback_flags, CBM_INDT_ACCEPT_CARGO)) { |
|
345 uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, GetIndustryByTile(tile), tile); |
|
346 if (res != CALLBACK_FAILED) { |
|
347 accepts_cargo = raw_accepts_cargo; |
|
348 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile); |
|
349 } |
|
350 } |
|
351 |
|
352 if (HASBIT(itspec->callback_flags, CBM_INDT_CARGO_ACCEPTANCE)) { |
|
353 uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, GetIndustryByTile(tile), tile); |
|
354 if (res != CALLBACK_FAILED) { |
|
355 acceptance = raw_acceptance; |
|
356 for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_acceptance[i] = GB(res, i * 4, 4); |
|
357 } |
|
358 } |
335 |
359 |
336 for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) { |
360 for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) { |
337 a = itspec->accepts_cargo[i]; |
361 CargoID a = accepts_cargo[i]; |
338 if (a != CT_INVALID) ac[a] = itspec->acceptance[i]; |
362 if (a != CT_INVALID) ac[a] = acceptance[i]; |
339 } |
363 } |
340 } |
364 } |
341 |
365 |
342 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td) |
366 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td) |
343 { |
367 { |
387 |
411 |
388 i->this_month_production[0] += cw; |
412 i->this_month_production[0] += cw; |
389 |
413 |
390 am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw); |
414 am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw); |
391 i->this_month_transported[0] += am; |
415 i->this_month_transported[0] += am; |
392 if (am != 0) { |
416 if (am != 0 && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) { |
393 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production; |
417 uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production; |
394 |
418 |
395 if (newgfx != INDUSTRYTILE_NOANIM) { |
419 if (newgfx != INDUSTRYTILE_NOANIM) { |
396 ResetIndustryConstructionStage(tile); |
420 ResetIndustryConstructionStage(tile); |
397 SetIndustryCompleted(tile, true); |
421 SetIndustryCompleted(tile, true); |
603 } |
633 } |
604 |
634 |
605 stage = GetIndustryConstructionStage(tile) + 1; |
635 stage = GetIndustryConstructionStage(tile) + 1; |
606 SetIndustryConstructionCounter(tile, 0); |
636 SetIndustryConstructionCounter(tile, 0); |
607 SetIndustryConstructionStage(tile, stage); |
637 SetIndustryConstructionStage(tile, stage); |
|
638 StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE); |
608 if (stage == 3) { |
639 if (stage == 3) { |
609 SetIndustryCompleted(tile, true); |
640 SetIndustryCompleted(tile, true); |
610 } |
641 } |
611 |
642 |
612 MarkTileDirtyByTile(tile); |
643 MarkTileDirtyByTile(tile); |
613 |
644 |
614 if (!IsIndustryCompleted(tile)) return; |
645 if (!IsIndustryCompleted(tile)) return; |
615 |
646 |
616 switch (GetIndustryGfx(tile)) { |
647 IndustryGfx gfx = GetIndustryGfx(tile); |
|
648 if (gfx >= NEW_INDUSTRYTILEOFFSET) { |
|
649 /* New industry */ |
|
650 const IndustryTileSpec *its = GetIndustryTileSpec(gfx); |
|
651 if (its->animation_info != 0xFFFF) AddAnimatedTile(tile); |
|
652 return; |
|
653 } |
|
654 |
|
655 switch (gfx) { |
617 case GFX_POWERPLANT_CHIMNEY: |
656 case GFX_POWERPLANT_CHIMNEY: |
618 CreateIndustryEffectSmoke(tile); |
657 CreateIndustryEffectSmoke(tile); |
619 break; |
658 break; |
620 |
659 |
621 case GFX_OILRIG_1: |
660 case GFX_OILRIG_1: |
903 TileIndex tile = TileAddWrap(i->xy, x, y); |
944 TileIndex tile = TileAddWrap(i->xy, x, y); |
904 |
945 |
905 if (tile != INVALID_TILE) PlantFarmField(tile, i->index); |
946 if (tile != INVALID_TILE) PlantFarmField(tile, i->index); |
906 } |
947 } |
907 |
948 |
908 static void MaybePlantFarmField(const Industry *i) |
|
909 { |
|
910 if (CHANCE16(1, 8)) PlantRandomFarmField(i); |
|
911 } |
|
912 |
|
913 /** |
949 /** |
914 * Search callback function for ChopLumberMillTrees |
950 * Search callback function for ChopLumberMillTrees |
915 * @param tile to test |
951 * @param tile to test |
916 * @param data that is passed by the caller. In this case, nothing |
952 * @param data that is passed by the caller. In this case, nothing |
917 * @return the result of the test |
953 * @return the result of the test |
972 |
1008 |
973 IndustyBehaviour indbehav = indsp->behaviour; |
1009 IndustyBehaviour indbehav = indsp->behaviour; |
974 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]); |
1010 i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]); |
975 i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]); |
1011 i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]); |
976 |
1012 |
977 if (indbehav & INDUSTRYBEH_PLANT_FIELDS) { |
1013 if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) { |
978 MaybePlantFarmField(i); |
1014 bool plant; |
979 } else if ((indbehav & INDUSTRYBEH_CUT_TREES) && (i->counter & 0x1FF) == 0) { |
1015 if (HASBIT(indsp->callback_flags, CBM_IND_SPECIAL_EFFECT)) { |
980 ChopLumberMillTrees(i); |
1016 plant = (GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->xy) != 0); |
|
1017 } else { |
|
1018 plant = CHANCE16(1, 8); |
|
1019 } |
|
1020 |
|
1021 if (plant) PlantRandomFarmField(i); |
|
1022 } |
|
1023 if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) { |
|
1024 bool cut = ((i->counter & 0x1FF) == 0); |
|
1025 if (HASBIT(indsp->callback_flags, CBM_IND_SPECIAL_EFFECT)) { |
|
1026 cut = (GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, 0, 1, i, i->type, i->xy) != 0); |
|
1027 } |
|
1028 |
|
1029 if (cut) ChopLumberMillTrees(i); |
981 } |
1030 } |
982 } |
1031 } |
983 } |
1032 } |
984 |
1033 |
985 void OnTick_Industry() |
1034 void OnTick_Industry() |
1152 } |
1202 } |
1153 } else { |
1203 } else { |
1154 if (!EnsureNoVehicle(cur_tile)) return false; |
1204 if (!EnsureNoVehicle(cur_tile)) return false; |
1155 if (MayHaveBridgeAbove(cur_tile) && IsBridgeAbove(cur_tile)) return false; |
1205 if (MayHaveBridgeAbove(cur_tile) && IsBridgeAbove(cur_tile)) return false; |
1156 |
1206 |
|
1207 const IndustryTileSpec *its = GetIndustryTileSpec(it->gfx); |
1157 IndustyBehaviour ind_behav = GetIndustrySpec(type)->behaviour; |
1208 IndustyBehaviour ind_behav = GetIndustrySpec(type)->behaviour; |
1158 |
1209 |
1159 if (ind_behav & INDUSTRYBEH_BUILT_ONWATER) { |
1210 if (HASBIT(its->callback_flags, CBM_INDT_SHAPE_CHECK)) { |
1160 /* As soon as the tile is not water, bail out. |
1211 if (custom_shape_check != NULL) *custom_shape_check = true; |
1161 * But that does not mean the search is over. You have |
1212 if (!PerformIndustryTileSlopeCheck(cur_tile, its, type, it->gfx)) return false; |
1162 * to make sure every tile of the industry will be only water*/ |
|
1163 if (!IsClearWaterTile(cur_tile)) return false; |
|
1164 } else { |
1213 } else { |
1165 Slope tileh; |
1214 if (ind_behav & INDUSTRYBEH_BUILT_ONWATER) { |
1166 |
1215 /* As soon as the tile is not water, bail out. |
1167 if (IsClearWaterTile(cur_tile)) return false; |
1216 * But that does not mean the search is over. You have |
1168 |
1217 * to make sure every tile of the industry will be only water*/ |
1169 tileh = GetTileSlope(cur_tile, NULL); |
1218 if (!IsClearWaterTile(cur_tile)) return false; |
1170 if (IsSteepSlope(tileh)) return false; |
1219 } else { |
1171 |
1220 Slope tileh; |
1172 if (_patches.land_generator != LG_TERRAGENESIS || !_generating_world) { |
1221 |
1173 /* It is almost impossible to have a fully flat land in TG, so what we |
1222 if (IsClearWaterTile(cur_tile)) return false; |
1174 * do is that we check if we can make the land flat later on. See |
1223 |
1175 * CheckIfCanLevelIndustryPlatform(). */ |
1224 tileh = GetTileSlope(cur_tile, NULL); |
1176 if (tileh != SLOPE_FLAT) { |
1225 if (IsSteepSlope(tileh)) return false; |
1177 Slope t; |
1226 |
1178 byte bits = GetIndustryTileSpec(it->gfx)->slopes_refused; |
1227 if (_patches.land_generator != LG_TERRAGENESIS || !_generating_world) { |
1179 |
1228 /* It is almost impossible to have a fully flat land in TG, so what we |
1180 if (bits & 0x10) return false; |
1229 * do is that we check if we can make the land flat later on. See |
1181 |
1230 * CheckIfCanLevelIndustryPlatform(). */ |
1182 t = ComplementSlope(tileh); |
1231 if (tileh != SLOPE_FLAT) { |
1183 |
1232 Slope t; |
1184 if (bits & 1 && (t & SLOPE_NW)) return false; |
1233 byte bits = its->slopes_refused; |
1185 if (bits & 2 && (t & SLOPE_NE)) return false; |
1234 |
1186 if (bits & 4 && (t & SLOPE_SW)) return false; |
1235 if (bits & 0x10) return false; |
1187 if (bits & 8 && (t & SLOPE_SE)) return false; |
1236 |
|
1237 t = ComplementSlope(tileh); |
|
1238 |
|
1239 if (bits & 1 && (t & SLOPE_NW)) return false; |
|
1240 if (bits & 2 && (t & SLOPE_NE)) return false; |
|
1241 if (bits & 4 && (t & SLOPE_SW)) return false; |
|
1242 if (bits & 8 && (t & SLOPE_SE)) return false; |
|
1243 } |
1188 } |
1244 } |
1189 } |
1245 } |
1190 |
1246 } |
1191 if (ind_behav & INDUSTRYBEH_ONLY_INTOWN) { |
1247 |
1192 if (!IsTileType(cur_tile, MP_HOUSE)) { |
1248 if (ind_behav & INDUSTRYBEH_ONLY_INTOWN) { |
1193 _error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS; |
1249 if (!IsTileType(cur_tile, MP_HOUSE)) { |
1194 return false; |
1250 _error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS; |
1195 } |
1251 return false; |
1196 } else { |
|
1197 if (ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) { |
|
1198 if (!IsTileType(cur_tile, MP_HOUSE)) goto do_clear; |
|
1199 } else { |
|
1200 do_clear: |
|
1201 if (CmdFailed(DoCommand(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) |
|
1202 return false; |
|
1203 } |
|
1204 } |
1252 } |
|
1253 if (CmdFailed(DoCommand(cur_tile, 0, 0, 0, CMD_LANDSCAPE_CLEAR))) return false; |
|
1254 } else if ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) == 0 || !IsTileType(cur_tile, MP_HOUSE)) { |
|
1255 if (CmdFailed(DoCommand(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) return false; |
1205 } |
1256 } |
1206 } |
1257 } |
1207 } while ((++it)->ti.x != -0x80); |
1258 } while ((++it)->ti.x != -0x80); |
1208 |
1259 |
1209 return true; |
1260 return true; |
1456 /** Helper function for Build/Fund an industry |
1507 /** Helper function for Build/Fund an industry |
1457 * @param tile tile where industry is built |
1508 * @param tile tile where industry is built |
1458 * @param type of industry to build |
1509 * @param type of industry to build |
1459 * @param flags of operations to conduct |
1510 * @param flags of operations to conduct |
1460 * @param indspec pointer to industry specifications |
1511 * @param indspec pointer to industry specifications |
1461 * @param it pointer to list of tile type to build |
1512 * @param itspec_index the index of the itsepc to build/fund |
1462 * @return the pointer of the newly created industry, or NULL if it failed |
1513 * @return the pointer of the newly created industry, or NULL if it failed |
1463 */ |
1514 */ |
1464 static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, const IndustryTileTable *it) |
1515 static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, uint itspec_index) |
1465 { |
1516 { |
1466 const Town *t; |
1517 const IndustryTileTable *it = indspec->table[itspec_index]; |
1467 Industry *i; |
1518 bool custom_shape_check = false; |
1468 |
1519 |
1469 if (!CheckIfIndustryTilesAreFree(tile, it, type)) return NULL; |
1520 if (!CheckIfIndustryTilesAreFree(tile, it, type, &custom_shape_check)) return NULL; |
1470 if (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL; |
1521 |
1471 if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL; |
1522 if (HASBIT(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) { |
|
1523 if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index)) return NULL; |
|
1524 } else { |
|
1525 if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL; |
|
1526 } |
|
1527 |
|
1528 if (!custom_shape_check && _patches.land_generator == LG_TERRAGENESIS && _generating_world && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL; |
1472 if (!CheckIfTooCloseToIndustry(tile, type)) return NULL; |
1529 if (!CheckIfTooCloseToIndustry(tile, type)) return NULL; |
1473 |
1530 |
1474 t = CheckMultipleIndustryInTown(tile, type); |
1531 const Town *t = CheckMultipleIndustryInTown(tile, type); |
1475 if (t == NULL) return NULL; |
1532 if (t == NULL) return NULL; |
1476 |
1533 |
1477 if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL; |
1534 if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL; |
1478 if (!CheckSuitableIndustryPos(tile)) return NULL; |
1535 if (!CheckSuitableIndustryPos(tile)) return NULL; |
1479 |
1536 |
1480 i = AllocateIndustry(); |
1537 Industry *i = AllocateIndustry(); |
1481 if (i == NULL) return NULL; |
1538 if (i == NULL) return NULL; |
1482 |
1539 |
1483 if (flags & DC_EXEC) { |
1540 if (flags & DC_EXEC) { |
1484 CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type); |
1541 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type); |
1485 DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE); |
1542 DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE); |
1486 } |
1543 } |
1487 |
1544 |
1488 return i; |
1545 return i; |
1489 } |
1546 } |
1511 return CMD_ERROR; |
1568 return CMD_ERROR; |
1512 } |
1569 } |
1513 |
1570 |
1514 /* If the patch for raw-material industries is not on, you cannot build raw-material industries. |
1571 /* If the patch for raw-material industries is not on, you cannot build raw-material industries. |
1515 * Raw material industries are industries that do not accept cargo (at least for now) */ |
1572 * Raw material industries are industries that do not accept cargo (at least for now) */ |
1516 if (_patches.raw_industry_construction == 0 && indspec->IsRawIndustry()) { |
1573 if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 0 && indspec->IsRawIndustry()) { |
1517 return CMD_ERROR; |
1574 return CMD_ERROR; |
1518 } |
1575 } |
1519 |
1576 |
1520 if (_patches.raw_industry_construction == 2 && indspec->IsRawIndustry()) { |
1577 if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indspec->IsRawIndustry()) { |
1521 if (flags & DC_EXEC) { |
1578 if (flags & DC_EXEC) { |
1522 /* Prospecting has a chance to fail, however we cannot guarantee that something can |
1579 /* Prospecting has a chance to fail, however we cannot guarantee that something can |
1523 * be built on the map, so the chance gets lower when the map is fuller, but there |
1580 * be built on the map, so the chance gets lower when the map is fuller, but there |
1524 * is nothing we can really do about that. */ |
1581 * is nothing we can really do about that. */ |
1525 if (Random() <= indspec->prospecting_chance) { |
1582 if (Random() <= indspec->prospecting_chance) { |
1526 for (int i = 0; i < 5000; i++) { |
1583 for (int i = 0; i < 5000; i++) { |
1527 const IndustryTileTable *it = indspec->table[RandomRange(indspec->num_table)]; |
1584 uint tilespec_index = RandomRange(indspec->num_table); |
1528 if (CreateNewIndustryHelper(RandomTile(), p1, flags, indspec, it) != NULL) break; |
1585 const Industry *ind = CreateNewIndustryHelper(RandomTile(), p1, flags, indspec, tilespec_index); |
|
1586 if (ind != NULL) { |
|
1587 SetDParam(0, indspec->name); |
|
1588 SetDParam(1, ind->town->index); |
|
1589 AddNewsItem(indspec->new_industry_text, |
|
1590 NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0); |
|
1591 break; |
|
1592 } |
1529 } |
1593 } |
1530 } |
1594 } |
1531 } |
1595 } |
1532 } else { |
1596 } else { |
1533 num = indspec->num_table; |
1597 num = indspec->num_table; |
1536 |
1600 |
1537 do { |
1601 do { |
1538 if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE); |
1602 if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE); |
1539 } while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1)); |
1603 } while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1)); |
1540 |
1604 |
1541 if (CreateNewIndustryHelper(tile, p1, flags, indspec, it) == NULL) return CMD_ERROR; |
1605 if (CreateNewIndustryHelper(tile, p1, flags, indspec, num) == NULL) return CMD_ERROR; |
1542 } |
1606 } |
1543 |
1607 |
1544 return CommandCost(indspec->GetConstructionCost()); |
1608 return CommandCost(indspec->GetConstructionCost()); |
1545 } |
1609 } |
1546 |
1610 |
1547 |
1611 |
1548 Industry *CreateNewIndustry(TileIndex tile, IndustryType type) |
1612 Industry *CreateNewIndustry(TileIndex tile, IndustryType type) |
1549 { |
1613 { |
1550 const IndustrySpec *indspec = GetIndustrySpec(type); |
1614 const IndustrySpec *indspec = GetIndustrySpec(type); |
1551 const IndustryTileTable *it = indspec->table[RandomRange(indspec->num_table)]; |
1615 |
1552 |
1616 return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table)); |
1553 return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, it); |
|
1554 } |
1617 } |
1555 |
1618 |
1556 static const byte _numof_industry_table[5][11] = { |
1619 static const byte _numof_industry_table[5][11] = { |
1557 /* difficulty settings for number of industries */ |
1620 /* difficulty settings for number of industries */ |
1558 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //none |
1621 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //none |