(svn r5946) -Add: merged the TGP branch to mainline. TGP adds:
- New optional landscape generator (TerraGenesis Perlin)
- Load heightmaps (either BMP or PNG)
- Progress dialog while generating worlds (no longer a 'hanging' screen)
- New dialogs for NewGame, Create Scenario and Play Heightmap
- Easier to configure your landscape
- More things to configure (tree-placer, ..)
- Speedup of world generation
- New console command 'restart': restart the map EXACTLY as it was when you
first started it (needs a game made after or with this commit)
- New console command 'getseed': get the seed of your map and share it with
others (of course only works with generated maps)
- Many new, world generation related, things
- Many internal cleanups and rewrites
Many tnx to those people who helped making this:
Belugas, DaleStan, glx, KUDr, RichK67, Rubidium, and TrueLight (alfabetic)
Many tnx to those who helped testing:
Arnau, Bjarni, and tokai (alfabetic)
And to all other people who helped testing and sending comments / bugs
Stats: 673 lines changed, 3534 new lines, 79 new strings
This commit is contained in:
236
industry_cmd.c
236
industry_cmd.c
@@ -22,6 +22,7 @@
|
||||
#include "variables.h"
|
||||
#include "table/industry_land.h"
|
||||
#include "table/build_industry.h"
|
||||
#include "genworld.h"
|
||||
#include "date.h"
|
||||
|
||||
enum {
|
||||
@@ -1026,7 +1027,7 @@ static bool CheckNewIndustry_Forest(TileIndex tile)
|
||||
static bool CheckNewIndustry_OilRefinery(TileIndex tile)
|
||||
{
|
||||
if (_game_mode == GM_EDITOR) return true;
|
||||
if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < 16) return true;
|
||||
if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true;
|
||||
|
||||
_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
|
||||
return false;
|
||||
@@ -1038,7 +1039,7 @@ static bool CheckNewIndustry_OilRig(TileIndex tile)
|
||||
{
|
||||
if (_game_mode == GM_EDITOR && _ignore_restrictions) return true;
|
||||
if (TileHeight(tile) == 0 &&
|
||||
DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < 16) return true;
|
||||
DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true;
|
||||
|
||||
_error_message = STR_483B_CAN_ONLY_BE_POSITIONED;
|
||||
return false;
|
||||
@@ -1161,7 +1162,7 @@ static const byte _industry_section_bits[] = {
|
||||
16, 16, 16, 16, 16, 16, 16,
|
||||
};
|
||||
|
||||
static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type, const Town *t)
|
||||
static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type)
|
||||
{
|
||||
_error_message = STR_0239_SITE_UNSUITABLE;
|
||||
|
||||
@@ -1191,22 +1192,27 @@ static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable
|
||||
tileh = GetTileSlope(cur_tile, NULL);
|
||||
if (IsSteepSlope(tileh)) return false;
|
||||
|
||||
if (tileh != SLOPE_FLAT) {
|
||||
Slope t;
|
||||
byte bits = _industry_section_bits[it->gfx];
|
||||
if (_patches.land_generator == LG_TERRAGENESIS || !_generating_world) {
|
||||
/* It is almost impossible to have a fully flat land in TG, so what we
|
||||
* do is that we check if we can make the land flat later on. See
|
||||
* CheckIfCanLevelIndustryPlatform(). */
|
||||
if (tileh != SLOPE_FLAT) {
|
||||
Slope t;
|
||||
byte bits = _industry_section_bits[it->gfx];
|
||||
|
||||
if (bits & 0x10) return false;
|
||||
if (bits & 0x10) return false;
|
||||
|
||||
t = ComplementSlope(tileh);
|
||||
t = ComplementSlope(tileh);
|
||||
|
||||
if (bits & 1 && (t & SLOPE_NW)) return false;
|
||||
if (bits & 2 && (t & SLOPE_NE)) return false;
|
||||
if (bits & 4 && (t & SLOPE_SW)) return false;
|
||||
if (bits & 8 && (t & SLOPE_SE)) return false;
|
||||
if (bits & 1 && (t & SLOPE_NW)) return false;
|
||||
if (bits & 2 && (t & SLOPE_NE)) return false;
|
||||
if (bits & 4 && (t & SLOPE_SW)) return false;
|
||||
if (bits & 8 && (t & SLOPE_SE)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == IT_BANK_TEMP) {
|
||||
if (!IsTileType(cur_tile, MP_HOUSE) || t->population < 1200) {
|
||||
if (!IsTileType(cur_tile, MP_HOUSE)) {
|
||||
_error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS;
|
||||
return false;
|
||||
}
|
||||
@@ -1216,7 +1222,6 @@ static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable
|
||||
return false;
|
||||
}
|
||||
} else if (type == IT_TOY_SHOP) {
|
||||
if (DistanceMax(t->xy, cur_tile) > 9) return false;
|
||||
if (!IsTileType(cur_tile, MP_HOUSE)) goto do_clear;
|
||||
} else if (type == IT_WATER_TOWER) {
|
||||
if (!IsTileType(cur_tile, MP_HOUSE)) {
|
||||
@@ -1235,6 +1240,115 @@ do_clear:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t)
|
||||
{
|
||||
if (type == IT_BANK_TEMP && t->population < 1200) {
|
||||
_error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == IT_TOY_SHOP && DistanceMax(t->xy, tile) > 9) {
|
||||
_error_message = STR_0239_SITE_UNSUITABLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CheckCanTerraformSurroundingTiles(TileIndex tile, uint height, int internal)
|
||||
{
|
||||
int size_x, size_y;
|
||||
uint curh;
|
||||
|
||||
size_x = 2;
|
||||
size_y = 2;
|
||||
|
||||
/* Check if we don't leave the map */
|
||||
if (TileX(tile) == 0 || TileY(tile) == 0 || GetTileType(tile) == MP_VOID) return false;
|
||||
|
||||
tile += TileDiffXY(-1, -1);
|
||||
BEGIN_TILE_LOOP(tile_walk, size_x, size_y, tile) {
|
||||
curh = TileHeight(tile_walk);
|
||||
/* Is the tile clear? */
|
||||
if ((GetTileType(tile_walk) != MP_CLEAR) && (GetTileType(tile_walk) != MP_TREES))
|
||||
return false;
|
||||
|
||||
/* Don't allow too big of a change if this is the sub-tile check */
|
||||
if (internal != 0 && myabs(curh - height) > 1) return false;
|
||||
|
||||
/* Different height, so the surrounding tiles of this tile
|
||||
* has to be correct too (in level, or almost in level)
|
||||
* else you get a chain-reaction of terraforming. */
|
||||
if (internal == 0 && curh != height) {
|
||||
if (!CheckCanTerraformSurroundingTiles(tile_walk + TileDiffXY(-1, -1), height, internal + 1))
|
||||
return false;
|
||||
}
|
||||
} END_TILE_LOOP(tile_walk, size_x, size_y, tile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tries to flatten out the land below an industry, without
|
||||
* damaging the surroundings too much.
|
||||
*/
|
||||
static bool CheckIfCanLevelIndustryPlatform(TileIndex tile, uint32 flags, const IndustryTileTable* it, int type)
|
||||
{
|
||||
const int MKEND = -0x80; // used for last element in an IndustryTileTable (see build_industry.h)
|
||||
int max_x = 0;
|
||||
int max_y = 0;
|
||||
TileIndex cur_tile;
|
||||
uint size_x, size_y;
|
||||
uint h, curh;
|
||||
|
||||
/* Finds dimensions of largest variant of this industry */
|
||||
do {
|
||||
if (it->ti.x > max_x) max_x = it->ti.x;
|
||||
if (it->ti.y > max_y) max_y = it->ti.y;
|
||||
} while ((++it)->ti.x != MKEND);
|
||||
|
||||
/* Remember level height */
|
||||
h = TileHeight(tile);
|
||||
|
||||
/* Check that all tiles in area and surrounding are clear
|
||||
* this determines that there are no obstructing items */
|
||||
cur_tile = tile + TileDiffXY(-1, -1);
|
||||
size_x = max_x + 4;
|
||||
size_y = max_y + 4;
|
||||
|
||||
/* Check if we don't leave the map */
|
||||
if (TileX(cur_tile) == 0 || TileY(cur_tile) == 0 || GetTileType(cur_tile) == MP_VOID) return false;
|
||||
|
||||
BEGIN_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) {
|
||||
curh = TileHeight(tile_walk);
|
||||
if (curh != h) {
|
||||
/* This tile needs terraforming. Check if we can do that without
|
||||
* damaging the surroundings too much. */
|
||||
if (!CheckCanTerraformSurroundingTiles(tile_walk, h, 0)) return false;
|
||||
/* This is not 100% correct check, but the best we can do without modifying the map.
|
||||
* What is missing, is if the difference in height is more than 1.. */
|
||||
if (CmdFailed(DoCommand(tile_walk, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND))) return false;
|
||||
}
|
||||
} END_TILE_LOOP(tile_walk, size_x, size_y, cur_tile)
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Terraform the land under the industry */
|
||||
BEGIN_TILE_LOOP(tile_walk, size_x, size_y, cur_tile) {
|
||||
curh = TileHeight(tile_walk);
|
||||
while (curh != h) {
|
||||
/* We give the terraforming for free here, because we can't calculate
|
||||
* exact cost in the test-round, and as we all know, that will cause
|
||||
* a nice assert if they don't match ;) */
|
||||
DoCommand(tile_walk, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
|
||||
curh += (curh > h) ? -1 : 1;
|
||||
}
|
||||
} END_TILE_LOOP(tile_walk, size_x, size_y, cur_tile)
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool CheckIfTooCloseToIndustry(TileIndex tile, int type)
|
||||
{
|
||||
const IndustrySpec *indspec = GetIndustrySpec(type);
|
||||
@@ -1373,6 +1487,33 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const Ind
|
||||
InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
|
||||
}
|
||||
|
||||
static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, const IndustryTileTable *it)
|
||||
{
|
||||
const Town *t;
|
||||
Industry *i;
|
||||
|
||||
if (!CheckIfIndustryTilesAreFree(tile, it, type)) return NULL;
|
||||
if (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
|
||||
if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
|
||||
if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
|
||||
|
||||
t = CheckMultipleIndustryInTown(tile, type);
|
||||
if (t == NULL) return NULL;
|
||||
|
||||
if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
|
||||
if (!CheckSuitableIndustryPos(tile)) return NULL;
|
||||
|
||||
i = AllocateIndustry();
|
||||
if (i == NULL) return NULL;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type);
|
||||
DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/** Build/Fund an industry
|
||||
* @param tile tile where industry is built
|
||||
* @param p1 industry type @see build_industry.h and @see industry.h
|
||||
@@ -1380,8 +1521,6 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const Ind
|
||||
*/
|
||||
int32 CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
const Town *t;
|
||||
Industry *i;
|
||||
int num;
|
||||
const IndustryTileTable * const *itt;
|
||||
const IndustryTileTable *it;
|
||||
@@ -1389,8 +1528,6 @@ int32 CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_OTHER);
|
||||
|
||||
if (!CheckSuitableIndustryPos(tile)) return CMD_ERROR;
|
||||
|
||||
/* Check if the to-be built/founded industry is available for this climate.
|
||||
* Unfortunately we have no easy way of checking, except for looping the table */
|
||||
{
|
||||
@@ -1418,25 +1555,14 @@ int32 CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
if (!_check_new_industry_procs[indspec->check_proc](tile)) return CMD_ERROR;
|
||||
|
||||
t = CheckMultipleIndustryInTown(tile, p1);
|
||||
if (t == NULL) return CMD_ERROR;
|
||||
|
||||
num = indspec->num_table;
|
||||
itt = indspec->table;
|
||||
|
||||
do {
|
||||
if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE);
|
||||
} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1, t));
|
||||
} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1));
|
||||
|
||||
|
||||
if (!CheckIfTooCloseToIndustry(tile, p1)) return CMD_ERROR;
|
||||
|
||||
i = AllocateIndustry();
|
||||
if (i == NULL) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) DoCreateNewIndustry(i, tile, p1, it, t, OWNER_NONE);
|
||||
if (CreateNewIndustryHelper(tile, p1, flags, indspec, it) == NULL) return CMD_ERROR;
|
||||
|
||||
return (_price.build_industry >> 5) * indspec->cost_multiplier;
|
||||
}
|
||||
@@ -1444,33 +1570,10 @@ int32 CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
|
||||
Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
|
||||
{
|
||||
const Town *t;
|
||||
const IndustryTileTable *it;
|
||||
Industry *i;
|
||||
const IndustrySpec *indspec = GetIndustrySpec(type);
|
||||
const IndustryTileTable *it = indspec->table[RandomRange(indspec->num_table)];
|
||||
|
||||
const IndustrySpec *indspec;
|
||||
|
||||
if (!CheckSuitableIndustryPos(tile)) return NULL;
|
||||
|
||||
indspec = GetIndustrySpec(type);
|
||||
|
||||
if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
|
||||
|
||||
t = CheckMultipleIndustryInTown(tile, type);
|
||||
if (t == NULL) return NULL;
|
||||
|
||||
/* pick a random layout */
|
||||
it = indspec->table[RandomRange(indspec->num_table)];
|
||||
|
||||
if (!CheckIfIndustryTilesAreFree(tile, it, type, t)) return NULL;
|
||||
if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
|
||||
|
||||
i = AllocateIndustry();
|
||||
if (i == NULL) return NULL;
|
||||
|
||||
DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE);
|
||||
|
||||
return i;
|
||||
return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, it);
|
||||
}
|
||||
|
||||
static const byte _numof_industry_table[4][12] = {
|
||||
@@ -1500,6 +1603,8 @@ static void PlaceInitialIndustry(IndustryType type, int amount)
|
||||
do {
|
||||
uint i;
|
||||
|
||||
IncreaseGeneratingWorldProgress(GWP_INDUSTRY);
|
||||
|
||||
for (i = 0; i < 2000; i++) {
|
||||
if (CreateNewIndustry(RandomTile(), type) != NULL) break;
|
||||
}
|
||||
@@ -1512,6 +1617,23 @@ static void PlaceInitialIndustry(IndustryType type, int amount)
|
||||
void GenerateIndustries(void)
|
||||
{
|
||||
const byte *b;
|
||||
uint i = 0;
|
||||
|
||||
/* Find the total amount of industries */
|
||||
b = _industry_create_table[_opt.landscape];
|
||||
do {
|
||||
int num = _numof_industry_table[_opt.diff.number_industries][b[0]];
|
||||
|
||||
if (b[1] == IT_OIL_REFINERY || b[1] == IT_OIL_RIG) {
|
||||
/* These are always placed next to the coastline, so we scale by the perimeter instead. */
|
||||
num = ScaleByMapSize1D(num);
|
||||
} else {
|
||||
num = ScaleByMapSize(num);
|
||||
}
|
||||
|
||||
i += num;
|
||||
} while ( (b+=2)[0] != 0);
|
||||
SetGeneratingWorldProgress(GWP_INDUSTRY, i);
|
||||
|
||||
b = _industry_create_table[_opt.landscape];
|
||||
do {
|
||||
|
||||
Reference in New Issue
Block a user