1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-24 15:09:10 +00:00

(svn r6108) -NewGRF Feature: Implement currencies replacment via grf file.

All properties can now be modified i.e:
Introduction date for euro conversion
Currency name, decimal separator, currency symbol (before or after amount)
and the rate compared to the base currency, the british pound
This commit is contained in:
belugas
2006-08-25 00:41:10 +00:00
parent 0189b8994d
commit c9b32982fc
5 changed files with 178 additions and 78 deletions

View File

@@ -8,79 +8,48 @@
#include "table/strings.h" #include "table/strings.h"
#include "date.h" #include "date.h"
// exchange rate prefix // exchange rate prefix symbol_pos
// | separator | postfix // | separator | postfix |
// | | Euro year | | // | | Euro year | | | name
// | | | | | // | | | | | | |
CurrencySpec _currency_specs[] = { const CurrencySpec origin_currency_specs[NUM_CURRENCY] = {
{ 1, ',', CF_NOEURO, "\xA3", "" }, // british pounds { 1, ',', CF_NOEURO, "\xA3", "", 0, STR_CURR_GBP }, // british pounds
{ 2, ',', CF_NOEURO, "$", "" }, // us dollars { 2, ',', CF_NOEURO, "$", "", 0, STR_CURR_USD }, // us dollars
{ 2, ',', CF_ISEURO, "<EFBFBD>", "" }, // Euro { 2, ',', CF_ISEURO, "<EFBFBD>", "", 0, STR_CURR_EUR }, // Euro
{ 200, ',', CF_NOEURO, "\xA5", "" }, // yen { 200, ',', CF_NOEURO, "\xA5", "", 0, STR_CURR_YEN }, // yen
{ 19, ',', 2002, "", " S." }, // austrian schilling { 19, ',', 2002, "", " S.", 1, STR_CURR_ATS }, // austrian schilling
{ 57, ',', 2002, "BEF ", "" }, // belgian franc { 57, ',', 2002, "BEF ", "", 0, STR_CURR_BEF }, // belgian franc
{ 2, ',', CF_NOEURO, "CHF ", "" }, // swiss franc { 2, ',', CF_NOEURO, "CHF ", "", 0, STR_CURR_CHF }, // swiss franc
{ 50, ',', CF_NOEURO, "", " Kc" }, // czech koruna // TODO: Should use the "c" with an upside down "^" { 50, ',', CF_NOEURO, "", " Kc", 1, STR_CURR_CZK }, // czech koruna // TODO: Should use the "c" with an upside down "^"
{ 4, '.', 2002, "DM ", "" }, // deutsche mark { 4, '.', 2002, "DM ", "", 0, STR_CURR_DEM }, // deutsche mark
{ 10, '.', CF_NOEURO, "", " kr" }, // danish krone { 10, '.', CF_NOEURO, "", " kr", 1, STR_CURR_DKK }, // danish krone
{ 200, '.', 2002, "Pts ", "" }, // spanish pesetas { 200, '.', 2002, "Pts ", "", 0, STR_CURR_ESP }, // spanish pesetas
{ 8, ',', 2002, "", " mk" }, // finnish markka { 8, ',', 2002, "", " mk", 1, STR_CURR_FIM }, // finnish markka
{ 10, '.', 2002, "FF ", "" }, // french francs { 10, '.', 2002, "FF ", "", 0, STR_CURR_FRF }, // french francs
{ 480, ',', 2002, "", "Dr." }, // greek drachma { 480, ',', 2002, "", "Dr.", 1, STR_CURR_GRD }, // greek drachma
{ 376, ',', 2002, "", " Ft" }, // hungarian forint { 376, ',', 2002, "", " Ft", 1, STR_CURR_HUF }, // hungarian forint
{ 130, '.', CF_NOEURO, "", " Kr" }, // icelandic krona { 130, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_ISK }, // icelandic krona
{ 2730, ',', 2002, "", " L." }, // italian lira { 2730, ',', 2002, "", " L.", 1, STR_CURR_ITL }, // italian lira
{ 3, ',', 2002, "NLG ", "" }, // dutch gulden { 3, ',', 2002, "NLG ", "", 0, STR_CURR_NLG }, // dutch gulden
{ 11, '.', CF_NOEURO, "", " Kr" }, // norwegian krone { 11, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_NOK }, // norwegian krone
{ 6, ' ', CF_NOEURO, "", " zl" }, // polish zloty { 6, ' ', CF_NOEURO, "", " zl", 1, STR_CURR_PLN }, // polish zloty
{ 6, '.', CF_NOEURO, "", " Lei" }, // romanian Lei { 6, '.', CF_NOEURO, "", " Lei", 1, STR_CURR_ROL }, // romanian Lei
{ 5, ' ', CF_NOEURO, "", " p" }, // russian rouble { 5, ' ', CF_NOEURO, "", " p", 1, STR_CURR_RUR }, // russian rouble
{ 350, '.', CF_NOEURO, "", " SIT" }, // slovenian tolar { 350, '.', CF_NOEURO, "", " SIT", 1, STR_CURR_SIT }, // slovenian tolar
{ 13, '.', CF_NOEURO, "", " Kr" }, // swedish krona { 13, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_SEK }, // swedish krona
{ 1, ' ', CF_NOEURO, "", "" }, // custom currency { 1, ' ', CF_NOEURO, "", "", 0, STR_CURR_CUSTOM }, // custom currency
}; };
const StringID _currency_string_list[] = { /* Array of currencies used by the system */
STR_CURR_GBP, CurrencySpec _currency_specs[NUM_CURRENCY];
STR_CURR_USD,
STR_CURR_EUR,
STR_CURR_YEN,
STR_CURR_ATS,
STR_CURR_BEF,
STR_CURR_CHF,
STR_CURR_CZK,
STR_CURR_DEM,
STR_CURR_DKK,
STR_CURR_ESP,
STR_CURR_FIM,
STR_CURR_FRF,
STR_CURR_GRD,
STR_CURR_HUF,
STR_CURR_ISK,
STR_CURR_ITL,
STR_CURR_NLG,
STR_CURR_NOK,
STR_CURR_PLN,
STR_CURR_ROL,
STR_CURR_RUR,
STR_CURR_SIT,
STR_CURR_SEK,
STR_CURR_CUSTOM,
INVALID_STRING_ID
};
// NOTE: Make sure both lists are in the same order /* get a mask of the allowed currencies depending on the year */
// + 1 string list terminator
assert_compile(lengthof(_currency_specs) + 1 == lengthof(_currency_string_list));
// get a mask of the allowed currencies depending on the year
uint GetMaskOfAllowedCurrencies(void) uint GetMaskOfAllowedCurrencies(void)
{ {
uint mask = 0; uint mask = 0;
uint i; uint i;
for (i = 0; i != lengthof(_currency_specs); i++) { for (i = 0; i < NUM_CURRENCY; i++) {
Year to_euro = _currency_specs[i].to_euro; Year to_euro = _currency_specs[i].to_euro;
if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue; if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue;
@@ -91,7 +60,9 @@ uint GetMaskOfAllowedCurrencies(void)
return mask; return mask;
} }
/**
* Verify if the currency chosen by the user is about to be converted to Euro
**/
void CheckSwitchToEuro(void) void CheckSwitchToEuro(void)
{ {
if (_currency_specs[_opt.currency].to_euro != CF_NOEURO && if (_currency_specs[_opt.currency].to_euro != CF_NOEURO &&
@@ -102,3 +73,31 @@ void CheckSwitchToEuro(void)
} }
} }
/**
* Called only from newgrf.c. Will fill _currency_specs array with
* default values from origin_currency_specs
**/
void ResetCurrencies(void)
{
memcpy(&_currency_specs, &origin_currency_specs, sizeof(origin_currency_specs));
}
/**
* Build a list of currency names StringIDs to use in a dropdown list
* @return Pointer to a (static) array of StringIDs
*/
StringID* BuildCurrencyDropdown(void)
{
/* Allow room for all currencies, plus a terminator entry */
static StringID names[CUSTOM_CURRENCY_ID];
uint i;
/* Add each name */
for (i = 0; i < NUM_CURRENCY; i++) {
names[i] = _currency_specs[i].name;
}
/* Terminate the list */
names[i] = INVALID_STRING_ID;
return names;
}

View File

@@ -6,6 +6,8 @@
enum { enum {
CF_NOEURO = 0, CF_NOEURO = 0,
CF_ISEURO = 1, CF_ISEURO = 1,
NUM_CURRENCY = 25,
CUSTOM_CURRENCY_ID = NUM_CURRENCY + 1,
}; };
typedef struct { typedef struct {
@@ -14,17 +16,24 @@ typedef struct {
Year to_euro; Year to_euro;
char prefix[16]; char prefix[16];
char suffix[16]; char suffix[16];
/**
* Position of the currency symbol on the amount string.
* 0 = placed before, 1 = placed after
*/
byte symbol_pos;
StringID name;
} CurrencySpec; } CurrencySpec;
extern CurrencySpec _currency_specs[];
extern const StringID _currency_string_list[]; extern CurrencySpec _currency_specs[NUM_CURRENCY];
// XXX small hack, but makes the rest of the code a bit nicer to read // XXX small hack, but makes the rest of the code a bit nicer to read
#define CUSTOM_CURRENCY_ID 24
#define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID]) #define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency]) #define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
uint GetMaskOfAllowedCurrencies(void); uint GetMaskOfAllowedCurrencies(void);
void CheckSwitchToEuro(void); void CheckSwitchToEuro(void);
void ResetCurrencies(void);
StringID* BuildCurrencyDropdown(void);
#endif /* CURRENCY_H */ #endif /* CURRENCY_H */

View File

@@ -24,7 +24,7 @@
#include "newgrf_text.h" #include "newgrf_text.h"
#include "table/sprites.h" #include "table/sprites.h"
#include "date.h" #include "date.h"
#include "currency.h"
#include "newgrf_spritegroup.h" #include "newgrf_spritegroup.h"
/* TTDPatch extended GRF format codec /* TTDPatch extended GRF format codec
@@ -1088,6 +1088,86 @@ static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, i
} }
break; break;
case 0x0A: // Currency display names
FOR_EACH_OBJECT {
StringID newone = GetGRFStringID(_cur_grffile->grfid,grf_load_word(&buf));
if (newone != STR_UNDEFINED) {
_currency_specs[gvid + i].name = newone;
}
}
break;
case 0x0B: // Currency multipliers
FOR_EACH_OBJECT {
uint curidx = gvid + i;
uint32 rate = grf_load_dword(&buf);
if (curidx < NUM_CURRENCY) {
_currency_specs[curidx].rate = rate;
} else {
grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency multipliers %d out of range, ignoring.", curidx);
}
}
break;
case 0x0C: // Currency options
FOR_EACH_OBJECT {
uint curidx = gvid +i;
uint16 options = grf_load_word(&buf);
if (curidx < NUM_CURRENCY) {
_currency_specs[curidx].separator = GB(options, 0, 8);
_currency_specs[curidx].symbol_pos = GB(options, 8, 8);
} else {
grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency option %d out of range, ignoring.", curidx);
}
}
break;
case 0x0D: // Currency symbols
FOR_EACH_OBJECT {
uint curidx = gvid +i;
uint32 tempfix = grf_load_dword(&buf);
if (curidx < NUM_CURRENCY) {
memcpy(_currency_specs[curidx].prefix,&tempfix,4);
_currency_specs[curidx].prefix[4] = 0;
} else {
grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring.", curidx);
}
}
break;
case 0x0E: // Currency symbols
FOR_EACH_OBJECT {
uint curidx = gvid +i;
uint32 tempfix = grf_load_dword(&buf);
if (curidx < NUM_CURRENCY) {
memcpy(&_currency_specs[curidx].suffix,&tempfix,4);
_currency_specs[curidx].suffix[4] = 0;
} else {
grfmsg(GMS_WARN, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring.", curidx);
}
}
break;
case 0x0F: // Euro introduction datess
FOR_EACH_OBJECT {
uint curidx = gvid +i;
Year year_euro = grf_load_word(&buf);
if (curidx < NUM_CURRENCY) {
_currency_specs[curidx].to_euro = year_euro;
} else {
grfmsg(GMS_WARN, "GlobalVarChangeInfo: Euro intro date %d out of range, ignoring.", curidx);
}
}
break;
case 0x09: // Cargo translation table
case 0x10: // 12 * 32 * B Snow line height table
default: default:
ret = true; ret = true;
} }
@@ -1820,6 +1900,11 @@ static void FeatureNewName(byte *buf, int len)
break; break;
} }
case 0x48 : { // this will allow things like currencies new strings, and everything else
AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id);
break;
}
default: default:
switch (GB(id, 8, 8)) { switch (GB(id, 8, 8)) {
case 0xC4: /* Station class name */ case 0xC4: /* Station class name */
@@ -2727,6 +2812,9 @@ static void ResetNewGRFData(void)
// Reset price base data // Reset price base data
ResetPriceBaseMultipliers(); ResetPriceBaseMultipliers();
/* Reset the curencies array */
ResetCurrencies();
// Reset station classes // Reset station classes
ResetStationClasses(); ResetStationClasses();
ResetCustomStations(); ResetCustomStations();

View File

@@ -97,7 +97,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e)
StringID str = STR_02BE_DEFAULT; StringID str = STR_02BE_DEFAULT;
w->disabled_state = (_vehicle_design_names & 1) ? (++str, 0) : (1 << 21); w->disabled_state = (_vehicle_design_names & 1) ? (++str, 0) : (1 << 21);
SetDParam(0, str); SetDParam(0, str);
SetDParam(1, _currency_string_list[_opt_ptr->currency]); SetDParam(1, _currency_specs[_opt_ptr->currency].name);
SetDParam(2, STR_UNITS_IMPERIAL + _opt_ptr->units); SetDParam(2, STR_UNITS_IMPERIAL + _opt_ptr->units);
SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side); SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side);
SetDParam(4, STR_TOWNNAME_ORIGINAL_ENGLISH + _opt_ptr->town_name); SetDParam(4, STR_TOWNNAME_ORIGINAL_ENGLISH + _opt_ptr->town_name);
@@ -115,7 +115,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e)
case WE_CLICK: case WE_CLICK:
switch (e->click.widget) { switch (e->click.widget) {
case 4: case 5: /* Setup currencies dropdown */ case 4: case 5: /* Setup currencies dropdown */
ShowDropDownMenu(w, _currency_string_list, _opt_ptr->currency, 5, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0); ShowDropDownMenu(w, BuildCurrencyDropdown(), _opt_ptr->currency, 5, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0);;
return; return;
case 7: case 8: /* Setup distance unit dropdown */ case 7: case 8: /* Setup distance unit dropdown */
ShowDropDownMenu(w, _units_dropdown, _opt_ptr->units, 8, 0, 0); ShowDropDownMenu(w, _units_dropdown, _opt_ptr->units, 8, 0, 0);

View File

@@ -381,9 +381,11 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n
number = -number; number = -number;
} }
// add prefix part /* add prefix part, only if it is specified by symbol_pos */
s = spec->prefix; if (spec->symbol_pos == 0) {
while (s != spec->prefix + lengthof(spec->prefix) && (c = *s++) != '\0') *buff++ = c; s = spec->prefix;
while (s != spec->prefix + lengthof(spec->prefix) && (c = *(s++)) != '\0') *(buff)++ = c;
}
// for huge numbers, compact the number into k or M // for huge numbers, compact the number into k or M
if (compact) { if (compact) {
@@ -411,9 +413,11 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n
if (compact) *buff++ = compact; if (compact) *buff++ = compact;
// add suffix part /* add suffix part, only if it is specified by symbol_pos */
s = spec->suffix; if (spec->symbol_pos != 0) {
while (s != spec->suffix + lengthof(spec->suffix) && (c = *s++) != '\0') *buff++ = c; s = spec->suffix;
while (s != spec->suffix + lengthof(spec->suffix) && (c = *(s++)) != '\0') *(buff++) = c;
}
return buff; return buff;
} }