mirror of https://github.com/OpenTTD/OpenTTD
(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 poundrelease/0.5
parent
0189b8994d
commit
c9b32982fc
131
currency.c
131
currency.c
|
@ -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;
|
||||
}
|
||||
|
|
15
currency.h
15
currency.h
|
@ -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 */
|
||||
|
|
90
newgrf.c
90
newgrf.c
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
16
strings.c
16
strings.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue