changeset 4377:39f478fcb1dd draft

(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
author belugas <belugas@openttd.org>
date Fri, 25 Aug 2006 00:41:10 +0000
parents 2523b7101575
children 77ae86063736
files currency.c currency.h newgrf.c settings_gui.c strings.c
diffstat 5 files changed, 178 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/currency.c
+++ b/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 @@
 	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 @@
 	}
 }
 
+/**
+ * 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;
+}
--- a/currency.h
+++ b/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 @@
 	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 */
--- a/newgrf.c
+++ b/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 @@
 			}
 			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 @@
 					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 @@
 	// Reset price base data
 	ResetPriceBaseMultipliers();
 
+	/* Reset the curencies array */
+	ResetCurrencies();
+
 	// Reset station classes
 	ResetStationClasses();
 	ResetCustomStations();
--- a/settings_gui.c
+++ b/settings_gui.c
@@ -97,7 +97,7 @@
 		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 @@
 	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);
--- a/strings.c
+++ b/strings.c
@@ -381,9 +381,11 @@
 		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 @@
 
 	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;
 }