Merge branch 'master' into jgrpp

# Conflicts:
#	src/dock_gui.cpp
#	src/rail_gui.cpp
#	src/road_gui.cpp
#	src/terraform_gui.cpp
#	src/vehicle.cpp
#	src/video/allegro_v.cpp
#	src/video/cocoa/cocoa_v.mm
#	src/video/dedicated_v.cpp
#	src/video/sdl2_v.cpp
#	src/video/sdl_v.cpp
#	src/video/win32_v.cpp
pull/221/head
Jonathan G Rennison 3 years ago
commit dfecdf3afb

@ -923,7 +923,7 @@ static bool AircraftController(Aircraft *v)
SoundID sfx = AircraftVehInfo(v->engine_type)->sfx;
/* For compatibility with old NewGRF we ignore the sfx property, unless a NewGRF-defined sound is used.
* The baseset has only one helicopter sound, so this only limits using plane or cow sounds. */
if (sfx < ORIGINAL_SAMPLE_COUNT) sfx = SND_18_HELICOPTER;
if (sfx < ORIGINAL_SAMPLE_COUNT) sfx = SND_18_TAKEOFF_HELICOPTER;
SndPlayVehicleFx(sfx, v);
}
}

@ -44,7 +44,7 @@ void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32
{
if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
}

@ -62,7 +62,7 @@ typedef GUIList<BuildBridgeData> GUIBridgeList; ///< List of bridges, used in #B
void CcBuildBridge(const CommandCost &result, TileIndex end_tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, end_tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile);
TransportType transport_type = Extract<TransportType, 15, 2>(p2);

@ -98,7 +98,7 @@ CommandCallback CcBuildBridge;
/* dock_gui.cpp */
CommandCallback CcBuildDocks;
CommandCallback CcPlaySound_SPLAT_WATER;
CommandCallback CcPlaySound_CONSTRUCTION_WATER;
/* depot_gui.cpp */
CommandCallback CcCloneVehicle;
@ -123,13 +123,13 @@ CommandCallback CcGiveMoney;
CommandCallback CcAddPlan;
/* rail_gui.cpp */
CommandCallback CcPlaySound_SPLAT_RAIL;
CommandCallback CcPlaySound_CONSTRUCTION_RAIL;
CommandCallback CcRailDepot;
CommandCallback CcStation;
CommandCallback CcBuildRailTunnel;
/* road_gui.cpp */
CommandCallback CcPlaySound_SPLAT_OTHER;
CommandCallback CcPlaySound_CONSTRUCTION_OTHER;
CommandCallback CcBuildRoadTunnel;
CommandCallback CcRoadDepot;
CommandCallback CcRoadStop;

@ -42,13 +42,13 @@ void CcBuildDocks(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p
{
if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_02_SPLAT_WATER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_02_CONSTRUCTION_WATER, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
}
void CcPlaySound_SPLAT_WATER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
void CcPlaySound_CONSTRUCTION_WATER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_02_SPLAT_WATER, tile);
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_02_CONSTRUCTION_WATER, tile);
}
@ -245,10 +245,10 @@ struct BuildDocksToolbarWindow : Window {
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
break;
case DDSP_CREATE_WATER:
DoCommandP(end_tile, start_tile, (_game_mode == GM_EDITOR && _ctrl_pressed) ? WATER_CLASS_SEA : WATER_CLASS_CANAL, CMD_BUILD_CANAL | CMD_MSG(STR_ERROR_CAN_T_BUILD_CANALS), CcPlaySound_SPLAT_WATER);
DoCommandP(end_tile, start_tile, (_game_mode == GM_EDITOR && _ctrl_pressed) ? WATER_CLASS_SEA : WATER_CLASS_CANAL, CMD_BUILD_CANAL | CMD_MSG(STR_ERROR_CAN_T_BUILD_CANALS), CcPlaySound_CONSTRUCTION_WATER);
break;
case DDSP_CREATE_RIVER:
DoCommandP(end_tile, start_tile, WATER_CLASS_RIVER | (_ctrl_pressed ? 1 << 2 : 0), CMD_BUILD_CANAL | CMD_MSG(STR_ERROR_CAN_T_PLACE_RIVERS), CcPlaySound_SPLAT_WATER);
DoCommandP(end_tile, start_tile, WATER_CLASS_RIVER | (_ctrl_pressed ? 1 << 2 : 0), CMD_BUILD_CANAL | CMD_MSG(STR_ERROR_CAN_T_PLACE_RIVERS), CcPlaySound_CONSTRUCTION_WATER);
break;
default: break;

@ -524,7 +524,7 @@ static bool BubbleTick(EffectVehicle *v)
if (b->y == 4 && b->x == 1) {
if (v->z_pos > 180 || Chance16I(1, 96, Random())) {
v->spritenum = 5;
if (_settings_client.sound.ambient) SndPlayVehicleFx(SND_2F_POP, v);
if (_settings_client.sound.ambient) SndPlayVehicleFx(SND_2F_BUBBLE_GENERATOR_FAIL, v);
}
anim_state = 0;
}
@ -533,7 +533,7 @@ static bool BubbleTick(EffectVehicle *v)
TileIndex tile;
anim_state++;
if (_settings_client.sound.ambient) SndPlayVehicleFx(SND_31_EXTRACT, v);
if (_settings_client.sound.ambient) SndPlayVehicleFx(SND_31_BUBBLE_GENERATOR_SUCCESS, v);
tile = TileVirtXY(v->x_pos, v->y_pos);
if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile);

@ -572,8 +572,8 @@ void AnimateTile_Industry(TileIndex tile)
if (_settings_client.sound.ambient) {
switch (m & 7) {
case 2: SndPlayTileFx(SND_2D_RIP_2, tile); break;
case 6: SndPlayTileFx(SND_29_RIP, tile); break;
case 2: SndPlayTileFx(SND_2D_SUGAR_MINE_1, tile); break;
case 6: SndPlayTileFx(SND_29_SUGAR_MINE_2, tile); break;
}
}
@ -592,7 +592,7 @@ void AnimateTile_Industry(TileIndex tile)
byte m = GetAnimationFrame(tile);
if (_industry_anim_offs_toffee[m] == 0xFF && _settings_client.sound.ambient) {
SndPlayTileFx(SND_30_CARTOON_SOUND, tile);
SndPlayTileFx(SND_30_TOFFEE_QUARRY, tile);
}
if (++m >= 70) {
@ -638,9 +638,9 @@ void AnimateTile_Industry(TileIndex tile)
byte m = GetAnimationFrame(tile) + 1;
switch (m) {
case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_MACHINERY, tile); break;
case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_COMEDY_HIT, tile); break;
case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_EXTRACT_AND_POP, tile); break;
case 1: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2C_TOY_FACTORY_1, tile); break;
case 23: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2B_TOY_FACTORY_2, tile); break;
case 28: if (_settings_client.sound.ambient) SndPlayTileFx(SND_2A_TOY_FACTORY_3, tile); break;
default:
if (m >= 50) {
int n = GetIndustryAnimationLoop(tile) + 1;
@ -703,7 +703,7 @@ void AnimateTile_Industry(TileIndex tile)
byte m = GetAnimationFrame(tile);
if (!(m & 0x40)) {
SetAnimationFrame(tile, m | 0x40);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINING_MACHINERY, tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0B_MINE, tile);
}
if (state & 7) return;
} else {
@ -845,7 +845,7 @@ static void TileLoopIndustry_BubbleGenerator(TileIndex tile)
{ 49, 59, 60, 65 },
};
if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_2E_BUBBLE_GENERATOR, tile);
int dir = Random() & 3;
@ -943,7 +943,7 @@ static void TileLoop_Industry(TileIndex tile)
case GFX_POWERPLANT_SPARKS:
if (Chance16(1, 3)) {
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_ELECTRIC_SPARK, tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_0C_POWER_STATION, tile);
AddAnimatedTile(tile);
}
break;
@ -1142,7 +1142,7 @@ static bool SearchLumberMillTrees(TileIndex tile, void *user_data)
_industry_sound_ctr = 1;
_industry_sound_tile = tile;
if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_CHAINSAW, tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_38_LUMBER_MILL_1, tile);
DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
@ -1264,10 +1264,10 @@ void OnTick_Industry()
_industry_sound_ctr++;
if (_industry_sound_ctr == 75) {
if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_BALLOON_SQUEAK, _industry_sound_tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_37_LUMBER_MILL_2, _industry_sound_tile);
} else if (_industry_sound_ctr == 160) {
_industry_sound_ctr = 0;
if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_CARTOON_CRASH, _industry_sound_tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_36_LUMBER_MILL_3, _industry_sound_tile);
}
}

@ -382,7 +382,7 @@ STR_GROUP_BY_NONE :Puudub
STR_GROUP_BY_SHARED_ORDERS :Jagatud korraldused
# Tooltips for the main toolbar
STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}Seiska mäng
STR_TOOLBAR_TOOLTIP_PAUSE_GAME :{BLACK}Mängu paus
STR_TOOLBAR_TOOLTIP_FORWARD :{BLACK}Kiirenda mängu
STR_TOOLBAR_TOOLTIP_OPTIONS :{BLACK}Seadistus
STR_TOOLBAR_TOOLTIP_SAVE_GAME_ABANDON_GAME :{BLACK}Mängu salvestamine/jätkamine, mängust lahkumine, väljumine
@ -665,14 +665,14 @@ STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP :{BLACK}Klõpsa,
STR_COMPANY_LEAGUE_TABLE_CAPTION :{WHITE}Ettevõtete edetabel
STR_COMPANY_LEAGUE_COMPANY_NAME :{ORANGE}{COMPANY} {BLACK}{COMPANY_NUM} '{STRING}'
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER :Insener
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER :Liiklusmänedžer
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR :Transpordi koordineerija
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR :Liiniinspektor
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER :Liikluskorraldaja
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRANSPORT_COORDINATOR :Transpordikorraldaja
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ROUTE_SUPERVISOR :Logistik
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_DIRECTOR :Direktor
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHIEF_EXECUTIVE :Tegevjuht
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_CHAIRMAN :Esimees
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_PRESIDENT :President
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON :Magnaat
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TYCOON :Ärioligarh
# Performance detail window
STR_PERFORMANCE_DETAIL :{WHITE}Täpsustatud tulemushinnang
@ -753,13 +753,13 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Vajuta l
STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK}Parimad ettevõtted aastal {NUM}
STR_HIGHSCORE_TOP_COMPANIES_NETWORK_GAME :{BIG_FONT}{BLACK}Ettevõtete edetabelis {NUM} kohal
STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}.
STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Ärimees
STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Äriinimene
STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Ettevõtja
STR_HIGHSCORE_PERFORMANCE_TITLE_INDUSTRIALIST :Tööstur
STR_HIGHSCORE_PERFORMANCE_TITLE_CAPITALIST :Kapitalist
STR_HIGHSCORE_PERFORMANCE_TITLE_MAGNATE :Magnaat
STR_HIGHSCORE_PERFORMANCE_TITLE_MOGUL :Mogul
STR_HIGHSCORE_PERFORMANCE_TITLE_TYCOON_OF_THE_CENTURY :Sajandi suurärimees
STR_HIGHSCORE_PERFORMANCE_TITLE_TYCOON_OF_THE_CENTURY :Sajandi ärioligarh
STR_HIGHSCORE_NAME :{PRESIDENT_NAME}, {COMPANY}
STR_HIGHSCORE_STATS :{BIG_FONT}'{STRING}' ({COMMA})
STR_HIGHSCORE_COMPANY_ACHIEVES_STATUS :{BIG_FONT}{BLACK}{COMPANY} saavutas '{STRING}' staatuse!
@ -1004,6 +1004,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :Uus Taiwani dol
STR_GAME_OPTIONS_CURRENCY_CNY :Hiina renminbi (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Hong Kongi dollar (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :India ruupia (INR)
STR_GAME_OPTIONS_CURRENCY_IDR :Indoneesia ruupia (IDR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Vasakpoolne liiklus
@ -1060,6 +1061,7 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :muu
STR_GAME_OPTIONS_GUI_ZOOM_FRAME :{BLACK}Liidese suurus
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Vali kasutatav liideseelementide suurus
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_AUTO :(automaattuvastus)
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL :Tavaline
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM :Topeltsuurus
STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Neljakordne suurus
@ -1067,6 +1069,7 @@ STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM :Neljakordne suu
STR_GAME_OPTIONS_FONT_ZOOM :{BLACK}Kirja suurus
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP :{BLACK}Vali kasutatav liideseelementide suurus
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_AUTO :(automaattuvastus)
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL :Tavaline
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM :Topeltsuurus
STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM :Neljakordne suurus
@ -1208,7 +1211,7 @@ STR_CONFIG_SETTING_CATEGORY_AND_TYPE_HIDES :{BLACK}Kõiki o
STR_CONFIG_SETTINGS_NONE :{WHITE}- Puudub -
STR_CONFIG_SETTING_OFF :Väljas
STR_CONFIG_SETTING_ON :Sees
STR_CONFIG_SETTING_ON :Peal
STR_CONFIG_SETTING_DISABLED :väljas
STR_CONFIG_SETTING_COMPANIES_OFF :Väljas
@ -1246,8 +1249,8 @@ STR_CONFIG_SETTING_DISASTERS_HELPTEXT :Lülita sisse/v
STR_CONFIG_SETTING_CITY_APPROVAL :Astuse omavalitsuse suhtumine pinnase restruktureerimisse: {STRING}
STR_CONFIG_SETTING_CITY_APPROVAL_HELPTEXT :Vali kui suurt mõju tekitavad müra ning keskkonna muudatused ettevõtte mainele ja edasistele ehitustoimingutele antud piirkonnas
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL :Maksimaalne mägede kõrgus: {STRING}
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL_HELPTEXT :Sätesta kaardi maksimaalne lubatud mägede kõrgus
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL :Kaardi ülemkõrgus: {STRING}
STR_CONFIG_SETTING_MAX_HEIGHTLEVEL_HELPTEXT :Sea kaardil paiknevatele mägedele ülemine kõrguspiir
STR_CONFIG_SETTING_TOO_HIGH_MOUNTAIN :{WHITE}Kaardi maksimaalset kõrgust pole sellisele kõrgusele võimalik sätestada. Vähemalt üks mägi on antud kõrgusest suurem.
STR_CONFIG_SETTING_AUTOSLOPE :Maastikukujundus majade, rööbaste jms. all (autoslope): {STRING}
STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Lase maja- ja rööpaalust maad kujundada ilma neid eemaldamata
@ -1277,12 +1280,12 @@ STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS :Mitte kõrvuti
STR_CONFIG_SETTING_DISTANT_JOIN_STATIONS_HELPTEXT :Lubab lisada uusi jaamade osi ilma puudutamata olemasolevaid osi. Vajalik Ctrl+Vajutus, kui asetada uut osa
STR_CONFIG_SETTING_INFLATION :Inflatsioon: {STRING}
STR_CONFIG_SETTING_INFLATION_HELPTEXT :Tekitab majandusinflatsiooni, kus hinnad tõusevad pisut kiiremini kui maksed
STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH :Maksimaalne silla pikkus: {STRING}
STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH_HELPTEXT :Maksimaalne pikkus ehitatud sildadele
STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT :Maksimaalne silla kõrgus: {STRING}
STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT_HELPTEXT :Maksimaalne sildade ehitamise kõrgus
STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH :Maksimaalne tunneli pikkus: {STRING}
STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH_HELPTEXT :Maksimaalne pikkus ehitatud tunnelitele
STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH :Sildade ülempikkus: {STRING}
STR_CONFIG_SETTING_MAX_BRIDGE_LENGTH_HELPTEXT :Ülempikkus sildade ehitamisele
STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT :Sildade ülemkõrgus: {STRING}
STR_CONFIG_SETTING_MAX_BRIDGE_HEIGHT_HELPTEXT :Ülemkõrgus sildade ehitamisele
STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH :Tunnelite ülempikkus: {STRING}
STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH_HELPTEXT :Ülempikkus tunnelite ehitamisele
STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD :Toorainetööstuse rajamise viis: {STRING}
STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :Toorainetööstuse rajamise viis. Valides 'pole' ei saa üldse toorainetööstuseid rajada, 'uuringutega' rajatakse tööstus suvalisse kohta, ning 'nagu kõik tööstused' ehitatakse toorainetööstuseid nagu töötlevat tööstust
STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE :Pole
@ -1308,7 +1311,7 @@ STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :keskel
STR_CONFIG_SETTING_STOP_LOCATION_FAR_END :lõpus
STR_CONFIG_SETTING_AUTOSCROLL :Vaade liigub, kui hiireosuti on servas: {STRING}
STR_CONFIG_SETTING_AUTOSCROLL_HELPTEXT :Sisse lülitamisel liigub vaade, kui hiireosuti on aknaserva lähedal
STR_CONFIG_SETTING_AUTOSCROLL_DISABLED :Väljas
STR_CONFIG_SETTING_AUTOSCROLL_DISABLED :Ei võimalda
STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Põhivaates, ainult täisekraaniga
STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Põhivaates
STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :Igas vaates
@ -1359,12 +1362,12 @@ STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Sõidukid ei ae
STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :Kui on aktiveeritud, siis jäävad kõik sõidukite tüübid igavesti avatuks
STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Vananenud sõidukite uuendamine: {STRING}
STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :Kui on sisse lülitatud, siis uuendatalse kõik kasutusaja lõpu lähedal olevad sõidukid automaatselt, järgides uuendamise tingimusi
STR_CONFIG_SETTING_AUTORENEW_MONTHS :Automaatne sõiduki uuendamine kui sõduk on {STRING} maksimaalse vanuse
STR_CONFIG_SETTING_AUTORENEW_MONTHS :Sõiduk uuendatakse automaatselt {STRING} sõiduki ülemvanust
STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT :Relatiivne sõiduki iga mille järel on peaks sõiduk saama automaatselt uuendatud
STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE :{COMMA} kuu{P 0 "" d} enne
STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_AFTER :{COMMA} kuu{P 0 "" d} pärast
STR_CONFIG_SETTING_AUTORENEW_MONEY :Nõutud rahasumma uuendamiseks: {STRING}
STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT :Pangakontol oleva raha alammäär sõidukite uuendamiseks
STR_CONFIG_SETTING_AUTORENEW_MONEY :Saldo alampiir automaatsete uuendamiste jaoks: {STRING}
STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT :Väikseim pangasaldo, mis arvel peab olema, enne kui sõidukeid hakatakse automaatselt uuendama
STR_CONFIG_SETTING_ERRMSG_DURATION :Veateadete kestvus: {STRING}
STR_CONFIG_SETTING_ERRMSG_DURATION_HELPTEXT :Punases aknas olevate veateadete näitamise kestvus. On ka mõned (tähtsad) veateated, mis ise ei sulgu, vaid mis tuleb käsitsi sulgeda
STR_CONFIG_SETTING_ERRMSG_DURATION_VALUE :{COMMA} sekund{P 0 "" it}
@ -1477,14 +1480,14 @@ STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_LONG :pikka (31. dets
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_SHORT :lühikest (31-12-2008)
STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_ISO :ISO (2008-12-31)
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME :Mängu alguses mäng seisab: {STRING}
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Sisse lülitamisel mängu alguses aeg seisab, et oleks rohkem aega kaardiga tutvuda
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Lubatud seisaku ajal: {STRING}
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT :Vali tegevuseg millede teostamine on lubatud mängu pausi ajal
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :Mitte ükski toiming
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :Kõik mitte-ehituslikud toimingud
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :Kõik peale maastikku muutvate toimingute
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :Kõik tõimingud
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME :Uus mäng algab pausiga: {STRING}
STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Kui võimaldatud, siis uus mäng algab automaatselt pausiga, et anda kaardiga tutvumiseks aega
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Pausi ajal on lubatud: {STRING}
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT :Vali, mis tegevusi saab pausi ajal teha
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :Mitte ükski tegevus
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_CONSTRUCTION :Kõik tegevused peale ehitamise
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_NON_LANDSCAPING :Kõik tegevused peale maastikukujunduse
STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_ALL_ACTIONS :Kõik tegevused
STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS :Põhjalikku sõidukiregistrit näidatakse: {STRING}
STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Laseb kasutada põhjalikke sõidukiregistreid sõidukite jaotamiseks
STR_CONFIG_SETTING_LOADING_INDICATORS :Kasuta laadimisnäidikuid: {STRING}
@ -1677,8 +1680,8 @@ STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Lineaarne
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT :Mängu jooksul kasvavad puud: {STRING}
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_HELPTEXT :Juhib suvalist puude kasvu mängu jooksul. See seade võib mõjutada osade tööstuste tööd, mis sõltuvad puude kasvust (näiteks saekaater)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Kasvab, aga ei laiene {RED}(saeveski kasutamatu)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :Kasvab, kuid laieneb vaid vihmametsas
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_SPREAD :Kasvavad, aga ei laiene {RED}(saeveski kasutamatu)
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_RAINFOREST :Kasvavad, kuid laienevad vaid vihmametsas
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_SPREAD_ALL :Kasvab ja laieneb kõikjal
STR_CONFIG_SETTING_EXTRA_TREE_PLACEMENT_NO_GROWTH_NO_SPREAD :Ei kasva, ei laiene {RED}(saeveski kasutamatu)
@ -1875,7 +1878,7 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Otsi all
STR_INTRO_TOOLTIP_SCRIPT_SETTINGS :{BLACK}Ava AI/GameScripti seaded
STR_INTRO_TOOLTIP_QUIT :{BLACK}Välju 'OpenTTD'st
STR_INTRO_BASESET :{BLACK}Hetkel valitud lähtegraafikakogust puudub {NUM} sprite{P "" 'i}. Kontrolli, kas lähtekogu on uuendatud.
STR_INTRO_BASESET :{BLACK}Hetkel valitud lähtegraafikakogust puudub {NUM} sprite{P "" 'i}. Kontrolli, kas lähtekogule on uuendusi.
STR_INTRO_TRANSLATION :{BLACK}Puudub {NUM} tõlge{P "" t}. Aita teha OpenTTD paremaks, panusta tõlkimisega. Rohkem teavet leiad «readme.txt» failist.
# Quit window
@ -1898,8 +1901,8 @@ STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Mängim
STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Võlubuldooser (eemaldab tööstused, paiksed objektid): {ORANGE}{STRING}
STR_CHEAT_CROSSINGTUNNELS :{LTBLUE}Tunnelid võivad üksteist läbida: {ORANGE}{STRING}
STR_CHEAT_NO_JETCRASH :{LTBLUE}Reaktiivlennukid ei kuku (tihti) väikestel lennuväljadel alla: {ORANGE} {STRING}
STR_CHEAT_EDIT_MAX_HL :{LTBLUE}Muuda maksimaalset kaardi kõrgust {ORANGE}{NUM}
STR_CHEAT_EDIT_MAX_HL_QUERY_CAPT :{WHITE}Muuda kaardi maksimaalset mägede kõrgust
STR_CHEAT_EDIT_MAX_HL :{LTBLUE}Muuda kaardi ülemkõrgust {ORANGE}{NUM}
STR_CHEAT_EDIT_MAX_HL_QUERY_CAPT :{WHITE}Muuda kaardil olevate mägede ülemkõrgust
STR_CHEAT_SWITCH_CLIMATE_TEMPERATE_LANDSCAPE :Parasvöötme maastik
STR_CHEAT_SWITCH_CLIMATE_SUB_ARCTIC_LANDSCAPE :Arktiline maastik
STR_CHEAT_SWITCH_CLIMATE_SUB_TROPICAL_LANDSCAPE :Troopiline maastik
@ -2037,7 +2040,7 @@ STR_NETWORK_SERVER_LIST_CURRENT_DATE :{SILVER}Aeg het
STR_NETWORK_SERVER_LIST_PASSWORD :{SILVER}Kaitstud salasõnaga!
STR_NETWORK_SERVER_LIST_SERVER_OFFLINE :{SILVER}SERVER ON MAAS
STR_NETWORK_SERVER_LIST_SERVER_FULL :{SILVER}SERVER ON TÄIS
STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}OSAD EI SOBI
STR_NETWORK_SERVER_LIST_VERSION_MISMATCH :{SILVER}ÜHILDUMATUD VERSIOONID
STR_NETWORK_SERVER_LIST_GRF_MISMATCH :{SILVER}NEWGRF SOBIMATUS
STR_NETWORK_SERVER_LIST_JOIN_GAME :{BLACK}Liitu mänguga
@ -2308,11 +2311,11 @@ STR_CONTENT_SELECT_UPDATES_CAPTION :{BLACK}Märgi u
STR_CONTENT_SELECT_UPDATES_CAPTION_TOOLTIP :{BLACK}Märgi kõik aineste uuendused allalaadimiseks
STR_CONTENT_UNSELECT_ALL_CAPTION :{BLACK}Eemalda märgistus kõigilt
STR_CONTENT_UNSELECT_ALL_CAPTION_TOOLTIP :{BLACK}Eemaldatakse allalaadimise märgistus
STR_CONTENT_SEARCH_EXTERNAL :{BLACK}Otsi kolmandatest lehtedest
STR_CONTENT_SEARCH_EXTERNAL :{BLACK}Otsi välistest veebilehtedest
STR_CONTENT_SEARCH_EXTERNAL_TOOLTIP :{BLACK}Otsi OpenTTD-st sõltumatutest lehtedest aineseid, mida OpenTTD aineste keskserverist ei saa
STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER_CAPTION :{WHITE}Sa oled lahkumas OpenTTD-st!
STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER :{WHITE}Kolmandatest lehtedest allalaadimise tingimused sõltuvad lehest.{}Aineste paigaldamisel kasutada kolmandate lehtede juhiseid.{}Kas jätkata?
STR_CONTENT_FILTER_TITLE :{BLACK}Sildi- ja nimefilter:
STR_CONTENT_SEARCH_EXTERNAL_DISCLAIMER :{WHITE}Välistest veebilehtedest aineste allalaadimisel võivad kasutustingimused vahelduda.{}Paigaldusjuhiseid otsida samadest välistest veebilehtedest.{}Kas jätkata?
STR_CONTENT_FILTER_TITLE :{BLACK}Siltide/nimede märksõna:
STR_CONTENT_OPEN_URL :{BLACK}Külasta lehekülge
STR_CONTENT_OPEN_URL_TOOLTIP :{BLACK}Külasta lehekülge selle sisu jaoks.
STR_CONTENT_DOWNLOAD_CAPTION :{BLACK}Laadi alla
@ -2326,11 +2329,11 @@ STR_CONTENT_DETAIL_SUBTITLE_ALREADY_HERE :{SILVER}Sul on
STR_CONTENT_DETAIL_SUBTITLE_DOES_NOT_EXIST :{SILVER}See ei ole ainesena tuvastatav, seega OpenTTD ei saa seda alla laadida
STR_CONTENT_DETAIL_UPDATE :{SILVER}See on asendus olemasolevale {STRING}
STR_CONTENT_DETAIL_NAME :{SILVER}Nimi: {WHITE}{STRING}
STR_CONTENT_DETAIL_VERSION :{SILVER}Osa: {WHITE}{STRING}
STR_CONTENT_DETAIL_VERSION :{SILVER}Versioon: {WHITE}{STRING}
STR_CONTENT_DETAIL_DESCRIPTION :{SILVER}Seletus: {WHITE}{STRING}
STR_CONTENT_DETAIL_URL :{SILVER}Aadress: {WHITE}{STRING}
STR_CONTENT_DETAIL_TYPE :{SILVER}Liik: {WHITE}{STRING}
STR_CONTENT_DETAIL_FILESIZE :{SILVER}Faili maht: {WHITE}{BYTES}
STR_CONTENT_DETAIL_FILESIZE :{SILVER}Allalaadimise suurus: {WHITE}{BYTES}
STR_CONTENT_DETAIL_SELECTED_BECAUSE_OF :{SILVER}Valitud kuna: {WHITE}{STRING}
STR_CONTENT_DETAIL_DEPENDENCIES :{SILVER}Sõltuvused: {WHITE}{STRING}
STR_CONTENT_DETAIL_TAGS :{SILVER}Sildid: {WHITE}{STRING}
@ -2662,12 +2665,18 @@ STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM :{BLACK}Suvaline
# Fund new industry window
STR_FUND_INDUSTRY_CAPTION :{WHITE}Uue tööstuse rahastamine
STR_FUND_INDUSTRY_SELECTION_TOOLTIP :{BLACK}Vali siit nimistust sobiv tööstus
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :Palju suvalisi tööstusi
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES :{BLACK}Tekita suvalised tööstused
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Katab kaardi suvaliselt paigutatud tööstustega
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Tekita suvalised tööstused
STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Kas oled kindel, et sa tahad tekitada palju suvalisi tööstuseid?
STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Hind: {YELLOW}{CURRENCY_LONG}
STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Rahasta
STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Ehita
STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Rahasta
STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Kõrvalda kõik tööstused
STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_TOOLTIP :{BLACK}Kõrvalda kõik hetkel kaardil asuvad tööstused
STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_CAPTION :{WHITE}Kõrvalda kõik tööstused
STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Kas oled kindel, et sa tahad kõrvaldada kõik tööstused?
# Industry cargoes window
STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Tööstuse {STRING} tööstusahel
@ -2810,7 +2819,7 @@ STR_LAI_OBJECT_DESCRIPTION_COMPANY_OWNED_LAND :Ettevõtte maa
# About OpenTTD window
STR_ABOUT_OPENTTD :{WHITE}OpenTTD lisainfo
STR_ABOUT_ORIGINAL_COPYRIGHT :{BLACK}Algne autorikaitse {COPYRIGHT} 1995 Chris Sawyer, kõik õigused kaitstud
STR_ABOUT_VERSION :{BLACK}OpenTTD osa {REV}
STR_ABOUT_VERSION :{BLACK}OpenTTD versioon {REV}
STR_ABOUT_COPYRIGHT_OPENTTD :{BLACK}OpenTTD {COPYRIGHT}2002-{STRING} OpenTTD meeskond
# Framerate display window
@ -2898,6 +2907,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF:
STR_SAVELOAD_FILTER_TITLE :{BLACK}Märksõna:
STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Ülekirjuta fail
STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Kas oled kindel, et soovid olemasoleva faili üle kirjutada?
STR_SAVELOAD_DIRECTORY :{STRING} (Kataloog)
STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Ülemkataloog)
STR_SAVELOAD_OSKTITLE :{BLACK}Sisesta salvestatavale mängule nimi
@ -2909,7 +2920,7 @@ STR_MAPGEN_BY :{BLACK}*
STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Asustusi:
STR_MAPGEN_DATE :{BLACK}Algus:
STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Tööstuste sagedus:
STR_MAPGEN_MAX_HEIGHTLEVEL :{BLACK}Maksimaalne kaardi kõrgus:
STR_MAPGEN_MAX_HEIGHTLEVEL :{BLACK}Kaardi ülemkõrgus:
STR_MAPGEN_MAX_HEIGHTLEVEL_UP :{BLACK}Tõsta maksimaalset kaardi mägede kõrgust ühe võrra
STR_MAPGEN_MAX_HEIGHTLEVEL_DOWN :{BLACK}Langeta maksimaalset kaardi mägede kõrgust ühe võrra
STR_MAPGEN_SNOW_LINE_HEIGHT :{BLACK}Lumepiiri kõrgus:
@ -3011,7 +3022,7 @@ STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP :{BLACK}Proovi p
STR_NEWGRF_SETTINGS_FILENAME :{BLACK}Faili nimi: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_GRF_ID :{BLACK}GRF ID: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_VERSION :{BLACK}Versioon: {SILVER}{NUM}
STR_NEWGRF_SETTINGS_MIN_VERSION :{BLACK}Min. ühilduv versioon: {SILVER}{NUM}
STR_NEWGRF_SETTINGS_MIN_VERSION :{BLACK}Vanim ühilduv versioon: {SILVER}{NUM}
STR_NEWGRF_SETTINGS_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE :{BLACK}Palett: {SILVER}{STRING}
STR_NEWGRF_SETTINGS_PALETTE_DEFAULT :Vaikimisi (D)
@ -3081,13 +3092,13 @@ STR_NEWGRF_ERROR_MSG_WARNING :{RED}Hoiatus: {
STR_NEWGRF_ERROR_MSG_ERROR :{RED}Viga: {SILVER}{STRING}
STR_NEWGRF_ERROR_MSG_FATAL :{RED}Saatuslik viga: {SILVER}{STRING}
STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Esines raske NewGRF-i tõrge:{}{STRING}
STR_NEWGRF_ERROR_VERSION_NUMBER :OpenTTD väitel {1:STRING} ei tööta selle TTDPatch osaga.
STR_NEWGRF_ERROR_VERSION_NUMBER :OpenTTD väitel {1:STRING} ei tööta selle TTDPatch versiooniga.
STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} on {STRING} TTD osa jaoks.
STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} on mõeldud kasutamiseks {STRING}
STR_NEWGRF_ERROR_INVALID_PARAMETER :kõlbmatu «{1:STRING}» parameeter: parameeter {STRING} ({NUM})
STR_NEWGRF_ERROR_LOAD_BEFORE :{1:STRING} peab olema laetud enne {STRING}
STR_NEWGRF_ERROR_LOAD_AFTER :{1:STRING} peab olema laetud pärast {STRING}
STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER :{1:STRING} nõuab OpenTTD osa {STRING} või uuemat
STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER :{1:STRING} nõuab OpenTTD versiooni {STRING} või uuemat
STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE :GRF fail, mis tehti tõlkimiseks,
STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED :Liiga palju NewGRF-e on laaditud
STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC :Laadides {1:STRING} staatilise NewGRF-na koos {STRING} võib põhjustada sünkrooni katkemist.
@ -4145,8 +4156,8 @@ STR_TIMETABLE_TRAVEL_FOR :Sõida {STRING}
STR_TIMETABLE_TRAVEL_FOR_SPEED :Reisi selleks {STRING} kõige rohkema {VELOCITY}
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Sõit ({STRING}, ei ole ajastatud)
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Sõit ({STRING}, ei ole ajastatud) kuni {VELOCITY}
STR_TIMETABLE_STAY_FOR_ESTIMATED :({STRING} oode, ei ole ajastatud)
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :({STRING} sõidukestus, ei ole ajastatud)
STR_TIMETABLE_STAY_FOR_ESTIMATED :(Oode {STRING}, ajastamata)
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :({STRING} sõidukestus, ajastamata)
STR_TIMETABLE_STAY_FOR :ja oota {STRING}
STR_TIMETABLE_AND_TRAVEL_FOR :ja sõida {STRING} jaoks
STR_TIMETABLE_DAYS :{COMMA} päev{P "" a}
@ -4176,10 +4187,10 @@ STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Muuda m
STR_TIMETABLE_CLEAR_SPEED :{BLACK}Kustuta kiiruspiirang
STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Eemalda märgitud korralduse kiiruspiirang
STR_TIMETABLE_RESET_LATENESS :{BLACK}Tühista hilinemisarvesti
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Tühista hilinemisarvesti, et sõiduk ei jääks hiljaks
STR_TIMETABLE_RESET_LATENESS :{BLACK}Nulli hilinemisarvesti
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Nulli hilinemisarvesti, nii et sõiduk oleks graafikus
STR_TIMETABLE_AUTOFILL :{BLACK}Täida ise
STR_TIMETABLE_AUTOFILL :{BLACK}Isetäituv
STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Kasuta liiniplaani täitmiseks järgmise sõidu andmeid (Ctrl+klõps säilitab ooteajad)
STR_TIMETABLE_EXPECTED :{BLACK}Eeldatav
@ -4207,7 +4218,7 @@ STR_AI_DEBUG_SETTINGS :{BLACK}Seaded
STR_AI_DEBUG_SETTINGS_TOOLTIP :{BLACK}Skripti seadistamine
STR_AI_DEBUG_RELOAD :{BLACK}Laadi AI uuesti
STR_AI_DEBUG_RELOAD_TOOLTIP :{BLACK}Sulge AI, laadi skript uuesti ning taaskäivita AI
STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP :{BLACK}Enable/disable breaking when an AI log message matches the break string
STR_AI_DEBUG_BREAK_STR_ON_OFF_TOOLTIP :{BLACK}Võimalda/ei võimalda peatamist kui AI logisõnum sisaldab peatamiskirjet
STR_AI_DEBUG_BREAK_ON_LABEL :{BLACK}Vahe sees:
STR_AI_DEBUG_BREAK_STR_OSKTITLE :{BLACK}Vahe sees
STR_AI_DEBUG_BREAK_STR_TOOLTIP :{BLACK}Kui AI logi sõnum vastab selle stringiga, mäng seisatakse.

@ -696,7 +696,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Poista m
STR_HIGHSCORE_TOP_COMPANIES_WHO_REACHED :{BIG_FONT}{BLACK}Parhaat yhtiöt, jotka saavuttivat vuoden {NUM}
STR_HIGHSCORE_TOP_COMPANIES_NETWORK_GAME :{BIG_FONT}{BLACK}Yhtiökilpailutaulukko vuonna {NUM}
STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}.
STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Liikemies
STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Kaupantekijä
STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Yrittäjä
STR_HIGHSCORE_PERFORMANCE_TITLE_INDUSTRIALIST :Teollisuudenharjoittaja
STR_HIGHSCORE_PERFORMANCE_TITLE_CAPITALIST :Kapitalisti
@ -947,6 +947,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :Uusi Taiwanin d
STR_GAME_OPTIONS_CURRENCY_CNY :Kiinan renminbi (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Hongkongin dollari (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Intian rupia (INR)
STR_GAME_OPTIONS_CURRENCY_IDR :Indonesian rupia (IDR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Vasemmanpuolinen liikenne

@ -959,6 +959,7 @@ STR_GAME_OPTIONS_CURRENCY_NTD :신 타이완
STR_GAME_OPTIONS_CURRENCY_CNY :중국 위안 (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :홍콩 달러 (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :인도 루피 (INR)
STR_GAME_OPTIONS_CURRENCY_IDR :인도네시아 루피아 (IDR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :좌측통행

@ -1087,12 +1087,13 @@ STR_GAME_OPTIONS_CURRENCY_ZAR :Южноафр
STR_GAME_OPTIONS_CURRENCY_CUSTOM :Своя...
STR_GAME_OPTIONS_CURRENCY_GEL :Грузинский лари (GEL)
STR_GAME_OPTIONS_CURRENCY_IRR :Иранский риал (IRR)
STR_GAME_OPTIONS_CURRENCY_RUB :Российский рубль (RUR)
STR_GAME_OPTIONS_CURRENCY_RUB :Российский рубль (RUB)
STR_GAME_OPTIONS_CURRENCY_MXN :Мексиканский песо (MXN)
STR_GAME_OPTIONS_CURRENCY_NTD :Новый тайваньский доллар (NTD)
STR_GAME_OPTIONS_CURRENCY_CNY :Китайский юань (CNY)
STR_GAME_OPTIONS_CURRENCY_HKD :Гонконгский доллар (HKD)
STR_GAME_OPTIONS_CURRENCY_INR :Индийская рупия (INR)
STR_GAME_OPTIONS_CURRENCY_IDR :Индонезийская рупия (IDR)
############ end of currency region
STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT :Левостороннее

@ -23,7 +23,7 @@ static CommandCallback * const _callback_table[] = {
/* 0x01 */ CcBuildPrimaryVehicle,
/* 0x02 */ CcBuildAirport,
/* 0x03 */ CcBuildBridge,
/* 0x04 */ CcPlaySound_SPLAT_WATER,
/* 0x04 */ CcPlaySound_CONSTRUCTION_WATER,
/* 0x05 */ CcBuildDocks,
/* 0x06 */ CcFoundTown,
/* 0x07 */ CcBuildRoadTunnel,
@ -33,8 +33,8 @@ static CommandCallback * const _callback_table[] = {
/* 0x0B */ CcRailDepot,
/* 0x0C */ CcPlaceSign,
/* 0x0D */ CcPlaySound_EXPLOSION,
/* 0x0E */ CcPlaySound_SPLAT_OTHER,
/* 0x0F */ CcPlaySound_SPLAT_RAIL,
/* 0x0E */ CcPlaySound_CONSTRUCTION_OTHER,
/* 0x0F */ CcPlaySound_CONSTRUCTION_RAIL,
/* 0x10 */ CcStation,
/* 0x11 */ CcTerraform,
/* 0x12 */ CcAI,

@ -239,7 +239,7 @@ static NewsTypeData _news_type_data[] = {
NewsTypeData("news_display.production_other", 30, SND_BEGIN ), ///< NT_INDUSTRY_OTHER
NewsTypeData("news_display.production_nobody", 30, SND_BEGIN ), ///< NT_INDUSTRY_NOBODY
NewsTypeData("news_display.advice", 150, SND_BEGIN ), ///< NT_ADVICE
NewsTypeData("news_display.new_vehicles", 30, SND_1E_OOOOH ), ///< NT_NEW_VEHICLES
NewsTypeData("news_display.new_vehicles", 30, SND_1E_NEW_ENGINE), ///< NT_NEW_VEHICLES
NewsTypeData("news_display.acceptance", 90, SND_BEGIN ), ///< NT_ACCEPTANCE
NewsTypeData("news_display.subsidies", 180, SND_BEGIN ), ///< NT_SUBSIDIES
NewsTypeData("news_display.general", 60, SND_BEGIN ), ///< NT_GENERAL
@ -606,7 +606,7 @@ static void ShowNewspaper(const NewsItem *ni)
/** Show news item in the ticker */
static void ShowTicker(const NewsItem *ni)
{
if (_settings_client.sound.news_ticker) SndPlayFx(SND_16_MORSE);
if (_settings_client.sound.news_ticker) SndPlayFx(SND_16_NEWS_TICKER);
_statusbar_news_item = ni;
InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_TICKER);

@ -42,7 +42,7 @@ class BuildObjectWindow : public Window {
int line_height; ///< The height of a single line.
int info_height; ///< The height of the info box.
Scrollbar* vscroll; ///< The scrollbar.
Scrollbar *vscroll; ///< The scrollbar.
static Listing last_sorting; ///< Default sorting of #GUIObjectClassList.
static Filtering last_filtering; ///< Default filtering of #GUIObjectClassList.
@ -114,7 +114,7 @@ public:
ResetObjectToPlace();
this->vscroll->SetCount((int) this->object_classes.size());
this->vscroll->SetCount((int)this->object_classes.size());
EnsureSelectedObjectClassIsVisible();
@ -122,7 +122,7 @@ public:
}
/** Sort object classes by class name. */
static bool NameSorter(const ObjectClass *const& a, const ObjectClass *const& b)
static bool NameSorter(const ObjectClass * const &a, const ObjectClass * const &b)
{
char buffer_a[DRAW_STRING_BUFFER];
GetString(buffer_a, a->name, lastof(buffer_a));
@ -134,7 +134,7 @@ public:
}
/** Filter object classes by class name. */
static bool CDECL TagNameFilter(const ObjectClass *const* oc, StringFilter& filter)
static bool CDECL TagNameFilter(const ObjectClass * const *oc, StringFilter &filter)
{
char buffer[DRAW_STRING_BUFFER];
GetString(buffer, (*oc)->name, lastof(buffer));
@ -180,7 +180,7 @@ public:
* result of starting a new game without the corresponding NewGRF. */
bool available = false;
for (uint i = 0; ObjectClass::GetClassCount(); ++i) {
ObjectClass* objclass = ObjectClass::Get((ObjectClassID)i);
ObjectClass *objclass = ObjectClass::Get((ObjectClassID)i);
if (objclass == _selected_object_class) {
available = true;
break;
@ -624,11 +624,11 @@ public:
Listing BuildObjectWindow::last_sorting = { false, 0 };
Filtering BuildObjectWindow::last_filtering = { false, 0 };
BuildObjectWindow::GUIObjectClassList::SortFunction* const BuildObjectWindow::sorter_funcs[] = {
BuildObjectWindow::GUIObjectClassList::SortFunction * const BuildObjectWindow::sorter_funcs[] = {
&NameSorter,
};
BuildObjectWindow::GUIObjectClassList::FilterFunction* const BuildObjectWindow::filter_funcs[] = {
BuildObjectWindow::GUIObjectClassList::FilterFunction * const BuildObjectWindow::filter_funcs[] = {
&TagNameFilter,
};

@ -94,9 +94,9 @@ static bool IsStationAvailable(const StationSpec *statspec)
return Convert8bitBooleanCallback(statspec->grf_prop.grffile, CBID_STATION_AVAILABILITY, cb_res);
}
void CcPlaySound_SPLAT_RAIL(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
void CcPlaySound_CONSTRUCTION_RAIL(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
}
static CommandContainer GenericPlaceRailCmd(TileIndex tile, Track track)
@ -108,7 +108,7 @@ static CommandContainer GenericPlaceRailCmd(TileIndex tile, Track track)
(uint32) (_remove_button_clicked ?
CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)), // cmd
CcPlaySound_SPLAT_RAIL // callback
CcPlaySound_CONSTRUCTION_RAIL // callback
);
return ret;
@ -150,7 +150,7 @@ void CcRailDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
DiagDirection dir = (DiagDirection)p2;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
tile += TileOffsByDiagDir(dir);
@ -189,7 +189,7 @@ void CcStation(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2,
{
if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
/* Only close the station builder window if the default station and non persistent building is chosen. */
if (_railstation.station_class == STAT_CLASS_DFLT && _railstation.station_type == 0 && !_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
}
@ -239,7 +239,7 @@ static void GenericPlaceSignals(TileIndex tile)
Track track = FindFirstTrack(trackbits);
if (_remove_button_clicked) {
DoCommandP(tile, track, 0, CMD_REMOVE_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM), CcPlaySound_SPLAT_RAIL);
DoCommandP(tile, track, 0, CMD_REMOVE_SIGNALS | CMD_MSG(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM), CcPlaySound_CONSTRUCTION_RAIL);
return;
}
@ -285,7 +285,7 @@ static void GenericPlaceSignals(TileIndex tile)
DoCommandP(tile, p1, 0, CMD_BUILD_SIGNALS |
CMD_MSG((w != nullptr && _convert_signal_button) ? STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE : STR_ERROR_CAN_T_BUILD_SIGNALS_HERE),
CcPlaySound_SPLAT_RAIL);
CcPlaySound_CONSTRUCTION_RAIL);
}
/**
@ -308,7 +308,7 @@ static void PlaceRail_Bridge(TileIndex tile, Window *w)
void CcBuildRailTunnel(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_SPLAT_RAIL, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_20_CONSTRUCTION_RAIL, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
StoreRailPlacementEndpoints(tile, _build_tunnel_endtile, TileX(tile) == TileX(_build_tunnel_endtile) ? TRACK_Y : TRACK_X, false);
} else {
@ -393,7 +393,7 @@ static CommandContainer DoRailroadTrackCmd(TileIndex start_tile, TileIndex end_t
(uint32) (_remove_button_clicked ?
CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) :
CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK)), // cmd
CcPlaySound_SPLAT_RAIL // callback
CcPlaySound_CONSTRUCTION_RAIL // callback
);
return ret;
@ -464,7 +464,7 @@ static void HandleAutoSignalPlacement()
_remove_button_clicked ?
CMD_REMOVE_SIGNAL_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM) :
CMD_BUILD_SIGNAL_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_SIGNALS_HERE),
CcPlaySound_SPLAT_RAIL);
CcPlaySound_CONSTRUCTION_RAIL);
}
@ -807,7 +807,7 @@ struct BuildRailToolbarWindow : Window {
break;
case DDSP_CONVERT_RAIL:
DoCommandP(end_tile, start_tile, _cur_railtype | (_ctrl_pressed ? (1 << 6) : 0), CMD_CONVERT_RAIL | CMD_MSG(STR_ERROR_CAN_T_CONVERT_RAIL), CcPlaySound_SPLAT_RAIL);
DoCommandP(end_tile, start_tile, _cur_railtype | (_ctrl_pressed ? (1 << 6) : 0), CMD_CONVERT_RAIL | CMD_MSG(STR_ERROR_CAN_T_CONVERT_RAIL), CcPlaySound_CONSTRUCTION_RAIL);
break;
case DDSP_REMOVE_STATION:
@ -815,20 +815,20 @@ struct BuildRailToolbarWindow : Window {
if (this->IsWidgetLowered(WID_RAT_BUILD_STATION)) {
/* Station */
if (_remove_button_clicked) {
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_REMOVE_PART_OF_STATION), CcPlaySound_SPLAT_RAIL);
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_REMOVE_PART_OF_STATION), CcPlaySound_CONSTRUCTION_RAIL);
} else {
HandleStationPlacement(start_tile, end_tile);
}
} else {
/* Waypoint */
if (_remove_button_clicked) {
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT), CcPlaySound_SPLAT_RAIL);
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 0 : 1, CMD_REMOVE_FROM_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT), CcPlaySound_CONSTRUCTION_RAIL);
} else {
TileArea ta(start_tile, end_tile);
uint32 p1 = _cur_railtype | (select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y) << 6 | ta.w << 8 | ta.h << 16 | _ctrl_pressed << 24;
uint32 p2 = STAT_CLASS_WAYP | _cur_waypoint_type << 8 | INVALID_STATION << 16;
CommandContainer cmdcont = NewCommandContainerBasic(ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT), CcPlaySound_SPLAT_RAIL);
CommandContainer cmdcont = NewCommandContainerBasic(ta.tile, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT), CcPlaySound_CONSTRUCTION_RAIL);
ShowSelectWaypointIfNeeded(cmdcont, ta);
}
}

@ -2427,7 +2427,7 @@ static void TileLoop_Road(TileIndex tile)
if (GetFoundationSlope(tile) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) {
StartRoadWorks(tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_JACKHAMMER, tile);
if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_ROAD_WORKS, tile);
CreateEffectVehicleAbove(
TileX(tile) * TILE_SIZE + 7,
TileY(tile) * TILE_SIZE + 7,

@ -67,9 +67,9 @@ static RoadType _cur_roadtype;
static DiagDirection _road_depot_orientation;
static DiagDirection _road_station_picker_orientation;
void CcPlaySound_SPLAT_OTHER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
void CcPlaySound_CONSTRUCTION_OTHER(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (result.Succeeded() && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
}
/**
@ -100,7 +100,7 @@ static void PlaceRoad_Bridge(TileIndex tile, Window *w)
void CcBuildRoadTunnel(const CommandCost &result, TileIndex start_tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, start_tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, start_tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
DiagDirection start_direction = ReverseDiagDir(GetTunnelBridgeDirection(start_tile));
@ -135,7 +135,7 @@ void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
if (result.Failed()) return;
DiagDirection dir = (DiagDirection)GB(p1, 0, 2);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
ConnectRoadToStructure(tile, dir);
}
@ -161,7 +161,7 @@ void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2,
if (result.Failed()) return;
DiagDirection dir = (DiagDirection)GB(p2, 3, 2);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
TileArea roadstop_area(tile, GB(p1, 0, 8), GB(p1, 8, 8));
TILE_AREA_LOOP(cur_tile, roadstop_area) {
@ -672,7 +672,7 @@ struct BuildRoadToolbarWindow : Window {
DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 10),
_remove_button_clicked ?
CMD_REMOVE_LONG_ROAD | CMD_MSG(this->rti->strings.err_remove_road) :
CMD_BUILD_LONG_ROAD | CMD_MSG(this->rti->strings.err_build_road), CcPlaySound_SPLAT_OTHER);
CMD_BUILD_LONG_ROAD | CMD_MSG(this->rti->strings.err_build_road), CcPlaySound_CONSTRUCTION_OTHER);
break;
case DDSP_BUILD_BUSSTOP:
@ -680,7 +680,7 @@ struct BuildRoadToolbarWindow : Window {
if (this->IsWidgetLowered(WID_ROT_BUS_STATION)) {
if (_remove_button_clicked) {
TileArea ta(start_tile, end_tile);
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(this->rti->strings.err_remove_station[ROADSTOP_BUS]), CcPlaySound_SPLAT_OTHER);
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(this->rti->strings.err_remove_station[ROADSTOP_BUS]), CcPlaySound_CONSTRUCTION_OTHER);
} else {
PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP | CMD_MSG(this->rti->strings.err_build_station[ROADSTOP_BUS]));
}
@ -692,7 +692,7 @@ struct BuildRoadToolbarWindow : Window {
if (this->IsWidgetLowered(WID_ROT_TRUCK_STATION)) {
if (_remove_button_clicked) {
TileArea ta(start_tile, end_tile);
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(this->rti->strings.err_remove_station[ROADSTOP_TRUCK]), CcPlaySound_SPLAT_OTHER);
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(this->rti->strings.err_remove_station[ROADSTOP_TRUCK]), CcPlaySound_CONSTRUCTION_OTHER);
} else {
PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP | CMD_MSG(this->rti->strings.err_build_station[ROADSTOP_TRUCK]));
}
@ -700,7 +700,7 @@ struct BuildRoadToolbarWindow : Window {
break;
case DDSP_CONVERT_ROAD:
DoCommandP(end_tile, start_tile, _cur_roadtype, CMD_CONVERT_ROAD | CMD_MSG(rti->strings.err_convert_road), CcPlaySound_SPLAT_OTHER);
DoCommandP(end_tile, start_tile, _cur_roadtype, CMD_CONVERT_ROAD | CMD_MSG(rti->strings.err_convert_road), CcPlaySound_CONSTRUCTION_OTHER);
break;
}
}

@ -661,8 +661,8 @@ static void StartRoadVehSound(const RoadVehicle *v)
{
if (!PlayVehicleSound(v, VSE_START)) {
SoundID s = RoadVehInfo(v->engine_type)->sfx;
if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0) {
s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN;
if (s == SND_19_DEPARTURE_OLD_RV_1 && (v->tick_counter & 3) == 0) {
s = SND_1A_DEPARTURE_OLD_RV_2;
}
SndPlayVehicleFx(s, v);
}

@ -36,79 +36,79 @@ struct SoundEntry {
*/
enum SoundFx {
SND_BEGIN = 0,
SND_02_SPLAT_WATER = 0, ///< Water construction.
SND_03_FACTORY_WHISTLE,
SND_04_TRAIN,
SND_05_TRAIN_THROUGH_TUNNEL,
SND_06_SHIP_HORN,
SND_07_FERRY_HORN,
SND_08_PLANE_TAKE_OFF,
SND_09_JET,
SND_0A_TRAIN_HORN,
SND_0B_MINING_MACHINERY,
SND_0C_ELECTRIC_SPARK,
SND_0D_STEAM,
SND_0E_LEVEL_CROSSING,
SND_0F_VEHICLE_BREAKDOWN,
SND_10_TRAIN_BREAKDOWN,
SND_11_CRASH,
SND_12_EXPLOSION, // 16 == 0x10
SND_13_BIG_CRASH,
SND_14_CASHTILL,
SND_15_BEEP, // 19 == 0x13
SND_16_MORSE, // 20 == 0x14
SND_17_SKID_PLANE,
SND_18_HELICOPTER,
SND_19_BUS_START_PULL_AWAY,
SND_1A_BUS_START_PULL_AWAY_WITH_HORN,
SND_1B_TRUCK_START,
SND_1C_TRUCK_START_2,
SND_1D_APPLAUSE,
SND_1E_OOOOH,
SND_1F_SPLAT_OTHER, ///< Non-water non-rail construction.
SND_20_SPLAT_RAIL, ///< Rail construction.
SND_21_JACKHAMMER,
SND_22_CAR_HORN,
SND_23_CAR_HORN_2,
SND_24_SHEEP,
SND_25_COW,
SND_26_HORSE,
SND_27_BLACKSMITH_ANVIL,
SND_28_SAWMILL, // 38 == 0x26 !
SND_00_GOOD_YEAR, // 39 == 0x27 !
SND_01_BAD_YEAR, // 40 == 0x28 !
SND_29_RIP, // 41 == 0x29 !
SND_2A_EXTRACT_AND_POP,
SND_2B_COMEDY_HIT,
SND_2C_MACHINERY,
SND_2D_RIP_2,
SND_2E_EXTRACT_AND_POP,
SND_2F_POP,
SND_30_CARTOON_SOUND,
SND_31_EXTRACT,
SND_32_POP_2,
SND_33_PLASTIC_MINE,
SND_34_WIND,
SND_35_COMEDY_BREAKDOWN,
SND_36_CARTOON_CRASH,
SND_37_BALLOON_SQUEAK,
SND_38_CHAINSAW,
SND_39_HEAVY_WIND,
SND_3A_COMEDY_BREAKDOWN_2,
SND_3B_JET_OVERHEAD,
SND_3C_COMEDY_CAR,
SND_3D_ANOTHER_JET_OVERHEAD,
SND_3E_COMEDY_CAR_2,
SND_3F_COMEDY_CAR_3,
SND_40_COMEDY_CAR_START_AND_PULL_AWAY,
SND_41_MAGLEV,
SND_42_LOON_BIRD,
SND_43_LION,
SND_44_MONKEYS,
SND_45_PLANE_CRASHING,
SND_46_PLANE_ENGINE_SPUTTERING,
SND_47_MAGLEV_2,
SND_48_DISTANT_BIRD, // 72 == 0x48
SND_02_CONSTRUCTION_WATER = 0, ///< 0 == 0x00 Construction: water infrastructure
SND_03_FACTORY, ///< 1 == 0x01 Industry producing: factory: whistle
SND_04_DEPARTURE_STEAM, ///< 2 == 0x02 Station departure: steam engine
SND_05_TRAIN_THROUGH_TUNNEL, ///< 3 == 0x03 Train enters tunnel
SND_06_DEPARTURE_CARGO_SHIP, ///< 4 == 0x04 Station departure: cargo ships
SND_07_DEPARTURE_FERRY, ///< 5 == 0x05 Station departure: passenger ships
SND_08_TAKEOFF_PROPELLER, ///< 6 == 0x06 Takeoff: propeller plane (non-toyland)
SND_09_TAKEOFF_JET, ///< 7 == 0x07 Takeoff: regular jet plane
SND_0A_DEPARTURE_TRAIN, ///< 8 == 0x08 Station departure: diesel and electric engine
SND_0B_MINE, ///< 9 == 0x09 Industry animation: coal/copper/gold mine: headgear
SND_0C_POWER_STATION, ///< 10 == 0x0A Industry animation: power station: spark
SND_0D_UNUSED, ///< 11 == 0x0B unused (1)
SND_0E_LEVEL_CROSSING, ///< 12 == 0x0C Train passes through level crossing
SND_0F_BREAKDOWN_ROADVEHICLE, ///< 13 == 0x0D Breakdown: road vehicle (non-toyland)
SND_10_BREAKDOWN_TRAIN_SHIP, ///< 14 == 0x0E Breakdown: train or ship (non-toyland)
SND_11_UNUSED, ///< 15 == 0x0F unused (2)
SND_12_EXPLOSION, ///< 16 == 0x10 Destruction, crashes, disasters, ...
SND_13_TRAIN_COLLISION, ///< 15 == 0x11 Train+train crash
SND_14_CASHTILL, ///< 18 == 0x12 Income from cargo delivery
SND_15_BEEP, ///< 19 == 0x13 GUI button click
SND_16_NEWS_TICKER, ///< 20 == 0x14 News ticker
SND_17_SKID_PLANE, ///< 21 == 0x15 Plane landing / touching ground
SND_18_TAKEOFF_HELICOPTER, ///< 22 == 0x16 Takeoff: helicopter
SND_19_DEPARTURE_OLD_RV_1, ///< 23 == 0x17 Station departure: truck and old bus (1) (non-toyland)
SND_1A_DEPARTURE_OLD_RV_2, ///< 24 == 0x18 Station departure: truck and old bus (2) (random variation of SND_19_DEPARTURE_OLD_RV_1) (non-toyland)
SND_1B_DEPARTURE_MODERN_BUS, ///< 25 == 0x19 Station departure: modern bus (non-toyland)
SND_1C_DEPARTURE_OLD_BUS, ///< 26 == 0x1A Station departure: old bus (non-toyland)
SND_1D_APPLAUSE, ///< 27 == 0x1B News: first vehicle at station
SND_1E_NEW_ENGINE, ///< 28 == 0x1C News: new engine available
SND_1F_CONSTRUCTION_OTHER, ///< 29 == 0x1D Construction: other (non-water, non-rail, non-bridge)
SND_20_CONSTRUCTION_RAIL, ///< 30 == 0x1E Construction: rail infrastructure
SND_21_ROAD_WORKS, ///< 31 == 0x1F Road reconstruction animation
SND_22_UNUSED, ///< 32 == 0x20 unused (3)
SND_23_UNUSED, ///< 33 == 0x21 unused (4)
SND_24_FARM_1, ///< 34 == 0x22 Industry producing: farm (1): sheep
SND_25_FARM_2, ///< 35 == 0x23 Industry producing: farm (2): cow
SND_26_FARM_3, ///< 36 == 0x24 Industry producing: farm (3): horse
SND_27_CONSTRUCTION_BRIDGE, ///< 37 == 0x25 Construction: bridge
SND_28_SAWMILL, ///< 38 == 0x26 Industry producing: sawmill
SND_00_GOOD_YEAR, ///< 39 == 0x27 New year: performance improved
SND_01_BAD_YEAR, ///< 40 == 0x28 New year: performance declined
SND_29_SUGAR_MINE_2, ///< 41 == 0x29 Industry animation: sugar mine (2): shaking sieve
SND_2A_TOY_FACTORY_3, ///< 42 == 0x2A Industry animation: toy factory (3): eject product
SND_2B_TOY_FACTORY_2, ///< 43 == 0x2B Industry animation: toy factory (2): stamp product
SND_2C_TOY_FACTORY_1, ///< 44 == 0x2C Industry animation: toy factory (1): conveyor belt
SND_2D_SUGAR_MINE_1, ///< 45 == 0x2D Industry animation: sugar mine (1): shaking sieve
SND_2E_BUBBLE_GENERATOR, ///< 46 == 0x2E Industry animation: bubble generator (1): generate bubble
SND_2F_BUBBLE_GENERATOR_FAIL, ///< 47 == 0x2F Industry animation: bubble generator (2a): bubble pop
SND_30_TOFFEE_QUARRY, ///< 48 == 0x30 Industry animation: toffee quarry: drill
SND_31_BUBBLE_GENERATOR_SUCCESS, ///< 49 == 0x31 Industry animation: bubble generator (2b): bubble slurped
SND_32_UNUSED, ///< 50 == 0x32 unused (5)
SND_33_PLASTIC_MINE, ///< 51 == 0x33 Industry producing: plastic fountain
SND_34_ARCTIC_SNOW_1, ///< 52 == 0x34 Tree ambient: arctic snow (1): wind
SND_35_BREAKDOWN_ROADVEHICLE_TOYLAND, ///< 53 == 0x35 Breakdown: road vehicle (toyland)
SND_36_LUMBER_MILL_3, ///< 54 == 0x36 Industry animation: lumber mill (3): crashing tree
SND_37_LUMBER_MILL_2, ///< 55 == 0x37 Industry animation: lumber mill (2): falling tree
SND_38_LUMBER_MILL_1, ///< 56 == 0x38 Industry animation: lumber mill (1): chainsaw
SND_39_ARCTIC_SNOW_2, ///< 57 == 0x39 Tree ambient: arctic snow (2): heavy wind
SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND, ///< 58 == 0x3A Breakdown: train or ship (toyland)
SND_3B_TAKEOFF_JET_FAST, ///< 59 == 0x3B Takeoff: supersonic plane (fast)
SND_3C_DEPARTURE_BUS_TOYLAND_1, ///< 60 == 0x3C Station departure: bus (1) (toyland)
SND_3D_TAKEOFF_JET_BIG, ///< 61 == 0x3D Takeoff: huge jet plane (high capacity)
SND_3E_DEPARTURE_BUS_TOYLAND_2, ///< 62 == 0x3E Station departure: bus (2) (toyland)
SND_3F_DEPARTURE_TRUCK_TOYLAND_1, ///< 63 == 0x3F Station departure: truck (1) (toyland)
SND_40_DEPARTURE_TRUCK_TOYLAND_2, ///< 64 == 0x40 Station departure: truck (2) (toyland)
SND_41_DEPARTURE_MAGLEV, ///< 65 == 0x41 Station departure: maglev engine
SND_42_RAINFOREST_1, ///< 66 == 0x42 Tree ambient: rainforest ambient (1): bird (1)
SND_43_RAINFOREST_2, ///< 67 == 0x43 Tree ambient: rainforest ambient (2): lion
SND_44_RAINFOREST_3, ///< 68 == 0x44 Tree ambient: rainforest ambient (3): monkeys
SND_45_TAKEOFF_PROPELLER_TOYLAND_1, ///< 69 == 0x45 Takeoff: propeller plane (1) (toyland)
SND_46_TAKEOFF_PROPELLER_TOYLAND_2, ///< 70 == 0x46 Takeoff: propeller plane (2) (toyland)
SND_47_DEPARTURE_MONORAIL, ///< 71 == 0x47 Station departure: monorail engine
SND_48_RAINFOREST_4, ///< 72 == 0x48 Tree ambient: rainforest ambient (4): bird (2)
SND_END
};

@ -319,8 +319,8 @@
typedef unsigned char byte;
/* This is already defined in unix, but not in QNX Neutrino (6.x)*/
#if (!defined(UNIX) && !defined(__HAIKU__)) || defined(__QNXNTO__)
/* This is already defined in unix, but not in QNX Neutrino (6.x) or Cygwin. */
#if (!defined(UNIX) && !defined(__HAIKU__)) || defined(__QNXNTO__) || defined(__CYGWIN__)
typedef unsigned int uint;
#endif

@ -1035,10 +1035,10 @@ static const std::vector<IndustryTileLayout> _tile_table_sugar_mine {
static const uint8 _sawmill_sounds[] = { SND_28_SAWMILL };
/** Array with whistle sound, for factory */
static const uint8 _factory_sounds[] = { SND_03_FACTORY_WHISTLE };
static const uint8 _factory_sounds[] = { SND_03_FACTORY };
/** Array with 3 animal sounds, for farms */
static const uint8 _farm_sounds[] = { SND_24_SHEEP, SND_25_COW, SND_26_HORSE };
static const uint8 _farm_sounds[] = { SND_24_FARM_1, SND_25_FARM_2, SND_26_FARM_3 };
/** Array with... hem... a sound of toyland */
static const uint8 _plastic_mine_sounds[] = { SND_33_PLASTIC_MINE };

@ -565,21 +565,21 @@ static const RailVehicleInfo _orig_rail_vehicle_info[] = {
*/
#define SVI(a, b, c, d, e, f, g) { a, b, c, d, e, f, g, VE_DEFAULT, 0, 0 }
static const ShipVehicleInfo _orig_ship_vehicle_info[] = {
/* image_index capacity refittable
* | cost_factor running_cost |
* | | max_speed | sfx |
* | | | | | | | */
SVI( 1, 160, 48, 220, 140, SND_06_SHIP_HORN, 0 ), // 0 MPS Oil Tanker
SVI( 1, 176, 80, 350, 125, SND_06_SHIP_HORN, 0 ), // 1 CS-Inc. Oil Tanker
SVI( 2, 96, 64, 100, 90, SND_07_FERRY_HORN, 0 ), // 2 MPS Passenger Ferry
SVI( 2, 112, 128, 130, 80, SND_07_FERRY_HORN, 0 ), // 3 FFP Passenger Ferry
SVI( 3, 148, 224, 100, 190, SND_07_FERRY_HORN, 0 ), // 4 Bakewell 300 Hovercraft
SVI( 2, 96, 64, 100, 90, SND_07_FERRY_HORN, 0 ), // 5 Chugger-Chug Passenger Ferry
SVI( 2, 112, 128, 130, 80, SND_07_FERRY_HORN, 0 ), // 6 Shivershake Passenger Ferry
SVI( 0, 128, 48, 160, 150, SND_06_SHIP_HORN, 1 ), // 7 Yate Cargo ship
SVI( 0, 144, 80, 190, 113, SND_06_SHIP_HORN, 1 ), // 8 Bakewell Cargo ship
SVI( 0, 128, 48, 160, 150, SND_06_SHIP_HORN, 1 ), // 9 Mightymover Cargo ship
SVI( 0, 144, 80, 190, 113, SND_06_SHIP_HORN, 1 ), // 10 Powernaut Cargo ship
/* image_index capacity refittable
* | cost_factor running_cost |
* | | max_speed | sfx |
* | | | | | | | */
SVI( 1, 160, 48, 220, 140, SND_06_DEPARTURE_CARGO_SHIP, 0 ), // 0 MPS Oil Tanker
SVI( 1, 176, 80, 350, 125, SND_06_DEPARTURE_CARGO_SHIP, 0 ), // 1 CS-Inc. Oil Tanker
SVI( 2, 96, 64, 100, 90, SND_07_DEPARTURE_FERRY, 0 ), // 2 MPS Passenger Ferry
SVI( 2, 112, 128, 130, 80, SND_07_DEPARTURE_FERRY, 0 ), // 3 FFP Passenger Ferry
SVI( 3, 148, 224, 100, 190, SND_07_DEPARTURE_FERRY, 0 ), // 4 Bakewell 300 Hovercraft
SVI( 2, 96, 64, 100, 90, SND_07_DEPARTURE_FERRY, 0 ), // 5 Chugger-Chug Passenger Ferry
SVI( 2, 112, 128, 130, 80, SND_07_DEPARTURE_FERRY, 0 ), // 6 Shivershake Passenger Ferry
SVI( 0, 128, 48, 160, 150, SND_06_DEPARTURE_CARGO_SHIP, 1 ), // 7 Yate Cargo ship
SVI( 0, 144, 80, 190, 113, SND_06_DEPARTURE_CARGO_SHIP, 1 ), // 8 Bakewell Cargo ship
SVI( 0, 128, 48, 160, 150, SND_06_DEPARTURE_CARGO_SHIP, 1 ), // 9 Mightymover Cargo ship
SVI( 0, 144, 80, 190, 113, SND_06_DEPARTURE_CARGO_SHIP, 1 ), // 10 Powernaut Cargo ship
};
#undef SVI
@ -601,52 +601,52 @@ static const ShipVehicleInfo _orig_ship_vehicle_info[] = {
#define P AIR_CTOL
#define J AIR_CTOL | AIR_FAST
static const AircraftVehicleInfo _orig_aircraft_vehicle_info[] = {
/* image_index sfx acceleration
* | cost_factor | | max_speed
* | | running_cost | | mail_capacity
* | | | subtype | | | | passenger_capacity
* | | | | | | | | | */
AVI( 1, 14, 85, P, SND_08_PLANE_TAKE_OFF, 18, 37, 4, 25 ), // 0 Sampson U52
AVI( 0, 15, 100, P, SND_08_PLANE_TAKE_OFF, 20, 37, 8, 65 ), // 1 Coleman Count
AVI( 2, 16, 130, J, SND_09_JET, 35, 74, 10, 90 ), // 2 FFP Dart
AVI( 8, 75, 250, J, SND_3B_JET_OVERHEAD, 50, 181, 20, 100 ), // 3 Yate Haugan
AVI( 5, 15, 98, P, SND_08_PLANE_TAKE_OFF, 20, 37, 6, 30 ), // 4 Bakewell Cotswald LB-3
AVI( 6, 18, 240, J, SND_09_JET, 40, 74, 30, 200 ), // 5 Bakewell Luckett LB-8
AVI( 2, 17, 150, P, SND_09_JET, 35, 74, 15, 100 ), // 6 Bakewell Luckett LB-9
AVI( 2, 18, 245, J, SND_09_JET, 40, 74, 30, 150 ), // 7 Bakewell Luckett LB80
AVI( 3, 19, 192, J, SND_09_JET, 40, 74, 40, 220 ), // 8 Bakewell Luckett LB-10
AVI( 3, 20, 190, J, SND_09_JET, 40, 74, 25, 230 ), // 9 Bakewell Luckett LB-11
AVI( 2, 16, 135, J, SND_09_JET, 35, 74, 10, 95 ), // 10 Yate Aerospace YAC 1-11
AVI( 2, 18, 240, J, SND_09_JET, 40, 74, 35, 170 ), // 11 Darwin 100
AVI( 4, 17, 155, J, SND_09_JET, 40, 74, 15, 110 ), // 12 Darwin 200
AVI( 7, 30, 253, J, SND_3D_ANOTHER_JET_OVERHEAD, 40, 74, 50, 300 ), // 13 Darwin 300
AVI( 4, 18, 210, J, SND_09_JET, 40, 74, 25, 200 ), // 14 Darwin 400
AVI( 4, 19, 220, J, SND_09_JET, 40, 74, 25, 240 ), // 15 Darwin 500
AVI( 4, 27, 230, J, SND_09_JET, 40, 74, 40, 260 ), // 16 Darwin 600
AVI( 3, 25, 225, J, SND_09_JET, 40, 74, 35, 240 ), // 17 Guru Galaxy
AVI( 4, 20, 235, J, SND_09_JET, 40, 74, 30, 260 ), // 18 Airtaxi A21
AVI( 4, 19, 220, J, SND_09_JET, 40, 74, 25, 210 ), // 19 Airtaxi A31
AVI( 4, 18, 170, J, SND_09_JET, 40, 74, 20, 160 ), // 20 Airtaxi A32
AVI( 4, 26, 210, J, SND_09_JET, 40, 74, 20, 220 ), // 21 Airtaxi A33
AVI( 6, 16, 125, P, SND_09_JET, 50, 74, 10, 80 ), // 22 Yate Aerospace YAe46
AVI( 2, 17, 145, P, SND_09_JET, 40, 74, 10, 85 ), // 23 Dinger 100
AVI( 11, 16, 130, P, SND_09_JET, 40, 74, 10, 75 ), // 24 AirTaxi A34-1000
AVI( 10, 16, 149, P, SND_09_JET, 40, 74, 10, 85 ), // 25 Yate Z-Shuttle
AVI( 15, 17, 170, P, SND_09_JET, 40, 74, 18, 65 ), // 26 Kelling K1
AVI( 12, 18, 210, J, SND_09_JET, 40, 74, 25, 110 ), // 27 Kelling K6
AVI( 13, 20, 230, J, SND_09_JET, 40, 74, 60, 180 ), // 28 Kelling K7
AVI( 14, 21, 220, J, SND_09_JET, 40, 74, 65, 150 ), // 29 Darwin 700
AVI( 16, 19, 160, J, SND_09_JET, 40, 181, 45, 85 ), // 30 FFP Hyperdart 2
AVI( 17, 24, 248, J, SND_3D_ANOTHER_JET_OVERHEAD, 40, 74, 80, 400 ), // 31 Dinger 200
AVI( 18, 80, 251, J, SND_3B_JET_OVERHEAD, 50, 181, 45, 130 ), // 32 Dinger 1000
AVI( 20, 13, 85, P, SND_45_PLANE_CRASHING, 18, 37, 5, 25 ), // 33 Ploddyphut 100
AVI( 21, 18, 100, P, SND_46_PLANE_ENGINE_SPUTTERING, 20, 37, 9, 60 ), // 34 Ploddyphut 500
AVI( 22, 25, 140, P, SND_09_JET, 40, 74, 12, 90 ), // 35 Flashbang X1
AVI( 23, 32, 220, J, SND_3D_ANOTHER_JET_OVERHEAD, 40, 74, 40, 200 ), // 36 Juggerplane M1
AVI( 24, 80, 255, J, SND_3B_JET_OVERHEAD, 50, 181, 30, 100 ), // 37 Flashbang Wizzer
AVI( 9, 15, 81, H, SND_09_JET, 20, 25, 15, 40 ), // 38 Tricario Helicopter
AVI( 19, 17, 77, H, SND_09_JET, 20, 40, 20, 55 ), // 39 Guru X2 Helicopter
AVI( 25, 15, 80, H, SND_09_JET, 20, 25, 10, 40 ), // 40 Powernaut Helicopter
/* image_index sfx acceleration
* | cost_factor | | max_speed
* | | running_cost | | mail_capacity
* | | | subtype | | | | passenger_capacity
* | | | | | | | | | */
AVI( 1, 14, 85, P, SND_08_TAKEOFF_PROPELLER, 18, 37, 4, 25 ), // 0 Sampson U52
AVI( 0, 15, 100, P, SND_08_TAKEOFF_PROPELLER, 20, 37, 8, 65 ), // 1 Coleman Count
AVI( 2, 16, 130, J, SND_09_TAKEOFF_JET, 35, 74, 10, 90 ), // 2 FFP Dart
AVI( 8, 75, 250, J, SND_3B_TAKEOFF_JET_FAST, 50, 181, 20, 100 ), // 3 Yate Haugan
AVI( 5, 15, 98, P, SND_08_TAKEOFF_PROPELLER, 20, 37, 6, 30 ), // 4 Bakewell Cotswald LB-3
AVI( 6, 18, 240, J, SND_09_TAKEOFF_JET, 40, 74, 30, 200 ), // 5 Bakewell Luckett LB-8
AVI( 2, 17, 150, P, SND_09_TAKEOFF_JET, 35, 74, 15, 100 ), // 6 Bakewell Luckett LB-9
AVI( 2, 18, 245, J, SND_09_TAKEOFF_JET, 40, 74, 30, 150 ), // 7 Bakewell Luckett LB80
AVI( 3, 19, 192, J, SND_09_TAKEOFF_JET, 40, 74, 40, 220 ), // 8 Bakewell Luckett LB-10
AVI( 3, 20, 190, J, SND_09_TAKEOFF_JET, 40, 74, 25, 230 ), // 9 Bakewell Luckett LB-11
AVI( 2, 16, 135, J, SND_09_TAKEOFF_JET, 35, 74, 10, 95 ), // 10 Yate Aerospace YAC 1-11
AVI( 2, 18, 240, J, SND_09_TAKEOFF_JET, 40, 74, 35, 170 ), // 11 Darwin 100
AVI( 4, 17, 155, J, SND_09_TAKEOFF_JET, 40, 74, 15, 110 ), // 12 Darwin 200
AVI( 7, 30, 253, J, SND_3D_TAKEOFF_JET_BIG, 40, 74, 50, 300 ), // 13 Darwin 300
AVI( 4, 18, 210, J, SND_09_TAKEOFF_JET, 40, 74, 25, 200 ), // 14 Darwin 400
AVI( 4, 19, 220, J, SND_09_TAKEOFF_JET, 40, 74, 25, 240 ), // 15 Darwin 500
AVI( 4, 27, 230, J, SND_09_TAKEOFF_JET, 40, 74, 40, 260 ), // 16 Darwin 600
AVI( 3, 25, 225, J, SND_09_TAKEOFF_JET, 40, 74, 35, 240 ), // 17 Guru Galaxy
AVI( 4, 20, 235, J, SND_09_TAKEOFF_JET, 40, 74, 30, 260 ), // 18 Airtaxi A21
AVI( 4, 19, 220, J, SND_09_TAKEOFF_JET, 40, 74, 25, 210 ), // 19 Airtaxi A31
AVI( 4, 18, 170, J, SND_09_TAKEOFF_JET, 40, 74, 20, 160 ), // 20 Airtaxi A32
AVI( 4, 26, 210, J, SND_09_TAKEOFF_JET, 40, 74, 20, 220 ), // 21 Airtaxi A33
AVI( 6, 16, 125, P, SND_09_TAKEOFF_JET, 50, 74, 10, 80 ), // 22 Yate Aerospace YAe46
AVI( 2, 17, 145, P, SND_09_TAKEOFF_JET, 40, 74, 10, 85 ), // 23 Dinger 100
AVI( 11, 16, 130, P, SND_09_TAKEOFF_JET, 40, 74, 10, 75 ), // 24 AirTaxi A34-1000
AVI( 10, 16, 149, P, SND_09_TAKEOFF_JET, 40, 74, 10, 85 ), // 25 Yate Z-Shuttle
AVI( 15, 17, 170, P, SND_09_TAKEOFF_JET, 40, 74, 18, 65 ), // 26 Kelling K1
AVI( 12, 18, 210, J, SND_09_TAKEOFF_JET, 40, 74, 25, 110 ), // 27 Kelling K6
AVI( 13, 20, 230, J, SND_09_TAKEOFF_JET, 40, 74, 60, 180 ), // 28 Kelling K7
AVI( 14, 21, 220, J, SND_09_TAKEOFF_JET, 40, 74, 65, 150 ), // 29 Darwin 700
AVI( 16, 19, 160, J, SND_09_TAKEOFF_JET, 40, 181, 45, 85 ), // 30 FFP Hyperdart 2
AVI( 17, 24, 248, J, SND_3D_TAKEOFF_JET_BIG, 40, 74, 80, 400 ), // 31 Dinger 200
AVI( 18, 80, 251, J, SND_3B_TAKEOFF_JET_FAST, 50, 181, 45, 130 ), // 32 Dinger 1000
AVI( 20, 13, 85, P, SND_45_TAKEOFF_PROPELLER_TOYLAND_1, 18, 37, 5, 25 ), // 33 Ploddyphut 100
AVI( 21, 18, 100, P, SND_46_TAKEOFF_PROPELLER_TOYLAND_2, 20, 37, 9, 60 ), // 34 Ploddyphut 500
AVI( 22, 25, 140, P, SND_09_TAKEOFF_JET, 40, 74, 12, 90 ), // 35 Flashbang X1
AVI( 23, 32, 220, J, SND_3D_TAKEOFF_JET_BIG, 40, 74, 40, 200 ), // 36 Juggerplane M1
AVI( 24, 80, 255, J, SND_3B_TAKEOFF_JET_FAST, 50, 181, 30, 100 ), // 37 Flashbang Wizzer
AVI( 9, 15, 81, H, SND_09_TAKEOFF_JET, 20, 25, 15, 40 ), // 38 Tricario Helicopter
AVI( 19, 17, 77, H, SND_09_TAKEOFF_JET, 20, 40, 20, 55 ), // 39 Guru X2 Helicopter
AVI( 25, 15, 80, H, SND_09_TAKEOFF_JET, 20, 25, 10, 40 ), // 40 Powernaut Helicopter
};
#undef J
#undef P
@ -669,98 +669,98 @@ static const AircraftVehicleInfo _orig_aircraft_vehicle_info[] = {
*/
#define ROV(a, b, c, d, e, f, g, h) { a, b, c, PR_RUNNING_ROADVEH, d, e, f, g, h, 76, 0, VE_DEFAULT, 0, ROADTYPE_ROAD }
static const RoadVehicleInfo _orig_road_vehicle_info[] = {
/* image_index sfx max_speed power
* | cost_factor | | capacity |
* | | running_cost | | weight
* | | | | | | | |*/
ROV( 0, 120, 91, SND_19_BUS_START_PULL_AWAY, 112, 31, 42, 9), // 0 MPS Regal Bus
ROV( 17, 140, 128, SND_1C_TRUCK_START_2, 176, 35, 60, 12), // 1 Hereford Leopard Bus
ROV( 17, 150, 178, SND_1B_TRUCK_START, 224, 37, 70, 15), // 2 Foster Bus
ROV( 34, 160, 240, SND_1B_TRUCK_START, 255, 40, 100, 25), // 3 Foster MkII Superbus
ROV( 51, 120, 91, SND_3C_COMEDY_CAR, 112, 30, 42, 9), // 4 Ploddyphut MkI Bus
ROV( 51, 140, 171, SND_3E_COMEDY_CAR_2, 192, 35, 60, 15), // 5 Ploddyphut MkII Bus
ROV( 51, 160, 240, SND_3C_COMEDY_CAR, 240, 38, 90, 25), // 6 Ploddyphut MkIII Bus
ROV( 1, 108, 90, SND_19_BUS_START_PULL_AWAY, 96, 20, 38, 12), // 7 Balogh Coal Truck
ROV( 18, 128, 168, SND_19_BUS_START_PULL_AWAY, 176, 25, 48, 22), // 8 Uhl Coal Truck
ROV( 35, 138, 240, SND_19_BUS_START_PULL_AWAY, 224, 28, 69, 45), // 9 DW Coal Truck
ROV( 2, 115, 90, SND_19_BUS_START_PULL_AWAY, 96, 22, 38, 12), // 10 MPS Mail Truck
ROV( 19, 135, 168, SND_19_BUS_START_PULL_AWAY, 176, 28, 48, 22), // 11 Reynard Mail Truck
ROV( 36, 145, 240, SND_19_BUS_START_PULL_AWAY, 224, 30, 69, 45), // 12 Perry Mail Truck
ROV( 57, 115, 90, SND_3E_COMEDY_CAR_2, 96, 22, 38, 12), // 13 MightyMover Mail Truck
ROV( 57, 135, 168, SND_3C_COMEDY_CAR, 176, 28, 48, 22), // 14 Powernaught Mail Truck
ROV( 57, 145, 240, SND_3E_COMEDY_CAR_2, 224, 30, 69, 45), // 15 Wizzowow Mail Truck
ROV( 3, 110, 90, SND_19_BUS_START_PULL_AWAY, 96, 21, 38, 12), // 16 Witcombe Oil Tanker
ROV( 20, 140, 168, SND_19_BUS_START_PULL_AWAY, 176, 25, 48, 22), // 17 Foster Oil Tanker
ROV( 37, 150, 240, SND_19_BUS_START_PULL_AWAY, 224, 27, 69, 45), // 18 Perry Oil Tanker
ROV( 4, 105, 90, SND_19_BUS_START_PULL_AWAY, 96, 14, 38, 12), // 19 Talbott Livestock Van
ROV( 21, 130, 168, SND_19_BUS_START_PULL_AWAY, 176, 16, 48, 22), // 20 Uhl Livestock Van
ROV( 38, 140, 240, SND_19_BUS_START_PULL_AWAY, 224, 18, 69, 45), // 21 Foster Livestock Van
ROV( 5, 107, 90, SND_19_BUS_START_PULL_AWAY, 96, 14, 38, 12), // 22 Balogh Goods Truck
ROV( 22, 130, 168, SND_19_BUS_START_PULL_AWAY, 176, 16, 48, 22), // 23 Craighead Goods Truck
ROV( 39, 140, 240, SND_19_BUS_START_PULL_AWAY, 224, 18, 69, 45), // 24 Goss Goods Truck
ROV( 6, 114, 90, SND_19_BUS_START_PULL_AWAY, 96, 20, 38, 12), // 25 Hereford Grain Truck
ROV( 23, 133, 168, SND_19_BUS_START_PULL_AWAY, 176, 25, 48, 22), // 26 Thomas Grain Truck
ROV( 40, 143, 240, SND_19_BUS_START_PULL_AWAY, 224, 30, 69, 45), // 27 Goss Grain Truck
ROV( 7, 118, 90, SND_19_BUS_START_PULL_AWAY, 96, 20, 38, 12), // 28 Witcombe Wood Truck
ROV( 24, 137, 168, SND_19_BUS_START_PULL_AWAY, 176, 22, 48, 22), // 29 Foster Wood Truck
ROV( 41, 147, 240, SND_19_BUS_START_PULL_AWAY, 224, 24, 69, 45), // 30 Moreland Wood Truck
ROV( 8, 121, 90, SND_19_BUS_START_PULL_AWAY, 96, 22, 38, 12), // 31 MPS Iron Ore Truck
ROV( 25, 140, 168, SND_19_BUS_START_PULL_AWAY, 176, 25, 48, 22), // 32 Uhl Iron Ore Truck
ROV( 42, 150, 240, SND_19_BUS_START_PULL_AWAY, 224, 27, 69, 45), // 33 Chippy Iron Ore Truck
ROV( 9, 112, 90, SND_19_BUS_START_PULL_AWAY, 96, 15, 38, 12), // 34 Balogh Steel Truck
ROV( 26, 135, 168, SND_19_BUS_START_PULL_AWAY, 176, 18, 48, 22), // 35 Uhl Steel Truck
ROV( 43, 145, 240, SND_19_BUS_START_PULL_AWAY, 224, 20, 69, 45), // 36 Kelling Steel Truck
ROV( 10, 145, 90, SND_19_BUS_START_PULL_AWAY, 96, 12, 38, 12), // 37 Balogh Armoured Truck
ROV( 27, 170, 168, SND_19_BUS_START_PULL_AWAY, 176, 15, 48, 22), // 38 Uhl Armoured Truck
ROV( 44, 180, 240, SND_19_BUS_START_PULL_AWAY, 224, 16, 69, 45), // 39 Foster Armoured Truck
ROV( 11, 112, 90, SND_19_BUS_START_PULL_AWAY, 96, 17, 38, 12), // 40 Foster Food Van
ROV( 28, 134, 168, SND_19_BUS_START_PULL_AWAY, 176, 20, 48, 22), // 41 Perry Food Van
ROV( 45, 144, 240, SND_19_BUS_START_PULL_AWAY, 224, 22, 69, 45), // 42 Chippy Food Van
ROV( 12, 112, 90, SND_19_BUS_START_PULL_AWAY, 96, 15, 38, 12), // 43 Uhl Paper Truck
ROV( 29, 135, 168, SND_19_BUS_START_PULL_AWAY, 176, 18, 48, 22), // 44 Balogh Paper Truck
ROV( 46, 145, 240, SND_19_BUS_START_PULL_AWAY, 224, 20, 69, 45), // 45 MPS Paper Truck
ROV( 13, 121, 90, SND_19_BUS_START_PULL_AWAY, 96, 22, 38, 12), // 46 MPS Copper Ore Truck
ROV( 30, 140, 168, SND_19_BUS_START_PULL_AWAY, 176, 25, 48, 22), // 47 Uhl Copper Ore Truck
ROV( 47, 150, 240, SND_19_BUS_START_PULL_AWAY, 224, 27, 69, 45), // 48 Goss Copper Ore Truck
ROV( 14, 111, 90, SND_19_BUS_START_PULL_AWAY, 96, 21, 38, 12), // 49 Uhl Water Tanker
ROV( 31, 141, 168, SND_19_BUS_START_PULL_AWAY, 176, 25, 48, 22), // 50 Balogh Water Tanker
ROV( 48, 151, 240, SND_19_BUS_START_PULL_AWAY, 224, 27, 69, 45), // 51 MPS Water Tanker
ROV( 15, 118, 90, SND_19_BUS_START_PULL_AWAY, 96, 18, 38, 12), // 52 Balogh Fruit Truck
ROV( 32, 148, 168, SND_19_BUS_START_PULL_AWAY, 176, 20, 48, 22), // 53 Uhl Fruit Truck
ROV( 49, 158, 240, SND_19_BUS_START_PULL_AWAY, 224, 23, 69, 45), // 54 Kelling Fruit Truck
ROV( 16, 117, 90, SND_19_BUS_START_PULL_AWAY, 96, 17, 38, 12), // 55 Balogh Rubber Truck
ROV( 33, 147, 168, SND_19_BUS_START_PULL_AWAY, 176, 19, 48, 22), // 56 Uhl Rubber Truck
ROV( 50, 157, 240, SND_19_BUS_START_PULL_AWAY, 224, 22, 69, 45), // 57 RMT Rubber Truck
ROV( 52, 117, 90, SND_3F_COMEDY_CAR_3, 96, 17, 38, 12), // 58 MightyMover Sugar Truck
ROV( 52, 147, 168, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 176, 19, 48, 22), // 59 Powernaught Sugar Truck
ROV( 52, 157, 240, SND_3F_COMEDY_CAR_3, 224, 22, 69, 45), // 60 Wizzowow Sugar Truck
ROV( 53, 117, 90, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 96, 17, 38, 12), // 61 MightyMover Cola Truck
ROV( 53, 147, 168, SND_3F_COMEDY_CAR_3, 176, 19, 48, 22), // 62 Powernaught Cola Truck
ROV( 53, 157, 240, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 224, 22, 69, 45), // 63 Wizzowow Cola Truck
ROV( 54, 117, 90, SND_3F_COMEDY_CAR_3, 96, 17, 38, 12), // 64 MightyMover Candyfloss Truck
ROV( 54, 147, 168, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 176, 19, 48, 22), // 65 Powernaught Candyfloss Truck
ROV( 54, 157, 240, SND_3F_COMEDY_CAR_3, 224, 22, 69, 45), // 66 Wizzowow Candyfloss Truck
ROV( 55, 117, 90, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 96, 17, 38, 12), // 67 MightyMover Toffee Truck
ROV( 55, 147, 168, SND_3F_COMEDY_CAR_3, 176, 19, 48, 22), // 68 Powernaught Toffee Truck
ROV( 55, 157, 240, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 224, 22, 69, 45), // 69 Wizzowow Toffee Truck
ROV( 56, 117, 90, SND_3F_COMEDY_CAR_3, 96, 17, 38, 12), // 70 MightyMover Toy Van
ROV( 56, 147, 168, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 176, 19, 48, 22), // 71 Powernaught Toy Van
ROV( 56, 157, 240, SND_3F_COMEDY_CAR_3, 224, 22, 69, 45), // 72 Wizzowow Toy Van
ROV( 58, 117, 90, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 96, 17, 38, 12), // 73 MightyMover Sweet Truck
ROV( 58, 147, 168, SND_3F_COMEDY_CAR_3, 176, 19, 48, 22), // 74 Powernaught Sweet Truck
ROV( 58, 157, 240, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 224, 22, 69, 45), // 75 Wizzowow Sweet Truck
ROV( 59, 117, 90, SND_3F_COMEDY_CAR_3, 96, 17, 38, 12), // 76 MightyMover Battery Truck
ROV( 59, 147, 168, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 176, 19, 48, 22), // 77 Powernaught Battery Truck
ROV( 59, 157, 240, SND_3F_COMEDY_CAR_3, 224, 22, 69, 45), // 78 Wizzowow Battery Truck
ROV( 60, 117, 90, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 96, 17, 38, 12), // 79 MightyMover Fizzy Drink Truck
ROV( 60, 147, 168, SND_3F_COMEDY_CAR_3, 176, 19, 48, 22), // 80 Powernaught Fizzy Drink Truck
ROV( 60, 157, 240, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 224, 22, 69, 45), // 81 Wizzowow Fizzy Drink Truck
ROV( 61, 117, 90, SND_3F_COMEDY_CAR_3, 96, 17, 38, 12), // 82 MightyMover Plastic Truck
ROV( 61, 147, 168, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 176, 19, 48, 22), // 83 Powernaught Plastic Truck
ROV( 61, 157, 240, SND_3F_COMEDY_CAR_3, 224, 22, 69, 45), // 84 Wizzowow Plastic Truck
ROV( 62, 117, 90, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 96, 17, 38, 12), // 85 MightyMover Bubble Truck
ROV( 62, 147, 168, SND_3F_COMEDY_CAR_3, 176, 19, 48, 22), // 86 Powernaught Bubble Truck
ROV( 62, 157, 240, SND_40_COMEDY_CAR_START_AND_PULL_AWAY, 224, 22, 69, 45), // 87 Wizzowow Bubble Truck
/* image_index sfx max_speed power
* | cost_factor | | capacity |
* | | running_cost | | weight
* | | | | | | | |*/
ROV( 0, 120, 91, SND_19_DEPARTURE_OLD_RV_1, 112, 31, 42, 9), // 0 MPS Regal Bus
ROV( 17, 140, 128, SND_1C_DEPARTURE_OLD_BUS, 176, 35, 60, 12), // 1 Hereford Leopard Bus
ROV( 17, 150, 178, SND_1B_DEPARTURE_MODERN_BUS, 224, 37, 70, 15), // 2 Foster Bus
ROV( 34, 160, 240, SND_1B_DEPARTURE_MODERN_BUS, 255, 40, 100, 25), // 3 Foster MkII Superbus
ROV( 51, 120, 91, SND_3C_DEPARTURE_BUS_TOYLAND_1, 112, 30, 42, 9), // 4 Ploddyphut MkI Bus
ROV( 51, 140, 171, SND_3E_DEPARTURE_BUS_TOYLAND_2, 192, 35, 60, 15), // 5 Ploddyphut MkII Bus
ROV( 51, 160, 240, SND_3C_DEPARTURE_BUS_TOYLAND_1, 240, 38, 90, 25), // 6 Ploddyphut MkIII Bus
ROV( 1, 108, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 20, 38, 12), // 7 Balogh Coal Truck
ROV( 18, 128, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 25, 48, 22), // 8 Uhl Coal Truck
ROV( 35, 138, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 28, 69, 45), // 9 DW Coal Truck
ROV( 2, 115, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 22, 38, 12), // 10 MPS Mail Truck
ROV( 19, 135, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 28, 48, 22), // 11 Reynard Mail Truck
ROV( 36, 145, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 30, 69, 45), // 12 Perry Mail Truck
ROV( 57, 115, 90, SND_3E_DEPARTURE_BUS_TOYLAND_2, 96, 22, 38, 12), // 13 MightyMover Mail Truck
ROV( 57, 135, 168, SND_3C_DEPARTURE_BUS_TOYLAND_1, 176, 28, 48, 22), // 14 Powernaught Mail Truck
ROV( 57, 145, 240, SND_3E_DEPARTURE_BUS_TOYLAND_2, 224, 30, 69, 45), // 15 Wizzowow Mail Truck
ROV( 3, 110, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 21, 38, 12), // 16 Witcombe Oil Tanker
ROV( 20, 140, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 25, 48, 22), // 17 Foster Oil Tanker
ROV( 37, 150, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 27, 69, 45), // 18 Perry Oil Tanker
ROV( 4, 105, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 14, 38, 12), // 19 Talbott Livestock Van
ROV( 21, 130, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 16, 48, 22), // 20 Uhl Livestock Van
ROV( 38, 140, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 18, 69, 45), // 21 Foster Livestock Van
ROV( 5, 107, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 14, 38, 12), // 22 Balogh Goods Truck
ROV( 22, 130, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 16, 48, 22), // 23 Craighead Goods Truck
ROV( 39, 140, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 18, 69, 45), // 24 Goss Goods Truck
ROV( 6, 114, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 20, 38, 12), // 25 Hereford Grain Truck
ROV( 23, 133, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 25, 48, 22), // 26 Thomas Grain Truck
ROV( 40, 143, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 30, 69, 45), // 27 Goss Grain Truck
ROV( 7, 118, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 20, 38, 12), // 28 Witcombe Wood Truck
ROV( 24, 137, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 22, 48, 22), // 29 Foster Wood Truck
ROV( 41, 147, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 24, 69, 45), // 30 Moreland Wood Truck
ROV( 8, 121, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 22, 38, 12), // 31 MPS Iron Ore Truck
ROV( 25, 140, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 25, 48, 22), // 32 Uhl Iron Ore Truck
ROV( 42, 150, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 27, 69, 45), // 33 Chippy Iron Ore Truck
ROV( 9, 112, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 15, 38, 12), // 34 Balogh Steel Truck
ROV( 26, 135, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 18, 48, 22), // 35 Uhl Steel Truck
ROV( 43, 145, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 20, 69, 45), // 36 Kelling Steel Truck
ROV( 10, 145, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 12, 38, 12), // 37 Balogh Armoured Truck
ROV( 27, 170, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 15, 48, 22), // 38 Uhl Armoured Truck
ROV( 44, 180, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 16, 69, 45), // 39 Foster Armoured Truck
ROV( 11, 112, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 17, 38, 12), // 40 Foster Food Van
ROV( 28, 134, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 20, 48, 22), // 41 Perry Food Van
ROV( 45, 144, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 22, 69, 45), // 42 Chippy Food Van
ROV( 12, 112, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 15, 38, 12), // 43 Uhl Paper Truck
ROV( 29, 135, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 18, 48, 22), // 44 Balogh Paper Truck
ROV( 46, 145, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 20, 69, 45), // 45 MPS Paper Truck
ROV( 13, 121, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 22, 38, 12), // 46 MPS Copper Ore Truck
ROV( 30, 140, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 25, 48, 22), // 47 Uhl Copper Ore Truck
ROV( 47, 150, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 27, 69, 45), // 48 Goss Copper Ore Truck
ROV( 14, 111, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 21, 38, 12), // 49 Uhl Water Tanker
ROV( 31, 141, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 25, 48, 22), // 50 Balogh Water Tanker
ROV( 48, 151, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 27, 69, 45), // 51 MPS Water Tanker
ROV( 15, 118, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 18, 38, 12), // 52 Balogh Fruit Truck
ROV( 32, 148, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 20, 48, 22), // 53 Uhl Fruit Truck
ROV( 49, 158, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 23, 69, 45), // 54 Kelling Fruit Truck
ROV( 16, 117, 90, SND_19_DEPARTURE_OLD_RV_1, 96, 17, 38, 12), // 55 Balogh Rubber Truck
ROV( 33, 147, 168, SND_19_DEPARTURE_OLD_RV_1, 176, 19, 48, 22), // 56 Uhl Rubber Truck
ROV( 50, 157, 240, SND_19_DEPARTURE_OLD_RV_1, 224, 22, 69, 45), // 57 RMT Rubber Truck
ROV( 52, 117, 90, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 96, 17, 38, 12), // 58 MightyMover Sugar Truck
ROV( 52, 147, 168, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 176, 19, 48, 22), // 59 Powernaught Sugar Truck
ROV( 52, 157, 240, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 224, 22, 69, 45), // 60 Wizzowow Sugar Truck
ROV( 53, 117, 90, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 96, 17, 38, 12), // 61 MightyMover Cola Truck
ROV( 53, 147, 168, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 176, 19, 48, 22), // 62 Powernaught Cola Truck
ROV( 53, 157, 240, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 224, 22, 69, 45), // 63 Wizzowow Cola Truck
ROV( 54, 117, 90, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 96, 17, 38, 12), // 64 MightyMover Candyfloss Truck
ROV( 54, 147, 168, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 176, 19, 48, 22), // 65 Powernaught Candyfloss Truck
ROV( 54, 157, 240, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 224, 22, 69, 45), // 66 Wizzowow Candyfloss Truck
ROV( 55, 117, 90, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 96, 17, 38, 12), // 67 MightyMover Toffee Truck
ROV( 55, 147, 168, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 176, 19, 48, 22), // 68 Powernaught Toffee Truck
ROV( 55, 157, 240, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 224, 22, 69, 45), // 69 Wizzowow Toffee Truck
ROV( 56, 117, 90, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 96, 17, 38, 12), // 70 MightyMover Toy Van
ROV( 56, 147, 168, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 176, 19, 48, 22), // 71 Powernaught Toy Van
ROV( 56, 157, 240, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 224, 22, 69, 45), // 72 Wizzowow Toy Van
ROV( 58, 117, 90, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 96, 17, 38, 12), // 73 MightyMover Sweet Truck
ROV( 58, 147, 168, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 176, 19, 48, 22), // 74 Powernaught Sweet Truck
ROV( 58, 157, 240, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 224, 22, 69, 45), // 75 Wizzowow Sweet Truck
ROV( 59, 117, 90, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 96, 17, 38, 12), // 76 MightyMover Battery Truck
ROV( 59, 147, 168, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 176, 19, 48, 22), // 77 Powernaught Battery Truck
ROV( 59, 157, 240, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 224, 22, 69, 45), // 78 Wizzowow Battery Truck
ROV( 60, 117, 90, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 96, 17, 38, 12), // 79 MightyMover Fizzy Drink Truck
ROV( 60, 147, 168, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 176, 19, 48, 22), // 80 Powernaught Fizzy Drink Truck
ROV( 60, 157, 240, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 224, 22, 69, 45), // 81 Wizzowow Fizzy Drink Truck
ROV( 61, 117, 90, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 96, 17, 38, 12), // 82 MightyMover Plastic Truck
ROV( 61, 147, 168, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 176, 19, 48, 22), // 83 Powernaught Plastic Truck
ROV( 61, 157, 240, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 224, 22, 69, 45), // 84 Wizzowow Plastic Truck
ROV( 62, 117, 90, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 96, 17, 38, 12), // 85 MightyMover Bubble Truck
ROV( 62, 147, 168, SND_3F_DEPARTURE_TRUCK_TOYLAND_1, 176, 19, 48, 22), // 86 Powernaught Bubble Truck
ROV( 62, 157, 240, SND_40_DEPARTURE_TRUCK_TOYLAND_2, 224, 22, 69, 45), // 87 Wizzowow Bubble Truck
};
#undef ROV

@ -7,8 +7,7 @@
[pre-amble]
/* win32_v.cpp only settings */
#if defined(_WIN32) && !defined(DEDICATED)
extern bool _force_full_redraw, _window_maximize;
extern uint _display_hz;
extern bool _window_maximize;
static const SettingDescGlobVarList _win32_settings[] = {
[post-amble]
@ -36,22 +35,6 @@ extver = SlXvFeatureTest()
orderproc = nullptr
[SDTG_VAR]
name = ""display_hz""
type = SLE_UINT
var = _display_hz
def = 0
min = 0
max = 120
cat = SC_EXPERT
[SDTG_BOOL]
name = ""force_full_redraw""
var = _force_full_redraw
def = false
cat = SC_EXPERT
[SDTG_BOOL]
name = ""window_maximize""
var = _window_maximize

@ -42,7 +42,7 @@
void CcTerraform(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2, uint64 p3, uint32 cmd)
{
if (result.Succeeded()) {
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
} else {
extern TileIndex _terraform_err_tile;
SetRedErrorSquare(_terraform_err_tile);
@ -92,7 +92,7 @@ static void GenerateRockyArea(TileIndex end, TileIndex start)
success = true;
}
if (success && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, end);
if (success && _settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, end);
}
/**
@ -133,7 +133,7 @@ bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_t
GenerateDesertArea(end_tile, start_tile);
break;
case DDSP_BUY_LAND:
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_PURCHASE_LAND_AREA | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound_SPLAT_RAIL);
DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_PURCHASE_LAND_AREA | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound_CONSTRUCTION_RAIL);
break;
default:
return false;
@ -255,7 +255,7 @@ struct TerraformToolbarWindow : Window {
switch (_settings_game.construction.purchase_land_permitted) {
case 0:
case 1:
DoCommandP(tile, OBJECT_OWNED_LAND, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound_SPLAT_RAIL);
DoCommandP(tile, OBJECT_OWNED_LAND, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound_CONSTRUCTION_RAIL);
break;
case 2:
@ -440,7 +440,7 @@ static void CommonRaiseLowerBigLand(TileIndex tile, int mode)
if (ta.w == 0 || ta.h == 0) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
uint h;
if (mode != 0) {

@ -1027,7 +1027,7 @@ void CcFoundTown(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
{
if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
}
@ -1987,7 +1987,7 @@ static void PlaceProc_House(TileIndex tile)
_cur_house, // p1 - house type and town index (town not yet set)
InteractiveRandom(), // p2 - random bits for the house
CMD_BUILD_HOUSE | CMD_MSG(STR_ERROR_CAN_T_BUILD_HOUSE_HERE),
CcPlaySound_SPLAT_RAIL
CcPlaySound_CONSTRUCTION_RAIL
);
if (!_ctrl_pressed) {

@ -2993,11 +2993,11 @@ bool Train::FindClosestDepot(TileIndex *location, DestinationID *destination, bo
void Train::PlayLeaveStationSound() const
{
static const SoundFx sfx[] = {
SND_04_TRAIN,
SND_0A_TRAIN_HORN,
SND_0A_TRAIN_HORN,
SND_47_MAGLEV_2,
SND_41_MAGLEV
SND_04_DEPARTURE_STEAM,
SND_0A_DEPARTURE_TRAIN,
SND_0A_DEPARTURE_TRAIN,
SND_47_DEPARTURE_MONORAIL,
SND_41_DEPARTURE_MAGLEV
};
if (PlayVehicleSound(this, VSE_START)) return;
@ -4633,7 +4633,7 @@ static bool CheckTrainCollision(Train *v)
AddTileNewsItem(STR_NEWS_TRAIN_CRASH, NT_ACCIDENT, v->tile);
ModifyStationRatingAround(v->tile, v->owner, -160, 30);
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_BIG_CRASH, v);
if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_TRAIN_COLLISION, v);
return true;
}

@ -728,10 +728,10 @@ static void TileLoopTreesDesert(TileIndex tile)
case TROPICZONE_RAINFOREST: {
static const SoundFx forest_sounds[] = {
SND_42_LOON_BIRD,
SND_43_LION,
SND_44_MONKEYS,
SND_48_DISTANT_BIRD
SND_42_RAINFOREST_1,
SND_43_RAINFOREST_2,
SND_44_RAINFOREST_3,
SND_48_RAINFOREST_4
};
uint32 r = Random();
@ -765,7 +765,7 @@ static void TileLoopTreesAlps(TileIndex tile)
if (GetTreeDensity(tile) == 3) {
uint32 r = Random();
if (Chance16I(1, 200, r) && _settings_client.sound.ambient) {
SndPlayTileFx((r & 0x80000000) ? SND_39_HEAVY_WIND : SND_34_WIND, tile);
SndPlayTileFx((r & 0x80000000) ? SND_39_ARCTIC_SNOW_2 : SND_34_ARCTIC_SNOW_1, tile);
}
}
return;

@ -2056,10 +2056,7 @@ bool Vehicle::HandleBreakdown()
/* FALL THROUGH */
case BREAKDOWN_CRITICAL:
if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
(train_or_ship ? SND_10_TRAIN_BREAKDOWN : SND_0F_VEHICLE_BREAKDOWN) :
(train_or_ship ? SND_3A_COMEDY_BREAKDOWN_2 : SND_35_COMEDY_BREAKDOWN), this);
SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ? SND_10_BREAKDOWN_TRAIN_SHIP : SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND, this);
}
if (!(this->vehstatus & VS_HIDDEN) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_NO_BREAKDOWN_SMOKE) && this->breakdown_delay > 0) {
EffectVehicle *u = CreateEffectVehicleRel(this, 4, 4, 5, EV_BREAKDOWN_SMOKE);
@ -2111,7 +2108,10 @@ bool Vehicle::HandleBreakdown()
switch (this->breakdown_type) {
case BREAKDOWN_CRITICAL:
if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ? SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, this);
bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
(train_or_ship ? SND_10_BREAKDOWN_TRAIN_SHIP : SND_0F_BREAKDOWN_ROADVEHICLE) :
(train_or_ship ? SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND : SND_35_BREAKDOWN_ROADVEHICLE_TOYLAND), this);
}
if (!(this->vehstatus & VS_HIDDEN) && !HasBit(EngInfo(this->engine_type)->misc_flags, EF_NO_BREAKDOWN_SMOKE) && this->breakdown_delay > 0) {
EffectVehicle *u = CreateEffectVehicleRel(this, 4, 4, 5, EV_BREAKDOWN_SMOKE);

@ -31,5 +31,6 @@ add_files(
dedicated_v.h
null_v.cpp
null_v.h
video_driver.cpp
video_driver.hpp
)

@ -56,7 +56,7 @@ void VideoDriver_Allegro::MakeDirty(int left, int top, int width, int height)
_num_dirty_rects++;
}
static void DrawSurfaceToScreen()
void VideoDriver_Allegro::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
@ -95,7 +95,7 @@ static void InitPalette()
UpdatePalette(0, 256);
}
static void CheckPaletteAnim()
void VideoDriver_Allegro::CheckPaletteAnim()
{
if (_cur_palette.count_dirty != 0) {
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
@ -447,95 +447,49 @@ void VideoDriver_Allegro::Stop()
if (--_allegro_instance_count == 0) allegro_exit();
}
void VideoDriver_Allegro::MainLoop()
void VideoDriver_Allegro::InputLoop()
{
auto cur_ticks = std::chrono::steady_clock::now();
auto last_realtime_tick = cur_ticks;
auto next_game_tick = cur_ticks;
auto next_draw_tick = cur_ticks;
CheckPaletteAnim();
for (;;) {
InteractiveRandom(); // randomness
bool old_ctrl_pressed = _ctrl_pressed;
PollEvent();
if (_exit_game) return;
_ctrl_pressed = !!(key_shifts & KB_CTRL_FLAG) != _invert_ctrl;
_shift_pressed = !!(key_shifts & KB_SHIFT_FLAG) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application */
if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0)
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application. */
if (key[KEY_TAB] && (key_shifts & KB_ALT_FLAG) == 0)
#endif
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
GameLoop();
GameLoopPaletteAnimations();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = !!(key_shifts & KB_CTRL_FLAG) != _invert_ctrl;
_shift_pressed = !!(key_shifts & KB_SHIFT_FLAG) != _invert_shift;
/* determine which directional keys are down */
_dirkeys =
(key[KEY_LEFT] ? 1 : 0) |
(key[KEY_UP] ? 2 : 0) |
(key[KEY_RIGHT] ? 4 : 0) |
(key[KEY_DOWN] ? 8 : 0);
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
/* Determine which directional keys are down. */
_dirkeys =
(key[KEY_LEFT] ? 1 : 0) |
(key[KEY_UP] ? 2 : 0) |
(key[KEY_RIGHT] ? 4 : 0) |
(key[KEY_DOWN] ? 8 : 0);
InputLoop();
UpdateWindows();
CheckPaletteAnim();
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
DrawSurfaceToScreen();
}
void VideoDriver_Allegro::MainLoop()
{
for (;;) {
InteractiveRandom(); // randomness
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
PollEvent();
if (_exit_game) return;
if (next_tick > now) {
std::this_thread::sleep_for(next_tick - now);
}
if (this->Tick()) {
this->Paint();
}
this->SleepTillNextTick();
}
}

@ -32,6 +32,11 @@ public:
bool ClaimMousePointer() override;
const char *GetName() const override { return "allegro"; }
protected:
void InputLoop() override;
void Paint() override;
void CheckPaletteAnim() override;
};
/** Factory for the allegro video driver. */

@ -32,10 +32,8 @@ private:
void *pixel_buffer; ///< used for direct pixel access
void *window_buffer; ///< Colour translation from palette to screen
static const int MAX_DIRTY_RECTS = 100;
Rect dirty_rect; ///< Region of the screen that needs redrawing.
Rect dirty_rects[MAX_DIRTY_RECTS]; ///< dirty rectangles
uint num_dirty_rects; ///< Number of dirty rectangles
uint32 palette[256]; ///< Colour Palette
public:
@ -74,6 +72,9 @@ public:
protected:
Dimension GetScreenSize() const override;
float GetDPIScale() override;
void InputLoop() override;
void Paint() override;
void CheckPaletteAnim() override;
private:
bool PollEvent();
@ -86,9 +87,7 @@ private:
bool MakeWindow(int width, int height);
void UpdatePalette(uint first_color, uint num_colors);
void CheckPaletteAnim();
void Draw(bool force_update = false);
void BlitIndexedToView32(int left, int top, int right, int bottom);
};

@ -21,12 +21,13 @@
#define Rect OTTDRect
#define Point OTTDPoint
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#undef Rect
#undef Point
#include "../../openttd.h"
#include "../../debug.h"
#include "../../core/geometry_type.hpp"
#include "../../core/geometry_func.hpp"
#include "../../core/math_func.hpp"
#include "cocoa_v.h"
#include "cocoa_wnd.h"
@ -125,7 +126,7 @@ VideoDriver_Cocoa::VideoDriver_Cocoa()
this->color_space = nullptr;
this->cgcontext = nullptr;
this->num_dirty_rects = lengthof(this->dirty_rects);
this->dirty_rect = {};
}
/** Stop Cocoa video driver. */
@ -192,13 +193,8 @@ const char *VideoDriver_Cocoa::Start(const StringList &parm)
*/
void VideoDriver_Cocoa::MakeDirty(int left, int top, int width, int height)
{
if (this->num_dirty_rects < lengthof(this->dirty_rects)) {
dirty_rects[this->num_dirty_rects].left = left;
dirty_rects[this->num_dirty_rects].top = top;
dirty_rects[this->num_dirty_rects].right = left + width;
dirty_rects[this->num_dirty_rects].bottom = top + height;
}
this->num_dirty_rects++;
Rect r = {left, top, left + width, top + height};
this->dirty_rect = BoundingRect(this->dirty_rect, r);
}
/**
@ -465,49 +461,39 @@ void VideoDriver_Cocoa::BlitIndexedToView32(int left, int top, int right, int bo
}
/**
* Draw window.
* Paint window.
* @param force_update Whether to redraw unconditionally
*/
void VideoDriver_Cocoa::Draw(bool force_update)
void VideoDriver_Cocoa::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
/* Check if we need to do anything */
if (this->num_dirty_rects == 0 || [ this->window isMiniaturized ]) return;
if (this->num_dirty_rects >= lengthof(this->dirty_rects)) {
this->num_dirty_rects = 1;
this->dirty_rects[0].left = 0;
this->dirty_rects[0].top = 0;
this->dirty_rects[0].right = this->window_width;
this->dirty_rects[0].bottom = this->window_height;
if (IsEmptyRect(this->dirty_rect) || [ this->window isMiniaturized ]) return;
/* We only need to blit in indexed mode since in 32bpp mode the game draws directly to the image. */
if (this->buffer_depth == 8) {
BlitIndexedToView32(
this->dirty_rect.left,
this->dirty_rect.top,
this->dirty_rect.right,
this->dirty_rect.bottom
);
}
/* Build the region of dirty rectangles */
for (uint i = 0; i < this->num_dirty_rects; i++) {
/* We only need to blit in indexed mode since in 32bpp mode the game draws directly to the image. */
if (this->buffer_depth == 8) {
BlitIndexedToView32(
this->dirty_rects[i].left,
this->dirty_rects[i].top,
this->dirty_rects[i].right,
this->dirty_rects[i].bottom
);
}
NSRect dirtyrect;
dirtyrect.origin.x = this->dirty_rect.left;
dirtyrect.origin.y = this->window_height - this->dirty_rect.bottom;
dirtyrect.size.width = this->dirty_rect.right - this->dirty_rect.left;
dirtyrect.size.height = this->dirty_rect.bottom - this->dirty_rect.top;
NSRect dirtyrect;
dirtyrect.origin.x = this->dirty_rects[i].left;
dirtyrect.origin.y = this->window_height - this->dirty_rects[i].bottom;
dirtyrect.size.width = this->dirty_rects[i].right - this->dirty_rects[i].left;
dirtyrect.size.height = this->dirty_rects[i].bottom - this->dirty_rects[i].top;
/* Notify OS X that we have new content to show. */
[ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ];
/* Normally drawRect will be automatically called by Mac OS X during next update cycle,
* and then blitting will occur. If force_update is true, it will be done right now. */
[ this->cocoaview setNeedsDisplayInRect:[ this->cocoaview getVirtualRect:dirtyrect ] ];
if (force_update) [ this->cocoaview displayIfNeeded ];
}
/* Tell the OS to get our contents to screen as soon as possible. */
[ CATransaction flush ];
this->num_dirty_rects = 0;
this->dirty_rect = {};
}
/** Update the palette. */
@ -523,7 +509,7 @@ void VideoDriver_Cocoa::UpdatePalette(uint first_color, uint num_colors)
this->palette[i] = clr;
}
this->num_dirty_rects = lengthof(this->dirty_rects);
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
/** Clear buffer to opaque black. */
@ -581,8 +567,8 @@ void VideoDriver_Cocoa::AllocateBackingStore()
}
/* Redraw screen */
this->num_dirty_rects = lengthof(this->dirty_rects);
this->GameSizeChanged();
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
/** Check if palette updates need to be performed. */
@ -632,14 +618,33 @@ bool VideoDriver_Cocoa::PollEvent()
return true;
}
void VideoDriver_Cocoa::InputLoop()
{
NSUInteger cur_mods = [ NSEvent modifierFlags ];
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = ((cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0) != _invert_ctrl;
_shift_pressed = ((cur_mods & NSShiftKeyMask) != 0) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed) {
#else
if (_tab_is_down) {
#endif
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
/** Main game loop. */
void VideoDriver_Cocoa::GameLoop()
{
auto cur_ticks = std::chrono::steady_clock::now();
auto last_realtime_tick = cur_ticks;
auto next_game_tick = cur_ticks;
auto next_draw_tick = cur_ticks;
for (;;) {
@autoreleasepool {
@ -653,69 +658,10 @@ void VideoDriver_Cocoa::GameLoop()
break;
}
NSUInteger cur_mods = [ NSEvent modifierFlags ];
#if defined(_DEBUG)
if (cur_mods & NSShiftKeyMask) {
#else
if (_tab_is_down) {
#endif
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
::GameLoop();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
_ctrl_pressed = (cur_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)) != 0;
_shift_pressed = (cur_mods & NSShiftKeyMask) != 0;
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
InputLoop();
UpdateWindows();
this->CheckPaletteAnim();
this->Draw();
}
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
std::this_thread::sleep_for(next_tick - now);
}
if (this->Tick()) {
this->Paint();
}
this->SleepTillNextTick();
}
}
}
@ -733,6 +679,7 @@ void VideoDriver_Cocoa::GameLoop()
self.wantsLayer = YES;
self.layer.magnificationFilter = kCAFilterNearest;
self.layer.opaque = YES;
}
return self;
}

@ -236,10 +236,6 @@ static void DedicatedHandleKeyInput()
void VideoDriver_Dedicated::MainLoop()
{
auto cur_ticks = std::chrono::steady_clock::now();
auto last_realtime_tick = cur_ticks;
auto next_game_tick = cur_ticks;
/* Signal handlers */
#if defined(UNIX)
signal(SIGTERM, DedicatedSignalHandler);
@ -283,44 +279,8 @@ void VideoDriver_Dedicated::MainLoop()
if (!_dedicated_forks) DedicatedHandleKeyInput();
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || _ddc_fastforward) {
if (_ddc_fastforward) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
GameLoop();
GameLoopPaletteAnimations();
InputLoop();
UpdateWindows();
}
/* Don't sleep when fast forwarding (for desync debugging) */
if (!_ddc_fastforward) {
/* Sleep longer on a dedicated server, if the game is paused and no clients connected.
* That can allow the CPU to better use deep sleep states. */
if (_pause_mode != 0 && !HasClients()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto now = std::chrono::steady_clock::now();
if (next_game_tick > now) {
std::this_thread::sleep_for(next_game_tick - now);
}
}
}
_fast_forward = _ddc_fastforward;
this->Tick();
this->SleepTillNextTick();
}
}

@ -338,7 +338,7 @@ void VideoDriver_SDL::CheckPaletteAnim()
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
static void Paint()
void VideoDriver_SDL::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
@ -372,10 +372,10 @@ static void Paint()
}
SDL_UpdateWindowSurfaceRects(_sdl_window, &r, 1);
MemSetT(&_dirty_rect, 0);
_dirty_rect = {};
}
static void PaintThread()
void VideoDriver_SDL::PaintThread()
{
/* First tell the main thread we're started */
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
@ -386,11 +386,16 @@ static void PaintThread()
while (_draw_continue) {
/* Then just draw and wait till we stop */
Paint();
this->Paint();
_draw_signal->wait(lock);
}
}
/* static */ void VideoDriver_SDL::PaintThreadThunk(VideoDriver_SDL *drv)
{
drv->PaintThread();
}
static const Dimension default_resolutions[] = {
{ 640, 480 },
{ 800, 600 },
@ -556,7 +561,7 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize)
* gotten smaller, reset our dirty rects. GameSizeChanged() a bit lower
* will mark the whole screen dirty again anyway, but this time with the
* new dimensions. */
MemSetT(&_dirty_rect, 0);
_dirty_rect = {};
_screen.width = _sdl_surface->w;
_screen.height = _sdl_surface->h;
@ -1059,36 +1064,22 @@ void VideoDriver_SDL::Stop()
}
}
void VideoDriver_SDL::LoopOnce()
void VideoDriver_SDL::InputLoop()
{
uint32 mod;
int numkeys;
const Uint8 *keys;
InteractiveRandom(); // randomness
uint32 mod = SDL_GetModState();
const Uint8 *keys = SDL_GetKeyboardState(NULL);
while (PollEvent() == -1) {}
if (_exit_game) {
#ifdef __EMSCRIPTEN__
/* Emscripten is event-driven, and as such the main loop is inside
* the browser. So if _exit_game goes true, the main loop ends (the
* cancel call), but we still have to call the cleanup that is
* normally done at the end of the main loop for non-Emscripten.
* After that, Emscripten just halts, and the HTML shows a nice
* "bye, see you next time" message. */
emscripten_cancel_main_loop();
MainLoopCleanup();
#endif
return;
}
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
mod = SDL_GetModState();
keys = SDL_GetKeyboardState(&numkeys);
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application */
* to switch to another application. */
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
#endif /* defined(_DEBUG) */
{
@ -1097,90 +1088,53 @@ void VideoDriver_SDL::LoopOnce()
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* Determine which directional keys are down. */
_dirkeys =
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
void VideoDriver_SDL::LoopOnce()
{
InteractiveRandom(); // randomness
/* The gameloop is the part that can run asynchronously. The rest
* except sleeping can't. */
if (_draw_mutex != nullptr) draw_lock.unlock();
GameLoop();
if (_draw_mutex != nullptr) draw_lock.lock();
GameLoopPaletteAnimations();
while (PollEvent() == -1) {}
if (_exit_game) {
#ifdef __EMSCRIPTEN__
/* Emscripten is event-driven, and as such the main loop is inside
* the browser. So if _exit_game goes true, the main loop ends (the
* cancel call), but we still have to call the cleanup that is
* normally done at the end of the main loop for non-Emscripten.
* After that, Emscripten just halts, and the HTML shows a nice
* "bye, see you next time" message. */
emscripten_cancel_main_loop();
MainLoopCleanup();
#endif
return;
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
/* determine which directional keys are down */
_dirkeys =
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
InputLoop();
UpdateWindows();
this->CheckPaletteAnim();
if (VideoDriver::Tick()) {
if (_draw_mutex != nullptr && !HasModalProgress()) {
_draw_signal->notify_one();
} else {
Paint();
this->Paint();
}
}
/* Emscripten is running an event-based mainloop; there is already some
* downtime between each iteration, so no need to sleep. */
#ifndef __EMSCRIPTEN__
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
if (_draw_mutex != nullptr) draw_lock.unlock();
std::this_thread::sleep_for(next_tick - now);
if (_draw_mutex != nullptr) draw_lock.lock();
}
}
this->SleepTillNextTick();
#endif
}
void VideoDriver_SDL::MainLoop()
{
cur_ticks = std::chrono::steady_clock::now();
last_realtime_tick = cur_ticks;
next_game_tick = cur_ticks;
this->CheckPaletteAnim();
if (_draw_threaded) {
/* Initialise the mutex first, because that's the thing we *need*
* directly in the newly created thread. */
@ -1192,7 +1146,7 @@ void VideoDriver_SDL::MainLoop()
_draw_signal = new std::condition_variable_any();
_draw_continue = true;
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &PaintThread);
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL::PaintThreadThunk, this);
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
@ -1317,3 +1271,14 @@ Dimension VideoDriver_SDL::GetScreenSize() const
return { static_cast<uint>(mode.w), static_cast<uint>(mode.h) };
}
bool VideoDriver_SDL::LockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.lock();
return true;
}
void VideoDriver_SDL::UnlockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.unlock();
}

@ -43,6 +43,12 @@ public:
protected:
Dimension GetScreenSize() const override;
void InputLoop() override;
bool LockVideoBuffer() override;
void UnlockVideoBuffer() override;
void Paint() override;
void PaintThread() override;
void CheckPaletteAnim() override;
private:
int PollEvent();
@ -50,7 +56,6 @@ private:
void MainLoopCleanup();
bool CreateMainSurface(uint w, uint h, bool resize);
bool CreateMainWindow(uint w, uint h);
void CheckPaletteAnim();
#ifdef __EMSCRIPTEN__
/* Convert a constant pointer back to a non-constant pointer to a member function. */
@ -62,14 +67,11 @@ private:
*/
bool edit_box_focused;
std::chrono::steady_clock::time_point cur_ticks;
std::chrono::steady_clock::time_point last_realtime_tick;
std::chrono::steady_clock::time_point next_game_tick;
std::chrono::steady_clock::time_point next_draw_tick;
int startup_display;
std::thread draw_thread;
std::unique_lock<std::recursive_mutex> draw_lock;
static void PaintThreadThunk(VideoDriver_SDL *drv);
};
/** Factory for the SDL video driver. */

@ -128,8 +128,10 @@ static void InitPalette()
UpdatePalette(true);
}
static void CheckPaletteAnim()
void VideoDriver_SDL::CheckPaletteAnim()
{
_local_palette = _cur_palette;
if (_cur_palette.count_dirty != 0) {
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
@ -152,7 +154,7 @@ static void CheckPaletteAnim()
}
}
static void DrawSurfaceToScreen()
void VideoDriver_SDL::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
@ -178,7 +180,7 @@ static void DrawSurfaceToScreen()
}
}
static void DrawSurfaceToScreenThread()
void VideoDriver_SDL::PaintThread()
{
/* First tell the main thread we're started */
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
@ -188,13 +190,17 @@ static void DrawSurfaceToScreenThread()
_draw_signal->wait(*_draw_mutex);
while (_draw_continue) {
CheckPaletteAnim();
/* Then just draw and wait till we stop */
DrawSurfaceToScreen();
this->Paint();
_draw_signal->wait(lock);
}
}
/* static */ void VideoDriver_SDL::PaintThreadThunk(VideoDriver_SDL *drv)
{
drv->PaintThread();
}
static const Dimension _default_resolutions[] = {
{ 640, 480},
{ 800, 600},
@ -410,11 +416,7 @@ bool VideoDriver_SDL::ClaimMousePointer()
}
struct SDLVkMapping {
#if SDL_VERSION_ATLEAST(1, 3, 0)
SDL_Keycode vk_from;
#else
uint16 vk_from;
#endif
byte vk_count;
byte map_to;
};
@ -653,20 +655,45 @@ void VideoDriver_SDL::Stop()
}
}
void VideoDriver_SDL::MainLoop()
void VideoDriver_SDL::InputLoop()
{
auto cur_ticks = std::chrono::steady_clock::now();
auto last_realtime_tick = cur_ticks;
auto next_game_tick = cur_ticks;
auto next_draw_tick = cur_ticks;
uint32 mod;
uint32 mod = SDL_GetModState();
int numkeys;
Uint8 *keys;
Uint8 *keys = SDL_GetKeyState(&numkeys);
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
CheckPaletteAnim();
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application. */
if (keys[SDLK_TAB] && (mod & KMOD_ALT) == 0)
#endif /* defined(_DEBUG) */
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
/* Determine which directional keys are down. */
_dirkeys =
(keys[SDLK_LEFT] ? 1 : 0) |
(keys[SDLK_UP] ? 2 : 0) |
(keys[SDLK_RIGHT] ? 4 : 0) |
(keys[SDLK_DOWN] ? 8 : 0);
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
void VideoDriver_SDL::MainLoop()
{
std::thread draw_thread;
std::unique_lock<std::recursive_mutex> draw_lock;
if (_draw_threaded) {
/* Initialise the mutex first, because that's the thing we *need*
* directly in the newly created thread. */
@ -674,16 +701,16 @@ void VideoDriver_SDL::MainLoop()
if (_draw_mutex == nullptr) {
_draw_threaded = false;
} else {
draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
_draw_signal = new std::condition_variable_any();
_draw_continue = true;
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &DrawSurfaceToScreenThread);
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL::PaintThreadThunk, this);
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
draw_lock.unlock();
draw_lock.release();
this->draw_lock.unlock();
this->draw_lock.release();
delete _draw_mutex;
delete _draw_signal;
_draw_mutex = nullptr;
@ -703,107 +730,14 @@ void VideoDriver_SDL::MainLoop()
while (PollEvent() == -1) {}
if (_exit_game) break;
mod = SDL_GetModState();
#if SDL_VERSION_ATLEAST(1, 3, 0)
keys = SDL_GetKeyboardState(&numkeys);
#else
keys = SDL_GetKeyState(&numkeys);
#endif
#if defined(_DEBUG)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application */
#if SDL_VERSION_ATLEAST(1, 3, 0)
if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0)
#else
if (keys[SDLK_TAB] && (mod & KMOD_ALT) == 0)
#endif /* SDL_VERSION_ATLEAST(1, 3, 0) */
#endif /* defined(_DEBUG) */
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
/* The gameloop is the part that can run asynchronously. The rest
* except sleeping can't. */
if (_draw_mutex != nullptr) draw_lock.unlock();
GameLoop();
if (_draw_mutex != nullptr) draw_lock.lock();
GameLoopPaletteAnimations();
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl;
_shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift;
/* determine which directional keys are down */
_dirkeys =
#if SDL_VERSION_ATLEAST(1, 3, 0)
(keys[SDL_SCANCODE_LEFT] ? 1 : 0) |
(keys[SDL_SCANCODE_UP] ? 2 : 0) |
(keys[SDL_SCANCODE_RIGHT] ? 4 : 0) |
(keys[SDL_SCANCODE_DOWN] ? 8 : 0);
#else
(keys[SDLK_LEFT] ? 1 : 0) |
(keys[SDLK_UP] ? 2 : 0) |
(keys[SDLK_RIGHT] ? 4 : 0) |
(keys[SDLK_DOWN] ? 8 : 0);
#endif
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
InputLoop();
UpdateWindows();
_local_palette = _cur_palette;
if (this->Tick()) {
if (_draw_mutex != nullptr && !HasModalProgress()) {
_draw_signal->notify_one();
} else {
CheckPaletteAnim();
DrawSurfaceToScreen();
}
}
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
if (_draw_mutex != nullptr) draw_lock.unlock();
std::this_thread::sleep_for(next_tick - now);
if (_draw_mutex != nullptr) draw_lock.lock();
this->Paint();
}
}
this->SleepTillNextTick();
}
if (_draw_mutex != nullptr) {
@ -811,8 +745,8 @@ void VideoDriver_SDL::MainLoop()
/* Sending signal if there is no thread blocked
* is very valid and results in noop */
_draw_signal->notify_one();
if (draw_lock.owns_lock()) draw_lock.unlock();
draw_lock.release();
if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
this->draw_lock.release();
draw_thread.join();
delete _draw_mutex;
@ -863,4 +797,15 @@ void VideoDriver_SDL::ReleaseBlitterLock()
if (_draw_mutex != nullptr) _draw_mutex->unlock();
}
bool VideoDriver_SDL::LockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.lock();
return true;
}
void VideoDriver_SDL::UnlockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.unlock();
}
#endif /* WITH_SDL */

@ -36,10 +36,23 @@ public:
bool ClaimMousePointer() override;
const char *GetName() const override { return "sdl"; }
protected:
void InputLoop() override;
bool LockVideoBuffer() override;
void UnlockVideoBuffer() override;
void Paint() override;
void PaintThread() override;
void CheckPaletteAnim();
private:
std::unique_lock<std::recursive_mutex> draw_lock;
int PollEvent();
bool CreateMainSurface(uint w, uint h);
void SetupKeyboard();
static void PaintThreadThunk(VideoDriver_SDL *drv);
};
/** Factory for the SDL video driver. */

@ -0,0 +1,84 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file video_driver.cpp Common code between video driver implementations. */
#include "../stdafx.h"
#include "../debug.h"
#include "../gfx_func.h"
#include "../progress.h"
#include "../thread.h"
#include "../window_func.h"
#include "video_driver.hpp"
bool VideoDriver::Tick()
{
auto cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - this->last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - this->last_realtime_tick);
_realtime_tick += delta.count();
this->last_realtime_tick += delta;
}
if (cur_ticks >= this->next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
this->next_game_tick = cur_ticks + this->GetGameInterval();
} else {
this->next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (this->next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) this->next_game_tick = cur_ticks;
}
/* The game loop is the part that can run asynchronously.
* The rest except sleeping can't. */
this->UnlockVideoBuffer();
::GameLoop();
this->LockVideoBuffer();
::GameLoopPaletteAnimations();
/* For things like dedicated server, don't run a separate draw-tick. */
if (!this->HasGUI()) {
::InputLoop();
UpdateWindows();
this->next_draw_tick = this->next_game_tick;
}
}
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (this->HasGUI() && cur_ticks >= this->next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
this->next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (this->next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) this->next_draw_tick = cur_ticks;
this->InputLoop();
::InputLoop();
UpdateWindows();
this->CheckPaletteAnim();
return true;
}
return false;
}
void VideoDriver::SleepTillNextTick()
{
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(this->next_draw_tick, this->next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
this->UnlockVideoBuffer();
std::this_thread::sleep_for(next_tick - now);
this->LockVideoBuffer();
}
}
}

@ -156,6 +156,50 @@ protected:
}
}
/**
* Handle input logic, is CTRL pressed, should we fast-forward, etc.
*/
virtual void InputLoop() {}
/**
* Make sure the video buffer is ready for drawing.
* @returns True if the video buffer has to be unlocked.
*/
virtual bool LockVideoBuffer() {
return false;
}
/**
* Unlock a previously locked video buffer.
*/
virtual void UnlockVideoBuffer() {}
/**
* Paint the window.
*/
virtual void Paint() {}
/**
* Thread function for threaded drawing.
*/
virtual void PaintThread() {}
/**
* Process any pending palette animation.
*/
virtual void CheckPaletteAnim() {}
/**
* Run the game for a single tick, processing boththe game-tick and draw-tick.
* @returns True if the driver should redraw the screen.
*/
bool Tick();
/**
* Sleep till the next tick is about to happen.
*/
void SleepTillNextTick();
std::chrono::steady_clock::duration GetGameInterval()
{
return std::chrono::milliseconds(MILLISECONDS_PER_TICK);
@ -165,6 +209,10 @@ protected:
{
return std::chrono::microseconds(1000000 / _settings_client.gui.refresh_rate);
}
std::chrono::steady_clock::time_point last_realtime_tick;
std::chrono::steady_clock::time_point next_game_tick;
std::chrono::steady_clock::time_point next_draw_tick;
};
#endif /* VIDEO_VIDEO_DRIVER_HPP */

@ -14,6 +14,7 @@
#include "../rev.h"
#include "../blitter/factory.hpp"
#include "../network/network.h"
#include "../core/geometry_func.hpp"
#include "../core/math_func.hpp"
#include "../core/random_func.hpp"
#include "../texteff.hpp"
@ -49,7 +50,6 @@ static struct {
HBITMAP dib_sect; ///< System bitmap object referencing our rendering buffer.
void *buffer_bits; ///< Internal rendering buffer.
HPALETTE gdi_palette; ///< Palette object for 8bpp blitter.
RECT update_rect; ///< Current dirty rect.
int width; ///< Width in pixels of our display surface.
int height; ///< Height in pixels of our display surface.
int width_org; ///< Original monitor resolution width, before we changed it.
@ -59,9 +59,7 @@ static struct {
bool running; ///< Is the main loop running?
} _wnd;
bool _force_full_redraw;
bool _window_maximize;
uint _display_hz;
static Dimension _bck_resolution;
DWORD _imm_props;
@ -75,6 +73,8 @@ static std::condition_variable_any *_draw_signal = nullptr;
static volatile bool _draw_continue;
/** Local copy of the palette for use in the drawing thread. */
static Palette _local_palette;
/** Region of the screen that needs redrawing. */
static Rect _dirty_rect;
static void MakePalette()
{
@ -256,12 +256,10 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
settings.dmFields =
DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
(_display_hz != 0 ? DM_DISPLAYFREQUENCY : 0);
DM_PELSHEIGHT;
settings.dmBitsPerPel = BlitterFactory::GetCurrentBlitter()->GetScreenDepth();
settings.dmPelsWidth = _wnd.width_org;
settings.dmPelsHeight = _wnd.height_org;
settings.dmDisplayFrequency = _display_hz;
/* Check for 8 bpp support. */
if (settings.dmBitsPerPel == 8 &&
@ -335,10 +333,24 @@ bool VideoDriver_Win32::MakeWindow(bool full_screen)
}
/** Do palette animation and blit to the window. */
static void PaintWindow(HDC dc)
void VideoDriver_Win32::Paint()
{
PerformanceMeasurer framerate(PFE_VIDEO);
if (IsEmptyRect(_dirty_rect)) return;
/* Convert update region from logical to device coordinates. */
POINT pt = {0, 0};
ClientToScreen(_wnd.main_wnd, &pt);
RECT r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right, _dirty_rect.bottom };
OffsetRect(&r, pt.x, pt.y);
/* Create a device context that is clipped to the region we need to draw.
* GetDCEx 'consumes' the update region, so we may not destroy it ourself. */
HRGN rgn = CreateRectRgnIndirect(&r);
HDC dc = GetDCEx(_wnd.main_wnd, rgn, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTRGN);
HDC dc2 = CreateCompatibleDC(dc);
HBITMAP old_bmp = (HBITMAP)SelectObject(dc2, _wnd.dib_sect);
HPALETTE old_palette = SelectPalette(dc, _wnd.gdi_palette, FALSE);
@ -368,9 +380,13 @@ static void PaintWindow(HDC dc)
SelectPalette(dc, old_palette, TRUE);
SelectObject(dc2, old_bmp);
DeleteDC(dc2);
ReleaseDC(_wnd.main_wnd, dc);
_dirty_rect = {};
}
static void PaintWindowThread()
void VideoDriver_Win32::PaintThread()
{
/* First tell the main thread we're started */
std::unique_lock<std::recursive_mutex> lock(*_draw_mutex);
@ -380,21 +396,7 @@ static void PaintWindowThread()
_draw_signal->wait(*_draw_mutex);
while (_draw_continue) {
/* Convert update region from logical to device coordinates. */
POINT pt = {0, 0};
ClientToScreen(_wnd.main_wnd, &pt);
OffsetRect(&_wnd.update_rect, pt.x, pt.y);
/* Create a device context that is clipped to the region we need to draw.
* GetDCEx 'consumes' the update region, so we may not destroy it ourself. */
HRGN rgn = CreateRectRgnIndirect(&_wnd.update_rect);
HDC dc = GetDCEx(_wnd.main_wnd, rgn, DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_INTERSECTRGN);
PaintWindow(dc);
/* Clear update rect. */
SetRectEmpty(&_wnd.update_rect);
ReleaseDC(_wnd.main_wnd, dc);
this->Paint();
/* Flush GDI buffer to ensure drawing here doesn't conflict with any GDI usage in the main WndProc. */
GdiFlush();
@ -403,6 +405,11 @@ static void PaintWindowThread()
}
}
/* static */ void VideoDriver_Win32::PaintThreadThunk(VideoDriver_Win32 *drv)
{
drv->PaintThread();
}
/** Forward key presses to the window system. */
static LRESULT HandleCharMsg(uint keycode, WChar charcode)
{
@ -606,7 +613,6 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
{
static uint32 keycode = 0;
static bool console = false;
static bool in_sizemove = false;
switch (msg) {
case WM_CREATE:
@ -615,32 +621,14 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
_imm_props = ImmGetProperty(GetKeyboardLayout(0), IGP_PROPERTY);
break;
case WM_ENTERSIZEMOVE:
in_sizemove = true;
break;
case WM_EXITSIZEMOVE:
in_sizemove = false;
break;
case WM_PAINT:
if (!in_sizemove && _draw_mutex != nullptr && !HasModalProgress()) {
/* Get the union of the old update rect and the new update rect. */
RECT r;
GetUpdateRect(hwnd, &r, FALSE);
UnionRect(&_wnd.update_rect, &_wnd.update_rect, &r);
/* Mark the window as updated, otherwise Windows would send more WM_PAINT messages. */
ValidateRect(hwnd, nullptr);
_draw_signal->notify_one();
} else {
PAINTSTRUCT ps;
case WM_PAINT: {
RECT r;
GetUpdateRect(hwnd, &r, FALSE);
static_cast<VideoDriver_Win32 *>(VideoDriver::GetInstance())->MakeDirty(r.left, r.top, r.right - r.left, r.bottom - r.top);
BeginPaint(hwnd, &ps);
PaintWindow(ps.hdc);
EndPaint(hwnd, &ps);
}
ValidateRect(hwnd, nullptr);
return 0;
}
case WM_PALETTECHANGED:
if ((HWND)wParam == hwnd) return 0;
@ -653,7 +641,9 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
SelectPalette(hDC, hOldPalette, TRUE);
ReleaseDC(hwnd, hDC);
if (nChanged != 0) InvalidateRect(hwnd, nullptr, FALSE);
if (nChanged != 0) {
static_cast<VideoDriver_Win32 *>(VideoDriver::GetInstance())->MakeDirty(0, 0, _screen.width, _screen.height);
}
return 0;
}
@ -1122,29 +1112,59 @@ void VideoDriver_Win32::Stop()
void VideoDriver_Win32::MakeDirty(int left, int top, int width, int height)
{
RECT r = { left, top, left + width, top + height };
InvalidateRect(_wnd.main_wnd, &r, FALSE);
Rect r = {left, top, left + width, top + height};
_dirty_rect = BoundingRect(_dirty_rect, r);
}
static void CheckPaletteAnim()
void VideoDriver_Win32::CheckPaletteAnim()
{
if (_cur_palette.count_dirty == 0) return;
_local_palette = _cur_palette;
InvalidateRect(_wnd.main_wnd, nullptr, FALSE);
this->MakeDirty(0, 0, _screen.width, _screen.height);
}
void VideoDriver_Win32::InputLoop()
{
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = (_wnd.has_focus && GetAsyncKeyState(VK_CONTROL) < 0) != _invert_ctrl;
_shift_pressed = (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0) != _invert_shift;
#if defined(_DEBUG)
if (_shift_pressed)
#else
/* Speedup when pressing tab, except when using ALT+TAB
* to switch to another application. */
if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0)
#endif
{
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
/* Determine which directional keys are down. */
if (_wnd.has_focus) {
_dirkeys =
(GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) +
(GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) +
(GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) +
(GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
} else {
_dirkeys = 0;
}
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
}
void VideoDriver_Win32::MainLoop()
{
MSG mesg;
auto cur_ticks = std::chrono::steady_clock::now();
auto last_realtime_tick = cur_ticks;
auto next_game_tick = cur_ticks;
auto next_draw_tick = cur_ticks;
std::thread draw_thread;
std::unique_lock<std::recursive_mutex> draw_lock;
if (_draw_threaded) {
/* Initialise the mutex first, because that's the thing we *need*
@ -1157,15 +1177,15 @@ void VideoDriver_Win32::MainLoop()
}
if (_draw_threaded) {
draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
this->draw_lock = std::unique_lock<std::recursive_mutex>(*_draw_mutex);
_draw_continue = true;
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &PaintWindowThread);
_draw_threaded = StartNewThread(&draw_thread, "ottd:draw-win32", &VideoDriver_Win32::PaintThreadThunk, this);
/* Free the mutex if we won't be able to use it. */
if (!_draw_threaded) {
draw_lock.unlock();
draw_lock.release();
this->draw_lock.unlock();
this->draw_lock.release();
delete _draw_mutex;
delete _draw_signal;
_draw_mutex = nullptr;
@ -1180,108 +1200,27 @@ void VideoDriver_Win32::MainLoop()
_wnd.running = true;
CheckPaletteAnim();
for (;;) {
InteractiveRandom(); // randomness
while (PeekMessage(&mesg, nullptr, 0, 0, PM_REMOVE)) {
InteractiveRandom(); // randomness
/* Convert key messages to char messages if we want text input. */
if (EditBoxInGlobalFocus()) TranslateMessage(&mesg);
DispatchMessage(&mesg);
}
if (_exit_game) break;
#if defined(_DEBUG)
if (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0 &&
#else
/* Speed up using TAB, but disable for ALT+TAB of course */
if (_wnd.has_focus && GetAsyncKeyState(VK_TAB) < 0 && GetAsyncKeyState(VK_MENU) >= 0 &&
#endif
!_networking && _game_mode != GM_MENU) {
_fast_forward |= 2;
} else if (_fast_forward & 2) {
_fast_forward = 0;
}
cur_ticks = std::chrono::steady_clock::now();
/* If more than a millisecond has passed, increase the _realtime_tick. */
if (cur_ticks - last_realtime_tick > std::chrono::milliseconds(1)) {
auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(cur_ticks - last_realtime_tick);
IncreaseRealtimeTick(delta.count());
last_realtime_tick += delta;
}
if (cur_ticks >= next_game_tick || (_fast_forward && !_pause_mode)) {
if (_fast_forward && !_pause_mode) {
next_game_tick = cur_ticks + this->GetGameInterval();
} else {
next_game_tick += this->GetGameInterval();
/* Avoid next_game_tick getting behind more and more if it cannot keep up. */
if (next_game_tick < cur_ticks - ALLOWED_DRIFT * this->GetGameInterval()) next_game_tick = cur_ticks;
}
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
GdiFlush();
/* The game loop is the part that can run asynchronously.
* The rest except sleeping can't. */
if (_draw_threaded) draw_lock.unlock();
GameLoop();
if (_draw_threaded) draw_lock.lock();
GameLoopPaletteAnimations();
}
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
GdiFlush();
/* Prevent drawing when switching mode, as windows can be removed when they should still appear. */
if (cur_ticks >= next_draw_tick && (_switch_mode == SM_NONE || HasModalProgress())) {
next_draw_tick += this->GetDrawInterval();
/* Avoid next_draw_tick getting behind more and more if it cannot keep up. */
if (next_draw_tick < cur_ticks - ALLOWED_DRIFT * this->GetDrawInterval()) next_draw_tick = cur_ticks;
bool old_ctrl_pressed = _ctrl_pressed;
bool old_shift_pressed = _shift_pressed;
_ctrl_pressed = (_wnd.has_focus && GetAsyncKeyState(VK_CONTROL) < 0) != _invert_ctrl;
_shift_pressed = (_wnd.has_focus && GetAsyncKeyState(VK_SHIFT) < 0) != _invert_shift;
/* determine which directional keys are down */
if (_wnd.has_focus) {
_dirkeys =
(GetAsyncKeyState(VK_LEFT) < 0 ? 1 : 0) +
(GetAsyncKeyState(VK_UP) < 0 ? 2 : 0) +
(GetAsyncKeyState(VK_RIGHT) < 0 ? 4 : 0) +
(GetAsyncKeyState(VK_DOWN) < 0 ? 8 : 0);
if (this->Tick()) {
if (_draw_mutex != nullptr && !HasModalProgress()) {
_draw_signal->notify_one();
} else {
_dirkeys = 0;
}
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
if (old_shift_pressed != _shift_pressed) HandleShiftChanged();
if (_force_full_redraw) MarkWholeScreenDirty();
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
GdiFlush();
InputLoop();
UpdateWindows();
CheckPaletteAnim();
}
/* If we are not in fast-forward, create some time between calls to ease up CPU usage. */
if (!_fast_forward || _pause_mode) {
/* See how much time there is till we have to process the next event, and try to hit that as close as possible. */
auto next_tick = std::min(next_draw_tick, next_game_tick);
auto now = std::chrono::steady_clock::now();
if (next_tick > now) {
/* Flush GDI buffer to ensure we don't conflict with the drawing thread. */
GdiFlush();
if (_draw_mutex != nullptr) draw_lock.unlock();
std::this_thread::sleep_for(next_tick - now);
if (_draw_mutex != nullptr) draw_lock.lock();
this->Paint();
}
}
this->SleepTillNextTick();
}
if (_draw_threaded) {
@ -1289,8 +1228,8 @@ void VideoDriver_Win32::MainLoop()
/* Sending signal if there is no thread blocked
* is very valid and results in noop */
_draw_signal->notify_all();
if (draw_lock.owns_lock()) draw_lock.unlock();
draw_lock.release();
if (this->draw_lock.owns_lock()) this->draw_lock.unlock();
this->draw_lock.release();
draw_thread.join();
delete _draw_mutex;
@ -1391,3 +1330,14 @@ float VideoDriver_Win32::GetDPIScale()
return cur_dpi > 0 ? cur_dpi / 96.0f : 1.0f; // Default Windows DPI value is 96.
}
bool VideoDriver_Win32::LockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.lock();
return true;
}
void VideoDriver_Win32::UnlockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.unlock();
}

@ -43,8 +43,18 @@ public:
protected:
Dimension GetScreenSize() const override;
float GetDPIScale() override;
void InputLoop() override;
bool LockVideoBuffer() override;
void UnlockVideoBuffer() override;
void Paint() override;
void PaintThread() override;
void CheckPaletteAnim() override;
private:
std::unique_lock<std::recursive_mutex> draw_lock;
static void PaintThreadThunk(VideoDriver_Win32 *drv);
};
/** The factory for Windows' video driver. */

Loading…
Cancel
Save