mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r17612) -Feature: possibility to choose (randomise or enter custom) town name before its creation (original patch by Terkhen)
This commit is contained in:
parent
665864e5b0
commit
1da745c9ad
|
@ -1527,6 +1527,10 @@
|
|||
RelativePath=".\..\src\townname_func.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\townname_type.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\town_type.h"
|
||||
>
|
||||
|
|
|
@ -1524,6 +1524,10 @@
|
|||
RelativePath=".\..\src\townname_func.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\townname_type.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\..\src\town_type.h"
|
||||
>
|
||||
|
|
|
@ -287,6 +287,7 @@ timetable.h
|
|||
toolbar_gui.h
|
||||
town.h
|
||||
townname_func.h
|
||||
townname_type.h
|
||||
town_type.h
|
||||
track_func.h
|
||||
track_type.h
|
||||
|
|
|
@ -2033,6 +2033,12 @@ STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Found to
|
|||
STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Many random towns
|
||||
STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cover the map with randomly placed towns
|
||||
|
||||
STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Town name:
|
||||
STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Enter town name
|
||||
STR_FOUND_TOWN_NAME_EDITOR_HELP :{BLACK}Click to enter town name
|
||||
STR_FOUND_TOWN_NAME_RANDOM_BUTTON :{BLACK}Random name
|
||||
STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP :{BLACK}Generate new random name
|
||||
|
||||
STR_FOUND_TOWN_INITIAL_SIZE_TITLE :{YELLOW}Town size:
|
||||
STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON :{BLACK}Small
|
||||
STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON :{BLACK}Medium
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "engine_base.h"
|
||||
#include "strgen/strgen.h"
|
||||
#include "gfx_func.h"
|
||||
#include "townname_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/control_codes.h"
|
||||
|
@ -105,7 +106,7 @@ const char *GetStringPtr(StringID string)
|
|||
* @param last
|
||||
* @return a formatted string of char
|
||||
*/
|
||||
static char *GetStringWithArgs(char *buffr, uint string, int64 *argv, const char *last)
|
||||
char *GetStringWithArgs(char *buffr, uint string, int64 *argv, const char *last)
|
||||
{
|
||||
if (GB(string, 0, 16) == 0) return GetStringWithArgs(buffr, STR_UNDEFINED, argv, last);
|
||||
|
||||
|
@ -913,27 +914,13 @@ static char *FormatString(char *buff, const char *str, int64 *argv, uint casei,
|
|||
|
||||
case SCC_TOWN_NAME: { // {TOWN}
|
||||
const Town *t = Town::Get(GetInt32(&argv));
|
||||
int64 temp[1];
|
||||
|
||||
assert(t != NULL);
|
||||
|
||||
temp[0] = t->townnameparts;
|
||||
uint32 grfid = t->townnamegrfid;
|
||||
|
||||
if (t->name != NULL) {
|
||||
buff = strecpy(buff, t->name, last);
|
||||
} else 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);
|
||||
}
|
||||
buff = GetTownName(buff, t, last);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
char *InlineString(char *buf, StringID string);
|
||||
char *GetString(char *buffr, StringID string, const char *last);
|
||||
char *GetStringWithArgs(char *buffr, uint string, int64 *argv, const char *last);
|
||||
const char *GetStringPtr(StringID string);
|
||||
|
||||
void InjectDParam(uint amount);
|
||||
|
|
|
@ -212,7 +212,6 @@ HouseZonesBits GetTownRadiusGroup(const Town *t, TileIndex tile);
|
|||
void SetTownRatingTestMode(bool mode);
|
||||
uint GetMaskOfTownActions(int *nump, CompanyID cid, const Town *t);
|
||||
bool GenerateTowns(TownLayout layout);
|
||||
bool GenerateTownName(uint32 *townnameparts);
|
||||
|
||||
|
||||
/** Town actions of a company. */
|
||||
|
|
129
src/town_cmd.cpp
129
src/town_cmd.cpp
|
@ -50,6 +50,8 @@
|
|||
#include "core/smallmap_type.hpp"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "town.h"
|
||||
#include "townname_func.h"
|
||||
#include "townname_type.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/town_land.h"
|
||||
|
@ -1392,90 +1394,6 @@ void UpdateTownRadius(Town *t)
|
|||
}
|
||||
}
|
||||
|
||||
extern int _nb_orig_names;
|
||||
|
||||
/**
|
||||
* Struct holding a parameters used to generate town name.
|
||||
* Speeds things up a bit because these values are computed only once per name generation.
|
||||
*/
|
||||
struct TownNameParams {
|
||||
uint32 grfid; ///< newgrf ID
|
||||
uint16 townnametype; ///< town name style
|
||||
bool grf; ///< true iff a newgrf is used to generate town name
|
||||
|
||||
TownNameParams(byte town_name)
|
||||
{
|
||||
this->grf = town_name >= _nb_orig_names;
|
||||
this->grfid = this->grf ? GetGRFTownNameId(town_name - _nb_orig_names) : 0;
|
||||
this->townnametype = this->grf ? GetGRFTownNameType(town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + town_name;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies the town name is valid and unique.
|
||||
* @param r random bits
|
||||
* @param par town name parameters
|
||||
* @return true iff name is valid and unique
|
||||
*/
|
||||
static bool VerifyTownName(uint32 r, const TownNameParams *par)
|
||||
{
|
||||
/* Reserve space for extra unicode character. We need to do this to be able
|
||||
* to detect too long town name. */
|
||||
char buf1[MAX_LENGTH_TOWN_NAME_BYTES + MAX_CHAR_LENGTH];
|
||||
char buf2[MAX_LENGTH_TOWN_NAME_BYTES + MAX_CHAR_LENGTH];
|
||||
|
||||
SetDParam(0, r);
|
||||
if (par->grf && par->grfid != 0) {
|
||||
GRFTownNameGenerate(buf1, par->grfid, par->townnametype, r, lastof(buf1));
|
||||
} else {
|
||||
GetString(buf1, par->townnametype, lastof(buf1));
|
||||
}
|
||||
|
||||
/* Check size and width */
|
||||
if (strlen(buf1) >= MAX_LENGTH_TOWN_NAME_BYTES) return false;
|
||||
|
||||
const Town *t;
|
||||
FOR_ALL_TOWNS(t) {
|
||||
/* We can't just compare the numbers since
|
||||
* several numbers may map to a single name. */
|
||||
SetDParam(0, t->index);
|
||||
GetString(buf2, STR_TOWN_NAME, lastof(buf2));
|
||||
if (strcmp(buf1, buf2) == 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates valid town name.
|
||||
* @param townnameparts if a name is generated, it's stored there
|
||||
* @return true iff a name was generated
|
||||
*/
|
||||
bool GenerateTownName(uint32 *townnameparts)
|
||||
{
|
||||
/* 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;
|
||||
TownNameParams par(_settings_game.game_creation.town_name);
|
||||
|
||||
assert(townnameparts != NULL);
|
||||
|
||||
for (;;) {
|
||||
uint32 r = InteractiveRandom();
|
||||
|
||||
if (!VerifyTownName(r, &par)) {
|
||||
if (tries-- < 0) return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
*townnameparts = r;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateTownMaxPass(Town *t)
|
||||
{
|
||||
t->max_pass = t->population >> 3;
|
||||
|
@ -1526,6 +1444,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize
|
|||
t->exclusive_counter = 0;
|
||||
t->statues = 0;
|
||||
|
||||
extern int _nb_orig_names;
|
||||
if (_settings_game.game_creation.town_name < _nb_orig_names) {
|
||||
/* Original town name */
|
||||
t->townnamegrfid = 0;
|
||||
|
@ -1587,6 +1506,22 @@ static CommandCost TownCanBePlacedHere(TileIndex tile)
|
|||
return CommandCost(EXPENSES_OTHER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies this custom name is unique. Only custom names are checked.
|
||||
* @param name name to check
|
||||
* @return is this name unique?
|
||||
*/
|
||||
static bool IsUniqueTownName(const char *name)
|
||||
{
|
||||
const Town *t;
|
||||
|
||||
FOR_ALL_TOWNS(t) {
|
||||
if (t->name != NULL && strcmp(t->name, name) == 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Create a new town.
|
||||
* This obviously only works in the scenario editor. Function not removed
|
||||
* as it might be possible in the future to fund your own town :)
|
||||
|
@ -1615,7 +1550,14 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
if (size > TS_RANDOM) return CMD_ERROR;
|
||||
if (layout > TL_RANDOM) return CMD_ERROR;
|
||||
|
||||
if (!VerifyTownName(townnameparts, &par)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
|
||||
if (StrEmpty(text)) {
|
||||
/* If supplied name is empty, townnameparts has to generate unique automatic name */
|
||||
if (!VerifyTownName(townnameparts, &par)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
|
||||
} else {
|
||||
/* If name is not empty, it has to be unique custom name */
|
||||
if (strlen(text) >= MAX_LENGTH_TOWN_NAME_BYTES) return CMD_ERROR;
|
||||
if (!IsUniqueTownName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
|
||||
}
|
||||
|
||||
/* Allocate town struct */
|
||||
if (!Town::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_TOWNS);
|
||||
|
@ -1630,19 +1572,21 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
if (flags & DC_EXEC) {
|
||||
_generating_world = true;
|
||||
UpdateNearestTownForRoadTiles(true);
|
||||
Town *t;
|
||||
if (random) {
|
||||
const Town *t = CreateRandomTown(20, townnameparts, size, city, layout);
|
||||
t = CreateRandomTown(20, townnameparts, size, city, layout);
|
||||
if (t == NULL) {
|
||||
cost = CommandCost(STR_ERROR_NO_SPACE_FOR_TOWN);
|
||||
} else {
|
||||
_new_town_id = t->index;
|
||||
}
|
||||
} else {
|
||||
Town *t = new Town(tile);
|
||||
t = new Town(tile);
|
||||
DoCreateTown(t, tile, townnameparts, size, city, layout);
|
||||
}
|
||||
UpdateNearestTownForRoadTiles(false);
|
||||
_generating_world = false;
|
||||
if (t != NULL && !StrEmpty(text)) t->name = strdup(text);
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
@ -2312,17 +2256,6 @@ void ClearTownHouse(Town *t, TileIndex tile)
|
|||
if (eflags & BUILDING_HAS_4_TILES) DoClearTownHouseHelper(tile + TileDiffXY(1, 1), t, ++house);
|
||||
}
|
||||
|
||||
static bool IsUniqueTownName(const char *name)
|
||||
{
|
||||
const Town *t;
|
||||
|
||||
FOR_ALL_TOWNS(t) {
|
||||
if (t->name != NULL && strcmp(t->name, name) == 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Rename a town (server-only).
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
#include "landscape.h"
|
||||
#include "cargotype.h"
|
||||
#include "tile_map.h"
|
||||
#include "querystring_gui.h"
|
||||
#include "window_func.h"
|
||||
#include "string_func.h"
|
||||
#include "townname_func.h"
|
||||
#include "townname_type.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
|
@ -850,11 +855,7 @@ void CcFoundTown(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
|||
|
||||
void CcFoundRandomTown(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (success) {
|
||||
tile = Town::Get(_new_town_id)->xy;
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ScrollMainWindowToTile(tile);
|
||||
}
|
||||
if (success) ScrollMainWindowToTile(Town::Get(_new_town_id)->xy);
|
||||
}
|
||||
|
||||
/** Widget numbers of town scenario editor window. */
|
||||
|
@ -866,6 +867,9 @@ enum TownScenarioEditorWidgets {
|
|||
TSEW_NEWTOWN,
|
||||
TSEW_RANDOMTOWN,
|
||||
TSEW_MANYRANDOMTOWNS,
|
||||
TSEW_TOWNNAME_TEXT,
|
||||
TSEW_TOWNNAME_EDITBOX,
|
||||
TSEW_TOWNNAME_RANDOM,
|
||||
TSEW_TOWNSIZE,
|
||||
TSEW_SIZE_SMALL,
|
||||
TSEW_SIZE_MEDIUM,
|
||||
|
@ -895,6 +899,14 @@ static const NWidgetPart _nested_found_town_widgets[] = {
|
|||
SetDataTip(STR_FOUND_TOWN_RANDOM_TOWN_BUTTON, STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP), SetPadding(0, 2, 1, 2),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, TSEW_MANYRANDOMTOWNS), SetMinimalSize(156, 12), SetFill(true, false),
|
||||
SetDataTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetPadding(0, 2, 0, 2),
|
||||
/* Town name selection. */
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_LABEL, COLOUR_DARK_GREEN, TSEW_TOWNSIZE), SetMinimalSize(156, 14), SetDataTip(STR_FOUND_TOWN_NAME_TITLE, STR_NULL),
|
||||
NWidget(WWT_EDITBOX, COLOUR_WHITE, TSEW_TOWNNAME_EDITBOX), SetMinimalSize(156, 12), SetDataTip(STR_FOUND_TOWN_NAME_EDITOR_TITLE, STR_FOUND_TOWN_NAME_EDITOR_HELP),
|
||||
NWidget(NWID_SPACER), SetMinimalSize(0, 3),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, TSEW_TOWNNAME_RANDOM), SetMinimalSize(78, 12), SetFill(true, false),
|
||||
SetDataTip(STR_FOUND_TOWN_NAME_RANDOM_BUTTON, STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP),
|
||||
EndContainer(),
|
||||
/* Town size selection. */
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_SPACER), SetFill(true, false),
|
||||
|
@ -940,23 +952,41 @@ static const NWidgetPart _nested_found_town_widgets[] = {
|
|||
};
|
||||
|
||||
/** Found a town window class. */
|
||||
struct FoundTownWindow : Window {
|
||||
struct FoundTownWindow : QueryStringBaseWindow {
|
||||
private:
|
||||
TownSize town_size; ///< Selected town size
|
||||
TownLayout town_layout; ///< Selected town layout
|
||||
bool city; ///< Are we building a city?
|
||||
bool townnamevalid; ///< Is generated town name valid?
|
||||
uint32 townnameparts; ///< Generated town name
|
||||
TownNameParams params; ///< Town name parameters
|
||||
|
||||
public:
|
||||
FoundTownWindow(const WindowDesc *desc, WindowNumber window_number) :
|
||||
Window(),
|
||||
QueryStringBaseWindow(MAX_LENGTH_TOWN_NAME_BYTES),
|
||||
town_size(TS_MEDIUM),
|
||||
town_layout(_settings_game.economy.town_layout),
|
||||
city(false)
|
||||
params(_settings_game.game_creation.town_name)
|
||||
{
|
||||
this->InitNested(desc, window_number);
|
||||
this->RandomTownName();
|
||||
this->UpdateButtons();
|
||||
}
|
||||
|
||||
void RandomTownName()
|
||||
{
|
||||
this->townnamevalid = GenerateTownName(&this->townnameparts);
|
||||
|
||||
if (!this->townnamevalid) {
|
||||
this->edit_str_buf[0] = '\0';
|
||||
} else {
|
||||
GetTownName(this->edit_str_buf, &this->params, this->townnameparts, &this->edit_str_buf[this->edit_str_size - 1]);
|
||||
}
|
||||
InitializeTextBuffer(&this->text, this->edit_str_buf, this->edit_str_size, MAX_LENGTH_TOWN_NAME_PIXELS);
|
||||
|
||||
this->SetFocusedWidget(TSEW_TOWNNAME_EDITBOX);
|
||||
}
|
||||
|
||||
void UpdateButtons()
|
||||
{
|
||||
for (int i = TSEW_SIZE_SMALL; i <= TSEW_SIZE_RANDOM; i++) {
|
||||
|
@ -974,19 +1004,27 @@ public:
|
|||
|
||||
void ExecuteFoundTownCommand(TileIndex tile, bool random, StringID errstr, CommandCallback cc)
|
||||
{
|
||||
uint32 townnameparts;
|
||||
if (!GenerateTownName(&townnameparts)) {
|
||||
ShowErrorMessage(STR_ERROR_TOO_MANY_TOWNS, errstr, 0, 0);
|
||||
return;
|
||||
const char *name = NULL;
|
||||
|
||||
if (!this->townnamevalid) {
|
||||
name = this->edit_str_buf;
|
||||
} else {
|
||||
/* If user changed the name, send it */
|
||||
char buf[MAX_LENGTH_TOWN_NAME_BYTES];
|
||||
GetTownName(buf, &this->params, this->townnameparts, lastof(buf));
|
||||
if (strcmp(buf, this->edit_str_buf) != 0) name = this->edit_str_buf;
|
||||
}
|
||||
|
||||
DoCommandP(tile, this->town_size | this->city << 2 | this->town_layout << 3 | random << 6,
|
||||
townnameparts, CMD_FOUND_TOWN | CMD_MSG(errstr), cc);
|
||||
bool success = DoCommandP(tile, this->town_size | this->city << 2 | this->town_layout << 3 | random << 6,
|
||||
townnameparts, CMD_FOUND_TOWN | CMD_MSG(errstr), cc, name);
|
||||
|
||||
if (success) this->RandomTownName();
|
||||
}
|
||||
|
||||
virtual void OnPaint()
|
||||
{
|
||||
this->DrawWidgets();
|
||||
this->DrawEditBox(TSEW_TOWNNAME_EDITBOX);
|
||||
}
|
||||
|
||||
virtual void OnClick(Point pt, int widget)
|
||||
|
@ -1001,6 +1039,10 @@ public:
|
|||
this->ExecuteFoundTownCommand(0, true, STR_ERROR_CAN_T_GENERATE_TOWN, CcFoundRandomTown);
|
||||
break;
|
||||
|
||||
case TSEW_TOWNNAME_RANDOM:
|
||||
this->RandomTownName();
|
||||
break;
|
||||
|
||||
case TSEW_MANYRANDOMTOWNS:
|
||||
this->HandleButtonClick(TSEW_MANYRANDOMTOWNS);
|
||||
|
||||
|
@ -1039,6 +1081,18 @@ public:
|
|||
this->SetDirty();
|
||||
}
|
||||
|
||||
virtual void OnMouseLoop()
|
||||
{
|
||||
this->HandleEditBox(TSEW_TOWNNAME_EDITBOX);
|
||||
}
|
||||
|
||||
virtual EventState OnKeyPress(uint16 key, uint16 keycode)
|
||||
{
|
||||
EventState state;
|
||||
this->HandleEditBoxKey(TSEW_TOWNNAME_EDITBOX, key, keycode, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
||||
{
|
||||
this->ExecuteFoundTownCommand(tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown);
|
||||
|
|
114
src/townname.cpp
114
src/townname.cpp
|
@ -12,11 +12,125 @@
|
|||
#include "stdafx.h"
|
||||
#include "townname_func.h"
|
||||
#include "string_func.h"
|
||||
#include "townname_func.h"
|
||||
#include "townname_type.h"
|
||||
#include "town.h"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "strings_func.h"
|
||||
|
||||
#include "table/townname.h"
|
||||
|
||||
|
||||
/**
|
||||
* Initializes this struct from town data
|
||||
* @param t town for which we will be printing name later
|
||||
*/
|
||||
TownNameParams::TownNameParams(const Town *t) :
|
||||
grfid(t->townnamegrfid), // by default, use supplied data
|
||||
type(t->townnametype)
|
||||
{
|
||||
if (t->townnamegrfid != 0 && GetGRFTownName(t->townnamegrfid) == NULL) {
|
||||
/* Fallback to english original */
|
||||
this->grfid = 0;
|
||||
this->type = SPECSTR_TOWNNAME_ENGLISH;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fills buffer with specified town name
|
||||
* @param buff buffer start
|
||||
* @param par town name parameters
|
||||
* @param townnameparts 'encoded' town name
|
||||
* @param last end of buffer
|
||||
* @return pointer to terminating '\0'
|
||||
*/
|
||||
char *GetTownName(char *buff, const TownNameParams *par, uint32 townnameparts, const char *last)
|
||||
{
|
||||
if (par->grfid == 0) {
|
||||
int64 temp[1] = { townnameparts };
|
||||
return GetStringWithArgs(buff, par->type, temp, last);
|
||||
}
|
||||
|
||||
return GRFTownNameGenerate(buff, par->grfid, par->type, townnameparts, last);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fills buffer with town's name
|
||||
* @param buff buffer start
|
||||
* @param t we want to get name of this town
|
||||
* @param last end of buffer
|
||||
* @return pointer to terminating '\0'
|
||||
*/
|
||||
char *GetTownName(char *buff, const Town *t, const char *last)
|
||||
{
|
||||
TownNameParams par(t);
|
||||
return GetTownName(buff, &par, t->townnameparts, last);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies the town name is valid and unique.
|
||||
* @param r random bits
|
||||
* @param par town name parameters
|
||||
* @return true iff name is valid and unique
|
||||
*/
|
||||
bool VerifyTownName(uint32 r, const TownNameParams *par)
|
||||
{
|
||||
/* reserve space for extra unicode character and terminating '\0' */
|
||||
char buf1[MAX_LENGTH_TOWN_NAME_BYTES + MAX_CHAR_LENGTH];
|
||||
char buf2[MAX_LENGTH_TOWN_NAME_BYTES + MAX_CHAR_LENGTH];
|
||||
|
||||
GetTownName(buf1, par, r, lastof(buf1));
|
||||
|
||||
/* Check size and width */
|
||||
if (strlen(buf1) >= MAX_LENGTH_TOWN_NAME_BYTES) return false;
|
||||
|
||||
const Town *t;
|
||||
FOR_ALL_TOWNS(t) {
|
||||
/* We can't just compare the numbers since
|
||||
* several numbers may map to a single name. */
|
||||
const char *buf = t->name;
|
||||
if (buf == NULL) {
|
||||
GetTownName(buf2, t, lastof(buf2));
|
||||
buf = buf2;
|
||||
}
|
||||
if (strcmp(buf1, buf2) == 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates valid town name.
|
||||
* @param townnameparts if a name is generated, it's stored there
|
||||
* @return true iff a name was generated
|
||||
*/
|
||||
bool GenerateTownName(uint32 *townnameparts)
|
||||
{
|
||||
/* 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). */
|
||||
TownNameParams par(_settings_game.game_creation.town_name);
|
||||
|
||||
for (int i = 1000; i != 0; i--) {
|
||||
uint32 r = InteractiveRandom();
|
||||
if (!VerifyTownName(r, &par)) continue;
|
||||
|
||||
*townnameparts = r;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates a number from given seed.
|
||||
* @param shift_by number of bits seed is shifted to the right
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
|
||||
/** @file townname_func.h Town name generator stuff. */
|
||||
|
||||
#ifndef NAMEGEN_FUNC_H
|
||||
#define NAMEGEN_FUNC_H
|
||||
#ifndef TOWNNAME_FUNC_H
|
||||
#define TOWNNAME_FUNC_H
|
||||
|
||||
char *GenerateTownNameString(char *buf, const char *last, size_t lang, uint32 seed);
|
||||
char *GetTownName(char *buff, const struct TownNameParams *par, uint32 townnameparts, const char *last);
|
||||
char *GetTownName(char *buff, const struct Town *t, const char *last);
|
||||
bool VerifyTownName(uint32 r, const struct TownNameParams *par);
|
||||
bool GenerateTownName(uint32 *townnameparts);
|
||||
|
||||
#endif /* NAMEGEN_FUNC_H */
|
||||
#endif /* TOWNNAME_FUNC_H */
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* $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 townname_type.h
|
||||
* Definition of structures used for generating town names.
|
||||
*/
|
||||
|
||||
#ifndef TOWNNAME_TYPE_H
|
||||
#define TOWNNAME_TYPE_H
|
||||
|
||||
#include "newgrf_townname.h"
|
||||
|
||||
/**
|
||||
* Struct holding a parameters used to generate town name.
|
||||
* Speeds things up a bit because these values are computed only once per name generation.
|
||||
*/
|
||||
struct TownNameParams {
|
||||
uint32 grfid; ///< newgrf ID (0 if not used)
|
||||
uint16 type; ///< town name style
|
||||
|
||||
/**
|
||||
* Initializes this struct from language ID
|
||||
* @param town_name town name 'language' ID
|
||||
*/
|
||||
TownNameParams(byte town_name)
|
||||
{
|
||||
extern int _nb_orig_names;
|
||||
bool grf = town_name >= _nb_orig_names;
|
||||
this->grfid = grf ? GetGRFTownNameId(town_name - _nb_orig_names) : 0;
|
||||
this->type = grf ? GetGRFTownNameType(town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + town_name;
|
||||
}
|
||||
|
||||
TownNameParams(const struct Town *t);
|
||||
};
|
||||
|
||||
#endif /* TOWNNAME_TYPE_H */
|
Loading…
Reference in New Issue