|
|
/* $Id$ */
|
|
|
|
|
|
/*
|
|
|
* This file is part of OpenTTD.
|
|
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
|
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
/** @file newgrf_industries.cpp Handling of NewGRF industries. */
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
#include "debug.h"
|
|
|
#include "tile_type.h"
|
|
|
#include "strings_type.h"
|
|
|
#include "company_type.h"
|
|
|
#include "industry_map.h"
|
|
|
#include "industry.h"
|
|
|
#include "newgrf.h"
|
|
|
#include "newgrf_industries.h"
|
|
|
#include "newgrf_commons.h"
|
|
|
#include "newgrf_text.h"
|
|
|
#include "newgrf_town.h"
|
|
|
#include "window_func.h"
|
|
|
#include "town.h"
|
|
|
#include "company_base.h"
|
|
|
#include "command_func.h"
|
|
|
#include "gui.h"
|
|
|
#include "strings_func.h"
|
|
|
|
|
|
#include "table/strings.h"
|
|
|
|
|
|
static uint32 _industry_creation_random_bits;
|
|
|
|
|
|
/* Since the industry IDs defined by the GRF file don't necessarily correlate
|
|
|
* to those used by the game, the IDs used for overriding old industries must be
|
|
|
* translated when the idustry spec is set. */
|
|
|
IndustryOverrideManager _industry_mngr(NEW_INDUSTRYOFFSET, NUM_INDUSTRYTYPES, INVALID_INDUSTRYTYPE);
|
|
|
IndustryTileOverrideManager _industile_mngr(NEW_INDUSTRYTILEOFFSET, NUM_INDUSTRYTILES, INVALID_INDUSTRYTILE);
|
|
|
|
|
|
IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32 grf_id)
|
|
|
{
|
|
|
if (grf_type == IT_INVALID) return IT_INVALID;
|
|
|
if (!HasBit(grf_type, 7)) return GB(grf_type, 0, 6);
|
|
|
|
|
|
return _industry_mngr.GetID(GB(grf_type, 0, 6), grf_id);
|
|
|
}
|
|
|
|
|
|
/** Make an analysis of a tile and check for its belonging to the same
|
|
|
* industry, and/or the same grf file
|
|
|
* @param tile TileIndex of the tile to query
|
|
|
* @param i Industry to which to compare the tile to
|
|
|
* @return value encoded as per NFO specs */
|
|
|
uint32 GetIndustryIDAtOffset(TileIndex tile, const Industry *i)
|
|
|
{
|
|
|
if (!IsTileType(tile, MP_INDUSTRY) || GetIndustryIndex(tile) != i->index) {
|
|
|
/* No industry and/or the tile does not have the same industry as the one we match it with */
|
|
|
return 0xFFFF;
|
|
|
}
|
|
|
|
|
|
IndustryGfx gfx = GetCleanIndustryGfx(tile);
|
|
|
const IndustryTileSpec *indtsp = GetIndustryTileSpec(gfx);
|
|
|
const IndustrySpec *indold = GetIndustrySpec(i->type);
|
|
|
|
|
|
if (gfx < NEW_INDUSTRYOFFSET) { // Does it belongs to an old type?
|
|
|
/* It is an old tile. We have to see if it's been overriden */
|
|
@@ -197,105 +197,105 @@ uint32 IndustryGetVariable(const Resolve
|
|
|
switch (variable) {
|
|
|
case 0x40:
|
|
|
case 0x41:
|
|
|
case 0x42: { // waiting cargo, but only if those two callback flags are set
|
|
|
uint16 callback = indspec->callback_flags;
|
|
|
if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
|
|
|
if ((indspec->behaviour & INDUSTRYBEH_PROD_MULTI_HNDLING) != 0) {
|
|
|
return min(industry->incoming_cargo_waiting[variable - 0x40] / industry->prod_level, (uint16)0xFFFF);
|
|
|
} else {
|
|
|
return min(industry->incoming_cargo_waiting[variable - 0x40], (uint16)0xFFFF);
|
|
|
}
|
|
|
} else {
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Manhattan distance of closes dry/water tile */
|
|
|
case 0x43: return GetClosestWaterDistance(tile, (indspec->behaviour & INDUSTRYBEH_BUILT_ONWATER) == 0);
|
|
|
|
|
|
/* Layout number */
|
|
|
case 0x44: return industry->selected_layout;
|
|
|
|
|
|
/* Company info */
|
|
|
case 0x45: {
|
|
|
byte colours;
|
|
|
bool is_ai = false;
|
|
|
|
|
|
const Company *c = Company::GetIfValid(industry->founder);
|
|
|
if (c != NULL) {
|
|
|
const Livery *l = &c->livery[LS_DEFAULT];
|
|
|
|
|
|
is_ai = c->is_ai;
|
|
|
colours = l->colour1 + l->colour2 * 16;
|
|
|
} else {
|
|
|
colours = GB(Random(), 0, 8);
|
|
|
}
|
|
|
|
|
|
return industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24);
|
|
|
}
|
|
|
|
|
|
case 0x46: return industry->construction_date; // Date when built - long format - (in days)
|
|
|
|
|
|
/* Get industry ID at offset param */
|
|
|
case 0x60: return GetIndustryIDAtOffset(GetNearbyTile(parameter, industry->xy), industry);
|
|
|
|
|
|
/* Get random tile bits at offset param */
|
|
|
case 0x61:
|
|
|
tile = GetNearbyTile(parameter, tile);
|
|
|
return (IsTileType(tile, MP_INDUSTRY) && GetIndustryByTile(tile) == industry) ? GetIndustryRandomBits(tile) : 0;
|
|
|
return (IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile) == industry) ? GetIndustryRandomBits(tile) : 0;
|
|
|
|
|
|
/* Land info of nearby tiles */
|
|
|
case 0x62: return GetNearbyIndustryTileInformation(parameter, tile, INVALID_INDUSTRY);
|
|
|
|
|
|
/* Animation stage of nearby tiles */
|
|
|
case 0x63:
|
|
|
tile = GetNearbyTile(parameter, tile);
|
|
|
if (IsTileType(tile, MP_INDUSTRY) && GetIndustryByTile(tile) == industry) {
|
|
|
if (IsTileType(tile, MP_INDUSTRY) && Industry::GetByTile(tile) == industry) {
|
|
|
return GetIndustryAnimationState(tile);
|
|
|
}
|
|
|
return 0xFFFFFFFF;
|
|
|
|
|
|
/* Distance of nearest industry of given type */
|
|
|
case 0x64: return GetClosestIndustry(tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), industry);
|
|
|
/* Get town zone and Manhattan distance of closest town */
|
|
|
case 0x65: return GetTownRadiusGroup(industry->town, tile) << 16 | min(DistanceManhattan(tile, industry->town->xy), 0xFFFF);
|
|
|
/* Get square of Euclidian distance of closes town */
|
|
|
case 0x66: return GetTownRadiusGroup(industry->town, tile) << 16 | min(DistanceSquare(tile, industry->town->xy), 0xFFFF);
|
|
|
|
|
|
/* Count of industry, distance of closest instance
|
|
|
* 68 is the same as 67, but with a filtering on selected layout */
|
|
|
case 0x67:
|
|
|
case 0x68: return GetCountAndDistanceOfClosestInstance(parameter, variable == 0x68 ? GB(GetRegister(0x101), 0, 8) : 0, industry);
|
|
|
|
|
|
/* Get a variable from the persistent storage */
|
|
|
case 0x7C: return industry->psa.Get(parameter);
|
|
|
|
|
|
/* Industry structure access*/
|
|
|
case 0x80: return industry->xy;
|
|
|
case 0x81: return GB(industry->xy, 8, 8);
|
|
|
/* Pointer to the town the industry is associated with */
|
|
|
case 0x82: return industry->town->index;
|
|
|
case 0x83:
|
|
|
case 0x84:
|
|
|
case 0x85: DEBUG(grf, 0, "NewGRFs shouldn't be doing pointer magic"); break; // not supported
|
|
|
case 0x86: return industry->width;
|
|
|
case 0x87: return industry->height;// xy dimensions
|
|
|
|
|
|
case 0x88:
|
|
|
case 0x89: return industry->produced_cargo[variable - 0x88];
|
|
|
case 0x8A: return industry->produced_cargo_waiting[0];
|
|
|
case 0x8B: return GB(industry->produced_cargo_waiting[0], 8, 8);
|
|
|
case 0x8C: return industry->produced_cargo_waiting[1];
|
|
|
case 0x8D: return GB(industry->produced_cargo_waiting[1], 8, 8);
|
|
|
case 0x8E:
|
|
|
case 0x8F: return industry->production_rate[variable - 0x8E];
|
|
|
case 0x90:
|
|
|
case 0x91:
|
|
|
case 0x92: return industry->accepts_cargo[variable - 0x90];
|
|
|
case 0x93: return industry->prod_level;
|
|
|
/* amount of cargo produced so far THIS month. */
|
|
|
case 0x94: return industry->this_month_production[0];
|
|
|
case 0x95: return GB(industry->this_month_production[0], 8, 8);
|
|
|
case 0x96: return industry->this_month_production[1];
|
|
|
case 0x97: return GB(industry->this_month_production[1], 8, 8);
|
|
|
/* amount of cargo transported so far THIS month. */
|