73 { |
74 { |
74 assert(type < INVALID_INDUSTRYTYPE); |
75 assert(type < INVALID_INDUSTRYTYPE); |
75 _industry_specs[type].appear_creation[_opt.landscape] = 0; |
76 _industry_specs[type].appear_creation[_opt.landscape] = 0; |
76 } |
77 } |
77 |
78 |
78 /** |
79 DEFINE_OLD_POOL_GENERIC(Industry, Industry) |
79 * Called if a new block is added to the industry-pool |
|
80 */ |
|
81 static void IndustryPoolNewBlock(uint start_item) |
|
82 { |
|
83 Industry *i; |
|
84 |
|
85 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
|
86 * TODO - This is just a temporary stage, this will be removed. */ |
|
87 for (i = GetIndustry(start_item); i != NULL; i = (i->index + 1U < GetIndustryPoolSize()) ? GetIndustry(i->index + 1U) : NULL) i->index = start_item++; |
|
88 } |
|
89 |
|
90 DEFINE_OLD_POOL(Industry, Industry, IndustryPoolNewBlock, NULL) |
|
91 |
80 |
92 /** |
81 /** |
93 * Retrieve the type for this industry. Although it is accessed by a tile, |
82 * Retrieve the type for this industry. Although it is accessed by a tile, |
94 * it will return the general type of industry, and not the sprite index |
83 * it will return the general type of industry, and not the sprite index |
95 * as would do GetIndustryGfx. |
84 * as would do GetIndustryGfx. |
122 /** |
111 /** |
123 * Accessor for array _industry_tile_specs. |
112 * Accessor for array _industry_tile_specs. |
124 * This will ensure at once : proper access and |
113 * This will ensure at once : proper access and |
125 * not allowing modifications of it. |
114 * not allowing modifications of it. |
126 * @param gfx of industrytile (which is the index in _industry_tile_specs) |
115 * @param gfx of industrytile (which is the index in _industry_tile_specs) |
|
116 * @param full_check (default to true) verify if an override is available. |
|
117 * If so, use it instead of the gfx provided. |
127 * @pre gfx < INVALID_INDUSTRYTILE |
118 * @pre gfx < INVALID_INDUSTRYTILE |
128 * @return a pointer to the corresponding industrytile spec |
119 * @return a pointer to the corresponding industrytile spec |
129 **/ |
120 **/ |
130 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx) |
121 const IndustryTileSpec *GetIndustryTileSpec(IndustryGfx gfx, bool full_check) |
131 { |
122 { |
132 assert(gfx < INVALID_INDUSTRYTILE); |
123 assert(gfx < INVALID_INDUSTRYTILE); |
133 return &_industry_tile_specs[gfx]; |
124 const IndustryTileSpec *its = &_industry_tile_specs[gfx]; |
134 } |
125 if (full_check && its->grf_prop.override != INVALID_INDUSTRYTILE) { |
135 |
126 its = &_industry_tile_specs[its->grf_prop.override]; |
136 void DestroyIndustry(Industry *i) |
127 } |
137 { |
128 return its; |
138 BEGIN_TILE_LOOP(tile_cur, i->width, i->height, i->xy); |
129 } |
|
130 |
|
131 Industry::~Industry() |
|
132 { |
|
133 /* Industry can also be destroyed when not fully initialized. |
|
134 * This means that we do not have to clear tiles either. */ |
|
135 if (this->width == 0) { |
|
136 this->xy = 0; |
|
137 return; |
|
138 } |
|
139 |
|
140 BEGIN_TILE_LOOP(tile_cur, this->width, this->height, this->xy); |
139 if (IsTileType(tile_cur, MP_INDUSTRY)) { |
141 if (IsTileType(tile_cur, MP_INDUSTRY)) { |
140 if (GetIndustryIndex(tile_cur) == i->index) { |
142 if (GetIndustryIndex(tile_cur) == this->index) { |
141 DoClearSquare(tile_cur); |
143 DoClearSquare(tile_cur); |
142 } |
144 } |
143 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) { |
145 } else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) { |
144 DeleteOilRig(tile_cur); |
146 DeleteOilRig(tile_cur); |
145 } |
147 } |
146 END_TILE_LOOP(tile_cur, i->width, i->height, i->xy); |
148 END_TILE_LOOP(tile_cur, this->width, this->height, this->xy); |
147 |
149 |
148 if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) { |
150 if (GetIndustrySpec(this->type)->behaviour & INDUSTRYBEH_PLANT_FIELDS) { |
149 /* Remove the farmland and convert it to regular tiles over time. */ |
151 /* Remove the farmland and convert it to regular tiles over time. */ |
150 BEGIN_TILE_LOOP(tile_cur, 42, 42, i->xy - TileDiffXY(21, 21)) { |
152 BEGIN_TILE_LOOP(tile_cur, 42, 42, this->xy - TileDiffXY(21, 21)) { |
151 tile_cur = TILE_MASK(tile_cur); |
153 tile_cur = TILE_MASK(tile_cur); |
152 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) && |
154 if (IsTileType(tile_cur, MP_CLEAR) && IsClearGround(tile_cur, CLEAR_FIELDS) && |
153 GetIndustryIndexOfField(tile_cur) == i->index) { |
155 GetIndustryIndexOfField(tile_cur) == this->index) { |
154 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY); |
156 SetIndustryIndexOfField(tile_cur, INVALID_INDUSTRY); |
155 } |
157 } |
156 } END_TILE_LOOP(tile_cur, 42, 42, i->xy - TileDiff(21, 21)) |
158 } END_TILE_LOOP(tile_cur, 42, 42, this->xy - TileDiff(21, 21)) |
157 } |
159 } |
158 |
160 |
159 _industry_sort_dirty = true; |
161 _industry_sort_dirty = true; |
160 DecIndustryTypeCount(i->type); |
162 DecIndustryTypeCount(this->type); |
161 |
163 |
162 DeleteSubsidyWithIndustry(i->index); |
164 DeleteSubsidyWithIndustry(this->index); |
163 DeleteWindowById(WC_INDUSTRY_VIEW, i->index); |
165 DeleteWindowById(WC_INDUSTRY_VIEW, this->index); |
164 InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); |
166 InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); |
|
167 this->xy = 0; |
165 } |
168 } |
166 |
169 |
167 static void IndustryDrawSugarMine(const TileInfo *ti) |
170 static void IndustryDrawSugarMine(const TileInfo *ti) |
168 { |
171 { |
169 const DrawIndustryAnimationStruct *d; |
172 const DrawIndustryAnimationStruct *d; |
285 pal = GENERAL_SPRITE_COLOR(ind->random_color); |
287 pal = GENERAL_SPRITE_COLOR(ind->random_color); |
286 } else { |
288 } else { |
287 pal = dits->ground.pal; |
289 pal = dits->ground.pal; |
288 } |
290 } |
289 |
291 |
290 z = ti->z; |
292 /* DrawFoundation() modifes ti->z and ti->tileh */ |
291 /* Add bricks below the industry? */ |
293 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED); |
292 if (ti->tileh != SLOPE_FLAT) { |
|
293 DrawFoundation(ti, ti->tileh); |
|
294 z += TILE_HEIGHT; |
|
295 } |
|
296 |
294 |
297 DrawGroundSprite(image, pal); |
295 DrawGroundSprite(image, pal); |
298 |
296 |
299 /* Add industry on top of the ground? */ |
297 /* Add industry on top of the ground? */ |
300 image = dits->building.sprite; |
298 image = dits->building.sprite; |
301 if (image != 0) { |
299 if (image != 0) { |
302 if (HASBIT(_transparent_opt, TO_INDUSTRIES)) { |
300 AddSortableSpriteToDraw(image, |
303 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
301 (HASBIT(image, PALETTE_MODIFIER_COLOR) && dits->building.pal == PAL_NONE) ? GENERAL_SPRITE_COLOR(ind->random_color) : dits->building.pal, |
304 pal = PALETTE_TO_TRANSPARENT; |
|
305 } else if (HASBIT(image, PALETTE_MODIFIER_COLOR) && dits->building.pal == PAL_NONE) { |
|
306 pal = GENERAL_SPRITE_COLOR(ind->random_color); |
|
307 } else { |
|
308 pal = dits->building.pal; |
|
309 } |
|
310 |
|
311 AddSortableSpriteToDraw(image, pal, |
|
312 ti->x + dits->subtile_x, |
302 ti->x + dits->subtile_x, |
313 ti->y + dits->subtile_y, |
303 ti->y + dits->subtile_y, |
314 dits->width + 1, |
304 dits->width + 1, |
315 dits->height + 1, |
305 dits->height + 1, |
316 dits->dz, |
306 dits->dz, |
317 z); |
307 ti->z, |
|
308 HASBIT(_transparent_opt, TO_INDUSTRIES)); |
318 |
309 |
319 if (HASBIT(_transparent_opt, TO_INDUSTRIES)) return; |
310 if (HASBIT(_transparent_opt, TO_INDUSTRIES)) return; |
320 } |
311 } |
321 |
312 |
322 { |
313 { |
1399 _error_message = STR_INDUSTRY_TOO_CLOSE; |
1390 _error_message = STR_INDUSTRY_TOO_CLOSE; |
1400 return false; |
1391 return false; |
1401 } |
1392 } |
1402 } |
1393 } |
1403 return true; |
1394 return true; |
1404 } |
|
1405 |
|
1406 static Industry *AllocateIndustry() |
|
1407 { |
|
1408 Industry *i; |
|
1409 |
|
1410 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
|
1411 * TODO - This is just a temporary stage, this will be removed. */ |
|
1412 for (i = GetIndustry(0); i != NULL; i = (i->index + 1U < GetIndustryPoolSize()) ? GetIndustry(i->index + 1U) : NULL) { |
|
1413 IndustryID index = i->index; |
|
1414 |
|
1415 if (IsValidIndustry(i)) continue; |
|
1416 |
|
1417 memset(i, 0, sizeof(*i)); |
|
1418 i->index = index; |
|
1419 |
|
1420 return i; |
|
1421 } |
|
1422 |
|
1423 /* Check if we can add a block to the pool */ |
|
1424 return AddBlockToPool(&_Industry_pool) ? AllocateIndustry() : NULL; |
|
1425 } |
1395 } |
1426 |
1396 |
1427 static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const IndustryTileTable *it, const Town *t, Owner owner) |
1397 static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const IndustryTileTable *it, const Town *t, Owner owner) |
1428 { |
1398 { |
1429 const IndustrySpec *indspec = GetIndustrySpec(type); |
1399 const IndustrySpec *indspec = GetIndustrySpec(type); |
1534 if (t == NULL) return NULL; |
1504 if (t == NULL) return NULL; |
1535 |
1505 |
1536 if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL; |
1506 if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL; |
1537 if (!CheckSuitableIndustryPos(tile)) return NULL; |
1507 if (!CheckSuitableIndustryPos(tile)) return NULL; |
1538 |
1508 |
1539 Industry *i = AllocateIndustry(); |
1509 Industry *i = new Industry(tile); |
1540 if (i == NULL) return NULL; |
1510 if (i == NULL) return NULL; |
|
1511 AutoPtrT<Industry> i_auto_delete = i; |
1541 |
1512 |
1542 if (flags & DC_EXEC) { |
1513 if (flags & DC_EXEC) { |
1543 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type); |
1514 if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type); |
1544 DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE); |
1515 DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE); |
|
1516 i_auto_delete.Detach(); |
1545 } |
1517 } |
1546 |
1518 |
1547 return i; |
1519 return i; |
1548 } |
1520 } |
1549 |
1521 |
1616 const IndustrySpec *indspec = GetIndustrySpec(type); |
1588 const IndustrySpec *indspec = GetIndustrySpec(type); |
1617 |
1589 |
1618 return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table)); |
1590 return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table)); |
1619 } |
1591 } |
1620 |
1592 |
1621 static const byte _numof_industry_table[5][11] = { |
1593 enum { |
|
1594 NB_NUMOFINDUSTRY = 11, |
|
1595 NB_DIFFICULTY_LEVEL = 5, |
|
1596 }; |
|
1597 |
|
1598 static const byte _numof_industry_table[NB_DIFFICULTY_LEVEL][NB_NUMOFINDUSTRY] = { |
1622 /* difficulty settings for number of industries */ |
1599 /* difficulty settings for number of industries */ |
1623 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //none |
1600 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, //none |
1624 {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //very low |
1601 {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, //very low |
1625 {0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5}, //low |
1602 {0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5}, //low |
1626 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, //normal |
1603 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, //normal |
1631 * of random industries during game creation |
1608 * of random industries during game creation |
1632 * @param type IndustryType of the desired industry |
1609 * @param type IndustryType of the desired industry |
1633 * @param amount of industries that need to be built */ |
1610 * @param amount of industries that need to be built */ |
1634 static void PlaceInitialIndustry(IndustryType type, int amount) |
1611 static void PlaceInitialIndustry(IndustryType type, int amount) |
1635 { |
1612 { |
1636 int num = _numof_industry_table[_opt.diff.number_industries][amount]; |
1613 /* We need to bypass the amount given in parameter if it exceeds the maximum dimension of the |
|
1614 * _numof_industry_table. newgrf can specify a big amount */ |
|
1615 int num = (amount > NB_NUMOFINDUSTRY) ? amount : _numof_industry_table[_opt.diff.number_industries][amount]; |
1637 const IndustrySpec *ind_spc = GetIndustrySpec(type); |
1616 const IndustrySpec *ind_spc = GetIndustrySpec(type); |
1638 |
1617 |
1639 /* These are always placed next to the coastline, so we scale by the perimeter instead. */ |
1618 /* These are always placed next to the coastline, so we scale by the perimeter instead. */ |
1640 num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); |
1619 num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); |
1641 |
1620 |
1680 chance = ind_spc->appear_creation[_opt.landscape]; |
1659 chance = ind_spc->appear_creation[_opt.landscape]; |
1681 if (ind_spc->enabled && chance > 0) { |
1660 if (ind_spc->enabled && chance > 0) { |
1682 /* once the chance of appearance is determind, it have to be scaled by |
1661 /* once the chance of appearance is determind, it have to be scaled by |
1683 * the difficulty level. The "chance" in question is more an index into |
1662 * the difficulty level. The "chance" in question is more an index into |
1684 * the _numof_industry_table,in fact */ |
1663 * the _numof_industry_table,in fact */ |
1685 int num = (chance < 11) ? chance : _numof_industry_table[_opt.diff.number_industries][chance]; |
1664 int num = (chance > NB_NUMOFINDUSTRY) ? chance : _numof_industry_table[_opt.diff.number_industries][chance]; |
1686 |
1665 |
1687 /* These are always placed next to the coastline, so we scale by the perimeter instead. */ |
1666 /* These are always placed next to the coastline, so we scale by the perimeter instead. */ |
1688 num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); |
1667 num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); |
1689 i += num; |
1668 i += num; |
1690 } |
1669 } |
1692 } |
1671 } |
1693 |
1672 |
1694 SetGeneratingWorldProgress(GWP_INDUSTRY, i); |
1673 SetGeneratingWorldProgress(GWP_INDUSTRY, i); |
1695 |
1674 |
1696 if (_opt.diff.number_industries > 0) { |
1675 if (_opt.diff.number_industries > 0) { |
1697 for (it = IT_COAL_MINE; it < NUM_INDUSTRYTYPES; it++) { |
1676 for (it = 0; it < NUM_INDUSTRYTYPES; it++) { |
1698 /* Once the number of industries has been determined, let's really create them. |
1677 /* Once the number of industries has been determined, let's really create them. |
1699 * The test for chance allows us to try create industries that are available only |
1678 * The test for chance allows us to try create industries that are available only |
1700 * for this landscape. |
1679 * for this landscape. |
1701 * @todo : Do we really have to pass chance as un-scaled value, since we've already |
1680 * @todo : Do we really have to pass chance as un-scaled value, since we've already |
1702 * processed that scaling above? No, don't think so. Will find a way. */ |
1681 * processed that scaling above? No, don't think so. Will find a way. */ |
2000 AnimateTile_Industry, /* animate_tile_proc */ |
1979 AnimateTile_Industry, /* animate_tile_proc */ |
2001 TileLoop_Industry, /* tile_loop_proc */ |
1980 TileLoop_Industry, /* tile_loop_proc */ |
2002 ChangeTileOwner_Industry, /* change_tile_owner_proc */ |
1981 ChangeTileOwner_Industry, /* change_tile_owner_proc */ |
2003 GetProducedCargo_Industry, /* get_produced_cargo_proc */ |
1982 GetProducedCargo_Industry, /* get_produced_cargo_proc */ |
2004 NULL, /* vehicle_enter_tile_proc */ |
1983 NULL, /* vehicle_enter_tile_proc */ |
2005 GetSlopeTileh_Industry, /* get_slope_tileh_proc */ |
1984 GetFoundation_Industry, /* get_foundation_proc */ |
2006 }; |
1985 }; |
2007 |
1986 |
2008 static const SaveLoad _industry_desc[] = { |
1987 static const SaveLoad _industry_desc[] = { |
2009 SLE_CONDVAR(Industry, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), |
1988 SLE_CONDVAR(Industry, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), |
2010 SLE_CONDVAR(Industry, xy, SLE_UINT32, 6, SL_MAX_VERSION), |
1989 SLE_CONDVAR(Industry, xy, SLE_UINT32, 6, SL_MAX_VERSION), |