tron@2186: /* $Id$ */ tron@2186: belugas@6201: /** @file misc.cpp */ belugas@6201: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@2308: #include "currency.h" maedhros@6453: #include "landscape.h" tron@2548: #include "news.h" truelight@0: #include "saveload.h" bjarni@842: #include "engine.h" matthijs@1752: #include "vehicle_gui.h" tron@2159: #include "variables.h" truelight@2706: #include "ai/ai.h" maedhros@6332: #include "newgrf_house.h" peter1138@6091: #include "cargotype.h" rubidium@6643: #include "group.h" rubidium@8224: #include "viewport_func.h" rubidium@8119: #include "economy_func.h" rubidium@8123: #include "zoom_func.h" rubidium@8131: #include "functions.h" rubidium@8139: #include "map_func.h" rubidium@8140: #include "date_func.h" rubidium@8144: #include "vehicle_func.h" rubidium@8144: #include "texteff.hpp" rubidium@8214: #include "string_func.h" rubidium@8224: #include "gfx_func.h" rubidium@8224: rubidium@8264: #include "table/strings.h" rubidium@8264: #include "table/sprites.h" truelight@0: tron@1328: char _name_array[512][32]; truelight@0: rubidium@6247: void InitializeVehicles(); rubidium@6247: void InitializeWaypoints(); rubidium@6247: void InitializeDepots(); rubidium@6247: void InitializeEngines(); rubidium@6247: void InitializeOrders(); rubidium@6247: void InitializeClearLand(); rubidium@6247: void InitializeRailGui(); rubidium@6247: void InitializeRoadGui(); rubidium@6247: void InitializeAirportGui(); rubidium@6247: void InitializeDockGui(); rubidium@6247: void InitializeIndustries(); rubidium@6247: void InitializeMainGui(); rubidium@6247: void InitializeTowns(); rubidium@6247: void InitializeTrees(); rubidium@6247: void InitializeSigns(); rubidium@6247: void InitializeStations(); rubidium@7010: void InitializeCargoPackets(); rubidium@6247: static void InitializeNameMgr(); rubidium@6247: void InitializePlayers(); rubidium@6247: static void InitializeCheats(); rubidium@6247: void InitializeNPF(); truelight@0: truelight@2828: void InitializeGame(int mode, uint size_x, uint size_y) truelight@0: { ludde@2051: AllocateMap(size_x, size_y); ludde@2051: rubidium@7889: SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0); truelight@0: truelight@6231: _pause_game = 0; truelight@0: _fast_forward = 0; truelight@0: _tick_counter = 0; truelight@7018: _realtime_tick = 0; truelight@0: _date_fract = 0; truelight@0: _cur_tileloop_tile = 0; truelight@201: truelight@2828: if ((mode & IG_DATE_RESET) == IG_DATE_RESET) { rubidium@4295: SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1)); truelight@0: } truelight@0: peter1138@2848: InitializeEngines(); truelight@0: InitializeVehicles(); truelight@1542: InitializeWaypoints(); truelight@4347: InitializeDepots(); truelight@1024: InitializeOrders(); rubidium@6643: InitializeGroup(); truelight@0: truelight@0: InitNewsItemStructs(); ludde@2051: InitializeLandscape(); truelight@0: InitializeClearLand(); truelight@0: InitializeRailGui(); truelight@0: InitializeRoadGui(); truelight@0: InitializeAirportGui(); truelight@0: InitializeDockGui(); truelight@0: InitializeTowns(); truelight@0: InitializeTrees(); truelight@988: InitializeSigns(); truelight@0: InitializeStations(); rubidium@7010: InitializeCargoPackets(); truelight@0: InitializeIndustries(); maedhros@6332: InitializeBuildingCounts(); celestar@3622: InitializeMainGui(); truelight@201: truelight@0: InitializeNameMgr(); darkvater@164: InitializeVehiclesGuiList(); truelight@0: InitializeTrains(); matthijs@1247: InitializeNPF(); truelight@0: truelight@2706: AI_Initialize(); truelight@0: InitializePlayers(); truelight@0: InitializeCheats(); truelight@0: truelight@0: InitTextEffects(); rubidium@7454: InitChatMessage(); truelight@0: InitializeAnimatedTiles(); truelight@0: truelight@0: InitializeLandscapeVariables(false); truelight@0: truelight@0: ResetObjectToPlace(); truelight@0: } truelight@0: peter1138@4862: bool IsCustomName(StringID id) peter1138@4862: { peter1138@4862: return GB(id, 11, 5) == 15; peter1138@4862: } peter1138@4862: truelight@0: rubidium@6247: static void InitializeCheats() truelight@0: { truelight@201: memset(&_cheats, 0, sizeof(Cheats)); truelight@0: } truelight@0: truelight@0: rubidium@6247: static void InitializeNameMgr() truelight@0: { truelight@0: memset(_name_array, 0, sizeof(_name_array)); truelight@0: } truelight@0: peter1138@8258: /* Copy and convert old custom names to UTF-8 */ peter1138@8258: char *CopyFromOldName(StringID id) truelight@0: { peter1138@8258: if (!IsCustomName(id)) return NULL; truelight@0: peter1138@8258: if (CheckSavegameVersion(37)) { peter1138@8258: /* Old names were 32 characters long, so 128 characters should be peter1138@8258: * plenty to allow for expansion when converted to UTF-8. */ peter1138@8258: char tmp[128]; peter1138@8258: const char *strfrom = _name_array[GB(id, 0, 9)]; peter1138@5108: char *strto = tmp; peter1138@5108: peter1138@5108: for (; *strfrom != '\0'; strfrom++) { peter1138@5108: WChar c = (byte)*strfrom; peter1138@8258: peter1138@8258: /* Map from non-ISO8859-15 characters to UTF-8. */ peter1138@5108: switch (c) { peter1138@5108: case 0xA4: c = 0x20AC; break; // Euro peter1138@5108: case 0xA6: c = 0x0160; break; // S with caron peter1138@5108: case 0xA8: c = 0x0161; break; // s with caron peter1138@5108: case 0xB4: c = 0x017D; break; // Z with caron peter1138@5108: case 0xB8: c = 0x017E; break; // z with caron peter1138@5108: case 0xBC: c = 0x0152; break; // OE ligature peter1138@5108: case 0xBD: c = 0x0153; break; // oe ligature peter1138@5108: case 0xBE: c = 0x0178; break; // Y with diaresis peter1138@5108: default: break; peter1138@5108: } peter1138@8258: peter1138@8258: /* Check character will fit into our buffer. */ peter1138@5108: if (strto + Utf8CharLen(c) > lastof(tmp)) break; peter1138@8258: peter1138@5108: strto += Utf8Encode(strto, c); peter1138@5108: } peter1138@5108: peter1138@5108: /* Terminate the new string and copy it back to the name array */ peter1138@5108: *strto = '\0'; peter1138@8258: peter1138@8258: return strdup(tmp); peter1138@8258: } else { peter1138@8258: /* Name will already be in UTF-8. */ peter1138@8258: return strdup(_name_array[GB(id, 0, 9)]); peter1138@5108: } peter1138@5108: } peter1138@5108: belugas@6201: /* Calculate constants that depend on the landscape type. */ truelight@0: void InitializeLandscapeVariables(bool only_constants) truelight@0: { peter1138@6091: if (only_constants) return; truelight@201: peter1138@6350: for (CargoID i = 0; i < NUM_CARGO; i++) { peter1138@6091: _cargo_payment_rates[i] = GetCargo(i)->initial_payment; peter1138@6091: _cargo_payment_rates_frac[i] = 0; truelight@0: } truelight@0: } truelight@0: rubidium@6247: static void Load_NAME() truelight@0: { truelight@0: int index; truelight@201: truelight@0: while ((index = SlIterateArray()) != -1) { rubidium@6491: SlArray(_name_array[index], SlGetFieldLength(), SLE_UINT8); truelight@0: } truelight@0: } truelight@0: truelight@0: static const SaveLoadGlobVarList _date_desc[] = { truelight@4383: SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), truelight@4383: SLEG_CONDVAR(_date, SLE_INT32, 31, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_date_fract, SLE_UINT16), rubidium@4344: SLEG_VAR(_tick_counter, SLE_UINT16), rubidium@4344: SLEG_VAR(_vehicle_id_ctr_day, SLE_UINT16), rubidium@4344: SLEG_VAR(_age_cargo_skip_counter, SLE_UINT8), tron@5971: SLE_CONDNULL(1, 0, 45), rubidium@4344: SLEG_CONDVAR(_cur_tileloop_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), rubidium@4344: SLEG_CONDVAR(_cur_tileloop_tile, SLE_UINT32, 6, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_disaster_delay, SLE_UINT16), rubidium@4344: SLEG_VAR(_station_tick_ctr, SLE_UINT16), rubidium@4344: SLEG_VAR(_random_seeds[0][0], SLE_UINT32), rubidium@4344: SLEG_VAR(_random_seeds[0][1], SLE_UINT32), rubidium@4344: SLEG_CONDVAR(_cur_town_ctr, SLE_FILE_U8 | SLE_VAR_U32, 0, 9), rubidium@4344: SLEG_CONDVAR(_cur_town_ctr, SLE_UINT32, 10, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_cur_player_tick_index, SLE_FILE_U8 | SLE_VAR_U32), rubidium@4344: SLEG_VAR(_next_competitor_start, SLE_FILE_U16 | SLE_VAR_U32), rubidium@4344: SLEG_VAR(_trees_tick_ctr, SLE_UINT8), truelight@6231: SLEG_CONDVAR(_pause_game, SLE_UINT8, 4, SL_MAX_VERSION), rubidium@4344: SLEG_CONDVAR(_cur_town_iter, SLE_UINT32, 11, SL_MAX_VERSION), Darkvater@3046: SLEG_END() truelight@0: }; truelight@0: belugas@6201: /* Save load date related variables as well as persistent tick counters belugas@6201: * XXX: currently some unrelated stuff is just put here */ rubidium@6247: static void SaveLoad_DATE() truelight@0: { truelight@0: SlGlobList(_date_desc); truelight@0: } truelight@0: truelight@0: truelight@0: static const SaveLoadGlobVarList _view_desc[] = { rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_x, SLE_FILE_I16 | SLE_VAR_I32, 0, 5), rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_x, SLE_INT32, 6, SL_MAX_VERSION), rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_y, SLE_FILE_I16 | SLE_VAR_I32, 0, 5), rubidium@4344: SLEG_CONDVAR(_saved_scrollpos_y, SLE_INT32, 6, SL_MAX_VERSION), rubidium@4344: SLEG_VAR(_saved_scrollpos_zoom, SLE_UINT8), Darkvater@3046: SLEG_END() truelight@0: }; truelight@0: rubidium@6247: static void SaveLoad_VIEW() truelight@0: { truelight@0: SlGlobList(_view_desc); truelight@0: } truelight@0: tron@1218: static uint32 _map_dim_x; tron@1218: static uint32 _map_dim_y; tron@1218: tron@1218: static const SaveLoadGlobVarList _map_dimensions[] = { Darkvater@3046: SLEG_CONDVAR(_map_dim_x, SLE_UINT32, 6, SL_MAX_VERSION), Darkvater@3046: SLEG_CONDVAR(_map_dim_y, SLE_UINT32, 6, SL_MAX_VERSION), Darkvater@3046: SLEG_END() tron@1218: }; tron@1218: rubidium@6247: static void Save_MAPS() tron@1218: { tron@1219: _map_dim_x = MapSizeX(); tron@1219: _map_dim_y = MapSizeY(); tron@1218: SlGlobList(_map_dimensions); tron@1218: } tron@1218: rubidium@6247: static void Load_MAPS() tron@1218: { tron@1218: SlGlobList(_map_dimensions); ludde@2051: AllocateMap(_map_dim_x, _map_dim_y); tron@1218: } tron@1218: rubidium@6247: static void Load_MAPT() ludde@2050: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].type_height = buf[j]; truelight@817: } truelight@0: } truelight@0: rubidium@6247: static void Save_MAPT() tron@1093: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].type_height; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } truelight@0: } truelight@0: rubidium@6247: static void Load_MAP1() tron@1093: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2360: for (j = 0; j != lengthof(buf); j++) _m[i++].m1 = buf[j]; tron@2295: } tron@2295: } tron@2295: rubidium@6247: static void Save_MAP1() tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2360: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m1; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } truelight@0: } truelight@0: rubidium@6247: static void Load_MAP2() tron@1093: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: tron@2049: for (i = 0; i != size;) { tron@2049: uint16 buf[4096]; tron@2049: uint j; tron@2049: tron@2049: SlArray(buf, lengthof(buf), tron@2049: /* In those versions the m2 was 8 bits */ truelight@2685: CheckSavegameVersion(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16 tron@2049: ); tron@2049: for (j = 0; j != lengthof(buf); j++) _m[i++].m2 = buf[j]; tron@2049: } tron@2049: } tron@2049: rubidium@6247: static void Save_MAP2() tron@2049: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: tron@2049: SlSetLength(size * sizeof(_m[0].m2)); tron@2049: for (i = 0; i != size;) { tron@2049: uint16 buf[4096]; tron@2049: uint j; tron@2049: tron@2049: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m2; tron@2049: SlArray(buf, lengthof(buf), SLE_UINT16); tron@2049: } tron@2049: } tron@2049: rubidium@6247: static void Load_MAP3() tron@2049: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].m3 = buf[j]; tron@2295: } tron@2049: } tron@2049: rubidium@6247: static void Save_MAP3() tron@2049: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m3; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } tron@2049: } tron@2049: rubidium@6247: static void Load_MAP4() tron@2049: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].m4 = buf[j]; tron@2295: } tron@2295: } tron@2295: rubidium@6247: static void Save_MAP4() tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m4; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } tron@2295: } tron@2295: rubidium@6247: static void Load_MAP5() tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: for (j = 0; j != lengthof(buf); j++) _m[i++].m5 = buf[j]; tron@2295: } tron@2295: } tron@2295: rubidium@6247: static void Save_MAP5() tron@2295: { tron@2295: uint size = MapSize(); tron@2295: uint i; tron@2295: tron@2295: SlSetLength(size); tron@2295: for (i = 0; i != size;) { tron@2295: byte buf[4096]; tron@2295: uint j; tron@2295: tron@2295: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m5; tron@2295: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2295: } tron@2049: } tron@2049: rubidium@6247: static void Load_MAP6() tron@2049: { belugas@5596: /* Still available for loading old games */ tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: celestar@5385: if (CheckSavegameVersion(42)) { celestar@5385: for (i = 0; i != size;) { celestar@5385: uint8 buf[1024]; celestar@5385: uint j; tron@2049: celestar@5385: SlArray(buf, lengthof(buf), SLE_UINT8); celestar@5385: for (j = 0; j != lengthof(buf); j++) { belugas@5596: _m[i++].m6 = GB(buf[j], 0, 2); belugas@5596: _m[i++].m6 = GB(buf[j], 2, 2); belugas@5596: _m[i++].m6 = GB(buf[j], 4, 2); belugas@5596: _m[i++].m6 = GB(buf[j], 6, 2); celestar@5385: } celestar@5385: } celestar@5385: } else { celestar@5385: for (i = 0; i != size;) { celestar@5385: byte buf[4096]; celestar@5385: uint j; celestar@5385: celestar@5385: SlArray(buf, lengthof(buf), SLE_UINT8); belugas@5596: for (j = 0; j != lengthof(buf); j++) _m[i++].m6 = buf[j]; tron@2049: } tron@2049: } tron@2049: } tron@2049: rubidium@6247: static void Save_MAP6() tron@2049: { tron@2049: uint size = MapSize(); tron@2049: uint i; tron@2049: celestar@5385: SlSetLength(size); tron@2049: for (i = 0; i != size;) { celestar@5385: uint8 buf[4096]; tron@2049: uint j; tron@2049: belugas@5596: for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m6; tron@2049: SlArray(buf, lengthof(buf), SLE_UINT8); tron@2049: } truelight@0: } truelight@0: maedhros@6332: static void Load_MAP7() maedhros@6332: { maedhros@6332: uint size = MapSize(); maedhros@6332: uint i; maedhros@6332: maedhros@6332: for (i = 0; i != size;) { maedhros@6332: uint8 buf[4096]; maedhros@6332: uint j; maedhros@6332: maedhros@6332: SlArray(buf, lengthof(buf), SLE_UINT8); maedhros@6332: for (j = 0; j != lengthof(buf); j++) _me[i++].m7 = buf[j]; maedhros@6332: } maedhros@6332: } maedhros@6332: maedhros@6332: static void Save_MAP7() maedhros@6332: { maedhros@6332: uint size = MapSize(); maedhros@6332: uint i; maedhros@6332: maedhros@6332: SlSetLength(size); maedhros@6332: for (i = 0; i != size;) { maedhros@6332: uint8 buf[4096]; maedhros@6332: uint j; maedhros@6332: maedhros@6332: for (j = 0; j != lengthof(buf); j++) buf[j] = _me[i++].m7; maedhros@6332: SlArray(buf, lengthof(buf), SLE_UINT8); maedhros@6332: } maedhros@6332: } truelight@0: rubidium@6247: static void Save_CHTS() truelight@0: { truelight@0: byte count = sizeof(_cheats)/sizeof(Cheat); truelight@0: Cheat* cht = (Cheat*) &_cheats; truelight@0: Cheat* cht_last = &cht[count]; truelight@0: tron@2951: SlSetLength(count * 2); tron@2951: for (; cht != cht_last; cht++) { truelight@0: SlWriteByte(cht->been_used); truelight@0: SlWriteByte(cht->value); truelight@0: } truelight@0: } truelight@0: rubidium@6247: static void Load_CHTS() truelight@0: { tron@2989: Cheat* cht = (Cheat*)&_cheats; tron@2989: uint count = SlGetFieldLength() / 2; tron@2989: uint i; truelight@0: tron@2989: for (i = 0; i < count; i++) { rubidium@5587: cht[i].been_used = (SlReadByte() != 0); rubidium@5587: cht[i].value = (SlReadByte() != 0); truelight@0: } truelight@0: } truelight@0: truelight@0: rubidium@5587: extern const ChunkHandler _misc_chunk_handlers[] = { rubidium@4344: { 'MAPS', Save_MAPS, Load_MAPS, CH_RIFF }, rubidium@4344: { 'MAPT', Save_MAPT, Load_MAPT, CH_RIFF }, rubidium@4344: { 'MAPO', Save_MAP1, Load_MAP1, CH_RIFF }, rubidium@4344: { 'MAP2', Save_MAP2, Load_MAP2, CH_RIFF }, rubidium@4344: { 'M3LO', Save_MAP3, Load_MAP3, CH_RIFF }, rubidium@4344: { 'M3HI', Save_MAP4, Load_MAP4, CH_RIFF }, rubidium@4344: { 'MAP5', Save_MAP5, Load_MAP5, CH_RIFF }, belugas@5596: { 'MAPE', Save_MAP6, Load_MAP6, CH_RIFF }, maedhros@6332: { 'MAP7', Save_MAP7, Load_MAP7, CH_RIFF }, truelight@0: peter1138@8258: { 'NAME', NULL, Load_NAME, CH_ARRAY}, truelight@0: { 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF}, truelight@0: { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF}, rubidium@4344: { 'CHTS', Save_CHTS, Load_CHTS, CH_RIFF | CH_LAST} truelight@0: };