(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 "date.h"
// exchange rate prefix
// | separator | postfix
// | | Euro year | |
// | | | | |
CurrencySpec _currency_specs[] = {
{ 1, ',', CF_NOEURO, "\xA3", "" }, // british pounds
{ 2, ',', CF_NOEURO, "$", "" }, // us dollars
{ 2, ',', CF_ISEURO, "¤", "" }, // Euro
{ 200, ',', CF_NOEURO, "\xA5", "" }, // yen
{ 19, ',', 2002, "", " S." }, // austrian schilling
{ 57, ',', 2002, "BEF ", "" }, // belgian franc
{ 2, ',', CF_NOEURO, "CHF ", "" }, // swiss franc
{ 50, ',', CF_NOEURO, "", " Kc" }, // czech koruna // TODO: Should use the "c" with an upside down "^"
{ 4, '.', 2002, "DM ", "" }, // deutsche mark
{ 10, '.', CF_NOEURO, "", " kr" }, // danish krone
{ 200, '.', 2002, "Pts ", "" }, // spanish pesetas
{ 8, ',', 2002, "", " mk" }, // finnish markka
{ 10, '.', 2002, "FF ", "" }, // french francs
{ 480, ',', 2002, "", "Dr." }, // greek drachma
{ 376, ',', 2002, "", " Ft" }, // hungarian forint
{ 130, '.', CF_NOEURO, "", " Kr" }, // icelandic krona
{ 2730, ',', 2002, "", " L." }, // italian lira
{ 3, ',', 2002, "NLG ", "" }, // dutch gulden
{ 11, '.', CF_NOEURO, "", " Kr" }, // norwegian krone
{ 6, ' ', CF_NOEURO, "", " zl" }, // polish zloty
{ 6, '.', CF_NOEURO, "", " Lei" }, // romanian Lei
{ 5, ' ', CF_NOEURO, "", " p" }, // russian rouble
{ 350, '.', CF_NOEURO, "", " SIT" }, // slovenian tolar
{ 13, '.', CF_NOEURO, "", " Kr" }, // swedish krona
{ 1, ' ', CF_NOEURO, "", "" }, // custom currency
// exchange rate prefix symbol_pos
// | separator | postfix |
// | | Euro year | | | name
// | | | | | | |
const CurrencySpec origin_currency_specs[NUM_CURRENCY] = {
{ 1, ',', CF_NOEURO, "\xA3", "", 0, STR_CURR_GBP }, // british pounds
{ 2, ',', CF_NOEURO, "$", "", 0, STR_CURR_USD }, // us dollars
{ 2, ',', CF_ISEURO, "¤", "", 0, STR_CURR_EUR }, // Euro
{ 200, ',', CF_NOEURO, "\xA5", "", 0, STR_CURR_YEN }, // yen
{ 19, ',', 2002, "", " S.", 1, STR_CURR_ATS }, // austrian schilling
{ 57, ',', 2002, "BEF ", "", 0, STR_CURR_BEF }, // belgian franc
{ 2, ',', CF_NOEURO, "CHF ", "", 0, STR_CURR_CHF }, // swiss franc
{ 50, ',', CF_NOEURO, "", " Kc", 1, STR_CURR_CZK }, // czech koruna // TODO: Should use the "c" with an upside down "^"
{ 4, '.', 2002, "DM ", "", 0, STR_CURR_DEM }, // deutsche mark
{ 10, '.', CF_NOEURO, "", " kr", 1, STR_CURR_DKK }, // danish krone
{ 200, '.', 2002, "Pts ", "", 0, STR_CURR_ESP }, // spanish pesetas
{ 8, ',', 2002, "", " mk", 1, STR_CURR_FIM }, // finnish markka
{ 10, '.', 2002, "FF ", "", 0, STR_CURR_FRF }, // french francs
{ 480, ',', 2002, "", "Dr.", 1, STR_CURR_GRD }, // greek drachma
{ 376, ',', 2002, "", " Ft", 1, STR_CURR_HUF }, // hungarian forint
{ 130, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_ISK }, // icelandic krona
{ 2730, ',', 2002, "", " L.", 1, STR_CURR_ITL }, // italian lira
{ 3, ',', 2002, "NLG ", "", 0, STR_CURR_NLG }, // dutch gulden
{ 11, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_NOK }, // norwegian krone
{ 6, ' ', CF_NOEURO, "", " zl", 1, STR_CURR_PLN }, // polish zloty
{ 6, '.', CF_NOEURO, "", " Lei", 1, STR_CURR_ROL }, // romanian Lei
{ 5, ' ', CF_NOEURO, "", " p", 1, STR_CURR_RUR }, // russian rouble
{ 350, '.', CF_NOEURO, "", " SIT", 1, STR_CURR_SIT }, // slovenian tolar
{ 13, '.', CF_NOEURO, "", " Kr", 1, STR_CURR_SEK }, // swedish krona
{ 1, ' ', CF_NOEURO, "", "", 0, STR_CURR_CUSTOM }, // custom currency
};
const StringID _currency_string_list[] = {
STR_CURR_GBP,
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
};
/* Array of currencies used by the system */
CurrencySpec _currency_specs[NUM_CURRENCY];
// NOTE: Make sure both lists are in the same order
// + 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
/* get a mask of the allowed currencies depending on the year */
uint GetMaskOfAllowedCurrencies(void)
{
uint mask = 0;
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;
if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue;
@ -91,7 +60,9 @@ uint GetMaskOfAllowedCurrencies(void)
return mask;
}
/**
* Verify if the currency chosen by the user is about to be converted to Euro
**/
void CheckSwitchToEuro(void)
{
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 {
CF_NOEURO = 0,
CF_ISEURO = 1,
NUM_CURRENCY = 25,
CUSTOM_CURRENCY_ID = NUM_CURRENCY + 1,
};
typedef struct {
@ -14,17 +16,24 @@ typedef struct {
Year to_euro;
char prefix[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;
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
#define CUSTOM_CURRENCY_ID 24
#define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID])
#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency])
uint GetMaskOfAllowedCurrencies(void);
void CheckSwitchToEuro(void);
void ResetCurrencies(void);
StringID* BuildCurrencyDropdown(void);
#endif /* CURRENCY_H */

View File

@ -24,7 +24,7 @@
#include "newgrf_text.h"
#include "table/sprites.h"
#include "date.h"
#include "currency.h"
#include "newgrf_spritegroup.h"
/* TTDPatch extended GRF format codec
@ -1088,6 +1088,86 @@ static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, i
}
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:
ret = true;
}
@ -1820,6 +1900,11 @@ static void FeatureNewName(byte *buf, int len)
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:
switch (GB(id, 8, 8)) {
case 0xC4: /* Station class name */
@ -2727,6 +2812,9 @@ static void ResetNewGRFData(void)
// Reset price base data
ResetPriceBaseMultipliers();
/* Reset the curencies array */
ResetCurrencies();
// Reset station classes
ResetStationClasses();
ResetCustomStations();

View File

@ -97,7 +97,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e)
StringID str = STR_02BE_DEFAULT;
w->disabled_state = (_vehicle_design_names & 1) ? (++str, 0) : (1 << 21);
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(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side);
SetDParam(4, STR_TOWNNAME_ORIGINAL_ENGLISH + _opt_ptr->town_name);
@ -115,7 +115,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e)
case WE_CLICK:
switch (e->click.widget) {
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;
case 7: case 8: /* Setup distance unit dropdown */
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;
}
// add prefix part
s = spec->prefix;
while (s != spec->prefix + lengthof(spec->prefix) && (c = *s++) != '\0') *buff++ = c;
/* add prefix part, only if it is specified by symbol_pos */
if (spec->symbol_pos == 0) {
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
if (compact) {
@ -411,9 +413,11 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, int64 n
if (compact) *buff++ = compact;
// add suffix part
s = spec->suffix;
while (s != spec->suffix + lengthof(spec->suffix) && (c = *s++) != '\0') *buff++ = c;
/* add suffix part, only if it is specified by symbol_pos */
if (spec->symbol_pos != 0) {
s = spec->suffix;
while (s != spec->suffix + lengthof(spec->suffix) && (c = *(s++)) != '\0') *(buff++) = c;
}
return buff;
}