Changeset - r6956:6398843f1341
[Not reviewed]
master
0 14 2
glx - 17 years ago 2007-06-18 23:00:55
glx@openttd.org
(svn r10211) -Feature: [NewGRF] Add support for action 0F
16 files changed with 404 insertions and 37 deletions:
0 comments (0 inline, 0 general)
projects/openttd.vcproj
Show inline comments
 
@@ -555,24 +555,27 @@
 
				RelativePath=".\..\src\newgrf_spritegroup.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_station.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_townname.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\news.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\npf.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\music\null_m.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\sound\null_s.h">
 
			</File>
 
			<File
 
@@ -1071,24 +1074,27 @@
 
			<File
 
				RelativePath=".\..\src\newgrf_spritegroup.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_station.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_townname.cpp">
 
			</File>
 
		</Filter>
 
		<Filter
 
			Name="Map Accessors"
 
			Filter="">
 
			<File
 
				RelativePath=".\..\src\bridge_map.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\bridge_map.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\clear_map.h">
projects/openttd_vs80.vcproj
Show inline comments
 
@@ -971,24 +971,28 @@
 
				RelativePath=".\..\src\newgrf_station.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_townname.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\news.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\npf.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\music\null_m.h"
 
				>
 
			</File>
 
			<File
 
@@ -1650,24 +1654,28 @@
 
			<File
 
				RelativePath=".\..\src\newgrf_station.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_townname.cpp"
 
				>
 
			</File>
 
		</Filter>
 
		<Filter
 
			Name="Map Accessors"
 
			>
 
			<File
 
				RelativePath=".\..\src\bridge_map.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\bridge_map.h"
 
				>
 
			</File>
source.list
Show inline comments
 
@@ -146,24 +146,25 @@ newgrf_canal.h
 
newgrf_cargo.h
 
newgrf_commons.h
 
newgrf_config.h
 
newgrf_engine.h
 
newgrf_house.h
 
newgrf_industries.h
 
newgrf_industrytiles.h
 
newgrf_sound.h
 
newgrf_spritegroup.h
 
newgrf_station.h
 
newgrf_text.h
 
newgrf_town.h
 
newgrf_townname.h
 
news.h
 
npf.h
 
music/null_m.h
 
sound/null_s.h
 
video/null_v.h
 
oldpool.h
 
openttd.h
 
pathfind.h
 
player.h
 
player_face.h
 
queue.h
 
rail.h
 
@@ -325,24 +326,25 @@ newgrf_canal.cpp
 
newgrf_cargo.cpp
 
newgrf_commons.cpp
 
newgrf_config.cpp
 
newgrf_engine.cpp
 
newgrf_house.cpp
 
newgrf_industries.cpp
 
newgrf_industrytiles.cpp
 
newgrf_sound.cpp
 
newgrf_spritegroup.cpp
 
newgrf_station.cpp
 
newgrf_text.cpp
 
newgrf_town.cpp
 
newgrf_townname.cpp
 

	
 
# Map Accessors
 
bridge_map.cpp
 
bridge_map.h
 
clear_map.h
 
industry_map.h
 
rail_map.h
 
road_map.cpp
 
road_map.h
 
station_map.cpp
 
station_map.h
 
town_map.h
src/network/network_gui.cpp
Show inline comments
 
@@ -1510,26 +1510,26 @@ static const char *ChatTabCompletionNext
 
		while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
 
		if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
 
	}
 

	
 
	/* Then, try townnames */
 
	/* Not that the following assumes all town indices are adjacent, ie no
 
	 * towns have been deleted. */
 
	if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
 
		const Town *t;
 

	
 
		FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
 
			/* Get the town-name via the string-system */
 
			SetDParam(0, t->townnameparts);
 
			GetString(chat_tab_temp_buffer, t->townnametype, lastof(chat_tab_temp_buffer));
 
			SetDParam(0, t->index);
 
			GetString(chat_tab_temp_buffer, STR_TOWN, lastof(chat_tab_temp_buffer));
 
			return &chat_tab_temp_buffer[0];
 
		}
 
	}
 

	
 
	return NULL;
 
}
 

	
 
/**
 
 * Find what text to complete. It scans for a space from the left and marks
 
 *  the word right from that as to complete. It also writes a \0 at the
 
 *  position of the space (if any). If nothing found, buf is returned.
 
 */
src/newgrf.cpp
Show inline comments
 
@@ -33,24 +33,25 @@
 
#include "landscape.h"
 
#include "sound.h"
 
#include "newgrf_config.h"
 
#include "newgrf_house.h"
 
#include "newgrf_sound.h"
 
#include "newgrf_spritegroup.h"
 
#include "helpers.hpp"
 
#include "table/town_land.h"
 
#include "cargotype.h"
 
#include "industry.h"
 
#include "newgrf_canal.h"
 
#include "newgrf_commons.h"
 
#include "newgrf_townname.h"
 

	
 
/* TTDPatch extended GRF format codec
 
 * (c) Petr Baudis 2004 (GPL'd)
 
 * Changes by Florian octo Forster are (c) by the OpenTTD development team.
 
 *
 
 * Contains portions of documentation by TTDPatch team.
 
 * Thanks especially to Josef Drexler for the documentation as well as a lot
 
 * of help at #tycoon. Also thanks to Michael Blunck for is GRF files which
 
 * served as subject to the initial testing of this codec. */
 

	
 

	
 
static int _skip_sprites; // XXX
 
@@ -3889,24 +3890,124 @@ static void GRFInhibit(byte *buf, int le
 
	for (uint i = 0; i < num; i++) {
 
		uint32 grfid = grf_load_dword(&buf);
 
		GRFConfig *file = GetGRFConfig(grfid);
 

	
 
		/* Unset activation flag */
 
		if (file != NULL && file != _cur_grfconfig) {
 
			grfmsg(2, "GRFInhibit: Deactivating file '%s'", file->filename);
 
			file->status = GCS_DISABLED;
 
		}
 
	}
 
}
 

	
 
/* Action 0x0F */
 
static void FeatureTownName(byte *buf, int len)
 
{
 
	/* <0F> <id> <style-name> <num-parts> <parts>
 
	 *
 
	 * B id          ID of this definition in bottom 7 bits (final definition if bit 7 set)
 
	 * V style-name  Name of the style (only for final definition)
 
	 * B num-parts   Number of parts in this definition
 
	 * V parts       The parts */
 

	
 
	if (!check_length(len, 1, "FeatureTownName: definition ID")) return;
 
	buf++; len--;
 

	
 
	uint32 grfid = _cur_grffile->grfid;
 

	
 
	GRFTownName *townname = AddGRFTownName(grfid);
 

	
 
	byte id = grf_load_byte(&buf);
 
	len--;
 
	grfmsg(6, "FeatureTownName: definition 0x%02X", id & 0x7F);
 

	
 
	if (HASBIT(id, 7)) {
 
		/* Final definition */
 
		CLRBIT(id, 7);
 
		bool new_scheme = _cur_grffile->grf_version >= 7;
 

	
 
		if (!check_length(len, 1, "FeatureTownName: lang_id")) return;
 
		byte lang = grf_load_byte(&buf);
 
		len--;
 

	
 
		byte nb_gen = townname->nb_gen;
 
		do {
 
			CLRBIT(lang, 7);
 

	
 
			if (!check_length(len, 1, "FeatureTownName: style name")) return;
 
			const char *name = grf_load_string(&buf, len);
 
			len -= strlen(name) + 1;
 
			grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, TranslateTTDPatchCodes(name));
 

	
 
			townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, name, STR_UNDEFINED);
 

	
 
			if (!check_length(len, 1, "FeatureTownName: lang_id")) return;
 
			lang = grf_load_byte(&buf);
 
			len--;
 
		} while (lang != 0);
 
		townname->id[nb_gen] = id;
 
		townname->nb_gen++;
 
	}
 

	
 
	if (!check_length(len, 1, "FeatureTownName: number of parts")) return;
 
	byte nb = grf_load_byte(&buf);
 
	len--;
 
	grfmsg(6, "FeatureTownName: %d parts", nb, nb);
 

	
 
	townname->nbparts[id] = nb;
 
	townname->partlist[id] = CallocT<NamePartList>(nb);
 

	
 
	for (int i = 0; i < nb; i++) {
 
		if (!check_length(len, 3, "FeatureTownName: parts header")) return;
 
		byte nbtext =  grf_load_byte(&buf);
 
		townname->partlist[id][i].bitstart  = grf_load_byte(&buf);
 
		townname->partlist[id][i].bitcount  = grf_load_byte(&buf);
 
		townname->partlist[id][i].maxprob   = 0;
 
		townname->partlist[id][i].partcount = nbtext;
 
		townname->partlist[id][i].parts     = CallocT<NamePart>(nbtext);
 
		len -= 3;
 
		grfmsg(6, "FeatureTownName: part %d contains %d texts and will use GB(seed, %d, %d)", i, nbtext, townname->partlist[id][i].bitstart, townname->partlist[id][i].bitcount);
 

	
 
		for (int j = 0; j < nbtext; j++) {
 
			if (!check_length(len, 2, "FeatureTownName: part")) return;
 
			byte prob = grf_load_byte(&buf);
 
			len--;
 

	
 
			if (HASBIT(prob, 7)) {
 
				byte ref_id = grf_load_byte(&buf);
 
				len--;
 

	
 
				if (townname->nbparts[ref_id] == 0) {
 
					grfmsg(0, "FeatureTownName: definition 0x%02X doesn't exist, deactivating", ref_id);
 
					DelGRFTownName(grfid);
 
					_cur_grfconfig->status = GCS_DISABLED;
 
					_skip_sprites = -1;
 
					return;
 
				}
 

	
 
				grfmsg(6, "FeatureTownName: part %d, text %d, uses intermediate definition 0x%02X (with probability %d)", i, j, ref_id, prob & 0x7F);
 
				townname->partlist[id][i].parts[j].data.id = ref_id;
 
			} else {
 
				const char *text = grf_load_string(&buf, len);
 
				len -= strlen(text) + 1;
 
				townname->partlist[id][i].parts[j].data.text = TranslateTTDPatchCodes(text);
 
				grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
 
			}
 
			townname->partlist[id][i].parts[j].prob = prob;
 
			townname->partlist[id][i].maxprob += GB(prob, 0, 7);
 
		}
 
		grfmsg(6, "FeatureTownName: part %d, total probability %d", i, townname->partlist[id][i].maxprob);
 
	}
 
}
 

	
 
/* Action 0x10 */
 
static void DefineGotoLabel(byte *buf, int len)
 
{
 
	/* <10> <label> [<comment>]
 
	 *
 
	 * B label      The label to define
 
	 * V comment    Optional comment - ignored */
 

	
 
	if (!check_length(len, 1, "DefineGotoLabel")) return;
 
	buf++; len--;
 

	
 
	GRFLabel *label = MallocT<GRFLabel>(1);
 
@@ -4232,25 +4333,25 @@ static void InitializeGRFSpecial()
 
	                   |                                        (1 << 0x0F)  // planespeed - TODO depends on patch when implemented
 
	                   |                                        (0 << 0x10)  // moreindustriesperclimate - obsolete
 
	                   |                                        (0 << 0x11)  // moretoylandfeatures
 
	                   |                                        (1 << 0x12)  // newstations
 
	                   |                                        (0 << 0x13)  // tracktypecostdiff
 
	                   |                                        (1 << 0x14)  // manualconvert
 
	                   |       ((_patches.build_on_slopes ? 1 : 0) << 0x15)  // buildoncoasts
 
	                   |                                        (1 << 0x16)  // canals
 
	                   |                                        (1 << 0x17)  // newstartyear
 
	                   |    ((_patches.freight_trains > 1 ? 1 : 0) << 0x18)  // freighttrains
 
	                   |                                        (1 << 0x19)  // newhouses
 
	                   |                                        (1 << 0x1A)  // newbridges
 
	                   |                                        (0 << 0x1B)  // newtownnames
 
	                   |                                        (1 << 0x1B)  // newtownnames
 
	                   |                                        (0 << 0x1C)  // moreanimations
 
	                   |    ((_patches.wagon_speed_limits ? 1 : 0) << 0x1D)  // wagonspeedlimits
 
	                   |                                        (1 << 0x1E)  // newshistory
 
	                   |                                        (0 << 0x1F); // custombridgeheads
 

	
 
	_ttdpatch_flags[3] =                                        (0 << 0x00)  // newcargodistribution
 
	                   |                                        (1 << 0x01)  // windowsnap
 
	                   |                                        (0 << 0x02)  // townbuildnoroad
 
	                   |                                        (0 << 0x03)  // pathbasedsignalling. To enable if ever pbs is back
 
	                   |                                        (0 << 0x04)  // aichoosechance
 
	                   |                                        (1 << 0x05)  // resolutionwidth
 
	                   |                                        (1 << 0x06)  // resolutionheight
 
@@ -4409,24 +4510,25 @@ static void ResetNewGRFErrors()
 
			c->error = NULL;
 
		}
 
	}
 
}
 

	
 
/**
 
 * Reset all NewGRF loaded data
 
 * TODO
 
 */
 
static void ResetNewGRFData()
 
{
 
	CleanUpStrings();
 
	CleanUpGRFTownNames();
 

	
 
	/* Copy/reset original engine info data */
 
	memcpy(&_engine_info, &orig_engine_info, sizeof(orig_engine_info));
 
	memcpy(&_rail_vehicle_info, &orig_rail_vehicle_info, sizeof(orig_rail_vehicle_info));
 
	memcpy(&_ship_vehicle_info, &orig_ship_vehicle_info, sizeof(orig_ship_vehicle_info));
 
	memcpy(&_aircraft_vehicle_info, &orig_aircraft_vehicle_info, sizeof(orig_aircraft_vehicle_info));
 
	memcpy(&_road_vehicle_info, &orig_road_vehicle_info, sizeof(orig_road_vehicle_info));
 

	
 
	/* Copy/reset original bridge info data
 
	 * First, free sprite table data */
 
	for (uint i = 0; i < MAX_BRIDGES; i++) {
 
		if (_bridge[i].sprite_table != NULL) {
 
@@ -4778,25 +4880,25 @@ static void DecodeSpecialSprite(uint num
 
		/* 0x03 */ { NULL,     GRFUnsafe, NULL,            NULL,           NULL,              FeatureMapSpriteGroup, },
 
		/* 0x04 */ { NULL,     NULL,      NULL,            NULL,           NULL,              FeatureNewName, },
 
		/* 0x05 */ { SkipAct5, SkipAct5,  SkipAct5,        SkipAct5,       SkipAct5,          GraphicsNew, },
 
		/* 0x06 */ { NULL,     NULL,      NULL,            CfgApply,       CfgApply,          CfgApply, },
 
		/* 0x07 */ { NULL,     NULL,      NULL,            NULL,           SkipIf,            SkipIf, },
 
		/* 0x08 */ { ScanInfo, NULL,      NULL,            GRFInfo,        GRFInfo,           GRFInfo, },
 
		/* 0x09 */ { NULL,     NULL,      NULL,            SkipIf,         SkipIf,            SkipIf, },
 
		/* 0x0A */ { SkipActA, SkipActA,  SkipActA,        SkipActA,       SkipActA,          SpriteReplace, },
 
		/* 0x0B */ { NULL,     NULL,      NULL,            GRFLoadError,   GRFLoadError,      GRFLoadError, },
 
		/* 0x0C */ { NULL,     NULL,      NULL,            GRFComment,     NULL,              GRFComment, },
 
		/* 0x0D */ { NULL,     SafeParamSet, NULL,         ParamSet,       ParamSet,          ParamSet, },
 
		/* 0x0E */ { NULL,     SafeGRFInhibit, NULL,       GRFInhibit,     GRFInhibit,        GRFInhibit, },
 
		/* 0x0F */ { NULL,     NULL,      NULL,            NULL,           NULL,              NULL, },
 
		/* 0x0F */ { NULL,     GRFUnsafe, NULL,            FeatureTownName, NULL,             NULL, },
 
		/* 0x10 */ { NULL,     NULL,      DefineGotoLabel, NULL,           NULL,              NULL, },
 
		/* 0x11 */ { NULL,     GRFUnsafe, NULL,            NULL,           NULL,              GRFSound, },
 
		/* 0x12 */ { NULL,     NULL,      NULL,            NULL,           NULL,              LoadFontGlyph, },
 
		/* 0x13 */ { NULL,     NULL,      NULL,            NULL,           NULL,              TranslateGRFStrings, },
 
	};
 

	
 
	byte* buf;
 

	
 
	if (_preload_sprite == NULL) {
 
		/* No preloaded sprite to work with; allocate and read the
 
		 * pseudo sprite content. */
 
		buf = MallocT<byte>(num);
 
@@ -4908,66 +5010,72 @@ void LoadNewGRFFile(GRFConfig *config, u
 
						FioReadByte();
 
					}
 
				}
 
			}
 
		}
 

	
 
		if (_skip_sprites > 0) _skip_sprites--;
 
	}
 
}
 

	
 
void InitDepotWindowBlockSizes();
 

	
 
extern void SortTownGeneratorNames();
 

	
 
static void AfterLoadGRFs()
 
{
 
	/* Update the bitmasks for the vehicle lists */
 
	Player *p;
 
	FOR_ALL_PLAYERS(p) {
 
		p->avail_railtypes = GetPlayerRailtypes(p->index);
 
		p->avail_roadtypes = GetPlayerRoadtypes(p->index);
 
	}
 

	
 
	/* Pre-calculate all refit masks after loading GRF files. */
 
	CalculateRefitMasks();
 

	
 
	/* Set the block size in the depot windows based on vehicle sprite sizes */
 
	InitDepotWindowBlockSizes();
 

	
 
	/* Add all new houses to the house array. */
 
	FinaliseHouseArray();
 

	
 
	/* Create dynamic list of industry legends for smallmap_gui.cpp */
 
	BuildIndustriesLegend();
 

	
 
	/* Map cargo strings. This is a separate step because cargos are
 
	 * loaded before strings... */
 
	MapNewCargoStrings();
 

	
 
	/* Update the townname generators list */
 
	SortTownGeneratorNames();
 
}
 

	
 
void LoadNewGRF(uint load_index, uint file_index)
 
{
 
	InitializeGRFSpecial();
 

	
 
	ResetNewGRFData();
 

	
 
	/* Load newgrf sprites
 
	 * in each loading stage, (try to) open each file specified in the config
 
	 * and load information from it. */
 
	for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
 
		uint slot = file_index;
 

	
 
		_cur_stage = stage;
 
		_cur_spriteid = load_index;
 
		for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 
			if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
 
			if (stage > GLS_INIT && HASBIT(c->flags, GCF_INIT_ONLY)) continue;
 

	
 
			/* @todo usererror() */
 
			if (!FioCheckFileExists(c->full_path)) error("NewGRF file is missing '%s'", c->filename);
 

	
 
			if (stage == GLS_LABELSCAN) InitNewGRFFile(c, _cur_spriteid);
 
			LoadNewGRFFile(c, slot++, stage);
 
			if (stage == GLS_RESERVE) {
 
				if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED;
 
			} else if (stage == GLS_ACTIVATION) {
 
				ClearTemporaryNewGRFData();
 
				BuildCargoTranslationMap();
 
				DEBUG(sprite, 2, "LoadNewGRF: Currently %i sprites are loaded", _cur_spriteid);
src/newgrf_config.cpp
Show inline comments
 
@@ -115,43 +115,46 @@ void ClearGRFConfigList(GRFConfig **conf
 
	GRFConfig *c, *next;
 
	for (c = *config; c != NULL; c = next) {
 
		next = c->next;
 
		ClearGRFConfig(&c);
 
	}
 
	*config = NULL;
 
}
 

	
 

	
 
/** Copy a GRF Config list
 
 * @param dst pointer to destination list
 
 * @param src pointer to source list values
 
 * @param init_only the copied GRF will be processed up to GLS_INIT
 
 * @return pointer to the last value added to the destination list */
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src)
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only)
 
{
 
	/* Clear destination as it will be overwritten */
 
	ClearGRFConfigList(dst);
 
	for (; src != NULL; src = src->next) {
 
		GRFConfig *c = CallocT<GRFConfig>(1);
 
		*c = *src;
 
		if (src->filename  != NULL) c->filename  = strdup(src->filename);
 
		if (src->full_path != NULL) c->full_path = strdup(src->full_path);
 
		if (src->name      != NULL) c->name      = strdup(src->name);
 
		if (src->info      != NULL) c->info      = strdup(src->info);
 
		if (src->error     != NULL) {
 
			c->error = CallocT<GRFError>(1);
 
			memcpy(c->error, src->error, sizeof(GRFError));
 
			if (src->error->data != NULL) c->error->data = strdup(src->error->data);
 
			if (src->error->custom_message != NULL) c->error->custom_message = strdup(src->error->custom_message);
 
		}
 

	
 
		if (init_only) SETBIT(c->flags, GCF_INIT_ONLY);
 

	
 
		*dst = c;
 
		dst = &c->next;
 
	}
 

	
 
	return dst;
 
}
 

	
 
/**
 
 * Removes duplicates from lists of GRFConfigs. These duplicates
 
 * are introduced when the _grfconfig_static GRFs are appended
 
 * to the _grfconfig on a newgame or savegame. As the parameters
 
 * of the static GRFs could be different that the parameters of
 
@@ -181,52 +184,45 @@ static void RemoveDuplicatesFromGRFConfi
 
	RemoveDuplicatesFromGRFConfigList(list->next);
 
}
 

	
 
/**
 
 * Appends the static GRFs to a list of GRFs
 
 * @param dst the head of the list to add to
 
 */
 
void AppendStaticGRFConfigs(GRFConfig **dst)
 
{
 
	GRFConfig **tail = dst;
 
	while (*tail != NULL) tail = &(*tail)->next;
 

	
 
	CopyGRFConfigList(tail, _grfconfig_static);
 
	CopyGRFConfigList(tail, _grfconfig_static, false);
 
	RemoveDuplicatesFromGRFConfigList(*dst);
 
}
 

	
 
/** Appends an element to a list of GRFs
 
 * @param dst the head of the list to add to
 
 * @param el the new tail to be */
 
void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el)
 
{
 
	GRFConfig **tail = dst;
 
	while (*tail != NULL) tail = &(*tail)->next;
 
	*tail = el;
 

	
 
	RemoveDuplicatesFromGRFConfigList(*dst);
 
}
 

	
 

	
 
/* Reset the current GRF Config to either blank or newgame settings */
 
void ResetGRFConfig(bool defaults)
 
{
 
	GRFConfig **c = &_grfconfig;
 

	
 
	if (defaults) {
 
		c = CopyGRFConfigList(c, _grfconfig_newgame);
 
	} else {
 
		ClearGRFConfigList(c);
 
	}
 

	
 
	CopyGRFConfigList(&_grfconfig, _grfconfig_newgame, !defaults);
 
	AppendStaticGRFConfigs(&_grfconfig);
 
}
 

	
 

	
 
/** Check if all GRFs in the GRF config from a savegame can be loaded.
 
 * @return will return any of the following 3 values:<br>
 
 * <ul>
 
 * <li> GLC_ALL_GOOD: No problems occured, all GRF files were found and loaded
 
 * <li> GLC_COMPATIBLE: For one or more GRF's no exact match was found, but a
 
 *     compatible GRF with the same grfid was found and used instead
 
 * <li> GLC_NOT_FOUND: For one or more GRF's no match was found at all
 
 * </ul> */
src/newgrf_config.h
Show inline comments
 
@@ -5,24 +5,25 @@
 
#ifndef NEWGRF_CONFIG_H
 
#define NEWGRF_CONFIG_H
 

	
 
#include "openttd.h"
 

	
 
/* GRF config bit flags */
 
enum GCF_Flags {
 
	GCF_SYSTEM,    ///< GRF file is an openttd-internal system grf
 
	GCF_UNSAFE,    ///< GRF file is unsafe for static usage
 
	GCF_STATIC,    ///< GRF file is used statically (can be used in any MP game)
 
	GCF_COMPATIBLE,///< GRF file does not exactly match the requested GRF (different MD5SUM), but grfid matches)
 
	GCF_COPY,      ///< The data is copied from a grf in _all_grfs
 
	GCF_INIT_ONLY, ///< GRF file is processed up to GLS_INIT
 
};
 

	
 
enum GRFStatus {
 
	GCS_UNKNOWN,      ///< The status of this grf file is unknown
 
	GCS_DISABLED,     ///< GRF file is disabled
 
	GCS_NOT_FOUND,    ///< GRF file was not found in the local cache
 
	GCS_INITIALISED,  ///< GRF file has been initialised
 
	GCS_ACTIVATED     ///< GRF file has been activated
 
};
 

	
 
enum GRFListCompatibility{
 
	GLC_ALL_GOOD,
 
@@ -65,25 +66,25 @@ extern GRFConfig *_all_grfs;
 
/* First item in list of current GRF set up */
 
extern GRFConfig *_grfconfig;
 

	
 
/* First item in list of default GRF set up */
 
extern GRFConfig *_grfconfig_newgame;
 

	
 
/* First item in list of static GRF set up */
 
extern GRFConfig *_grfconfig_static;
 

	
 
void ScanNewGRFFiles();
 
const GRFConfig *FindGRFConfig(uint32 grfid, const uint8 *md5sum = NULL);
 
GRFConfig *GetGRFConfig(uint32 grfid);
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src);
 
GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src, bool init_only);
 
void AppendStaticGRFConfigs(GRFConfig **dst);
 
void AppendToGRFConfigList(GRFConfig **dst, GRFConfig *el);
 
void ClearGRFConfig(GRFConfig **config);
 
void ClearGRFConfigList(GRFConfig **config);
 
void ResetGRFConfig(bool defaults);
 
GRFListCompatibility IsGoodGRFConfigList();
 
bool FillGRFDetails(GRFConfig *config, bool is_static);
 
char *GRFBuildParamList(char *dst, const GRFConfig *c, const char *last);
 

	
 
/* In newgrf_gui.cpp */
 
void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config);
 

	
src/newgrf_gui.cpp
Show inline comments
 
@@ -298,30 +298,30 @@ static void SetupNewGRFWindow(Window *w)
 

	
 
/** Callback function for the newgrf 'apply changes' confirmation window
 
 * @param w Window which is calling this callback
 
 * @param confirmed boolean value, true when yes was clicked, false otherwise
 
 */
 
static void NewGRFConfirmationCallback(Window *w, bool confirmed)
 
{
 
	if (confirmed) {
 
		newgrf_d *nd = &WP(w, newgrf_d);
 
		GRFConfig *c;
 
		int i = 0;
 

	
 
		CopyGRFConfigList(nd->orig_list, *nd->list);
 
		CopyGRFConfigList(nd->orig_list, *nd->list, false);
 
		ReloadNewGRFData();
 

	
 
		/* Show new, updated list */
 
		for (c = *nd->list; c != NULL && c != nd->sel; c = c->next, i++);
 
		CopyGRFConfigList(nd->list, *nd->orig_list);
 
		CopyGRFConfigList(nd->list, *nd->orig_list, false);
 
		for (c = *nd->list; c != NULL && i > 0; c = c->next, i--);
 
		nd->sel = c;
 

	
 
		SetWindowDirty(w);
 
	}
 
}
 

	
 

	
 
static void NewGRFWndProc(Window *w, WindowEvent *e)
 
{
 
	switch (e->event) {
 
		case WE_PAINT: {
 
@@ -460,25 +460,27 @@ static void NewGRFWndProc(Window *w, Win
 
					break;
 
				}
 

	
 
				case SNGRFS_APPLY_CHANGES: // Apply changes made to GRF list
 
					if (WP(w, newgrf_d).execute) {
 
						ShowQuery(
 
							STR_POPUP_CAUTION_CAPTION,
 
							STR_NEWGRF_CONFIRMATION_TEXT,
 
							w,
 
							NewGRFConfirmationCallback
 
						);
 
					} else {
 
						CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list);
 
						CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list, true);
 
						ResetGRFConfig(false);
 
						ReloadNewGRFData();
 
					}
 
					break;
 

	
 
				case SNGRFS_SET_PARAMETERS: { // Edit parameters
 
					char buff[512];
 
					if (WP(w, newgrf_d).sel == NULL) break;
 

	
 
					GRFBuildParamList(buff, WP(w, newgrf_d).sel, lastof(buff));
 
					ShowQueryString(BindCString(buff), STR_NEWGRF_PARAMETER_QUERY, 63, 250, w, CS_ALPHANUMERAL);
 
					break;
 
				}
 
			}
 
@@ -489,25 +491,27 @@ static void NewGRFWndProc(Window *w, Win
 
				/* Parse our new "int list" */
 
				GRFConfig *c = WP(w, newgrf_d).sel;
 
				c->num_params = parse_intlist(e->we.edittext.str, (int*)c->param, lengthof(c->param));
 

	
 
				/* parse_intlist returns -1 on error */
 
				if (c->num_params == (byte)-1) c->num_params = 0;
 
			}
 
			SetWindowDirty(w);
 
			break;
 

	
 
		case WE_DESTROY:
 
			if (!WP(w, newgrf_d).execute) {
 
				CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list);
 
				CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list, true);
 
				ResetGRFConfig(false);
 
				ReloadNewGRFData();
 
			}
 
			/* Remove the temporary copy of grf-list used in window */
 
			ClearGRFConfigList(WP(w, newgrf_d).list);
 
			break;
 

	
 
		case WE_RESIZE:
 
			w->vscroll.cap += e->we.sizing.diff.y / 14;
 
			w->widget[SNGRFS_FILE_LIST].data = (w->vscroll.cap << 8) + 1;
 
			break;
 
	}
 
}
 

	
 
@@ -556,24 +560,24 @@ static const WindowDesc _newgrf_desc = {
 
 *        changes immediately or only update the list
 
 * @param config pointer to a linked-list of grfconfig's that will be shown */
 
void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config)
 
{
 
	static GRFConfig *local = NULL;
 
	Window *w;
 

	
 
	DeleteWindowByClass(WC_GAME_OPTIONS);
 
	w = AllocateWindowDesc(&_newgrf_desc);
 
	if (w == NULL) return;
 

	
 
	w->resize.step_height = 14;
 
	CopyGRFConfigList(&local, *config);
 
	CopyGRFConfigList(&local, *config, false);
 

	
 
	/* Clear selections */
 
	WP(w, newgrf_d).sel         = NULL;
 
	WP(w, newgrf_d).list        = &local;
 
	WP(w, newgrf_d).orig_list   = config;
 
	WP(w, newgrf_d).editable    = editable;
 
	WP(w, newgrf_d).execute     = exec_changes;
 
	WP(w, newgrf_d).show_params = show_params;
 

	
 
	SetupNewGRFWindow(w);
 
}
src/newgrf_townname.cpp
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
/** @file newgrf_townname.cpp
 
 * Implementation of  Action 0F "universal holder" structure and functions.
 
 * This file implements a linked-lists of townname generators,
 
 * holding everything that the newgrf action 0F will send over to OpenTTD.
 
 */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "table/strings.h"
 
#include "newgrf_townname.h"
 
#include "string.h"
 

	
 
static GRFTownName *_grf_townnames = NULL;
 

	
 
GRFTownName *GetGRFTownName(uint32 grfid)
 
{
 
	GRFTownName *t = _grf_townnames;
 
	for (; t != NULL; t = t->next) {
 
		if (t->grfid == grfid) return t;
 
	}
 
	return NULL;
 
}
 

	
 
GRFTownName *AddGRFTownName(uint32 grfid)
 
{
 
	GRFTownName *t = GetGRFTownName(grfid);
 
	if (t == NULL) {
 
		t = CallocT<GRFTownName>(1);
 
		t->grfid = grfid;
 
		t->next = _grf_townnames;
 
		_grf_townnames = t;
 
	}
 
	return t;
 
}
 

	
 
void DelGRFTownName(uint32 grfid)
 
{
 
	GRFTownName *t = _grf_townnames;
 
	GRFTownName *p = NULL;
 
	for (;t != NULL; p = t, t = t->next) if (t->grfid == grfid) break;
 
	if (t != NULL) {
 
		for (int i = 0; i < 128; i++) {
 
			for (int j = 0; j < t->nbparts[i]; j++) {
 
				for (int k = 0; k < t->partlist[i][j].partcount; k++) {
 
					if (!HASBIT(t->partlist[i][j].parts[k].prob, 7)) free(t->partlist[i][j].parts[k].data.text);
 
				}
 
				free(t->partlist[i][j].parts);
 
			}
 
			free(t->partlist[i]);
 
		}
 
		if (p != NULL) {
 
			p->next = t->next;
 
		} else {
 
			_grf_townnames = t->next;
 
		}
 
		free(t);
 
	}
 
}
 

	
 
static char *RandomPart(char *buf, GRFTownName *t, uint32 seed, byte id, const char *last)
 
{
 
	assert(t != NULL);
 
	for (int i = 0; i < t->nbparts[id]; i++) {
 
		byte count = t->partlist[id][i].bitcount;
 
		uint16 maxprob = t->partlist[id][i].maxprob;
 
		uint32 r = (GB(seed, t->partlist[id][i].bitstart, count) * maxprob) >> count;
 
		for (int j = 0; j < t->partlist[id][i].partcount; j++) {
 
			byte prob = t->partlist[id][i].parts[j].prob;
 
			maxprob -= GB(prob, 0, 7);
 
			if (maxprob > r) continue;
 
			if (HASBIT(prob, 7)) {
 
				buf = RandomPart(buf, t, seed, t->partlist[id][i].parts[j].data.id, last);
 
			} else {
 
				buf = strecat(buf, t->partlist[id][i].parts[j].data.text, last);
 
			}
 
			break;
 
		}
 
	}
 
	return buf;
 
}
 

	
 
char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last)
 
{
 
	strecpy(buf, "", last);
 
	for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) {
 
		if (t->grfid == grfid) {
 
			assert(gen < t->nb_gen);
 
			buf = RandomPart(buf, t, seed, t->id[gen], last);
 
			break;
 
		}
 
	}
 
	return buf;
 
}
 

	
 
StringID *GetGRFTownNameList()
 
{
 
	int nb_names = 0, n = 0;
 
	for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) nb_names += t->nb_gen;
 
	StringID *list = MallocT<StringID>(nb_names + 1);
 
	for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) {
 
		for (int j = 0; j < t->nb_gen; j++) list[n++] = t->name[j];
 
	}
 
	list[n] = INVALID_STRING_ID;
 
	return list;
 
}
 

	
 
void CleanUpGRFTownNames()
 
{
 
	while (_grf_townnames != NULL) DelGRFTownName(_grf_townnames->grfid);
 
}
 

	
 
uint32 GetGRFTownNameId(int gen)
 
{
 
	for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) {
 
		if (gen < t->nb_gen) return t->grfid;
 
		gen -= t->nb_gen;
 
	}
 
	/* Fallback to no NewGRF */
 
	return 0;
 
}
 

	
 
uint16 GetGRFTownNameType(int gen)
 
{
 
	for (GRFTownName *t = _grf_townnames; t != NULL; t = t->next) {
 
		if (gen < t->nb_gen) return gen;
 
		gen -= t->nb_gen;
 
	}
 
	/* Fallback to english original */
 
	return SPECSTR_TOWNNAME_ENGLISH;
 
}
src/newgrf_townname.h
Show inline comments
 
new file 100644
 
/* $Id$ */
 
#ifndef NEWGRF_TOWNNAME_H
 
#define NEWGRF_TOWNNAME_H
 

	
 
/** @file newgrf_townname.h
 
 * Header of Action 0F "universal holder" structure and functions
 
 */
 

	
 
struct NamePart {
 
	byte prob;     ///< The relative probablity of the following name to appear in the bottom 7 bits.
 
	union {
 
		char *text;    ///< If probability bit 7 is clear
 
		byte id;       ///< If probability bit 7 is set
 
	} data;
 
};
 

	
 
struct NamePartList {
 
	byte partcount;
 
	byte bitstart;
 
	byte bitcount;
 
	uint16 maxprob;
 
	NamePart *parts;
 
};
 

	
 
struct GRFTownName {
 
	uint32 grfid;
 
	byte nb_gen;
 
	byte id[128];
 
	StringID name[128];
 
	byte nbparts[128];
 
	NamePartList *partlist[128];
 
	GRFTownName *next;
 
};
 

	
 
GRFTownName *AddGRFTownName(uint32 grfid);
 
GRFTownName *GetGRFTownName(uint32 grfid);
 
void DelGRFTownName(uint32 grfid);
 
void CleanUpGRFTownNames();
 
StringID *GetGRFTownNameList();
 
char *GRFTownNameGenerate(char *buf, uint32 grfid, uint16 gen, uint32 seed, const char *last);
 
uint32 GetGRFTownNameId(int gen);
 
uint16 GetGRFTownNameType(int gen);
 

	
 
#endif /* NEWGRF_TOWNNAME_H */
src/saveload.cpp
Show inline comments
 
@@ -20,25 +20,25 @@
 
#include "hal.h"
 
#include "vehicle.h"
 
#include "station.h"
 
#include "thread.h"
 
#include "town.h"
 
#include "player.h"
 
#include "saveload.h"
 
#include "network/network.h"
 
#include "variables.h"
 
#include <setjmp.h>
 
#include <list>
 

	
 
extern const uint16 SAVEGAME_VERSION = 65;
 
extern const uint16 SAVEGAME_VERSION = 66;
 
uint16 _sl_version;       ///< the major savegame version identifier
 
byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 

	
 
typedef void WriterProc(uint len);
 
typedef uint ReaderProc();
 

	
 
/** The saveload struct, containing reader-writer functions, bufffer, version, etc. */
 
static struct {
 
	bool save;                           ///< are we doing a save or a load atm. True when saving
 
	byte need_length;                    ///< ???
 
	byte block_mode;                     ///< ???
 
	bool error;                          ///< did an error occur or not
src/settings.cpp
Show inline comments
 
@@ -1297,25 +1297,26 @@ static const SettingDesc _gameopt_settin
 
	/* In version 4 a new difficulty setting has been added to the difficulty settings,
 
	 * town attitude towards demolishing. Needs special handling because some dimwit thought
 
	 * it funny to have the GameDifficulty struct be an array while it is a struct of
 
	 * same-sized members
 
	 * XXX - To save file-space and since values are never bigger than about 10? only
 
	 * save the first 16 bits in the savegame. Question is why the values are still int32
 
	 * and why not byte for example? */
 
	SDT_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, (SLE_FILE_I16 | SLE_VAR_I32), 0, 0, GameOptions, diff, 17, 0, 0, 0, 0, NULL, STR_NULL, NULL, NULL, 0, 3),
 
	SDT_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, (SLE_FILE_I16 | SLE_VAR_I32), 0, 0, GameOptions, diff, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, NULL, 4, SL_MAX_VERSION),
 
	    SDT_VAR(GameOptions, diff_level, SLE_UINT8, 0, 0, 0, 0,  3, 0, STR_NULL, NULL),
 
	  SDT_OMANY(GameOptions, currency,  SLE_UINT8, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL),
 
	  SDT_OMANY(GameOptions, units,     SLE_UINT8, N, 0, 1,     2, "imperial|metric|si", STR_NULL, NULL, NULL),
 
	  SDT_OMANY(GameOptions, town_name, SLE_UINT8, 0, 0, 0,    20, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
 
	/* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */
 
	  SDT_OMANY(GameOptions, town_name, SLE_UINT8, 0, 0, 0,   255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
 
	  SDT_OMANY(GameOptions, landscape, SLE_UINT8, 0, 0, 0,     3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
 
	    SDT_VAR(GameOptions, snow_line, SLE_UINT8, 0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
 
	SDT_CONDOMANY(GameOptions,autosave, SLE_UINT8, 0, 22,             N, 0, 0, 0, "", STR_NULL, NULL, NULL),
 
	SDT_CONDOMANY(GameOptions,autosave, SLE_UINT8,23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL, NULL),
 
	  SDT_OMANY(GameOptions, road_side, SLE_UINT8, 0, 0, 1,   1, "left|right", STR_NULL, NULL, NULL),
 
	    SDT_END()
 
};
 

	
 
/* Some patches do not need to be synchronised when playing in multiplayer.
 
 * These include for example the GUI settings and will not be saved with the
 
 * savegame.
 
 * It is also a bit tricky since you would think that service_interval
src/settings_gui.cpp
Show inline comments
 
@@ -15,24 +15,25 @@
 
#include "gfx.h"
 
#include "command.h"
 
#include "engine.h"
 
#include "screenshot.h"
 
#include "newgrf.h"
 
#include "network/network.h"
 
#include "town.h"
 
#include "variables.h"
 
#include "settings.h"
 
#include "vehicle.h"
 
#include "date.h"
 
#include "helpers.hpp"
 
#include "newgrf_townname.h"
 

	
 
static uint32 _difficulty_click_a;
 
static uint32 _difficulty_click_b;
 
static byte _difficulty_timeout;
 

	
 
static const StringID _units_dropdown[] = {
 
	STR_UNITS_IMPERIAL,
 
	STR_UNITS_METRIC,
 
	STR_UNITS_SI,
 
	INVALID_STRING_ID
 
};
 

	
 
@@ -57,37 +58,62 @@ static const StringID _designnames_dropd
 
	INVALID_STRING_ID
 
};
 

	
 
static StringID *BuildDynamicDropdown(StringID base, int num)
 
{
 
	static StringID buf[32 + 1];
 
	StringID *p = buf;
 
	while (--num>=0) *p++ = base++;
 
	*p = INVALID_STRING_ID;
 
	return buf;
 
}
 

	
 
static StringID _town_names[SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 2] = {STR_NULL};
 
int _nb_orig_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1;
 
static StringID *_town_names = NULL;
 
static StringID *_grf_names = NULL;
 
static int _nb_grf_names = 0;
 

	
 
void SortTownGeneratorNames()
 
{
 
	int nb_town_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1;
 
	/* Init the strings */
 
	if (_town_names[0] == STR_NULL) {
 
		for (int i = 0; i < nb_town_names; i++) _town_names[i] = STR_TOWNNAME_ORIGINAL_ENGLISH + i;
 
		_town_names[nb_town_names] = INVALID_STRING_ID;
 
	int n = 0;
 

	
 
	/* Get Newgrf generators' names */
 
	free(_grf_names);
 
	_grf_names = GetGRFTownNameList();
 
	_nb_grf_names = 0;
 
	for (StringID *s = _grf_names; *s != INVALID_STRING_ID; s++) _nb_grf_names++;
 

	
 
	/* Prepare the list */
 
	free(_town_names);
 
	_town_names = MallocT<StringID>(_nb_orig_names + _nb_grf_names + 1);
 

	
 
	/* Put the original strings */
 
	for (int i = 0; i < _nb_orig_names; i++) _town_names[n++] = STR_TOWNNAME_ORIGINAL_ENGLISH + i;
 

	
 
	/* Put the grf strings */
 
	for (int i = 0; i < _nb_grf_names; i++) _town_names[n++] = _grf_names[i];
 

	
 
	/* Put the terminator */
 
	_town_names[n] = INVALID_STRING_ID;
 

	
 
	/* Sort the strings */
 
	qsort(&_town_names[0], _nb_orig_names + _nb_grf_names, sizeof(StringID), &StringIDSorter);
 
	}
 

	
 
	/* Sort the strings */
 
	qsort(&_town_names[0], nb_town_names, sizeof(StringID), &StringIDSorter);
 
static inline StringID TownName(int town_name)
 
{
 
	if (town_name < _nb_orig_names) return STR_TOWNNAME_ORIGINAL_ENGLISH + town_name;
 
	town_name -= _nb_orig_names;
 
	if (town_name < _nb_grf_names) return _grf_names[town_name];
 
	return STR_UNDEFINED;
 
}
 

	
 
static int GetCurRes()
 
{
 
	int i;
 

	
 
	for (i = 0; i != _num_resolutions; i++) {
 
		if (_resolutions[i][0] == _screen.width &&
 
				_resolutions[i][1] == _screen.height) {
 
			break;
 
		}
 
	}
 
@@ -111,25 +137,25 @@ static void GameOptionsWndProc(Window *w
 
{
 
	switch (e->event) {
 
	case WE_PAINT: {
 
		int i;
 
		StringID str = STR_02BE_DEFAULT;
 

	
 
		SetWindowWidgetDisabledState(w, 21, !(_vehicle_design_names & 1));
 
		if (!IsWindowWidgetDisabled(w, 21)) str = STR_02BF_CUSTOM;
 
		SetDParam(0, str);
 
		SetDParam(1, _currency_specs[_opt_ptr->currency].name);
 
		SetDParam(2, STR_UNITS_IMPERIAL + _opt_ptr->units);
 
		SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side);
 
		SetDParam(4, STR_TOWNNAME_ORIGINAL_ENGLISH + _opt_ptr->town_name);
 
		SetDParam(4, TownName(_opt_ptr->town_name));
 
		SetDParam(5, _autosave_dropdown[_opt_ptr->autosave]);
 
		SetDParam(6, SPECSTR_LANGUAGE_START + _dynlang.curr);
 
		i = GetCurRes();
 
		SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i);
 
		SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format);
 
		SetWindowWidgetLoweredState(w, 28, _fullscreen);
 

	
 
		DrawWindowWidgets(w);
 
		DrawString(20, 175, STR_OPTIONS_FULLSCREEN, 0); // fullscreen
 
	} break;
 

	
 
	case WE_CLICK:
 
@@ -143,26 +169,26 @@ static void GameOptionsWndProc(Window *w
 
		case 10: case 11: { /* Setup road-side dropdown */
 
			int i = 0;
 

	
 
			/* You can only change the drive side if you are in the menu or ingame with
 
			 * no vehicles present. In a networking game only the server can change it */
 
			if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server))
 
				i = (-1) ^ (1 << _opt_ptr->road_side); // disable the other value
 

	
 
			ShowDropDownMenu(w, _driveside_dropdown, _opt_ptr->road_side, 11, i, 0);
 
		} return;
 
		case 13: case 14: { /* Setup townname dropdown */
 
			uint sel = 0;
 
			for (uint i = 0; i < lengthof(_town_names) - 1; i++) {
 
				if (_town_names[i] == STR_TOWNNAME_ORIGINAL_ENGLISH + _opt_ptr->town_name) {
 
			for (uint i = 0; _town_names[i] != INVALID_STRING_ID; i++) {
 
				if (_town_names[i] == TownName(_opt_ptr->town_name)) {
 
					sel = i;
 
					break;
 
				}
 
			}
 
			ShowDropDownMenu(w, _town_names, sel, 14, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << sel), 0);
 
			return;
 
		}
 
		case 16: case 17: /* Setup autosave dropdown */
 
			ShowDropDownMenu(w, _autosave_dropdown, _opt_ptr->autosave, 17, 0, 0);
 
			return;
 
		case 19: case 20: /* Setup customized vehicle-names dropdown */
 
			ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names & 1) ? 1 : 0, 20, (_vehicle_design_names & 2) ? 0 : 2, 0);
 
@@ -205,25 +231,30 @@ static void GameOptionsWndProc(Window *w
 
		case 8: /* Measuring units */
 
			_opt_ptr->units = e->we.dropdown.index;
 
			MarkWholeScreenDirty();
 
			break;
 
		case 11: /* Road side */
 
			if (_opt_ptr->road_side != e->we.dropdown.index) { // only change if setting changed
 
				DoCommandP(0, e->we.dropdown.index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_00B4_CAN_T_DO_THIS));
 
				MarkWholeScreenDirty();
 
			}
 
			break;
 
		case 14: /* Town names */
 
			if (_game_mode == GM_MENU) {
 
				_opt_ptr->town_name = _town_names[e->we.dropdown.index] - STR_TOWNNAME_ORIGINAL_ENGLISH;
 
				for (uint i = 0; _town_names[i] != INVALID_STRING_ID; i++) {
 
					if (_town_names[e->we.dropdown.index] == TownName(i)) {
 
						_opt_ptr->town_name = i;
 
						break;
 
					}
 
				}
 
				InvalidateWindow(WC_GAME_OPTIONS, 0);
 
			}
 
			break;
 
		case 17: /* Autosave options */
 
			_opt.autosave = _opt_newgame.autosave = e->we.dropdown.index;
 
			SetWindowDirty(w);
 
			break;
 
		case 24: /* Change interface language */
 
			ReadLanguagePack(e->we.dropdown.index);
 
			UpdateAllStationVirtCoord();
 
			MarkWholeScreenDirty();
 
			break;
src/strings.cpp
Show inline comments
 
@@ -19,24 +19,25 @@
 
#include "industry.h"
 
#include "variables.h"
 
#include "newgrf_text.h"
 
#include "table/control_codes.h"
 
#include "music.h"
 
#include "date.h"
 
#include "industry.h"
 
#include "fileio.h"
 
#include "helpers.hpp"
 
#include "cargotype.h"
 
#include "group.h"
 
#include "debug.h"
 
#include "newgrf_townname.h"
 

	
 
/* for opendir/readdir/closedir */
 
# include "fios.h"
 

	
 
DynamicLanguages _dynlang;
 
char _userstring[128];
 

	
 
static char *StationGetSpecialString(char *buff, int x, const char* last);
 
static char *GetSpecialTownNameString(char *buff, int ind, uint32 seed, const char* last);
 
static char *GetSpecialPlayerNameString(char *buff, int ind, const int32 *argv, const char* last);
 

	
 
static char *FormatString(char *buff, const char *str, const int32 *argv, uint casei, const char* last);
 
@@ -816,39 +817,53 @@ static char* FormatString(char* buff, co
 
				}
 
				buff = GetStringWithArgs(buff, str, temp, last);
 
				break;
 
			}
 

	
 
			case SCC_STATION_NAME: { // {STATION}
 
				const Station* st = GetStation(GetInt32(&argv));
 

	
 
				if (!st->IsValid()) { // station doesn't exist anymore
 
					buff = GetStringWithArgs(buff, STR_UNKNOWN_DESTINATION, NULL, last);
 
				} else {
 
					int32 temp[2];
 
					temp[0] = st->town->townnametype;
 
					temp[1] = st->town->townnameparts;
 
					temp[0] = STR_TOWN;
 
					temp[1] = st->town->index;
 
					buff = GetStringWithArgs(buff, st->string_id, temp, last);
 
				}
 
				break;
 
			}
 

	
 
			case SCC_TOWN_NAME: { // {TOWN}
 
				const Town* t = GetTown(GetInt32(&argv));
 
				int32 temp[1];
 

	
 
				assert(IsValidTown(t));
 

	
 
				temp[0] = t->townnameparts;
 
				uint32 grfid = t->townnamegrfid;
 

	
 
				if (grfid == 0) {
 
					/* Original town name */
 
				buff = GetStringWithArgs(buff, t->townnametype, temp, last);
 
				} else {
 
					/* Newgrf town name */
 
					if (GetGRFTownName(grfid) != NULL) {
 
						/* The grf is loaded */
 
						buff = GRFTownNameGenerate(buff, t->townnamegrfid, t->townnametype, t->townnameparts, last);
 
					} else {
 
						/* Fallback to english original */
 
						buff = GetStringWithArgs(buff, SPECSTR_TOWNNAME_ENGLISH, temp, last);
 
					}
 
				}
 
				break;
 
			}
 

	
 
			case SCC_GROUP_NAME: { // {GROUP}
 
				const Group *g = GetGroup(GetInt32(&argv));
 
				int32 args[1];
 

	
 
				assert(IsValidGroup(g));
 

	
 
				args[0] = g->index;
 
				buff = GetStringWithArgs(buff, (g->string_id == STR_SV_GROUP_NAME) ? (StringID)STR_GROUP_NAME_FORMAT : g->string_id, args, last);
 

	
src/town.h
Show inline comments
 
@@ -74,24 +74,25 @@ struct BuildingCounts {
 
	uint8 id_count[HOUSE_MAX];
 
	uint8 class_count[HOUSE_CLASS_MAX];
 
};
 

	
 
struct Town {
 
	TileIndex xy;
 

	
 
	/* Current population of people and amount of houses. */
 
	uint16 num_houses;
 
	uint32 population;
 

	
 
	/* Town name */
 
	uint32 townnamegrfid;
 
	uint16 townnametype;
 
	uint32 townnameparts;
 

	
 
	/* NOSAVE: Location of name sign, UpdateTownVirtCoord updates this. */
 
	ViewportSign sign;
 

	
 
	/* Makes sure we don't build certain house types twice.
 
	 * bit 0 = Building funds received
 
	 * bit 1 = CHURCH
 
	 * bit 2 = STADIUM */
 
	byte flags12;
 

	
src/town_cmd.cpp
Show inline comments
 
@@ -30,24 +30,25 @@
 
#include "unmovable_map.h"
 
#include "water_map.h"
 
#include "variables.h"
 
#include "bridge.h"
 
#include "bridge_map.h"
 
#include "date.h"
 
#include "table/town_land.h"
 
#include "genworld.h"
 
#include "newgrf.h"
 
#include "newgrf_callbacks.h"
 
#include "newgrf_house.h"
 
#include "newgrf_commons.h"
 
#include "newgrf_townname.h"
 

	
 
/**
 
 * Called if a new block is added to the town-pool
 
 */
 
static void TownPoolNewBlock(uint start_item)
 
{
 
	Town *t;
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 * TODO - This is just a temporary stage, this will be removed. */
 
	for (t = GetTown(start_item); t != NULL; t = (t->index + 1U < GetTownPoolSize()) ? GetTown(t->index + 1U) : NULL) t->index = start_item++;
 
}
 
@@ -1286,44 +1287,51 @@ static void UpdateTownRadius(Town *t)
 
		/* Actually we are proportional to sqrt() but that's right because
 
		 * we are covering an area. */
 
		t->radius[1] = mass * 7;
 
		t->radius[2] = 0;
 
		t->radius[3] = mass * 4;
 
		t->radius[4] = mass * 3;
 
		//debug("%d (->%d): %d %d %d %d\n", t->num_houses, mass, t->radius[0], t->radius[1], t->radius[3], t->radius[4]);
 
	}
 
}
 

	
 
static bool CreateTownName(uint32 *townnameparts)
 
{
 
	extern int _nb_orig_names;
 
	Town *t2;
 
	char buf1[64];
 
	char buf2[64];
 
	uint32 r;
 
	/* Do not set too low tries, since when we run out of names, we loop
 
	 * for #tries only one time anyway - then we stop generating more
 
	 * towns. Do not show it too high neither, since looping through all
 
	 * the other towns may take considerable amount of time (10000 is
 
	 * too much). */
 
	int tries = 1000;
 
	uint16 townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
 
	bool grf = (_opt.town_name >= _nb_orig_names);
 
	uint32 grfid = grf ? GetGRFTownNameId(_opt.town_name - _nb_orig_names) : 0;
 
	uint16 townnametype = grf ? GetGRFTownNameType(_opt.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _opt.town_name;
 

	
 
	assert(townnameparts);
 

	
 
	for (;;) {
 
restart:
 
		r = Random();
 

	
 
		SetDParam(0, r);
 
		if (grf && grfid != 0) {
 
			GRFTownNameGenerate(buf1, grfid, townnametype, r, lastof(buf1));
 
		} else {
 
		GetString(buf1, townnametype, lastof(buf1));
 
		}
 

	
 
		/* Check size and width */
 
		if (strlen(buf1) >= 31 || GetStringBoundingBox(buf1).width > 130) continue;
 

	
 
		FOR_ALL_TOWNS(t2) {
 
			/* We can't just compare the numbers since
 
			 * several numbers may map to a single name. */
 
			SetDParam(0, t2->index);
 
			GetString(buf2, STR_TOWN, lastof(buf2));
 
			if (strcmp(buf1, buf2) == 0) {
 
				if (tries-- < 0) return false;
 
				goto restart;
 
@@ -1342,24 +1350,25 @@ void UpdateTownMaxPass(Town *t)
 

	
 
/**
 
 * Does the actual town creation.
 
 *
 
 * @param t The town
 
 * @param tile Where to put it
 
 * @param townnameparts The town name
 
 * @param size_mode How the size should be determined
 
 * @param size Parameter for size determination
 
 */
 
static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSizeMode size_mode, uint size)
 
{
 
	extern int _nb_orig_names;
 
	int x, i;
 

	
 
	/* clear the town struct */
 
	i = t->index;
 
	memset(t, 0, sizeof(Town));
 
	t->index = i;
 
	_total_towns++;
 

	
 
	t->xy = tile;
 
	t->num_houses = 0;
 
	t->time_until_rebuild = 10;
 
	UpdateTownRadius(t);
 
@@ -1383,25 +1392,33 @@ static void DoCreateTown(Town *t, TileIn
 
	t->new_act_water = 0;
 
	t->act_food = 0;
 
	t->act_water = 0;
 

	
 
	for (i = 0; i != MAX_PLAYERS; i++)
 
		t->ratings[i] = 500;
 

	
 
	t->have_ratings = 0;
 
	t->exclusivity = INVALID_PLAYER;
 
	t->exclusive_counter = 0;
 
	t->statues = 0;
 

	
 
	if (_opt.town_name < _nb_orig_names) {
 
		/* Original town name */
 
		t->townnamegrfid = 0;
 
	t->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name;
 
	} else {
 
		/* Newgrf town name */
 
		t->townnamegrfid = GetGRFTownNameId(_opt.town_name  - _nb_orig_names);
 
		t->townnametype  = GetGRFTownNameType(_opt.town_name - _nb_orig_names);
 
	}
 
	t->townnameparts = townnameparts;
 

	
 
	UpdateTownVirtCoord(t);
 
	_town_sort_dirty = true;
 

	
 
	/* Random town size. */
 
	x = (Random() & 0xF) + 8;
 

	
 
	switch (size_mode) {
 
		default: NOT_REACHED();
 

	
 
		case TSM_RANDOM:
 
@@ -2329,24 +2346,25 @@ extern const TileTypeProcs _tile_type_to
 

	
 

	
 
/** Save and load of towns. */
 
static const SaveLoad _town_desc[] = {
 
	SLE_CONDVAR(Town, xy,                    SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
 
	SLE_CONDVAR(Town, xy,                    SLE_UINT32,                 6, SL_MAX_VERSION),
 

	
 
	SLE_CONDVAR(Town, population,            SLE_FILE_U16 | SLE_VAR_U32, 0, 2),
 
	SLE_CONDVAR(Town, population,            SLE_UINT32,                 3, SL_MAX_VERSION),
 

	
 

	
 
	    SLE_VAR(Town, num_houses,            SLE_UINT16),
 
	SLE_CONDVAR(Town, townnamegrfid,         SLE_UINT32, 66, SL_MAX_VERSION),
 
	    SLE_VAR(Town, townnametype,          SLE_UINT16),
 
	    SLE_VAR(Town, townnameparts,         SLE_UINT32),
 

	
 
	    SLE_VAR(Town, flags12,               SLE_UINT8),
 
	    SLE_VAR(Town, statues,               SLE_UINT8),
 

	
 
	/* sort_index_obsolete was stored here in savegame format 0 - 1 */
 
	SLE_CONDNULL(1, 0, 1),
 

	
 
	    SLE_VAR(Town, have_ratings,          SLE_UINT8),
 
	    SLE_ARR(Town, ratings,               SLE_INT16, 8),
 
	/* failed bribe attempts are stored since savegame format 4 */
0 comments (0 inline, 0 general)