# HG changeset patch # User richk # Date 1211849455 0 # Node ID 67db0d431d5e428ac87c7b87fecb456968e313ab # Parent 68a692eacf22f7aae74106de4cb99eb8a65d16a2 (svn r13281) [NewGRF_ports] -Sync: with trunk r13145:13280. Includes support for Noise Level on Prop 24 in .grf files. diff -r 68a692eacf22 -r 67db0d431d5e bin/data/airportsbasic.grf Binary file bin/data/airportsbasic.grf has changed diff -r 68a692eacf22 -r 67db0d431d5e bin/data/airportsextended.grf Binary file bin/data/airportsextended.grf has changed diff -r 68a692eacf22 -r 67db0d431d5e bin/data/seaplaneport.grf Binary file bin/data/seaplaneport.grf has changed diff -r 68a692eacf22 -r 67db0d431d5e bin/data/sprites/airportsbasic.nfo --- a/bin/data/sprites/airportsbasic.nfo Mon May 26 20:45:25 2008 +0000 +++ b/bin/data/sprites/airportsbasic.nfo Tue May 27 00:50:55 2008 +0000 @@ -40,7 +40,7 @@ // Small Airport //---------------------------- // 11 properties to change, 1 station to change, station id = 0 - 15 * 656 00 0D 0B 01 00 + 15 * 656 00 0D 0C 01 00 // Class ID 08 "SMLL" @@ -263,12 +263,15 @@ // Prop22 Catchment Area 22 04 +// Prop24 Noise Level + 24 03 + //------------------------------ // Large Airport //------------------------------ // 11 properties to change, 1 airport to change, airport id = 1 - 16 * 1086 00 0D 0B 01 01 + 16 * 1086 00 0D 0C 01 01 // Class ID 08 "LRGE" @@ -649,6 +652,9 @@ // Prop22 Catchment Area 22 05 +// Prop24 Noise Level + 24 05 + //availability date varaction2 //small airport available from 1927 (1920+7) to 1964 (1920+44) 17 * 14 02 0D @@ -695,7 +701,7 @@ // Heliport //------------------------------ // 10 properties to change, 1 airport to change, airport id = 2 - 23 * 204 00 0D 0A 01 02 + 23 * 204 00 0D 0B 01 02 // Class ID 08 "HELI" @@ -787,6 +793,9 @@ // Prop22 Catchment area 22 04 +// Prop24 Noise Level + 24 01 + //availability date varaction2 //large airport available from 1975 (1920+55) to 2175 (1920+255) 24 * 14 02 0D @@ -814,7 +823,7 @@ //------------------------- // 10 properties to change, 1 station to change, station id = 3 - 27 * 189 00 0D 09 01 03 + 27 * 189 00 0D 0A 01 03 // Class ID 08 "SYST" @@ -895,6 +904,9 @@ // Prop22 Catchment Area 22 03 +// Prop24 Noise Level + 24 00 + //availability date varaction2 //Oilrig available from 1920 (1920+00) to 2175 (1920+255) 28 * 14 02 0D @@ -923,7 +935,7 @@ //------------------------- // 10 properties to change, 1 station to change, station id = 4 - 31 * 87 00 0D 06 01 04 + 31 * 87 00 0D 07 01 04 // Class ID 08 "SYST" @@ -965,6 +977,9 @@ // Prop20 Port Subtype 20 0F +// Prop24 Noise Level + 24 00 + // Use graphics ID (1 station, ID 0, 3 cargo specific graphics, default cargo = 0) 32 * 7 03 0D 01 04 00 00 00 diff -r 68a692eacf22 -r 67db0d431d5e bin/data/sprites/airportsextended.nfo --- a/bin/data/sprites/airportsextended.nfo Mon May 26 20:45:25 2008 +0000 +++ b/bin/data/sprites/airportsextended.nfo Tue May 27 00:50:55 2008 +0000 @@ -167,7 +167,7 @@ //Commuter Airport // 10 properties to change, 1 station to change, station id = 0 - 140 * 1191 00 0D 0C 01 00 + 140 * 1191 00 0D 0D 01 00 // Class ID 08 "SMLL" // Sprite layout, of 23 sprites @@ -550,6 +550,9 @@ // Prop22 Catchment Area 22 04 +// Prop24 Noise Level + 24 04 + //availability date varaction2 //commuter airport available from 1981 (1920+61) to 2175 (1920+255) 141 * 14 02 0D @@ -578,7 +581,7 @@ //------------------------- // 11 properties to change, 1 station to change, station id = 01 - 144 * 935 00 0D 0B 01 01 + 144 * 935 00 0D 0C 01 01 // Class ID 08 "LRGE" @@ -894,6 +897,9 @@ // Prop22 Catchment Area 22 06 +// Prop24 Noise Level + 24 08 + //availability date varaction2 //Metropolitan Airport available from 1980 (1920+60) to 2175 (1920+255) 145 * 14 02 0D @@ -923,7 +929,7 @@ // 12 properties to change, 1 station to change, station id = 02 //!!Fatal Error (64): Expected more data for prop 1A. (1 bytes at 1768.) - 148 * 1768 00 0D 0C 01 02 + 148 * 1768 00 0D 0D 01 02 // Class ID 08 "INTL" @@ -1415,6 +1421,9 @@ // Prop22 Catchment Area 22 08 +// Prop24 Noise Level + 24 11 + //availability date varaction2 //International Airport available from 1994 (1920+74) to 2175 (1920+255) 149 * 14 02 0D @@ -1443,7 +1452,7 @@ //------------------------- // 11 properties to change, 1 station to change, station id = nn - 152 * 817 00 0D 0B 01 03 + 152 * 817 00 0D 0C 01 03 // Class ID 08 "HELI" @@ -1688,6 +1697,9 @@ // Prop22 Catchment Area 22 04 +// Prop24 Noise Level + 24 02 + //availability date varaction2 //Helidepot available from 1981 (1920+61) to 2175 (1920+255) 153 * 14 02 0D @@ -1718,7 +1730,7 @@ // 12 properties to change, 1 station to change, station id = 04 //!!Fatal Error (64): Expected more data for prop 1A. (1 bytes at 2395.) - 156 * 2395 00 0D 0C 01 04 + 156 * 2395 00 0D 0D 01 04 // Class ID 08 "INTL" @@ -2424,6 +2436,9 @@ // Prop22 Catchment Area 22 0A +// Prop24 Noise Level + 24 19 + //availability date varaction2 //Intercontinental Airport available from 2003 (1920+83) to 2175 (1920+255) 157 * 14 02 0D @@ -2453,7 +2468,7 @@ // 11 properties to change, 1 station to change, station id = 05 //!!Fatal Error (64): Expected more data for prop 1A. (1 bytes at 876.) - 160 * 876 00 0D 0B 01 05 + 160 * 876 00 0D 0C 01 05 // Class ID 08 "HELI" @@ -2734,6 +2749,9 @@ // Prop22 Catchment Area 22 04 +// Prop24 Noise Level + 24 03 + //availability date varaction2 //Helistation available from 1999 (1920+79) to 2175 (1920+255) 161 * 14 02 0D diff -r 68a692eacf22 -r 67db0d431d5e bin/data/sprites/seaplaneport.nfo --- a/bin/data/sprites/seaplaneport.nfo Mon May 26 20:45:25 2008 +0000 +++ b/bin/data/sprites/seaplaneport.nfo Tue May 27 00:50:55 2008 +0000 @@ -21,7 +21,7 @@ 7 * 53 08 07 C0 DE D0 0D "Seaplane Airport" 00 "Adds a Small Seaplane Airport" 00 // 13 properties to change, 1 station to change, station id = 0 - 8 * 734 00 0D 0C 01 00 + 8 * 734 00 0D 0D 01 00 // Small Seaplane Airport // uses normal small airport state machine. Runway moved to lower position @@ -257,6 +257,9 @@ // Prop22 Catchment Area 22 04 +// Prop24 Noise Level + 24 02 + // Define placement layout mask // similar format to custom layout, but gives tile info for placement checks // set order must match custom layout order and orientations. diff -r 68a692eacf22 -r 67db0d431d5e docs/NewGRFAirports.doc Binary file docs/NewGRFAirports.doc has changed diff -r 68a692eacf22 -r 67db0d431d5e projects/openttd_vs80.vcproj --- a/projects/openttd_vs80.vcproj Mon May 26 20:45:25 2008 +0000 +++ b/projects/openttd_vs80.vcproj Tue May 27 00:50:55 2008 +0000 @@ -508,6 +508,10 @@ > + + @@ -880,7 +884,19 @@ > + + + + + + - - diff -r 68a692eacf22 -r 67db0d431d5e projects/openttd_vs90.vcproj --- a/projects/openttd_vs90.vcproj Mon May 26 20:45:25 2008 +0000 +++ b/projects/openttd_vs90.vcproj Tue May 27 00:50:55 2008 +0000 @@ -505,6 +505,10 @@ > + + @@ -873,7 +877,19 @@ > + + + + + + - - diff -r 68a692eacf22 -r 67db0d431d5e source.list --- a/source.list Mon May 26 20:45:25 2008 +0000 +++ b/source.list Tue May 27 00:50:55 2008 +0000 @@ -13,6 +13,7 @@ command.cpp console.cpp console_cmds.cpp +console_gui.cpp currency.cpp date.cpp debug.cpp @@ -145,7 +146,10 @@ cmd_helper.h command_func.h command_type.h -console.h +console_func.h +console_gui.h +console_internal.h +console_type.h cheat_func.h cheat_type.h currency.h @@ -577,7 +581,6 @@ yapf/yapf_node_road.hpp yapf/yapf_rail.cpp yapf/yapf_road.cpp -yapf/yapf_settings.h yapf/yapf_ship.cpp # Video diff -r 68a692eacf22 -r 67db0d431d5e src/ai/ai.cpp --- a/src/ai/ai.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/ai/ai.cpp Tue May 27 00:50:55 2008 +0000 @@ -154,7 +154,7 @@ Player *p = GetPlayer(player); _current_player = player; - if (_patches.ainew_active) { + if (_settings.ai.ainew_active) { AiNewDoGameLoop(p); } else { /* Enable all kind of cheats the old AI needs in order to operate correctly... */ @@ -178,14 +178,14 @@ if (!_ai.enabled) return; /* Don't do anything if we are a network-client, or the AI has been disabled */ - if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return; + if (_networking && (!_network_server || !_settings.ai.ai_in_multiplayer)) return; /* New tick */ _ai.tick++; /* Make sure the AI follows the difficulty rule.. */ - assert(_opt.diff.competitor_speed <= 4); - if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return; + assert(_settings.difficulty.competitor_speed <= 4); + if ((_ai.tick & ((1 << (4 - _settings.difficulty.competitor_speed)) - 1)) != 0) return; /* Check for AI-client (so joining a network with an AI) */ if (!_networking || _network_server) { diff -r 68a692eacf22 -r 67db0d431d5e src/ai/ai.h --- a/src/ai/ai.h Mon May 26 20:45:25 2008 +0000 +++ b/src/ai/ai.h Tue May 27 00:50:55 2008 +0000 @@ -67,14 +67,14 @@ /* If in network, and server, possible AI */ if (_networking && _network_server) { /* Do we want AIs in multiplayer? */ - if (!_patches.ai_in_multiplayer) + if (!_settings.ai.ai_in_multiplayer) return false; /* Only the NewAI is allowed... sadly enough the old AI just doesn't support this * system, because all commands are delayed by at least 1 tick, which causes * a big problem, because it uses variables that are only set AFTER the command * is really executed... */ - if (!_patches.ainew_active) + if (!_settings.ai.ainew_active) return false; } diff -r 68a692eacf22 -r 67db0d431d5e src/ai/default/default.cpp --- a/src/ai/default/default.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/ai/default/default.cpp Tue May 27 00:50:55 2008 +0000 @@ -1570,21 +1570,21 @@ for (;;) { r = (uint16)Random(); - if (_patches.ai_disable_veh_train && - _patches.ai_disable_veh_roadveh && - _patches.ai_disable_veh_aircraft && - _patches.ai_disable_veh_ship) { + if (_settings.ai.ai_disable_veh_train && + _settings.ai.ai_disable_veh_roadveh && + _settings.ai.ai_disable_veh_aircraft && + _settings.ai.ai_disable_veh_ship) { return; } if (r < 0x7626) { - if (_patches.ai_disable_veh_train) continue; + if (_settings.ai.ai_disable_veh_train) continue; AiWantTrainRoute(p); } else if (r < 0xC4EA) { - if (_patches.ai_disable_veh_roadveh) continue; + if (_settings.ai.ai_disable_veh_roadveh) continue; AiWantRoadRoute(p); } else if (r < 0xD89B) { - if (_patches.ai_disable_veh_aircraft) continue; + if (_settings.ai.ai_disable_veh_aircraft) continue; AiWantAircraftRoute(p); } else { /* Ships are not implemented in this (broken) AI */ @@ -1603,7 +1603,7 @@ static bool AiCheckTrackResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo) { - uint rad = (_patches.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED; + uint rad = (_settings.station.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED; for (; p->mode != 4; p++) { AcceptedCargo values; @@ -2550,7 +2550,7 @@ bool is_pass = ( _players_ai[p->index].cargo_type == CT_PASSENGERS || _players_ai[p->index].cargo_type == CT_MAIL || - (_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES) + (_settings.game_creation.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES) ); Order order; @@ -2599,7 +2599,7 @@ uint values[NUM_CARGO]; int rad; - if (_patches.modified_catchment) { + if (_settings.station.modified_catchment) { rad = CA_TRUCK; // Same as CA_BUS at the moment? } else { // change that at some point? rad = 4; @@ -3285,7 +3285,7 @@ bool is_pass = ( _players_ai[p->index].cargo_type == CT_PASSENGERS || _players_ai[p->index].cargo_type == CT_MAIL || - (_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES) + (_settings.game_creation.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES) ); Order order; @@ -3352,7 +3352,8 @@ AirportFTAClass::Flags flags = st->Airport()->flags; - if (!(flags & (_players_ai[p->index].build_kind == 1 && i == 0 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) { + /* if airport doesn't accept our kind of plane, dismiss it */ + if (!(flags & (_players_ai[p->index].build_kind == 1 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) { continue; } @@ -3415,7 +3416,7 @@ uint w = p->size_x[0]; uint h = p->size_y[0]; - uint rad = _patches.modified_catchment ? p->portFSM->catchment : (uint)CA_UNMODIFIED; + uint rad = _settings.station.modified_catchment ? p->portFSM->catchment : (uint)CA_UNMODIFIED; if (cargo & 0x80) { GetProductionAroundTiles(values, tile, w, h, rad); @@ -3431,14 +3432,33 @@ { std::list airports = GetAvailableAirports(); + bool no_small = false; + if (!heli) { + /* do not build small airport if we have large available and we are not building heli route */ + for (std::list::const_iterator it = airports.begin(); it != airports.end(); it++) { + const FSMportsSpec *spec = GetCustomFSMportsSpec((FSMportsClassID)GB(*it, 8, 8), GB(*it, 0, 8)); + uint flags = spec->flags; + if ((flags & AirportFTAClass::AIRPLANES) && !(flags & AirportFTAClass::SHORT_STRIP)) { + no_small = true; + break; + } + } + } + for (std::list::const_iterator it = airports.begin(); it != airports.end(); it++) { const FSMportsSpec *spec = GetCustomFSMportsSpec((FSMportsClassID)GB(*it, 8, 8), GB(*it, 0, 8)); - // If we are doing a helicopter service, avoid building - // airports where they can't land. - if (heli && !(spec->flags & AirportFTAClass::HELICOPTERS)) continue; + uint flags = spec->flags; + + /* If we are doing a helicopter service, avoid building airports where they can't land */ + if (heli && !(flags & AirportFTAClass::HELICOPTERS)) continue; + /* Similiar with aircraft ... */ + if (!heli && !(flags & AirportFTAClass::AIRPLANES)) continue; + /* Do not build small airport if we prefer large */ + if (no_small && (flags & AirportFTAClass::SHORT_STRIP)) continue; *cost = AiDoBuildDefaultAirportBlock(tile, *it, 0); - if (CmdSucceeded(*cost) && AiCheckAirportResources(tile, spec, cargo)) return *it; + if (CmdSucceeded(*cost) && AiCheckAirportResources(tile, spec, cargo)) + return *it; } return 0xFFFF; } @@ -3721,11 +3741,11 @@ DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); } } else if (IsTileType(tile, MP_ROAD)) { - if (!IsTileOwner(tile, _current_player)) return; - if (IsLevelCrossing(tile)) goto is_rail_crossing; if (IsRoadDepot(tile)) { + if (!IsTileOwner(tile, _current_player)) return; + DiagDirection dir; TileIndex t; @@ -3933,7 +3953,7 @@ // to the patch-setting // Also, it takes into account the setting if the service-interval is in days // or in % - _ai_service_interval = _patches.servint_ispercent ? 80 : 180; + _ai_service_interval = _settings.vehicle.servint_ispercent ? 80 : 180; if (IsHumanPlayer(_current_player)) return; diff -r 68a692eacf22 -r 67db0d431d5e src/ai/trolly/trolly.cpp --- a/src/ai/trolly/trolly.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/ai/trolly/trolly.cpp Tue May 27 00:50:55 2008 +0000 @@ -130,9 +130,9 @@ // Check all vehicles once in a while _players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES; _players_ainew[p->index].last_vehiclecheck_date = _date; - } else if (c < 100 && !_patches.ai_disable_veh_roadveh) { + } else if (c < 100 && !_settings.ai.ai_disable_veh_roadveh) { // Do we have any spots for road-vehicles left open? - if (GetFreeUnitNumber(VEH_ROAD) <= _patches.max_roadveh) { + if (GetFreeUnitNumber(VEH_ROAD) <= _settings.vehicle.max_roadveh) { if (c < 85) { _players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE; } else { @@ -140,8 +140,8 @@ } } #if 0 - } else if (c < 200 && !_patches.ai_disable_veh_train) { - if (GetFreeUnitNumber(VEH_TRAIN) <= _patches.max_trains) { + } else if (c < 200 && !_settings.ai.ai_disable_veh_train) { + if (GetFreeUnitNumber(VEH_TRAIN) <= _settings.vehicle.max_trains) { _players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE; } #endif @@ -155,7 +155,7 @@ return; } - if (_patches.ai_disable_veh_roadveh && ( + if (_settings.ai.ai_disable_veh_roadveh && ( _players_ainew[p->index].action == AI_ACTION_BUS_ROUTE || _players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE )) { @@ -179,7 +179,7 @@ // to build the route anyway.. if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE && money > AI_MINIMUM_BUS_ROUTE_MONEY) { - if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) { + if (GetFreeUnitNumber(VEH_ROAD) > _settings.vehicle.max_roadveh) { _players_ainew[p->index].action = AI_ACTION_NONE; return; } @@ -190,7 +190,7 @@ } if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE && money > AI_MINIMUM_TRUCK_ROUTE_MONEY) { - if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) { + if (GetFreeUnitNumber(VEH_ROAD) > _settings.vehicle.max_roadveh) { _players_ainew[p->index].action = AI_ACTION_NONE; return; } @@ -1017,7 +1017,7 @@ if (_players_ainew[p->index].temp == -1) { DEBUG(ai, 1, "Starting to build new path"); // Init the counter - _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1; + _players_ainew[p->index].counter = (4 - _settings.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1; // Set the position to the startingplace (-1 because in a minute we do ++) _players_ainew[p->index].path_info.position = -1; // And don't do this again @@ -1026,7 +1026,7 @@ // Building goes very fast on normal rate, so we are going to slow it down.. // By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :) if (--_players_ainew[p->index].counter != 0) return; - _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1; + _players_ainew[p->index].counter = (4 - _settings.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1; // Increase the building position _players_ainew[p->index].path_info.position++; @@ -1035,7 +1035,7 @@ if (_players_ainew[p->index].path_info.position == -2) { // This means we are done building! - if (_players_ainew[p->index].tbt == AI_TRUCK && !_patches.roadveh_queue) { + if (_players_ainew[p->index].tbt == AI_TRUCK && !_settings.pf.roadveh_queue) { // If they not queue, they have to go up and down to try again at a station... // We don't want that, so try building some road left or right of the station DiagDirection dir1, dir2, dir3; @@ -1186,7 +1186,7 @@ } // Very handy for AI, goto depot.. but yeah, it needs to be activated ;) - if (_patches.gotodepot) { + if (_settings.order.gotodepot) { idx = 0; order.MakeGoToDepot(GetDepotByTile(_players_ainew[p->index].depot_tile)->index, ODTFB_PART_OF_ORDERS); AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); diff -r 68a692eacf22 -r 67db0d431d5e src/aircraft_cmd.cpp --- a/src/aircraft_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/aircraft_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -317,7 +317,7 @@ } UnitID unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_AIRCRAFT); - if (unit_num > _patches.max_aircraft) + if (unit_num > _settings.vehicle.max_aircraft) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); if (flags & DC_EXEC) { @@ -443,7 +443,7 @@ v->u.air.targetairport = GetStationIndex(tile); v->SetNext(u); - v->service_interval = _patches.servint_aircraft; + v->service_interval = _settings.vehicle.servint_aircraft; v->date_of_last_service = _date; v->build_year = u->build_year = _cur_year; @@ -485,7 +485,7 @@ } InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); if (IsLocalPlayer()) InvalidateAutoreplaceWindow(v->engine_type, v->group_id); //updates the replace Aircraft window @@ -500,11 +500,10 @@ static void DoDeleteAircraft(Vehicle *v) { DeleteWindowById(WC_VEHICLE_VIEW, v->index); - RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); DeleteDepotHighlightOfVehicle(v); DeleteVehicleChain(v); - InvalidateWindowClasses(WC_AIRCRAFT_LIST); + InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0); } /** Sell an aircraft. @@ -697,7 +696,7 @@ v->cargo_subtype = new_subtype; InvalidateWindow(WC_VEHICLE_DETAILS, v->index); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0); } return cost; @@ -706,7 +705,7 @@ static void CheckIfAircraftNeedsService(Vehicle *v) { - if (_patches.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return; + if (_settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return; if (v->IsInDepot()) { VehicleServiceInDepot(v); return; @@ -944,7 +943,7 @@ /* Adjust speed limits by plane speed factor to prevent taxiing * and take-off speeds being too low. */ - speed_limit *= _patches.plane_speed; + speed_limit *= _settings.vehicle.plane_speed; if (v->u.air.cached_max_speed < speed_limit) { if (v->cur_speed < speed_limit) hard_limit = false; @@ -962,7 +961,7 @@ * speeds to that aircraft do not get to taxi speed straight after * touchdown. */ if (!hard_limit && v->cur_speed > speed_limit) { - speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _patches.plane_speed); + speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings.vehicle.plane_speed); } spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit); @@ -973,12 +972,12 @@ /* updates statusbar only if speed have changed to save CPU time */ if (spd != v->cur_speed) { v->cur_speed = spd; - if (_patches.vehicle_speed) + if (_settings.gui.vehicle_speed) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } /* Adjust distance moved by plane speed setting */ - if (_patches.plane_speed > 1) spd /= _patches.plane_speed; + if (_settings.vehicle.plane_speed > 1) spd /= _settings.vehicle.plane_speed; if (!(v->direction & 1)) spd = spd * 3 / 4; @@ -1740,7 +1739,7 @@ AircraftEventHandler_EnterTerminal(v, apc); /* on an airport with helipads, a helicopter will always land there * and get serviced at the same time - patch setting */ - if (_patches.serviceathelipad) { + if (_settings.order.serviceathelipad) { if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) { /* an exerpt of ServiceAircraft, without the invisibility stuff */ v->date_of_last_service = _date; diff -r 68a692eacf22 -r 67db0d431d5e src/airport.h --- a/src/airport.h Mon May 26 20:45:25 2008 +0000 +++ b/src/airport.h Tue May 27 00:50:55 2008 +0000 @@ -7,6 +7,7 @@ #include "fsmport.h" #include +#include "tile_type.h" typedef FSMCommand AirportFTA; typedef FSMPortMovingData AirportMovingData; @@ -104,6 +105,7 @@ byte *helipads; Flags flags; byte *entry_points; ///< when an airplane arrives at this airport, enter it at position entry_point, index depends on direction + uint8 noise_level; }; DECLARE_ENUM_AS_BIT_SET(AirportFTAClass::Flags) @@ -115,4 +117,8 @@ */ std::list GetAvailableAirports(); + +/* Calculate the noise this type airport will generate */ +uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile); + #endif /* AIRPORT_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/airport_gui.cpp --- a/src/airport_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/airport_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -19,6 +19,8 @@ #include "strings_func.h" #include "core/alloc_func.hpp" #include "window_func.h" +#include "strings_func.h" +#include "settings_type.h" #include "viewport_func.h" #include "gfx_func.h" #include "widgets/dropdown_func.h" @@ -41,7 +43,7 @@ DirectionByte direction; } _airport; -static void ShowBuildAirportPicker(); +static void ShowBuildAirportPicker(Window *parent); void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2) @@ -69,7 +71,7 @@ static void BuildAirClick_Airport(Window *w) { - if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, VHM_RECT, PlaceAirport)) ShowBuildAirportPicker(); + if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, VHM_RECT, PlaceAirport)) ShowBuildAirportPicker(w); } static void BuildAirClick_Demolish(Window *w) @@ -84,52 +86,65 @@ BuildAirClick_Demolish, }; -static void BuildAirToolbWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: - w->DrawWidgets(); - break; - - case WE_CLICK: - if (e->we.click.widget - 3 >= 0) - _build_air_button_proc[e->we.click.widget - 3](w); - break; - - case WE_KEYPRESS: { - switch (e->we.keypress.keycode) { - case '1': BuildAirClick_Airport(w); break; - case '2': BuildAirClick_Demolish(w); break; - default: return; - } - break; - } +struct BuildAirToolbarWindow : Window { + BuildAirToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this); + } - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - break; - - case WE_PLACE_DRAG: - VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); - break; + ~BuildAirToolbarWindow() + { + if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); + } - case WE_PLACE_MOUSEUP: - if (e->we.place.pt.x != -1 && e->we.place.select_proc == DDSP_DEMOLISH_AREA) { - GUIPlaceProcDragXY(e); - } - break; + virtual void OnPaint() + { + this->DrawWidgets(); + } - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); + virtual void OnClick(Point pt, int widget) + { + if (widget - 3 >= 0) { + _build_air_button_proc[widget - 3](this); + } + } - delete FindWindowById(WC_BUILD_STATION, 0); - break; - case WE_DESTROY: - if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); - break; + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + switch (keycode) { + case '1': BuildAirClick_Airport(this); break; + case '2': BuildAirClick_Demolish(this); break; + default: return ES_NOT_HANDLED; + } + return ES_HANDLED; } -} + + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } + + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) + { + VpSelectTilesWithMethod(pt.x, pt.y, select_method); + } + + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + { + if (pt.x != -1 && select_proc == DDSP_DEMOLISH_AREA) { + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); + } + } + + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + + delete FindWindowById(WC_BUILD_STATION, 0); + } +}; static const Widget _air_toolbar_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, @@ -146,7 +161,6 @@ WC_BUILD_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _air_toolbar_widgets, - BuildAirToolbWndProc }; void ShowBuildAirToolbar() @@ -154,8 +168,7 @@ if (!IsValidPlayer(_current_player)) return; DeleteWindowByClass(WC_BUILD_TOOLBAR); - Window *w = AllocateWindowDescFront(&_air_toolbar_desc, TRANSPORT_AIR); - if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w); + AllocateWindowDescFront(&_air_toolbar_desc, TRANSPORT_AIR); } class AirportPickerWindow : public PickerWindowBase { @@ -181,13 +194,17 @@ }; public: - AirportPickerWindow(const WindowDesc *desc) : PickerWindowBase(desc) + AirportPickerWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { _airport.station_type = 0; _airport.layout_set = 0; _airport.direction = DIR_NE; _airport.station_count = GetNumCustomFSMports(_airport.fsmports_class); + if (_settings.economy.station_noise_level) { + ResizeWindowForWidget(this, BAPW_BACKGROUND, 0, 10); + } + this->vscroll.count = _airport.station_count; this->vscroll.cap = 5; this->vscroll.pos = Clamp(_airport.station_type - 2, 0, this->vscroll.count - this->vscroll.cap); @@ -200,6 +217,7 @@ virtual void OnPaint() { byte preview_sprite = 0xFF; + uint16 y_noise_offset = 0; FSMportsSpec *fsmportspec = GetCustomFSMportsSpec(_airport.fsmports_class, _airport.station_type); /* if the port is no longer available, find one that is */ @@ -255,7 +273,7 @@ _thd.FSMportLayout = &fsmportspec->layouts[_airport.layout_set]; // irregular airport support _thd.FSMportMask = NULL; if (fsmportspec->layout_mask != NULL) _thd.FSMportMask = &fsmportspec->layout_mask[_airport.layout_set]; // irregular airport support - int rad = _patches.modified_catchment ? fsmportspec->portFSM->catchment : 4; + int rad = _settings.station.modified_catchment ? fsmportspec->portFSM->catchment : 4; if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); int text_end = DrawStationCoverageAreaText(2, 206, SCT_ALL, rad, false); text_end = DrawStationCoverageAreaText(2, text_end + 4, SCT_ALL, rad, true) + 4; @@ -411,12 +429,11 @@ WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_airport_picker_widgets, - NULL }; -static void ShowBuildAirportPicker() +static void ShowBuildAirportPicker(Window *parent) { - new AirportPickerWindow(&_build_airport_desc); + new AirportPickerWindow(&_build_airport_desc, parent); } void InitializeAirportGui() diff -r 68a692eacf22 -r 67db0d431d5e src/autoreplace_cmd.cpp --- a/src/autoreplace_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/autoreplace_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -216,7 +216,7 @@ // copy/clone the orders DoCommand(0, (old_v->index << 16) | new_v->index, old_v->IsOrderListShared() ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER); new_v->cur_order_index = old_v->cur_order_index; - ChangeVehicleViewWindow(old_v, new_v); + ChangeVehicleViewWindow(old_v->index, new_v->index); new_v->profit_this_year = old_v->profit_this_year; new_v->profit_last_year = old_v->profit_last_year; new_v->service_interval = old_v->service_interval; diff -r 68a692eacf22 -r 67db0d431d5e src/autoreplace_gui.cpp --- a/src/autoreplace_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/autoreplace_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -533,7 +533,6 @@ WC_REPLACE_VEHICLE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _replace_vehicle_widgets, - NULL }; static const WindowDesc _replace_vehicle_desc = { @@ -541,7 +540,6 @@ WC_REPLACE_VEHICLE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _replace_vehicle_widgets, - NULL }; RailType ReplaceVehicleWindow::sel_railtype = RAILTYPE_RAIL; diff -r 68a692eacf22 -r 67db0d431d5e src/autoslope.h --- a/src/autoslope.h Mon May 26 20:45:25 2008 +0000 +++ b/src/autoslope.h Tue May 27 00:50:55 2008 +0000 @@ -38,7 +38,7 @@ */ static inline bool AutoslopeEnabled() { - return (_patches.autoslope && + return (_settings.construction.autoslope && ((IsValidPlayer(_current_player) && !_is_old_ai_player) || (_current_player == OWNER_NONE && _game_mode == GM_EDITOR))); } diff -r 68a692eacf22 -r 67db0d431d5e src/blitter/factory.hpp --- a/src/blitter/factory.hpp Mon May 26 20:45:25 2008 +0000 +++ b/src/blitter/factory.hpp Tue May 27 00:50:55 2008 +0000 @@ -56,7 +56,13 @@ name(NULL) {} - virtual ~BlitterFactoryBase() { if (this->name != NULL) GetBlitters().erase(this->name); free(this->name); } + virtual ~BlitterFactoryBase() + { + if (this->name == NULL) return; + GetBlitters().erase(this->name); + if (GetBlitters().empty()) delete &GetBlitters(); + free(this->name); + } /** * Find the requested blitter and return his class. diff -r 68a692eacf22 -r 67db0d431d5e src/bridge_gui.cpp --- a/src/bridge_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/bridge_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -17,146 +17,282 @@ #include "viewport_func.h" #include "gfx_func.h" #include "tunnelbridge.h" +#include "sortlist_type.h" +#include "widgets/dropdown_func.h" #include "table/strings.h" -static struct BridgeData { - uint8 last_size; - uint count; - TileIndex start_tile; - TileIndex end_tile; - uint32 type; ///< Data type for the bridge. Bit 16,15 = transport type, 14..8 = road/rail pieces, 7..0 = type of bridge - BridgeType indexes[MAX_BRIDGES]; - Money costs[MAX_BRIDGES]; +/** + * Carriage for the data we need if we want to build a bridge + */ +struct BuildBridgeData { + BridgeType index; + const BridgeSpec *spec; + Money cost; +}; - BridgeData() - : last_size(4) - , count(0) - {}; -} _bridgedata; +typedef GUIList GUIBridgeList; +/** + * Callback executed after a build Bridge CMD has been called + * + * @param scucess True if the build succeded + * @param tile The tile where the command has been executed + * @param p1 not used + * @param p2 not used + */ void CcBuildBridge(bool success, TileIndex tile, uint32 p1, uint32 p2) { if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile); } -static void BuildBridge(Window *w, int i) -{ - delete w; - DoCommandP(_bridgedata.end_tile, _bridgedata.start_tile, - _bridgedata.type | _bridgedata.indexes[i], CcBuildBridge, - CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE)); -} - /* Names of the build bridge selection window */ enum BuildBridgeSelectionWidgets { BBSW_CLOSEBOX = 0, BBSW_CAPTION, + BBSW_DROPDOWN_ORDER, + BBSW_DROPDOWN_CRITERIA, BBSW_BRIDGE_LIST, BBSW_SCROLLBAR, BBSW_RESIZEBOX }; -static void BuildBridgeWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: - w->resize.step_height = 22; - w->vscroll.count = _bridgedata.count; +class BuildBridgeWindow : public Window { +private: + /* Runtime saved values */ + static uint last_size; + static Listing last_sorting; - if (_bridgedata.last_size <= 4) { - w->vscroll.cap = 4; - } else { - /* Resize the bridge selection window if we used a bigger one the last time */ - w->vscroll.cap = (w->vscroll.count > _bridgedata.last_size) ? _bridgedata.last_size : w->vscroll.count; - ResizeWindow(w, 0, (w->vscroll.cap - 4) * w->resize.step_height); - w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1; - } - break; - - case WE_PAINT: { - w->DrawWidgets(); + /* Constants for sorting the bridges */ + static const StringID sorter_names[]; + static GUIBridgeList::SortFunction *const sorter_funcs[]; - uint y = 15; - for (uint i = 0; (i < w->vscroll.cap) && ((i + w->vscroll.pos) < _bridgedata.count); i++) { - const BridgeSpec *b = GetBridgeSpec(_bridgedata.indexes[i + w->vscroll.pos]); + /* Internal variables */ + TileIndex start_tile; + TileIndex end_tile; + uint32 type; + GUIBridgeList *bridges; - SetDParam(2, _bridgedata.costs[i + w->vscroll.pos]); - SetDParam(1, b->speed * 10 / 16); - SetDParam(0, b->material); + /** Sort the bridges by their index */ + static int CDECL BridgeIndexSorter(const BuildBridgeData *a, const BuildBridgeData *b) + { + return a->index - b->index; + } - DrawSprite(b->sprite, b->pal, 3, y); - DrawString(44, y, STR_500D, TC_FROMSTRING); - y += w->resize.step_height; - } - break; + /** Sort the bridges by their price */ + static int CDECL BridgePriceSorter(const BuildBridgeData *a, const BuildBridgeData *b) + { + return a->cost - b->cost; + } + + /** Sort the bridges by their maximum speed */ + static int CDECL BridgeSpeedSorter(const BuildBridgeData *a, const BuildBridgeData *b) + { + return a->spec->speed - b->spec->speed; + } + + void BuildBridge(uint8 i) + { + DoCommandP(this->end_tile, this->start_tile, this->type | this->bridges->Get(i)->index, + CcBuildBridge, CMD_BUILD_BRIDGE | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE)); + } + + /** Sort the builable bridges */ + void SortBridgeList() + { + this->bridges->Sort(); + + /* Display the current sort variant */ + this->widget[BBSW_DROPDOWN_CRITERIA].data = this->sorter_names[this->bridges->SortType()]; + + /* Set the modified widgets dirty */ + this->InvalidateWidget(BBSW_DROPDOWN_CRITERIA); + this->InvalidateWidget(BBSW_BRIDGE_LIST); + } + +public: + BuildBridgeWindow(const WindowDesc *desc, TileIndex start, TileIndex end, uint32 br_type, GUIBridgeList *bl) : Window(desc), + start_tile(start), + end_tile(end), + type(br_type), + bridges(bl) + { + this->bridges->SetListing(this->last_sorting); + this->bridges->SetSortFuncs(this->sorter_funcs); + this->SortBridgeList(); + + /* Change the data, or the caption of the gui. Set it to road or rail, accordingly */ + this->widget[BBSW_CAPTION].data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE; + + this->resize.step_height = 22; + this->vscroll.count = bl->Length(); + + if (this->last_size <= 4) { + this->vscroll.cap = 4; + } else { + /* Resize the bridge selection window if we used a bigger one the last time */ + this->vscroll.cap = (this->vscroll.count > this->last_size) ? this->last_size : this->vscroll.count; + ResizeWindow(this, 0, (this->vscroll.cap - 4) * this->resize.step_height); + this->widget[BBSW_BRIDGE_LIST].data = (this->vscroll.cap << 8) + 1; } - case WE_KEYPRESS: { - const uint8 i = e->we.keypress.keycode - '1'; - if (i < 9 && i < _bridgedata.count) { - e->we.keypress.cont = false; - BuildBridge(w, i); - } + this->FindWindowPlacementAndResize(desc); + } - break; - } + ~BuildBridgeWindow() + { + this->last_sorting = this->bridges->GetListing(); - case WE_CLICK: - if (e->we.click.widget == BBSW_BRIDGE_LIST) { - uint ind = ((int)e->we.click.pt.y - 14) / w->resize.step_height; - if (ind < w->vscroll.cap) { - ind += w->vscroll.pos; - if (ind < _bridgedata.count) { - BuildBridge(w, ind); + delete bridges; + } + + virtual void OnPaint() + { + this->DrawWidgets(); + + this->DrawSortButtonState(BBSW_DROPDOWN_ORDER, (this->bridges->flags & VL_DESC) ? SBS_DOWN : SBS_UP); + + uint y = this->widget[BBSW_BRIDGE_LIST].top + 2; + + for (int i = this->vscroll.pos; (i < (this->vscroll.cap + this->vscroll.pos)) && (i < (int)this->bridges->Length()); i++) { + const BridgeSpec *b = this->bridges->Get(i)->spec; + + SetDParam(2, this->bridges->Get(i)->cost); + SetDParam(1, b->speed * 10 / 16); + SetDParam(0, b->material); + + DrawSprite(b->sprite, b->pal, 3, y); + DrawString(44, y, STR_500D, TC_FROMSTRING); + y += this->resize.step_height; + + } + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + const uint8 i = keycode - '1'; + if (i < 9 && i < this->bridges->Length()) { + /* Build the requested bridge */ + this->BuildBridge(i); + delete this; + return ES_HANDLED; + } + return ES_NOT_HANDLED; + } + + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + default: break; + case BBSW_BRIDGE_LIST: { + uint i = ((int)pt.y - this->widget[BBSW_BRIDGE_LIST].top) / this->resize.step_height; + if (i < this->vscroll.cap) { + i += this->vscroll.pos; + if (i < this->bridges->Length()) { + this->BuildBridge(i); + delete this; } } - } - break; + } break; - case WE_RESIZE: - w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height; - w->widget[BBSW_BRIDGE_LIST].data = (w->vscroll.cap << 8) + 1; - SetVScrollCount(w, _bridgedata.count); + case BBSW_DROPDOWN_ORDER: + this->bridges->ToggleSortOrder(); + this->SetDirty(); + break; - _bridgedata.last_size = w->vscroll.cap; - break; + case BBSW_DROPDOWN_CRITERIA: + ShowDropDownMenu(this, this->sorter_names, this->bridges->SortType(), BBSW_DROPDOWN_CRITERIA, 0, 0); + break; + } } -} + + virtual void OnDropdownSelect(int widget, int index) + { + if (widget == BBSW_DROPDOWN_CRITERIA && this->bridges->SortType() != index) { + this->bridges->SetSortType(index); + + this->SortBridgeList(); + } + } + + virtual void OnResize(Point new_size, Point delta) + { + this->vscroll.cap += delta.y / (int)this->resize.step_height; + this->widget[BBSW_BRIDGE_LIST].data = (this->vscroll.cap << 8) + 1; + SetVScrollCount(this, this->bridges->Length()); + + this->last_size = this->vscroll.cap; + } +}; + +/* Set the default size of the Build Bridge Window */ +uint BuildBridgeWindow::last_size = 4; +/* Set the default sorting for the bridges */ +Listing BuildBridgeWindow::last_sorting = {false, 0}; + +/* Availible bridge sorting functions */ +GUIBridgeList::SortFunction* const BuildBridgeWindow::sorter_funcs[] = { + &BridgeIndexSorter, + &BridgePriceSorter, + &BridgeSpeedSorter +}; + +/* Names of the sorting functions */ +const StringID BuildBridgeWindow::sorter_names[] = { + STR_SORT_BY_NUMBER, + STR_ENGINE_SORT_COST, + STR_SORT_BY_MAX_SPEED, + INVALID_STRING_ID +}; /* Widget definition for the rail bridge selection window */ static const Widget _build_bridge_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // BBSW_CLOSEBOX { WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS}, // BBSW_CAPTION -{ WWT_MATRIX, RESIZE_BOTTOM, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK}, // BBSW_BRIDGE_LIST -{ WWT_SCROLLBAR, RESIZE_BOTTOM, 7, 188, 199, 14, 89, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BBSW_SCROLLBAR -{ WWT_RESIZEBOX, RESIZE_TB, 7, 188, 199, 90, 101, 0x0, STR_RESIZE_BUTTON}, // BBSW_RESIZEBOX + +{ WWT_TEXTBTN, RESIZE_NONE, 7, 0, 80, 14, 25, STR_SORT_BY, STR_SORT_ORDER_TIP}, // BBSW_DROPDOWN_ORDER +{ WWT_DROPDOWN, RESIZE_NONE, 7, 81, 199, 14, 25, 0x0, STR_SORT_CRITERIA_TIP}, // BBSW_DROPDOWN_CRITERIA + +{ WWT_MATRIX, RESIZE_BOTTOM, 7, 0, 187, 26, 113, 0x401, STR_101F_BRIDGE_SELECTION_CLICK}, // BBSW_BRIDGE_LIST +{ WWT_SCROLLBAR, RESIZE_BOTTOM, 7, 188, 199, 26, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BBSW_SCROLLBAR +{ WWT_RESIZEBOX, RESIZE_TB, 7, 188, 199, 102, 113, 0x0, STR_RESIZE_BUTTON}, // BBSW_RESIZEBOX { WIDGETS_END}, }; /* Window definition for the rail bridge selection window */ static const WindowDesc _build_bridge_desc = { - WDP_AUTO, WDP_AUTO, 200, 102, 200, 102, + WDP_AUTO, WDP_AUTO, 200, 114, 200, 114, WC_BUILD_BRIDGE, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE, _build_bridge_widgets, - BuildBridgeWndProc }; +/** + * Prepare the data for the build a bridge window. + * If we can't build a bridge under the given conditions + * show an error message. + * + * @parma start The start tile of the bridge + * @param end The end tile of the bridge + * @param transport_type The transport type + * @param bridge_type The bridge type + */ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, byte bridge_type) { DeleteWindowById(WC_BUILD_BRIDGE, 0); - _bridgedata.type = (transport_type << 15) | (bridge_type << 8); //prepare the parameter for use only once - _bridgedata.start_tile = start; - _bridgedata.end_tile = end; + /* Data type for the bridge. + * Bit 16,15 = transport type, + * 14..8 = road/rail pieces, + * 7..0 = type of bridge */ + uint32 type = (transport_type << 15) | (bridge_type << 8); /* only query bridge building possibility once, result is the same for all bridges! * returns CMD_ERROR on failure, and price on success */ StringID errmsg = INVALID_STRING_ID; - CommandCost ret = DoCommand(end, start, _bridgedata.type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE); + CommandCost ret = DoCommand(end, start, type, DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE); - uint8 j = 0; + GUIBridgeList *bl = NULL; if (CmdFailed(ret)) { errmsg = _error_message; } else { @@ -167,27 +303,26 @@ /* total length of bridge */ const uint tot_bridgedata_len = CalcBridgeLenCostFactor(bridge_len + 2); + bl = new GUIBridgeList(); + /* loop for all bridgetypes */ for (BridgeType brd_type = 0; brd_type != MAX_BRIDGES; brd_type++) { if (CheckBridge_Stuff(brd_type, bridge_len)) { /* bridge is accepted, add to list */ - const BridgeSpec *b = GetBridgeSpec(brd_type); + BuildBridgeData *item = bl->Append(); + item->index = brd_type; + item->spec = GetBridgeSpec(brd_type); /* Add to terraforming & bulldozing costs the cost of the * bridge itself (not computed with DC_QUERY_COST) */ - _bridgedata.costs[j] = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * b->price) >> 8); - _bridgedata.indexes[j] = brd_type; - j++; + item->cost = ret.GetCost() + (((int64)tot_bridgedata_len * _price.build_bridge * item->spec->price) >> 8); } } - - _bridgedata.count = j; } - if (j != 0) { - Window *w = new Window(&_build_bridge_desc); - /* Change the data, or the caption of the gui. Set it to road or rail, accordingly */ - w->widget[BBSW_CAPTION].data = (transport_type == TRANSPORT_ROAD) ? STR_1803_SELECT_ROAD_BRIDGE : STR_100D_SELECT_RAIL_BRIDGE; + if (bl != NULL && bl->Length() != 0) { + new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl); } else { + if (bl != NULL) delete bl; ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE); } } diff -r 68a692eacf22 -r 67db0d431d5e src/build_vehicle_gui.cpp --- a/src/build_vehicle_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/build_vehicle_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -506,7 +506,7 @@ y += 10; /* Wagon speed limit, displayed if above zero */ - if (_patches.wagon_speed_limits) { + if (_settings.vehicle.wagon_speed_limits) { uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed); if (max_speed > 0) { SetDParam(0, max_speed * 10 / 16); @@ -544,7 +544,7 @@ y += 10; /* Max tractive effort - not applicable if old acceleration or maglev */ - if (_patches.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) { + if (_settings.vehicle.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) { SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256); DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING); y += 10; @@ -800,7 +800,6 @@ AirportFTAClass::Flags flags; RoadTypes roadtypes; } filter; - byte sel_index; ///< deprecated value, used for 'unified' ship and road bool descending_sort_order; byte sort_criteria; bool regenerate_list; @@ -1182,7 +1181,6 @@ WC_BUILD_VEHICLE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _build_vehicle_widgets, - NULL }; void ShowBuildVehicleWindow(TileIndex tile, VehicleType type) diff -r 68a692eacf22 -r 67db0d431d5e src/cheat_gui.cpp --- a/src/cheat_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/cheat_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -64,9 +64,9 @@ { if (p1 == -1) p1 = 3; if (p1 == 4) p1 = 0; - _opt.landscape = p1; + _settings.game_creation.landscape = p1; ReloadNewGRFData(); - return _opt.landscape; + return _settings.game_creation.landscape; } extern void EnginesMonthlyLoop(); @@ -100,15 +100,15 @@ }; static const CheatEntry _cheats_ui[] = { - {SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat }, - {SLE_UINT8, STR_CHEAT_CHANGE_PLAYER, &_local_player, &_cheats.switch_player.been_used, &ClickChangePlayerCheat }, - {SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, NULL }, - {SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, NULL }, - {SLE_BOOL, STR_CHEAT_BUILD_IN_PAUSE, &_cheats.build_in_pause.value, &_cheats.build_in_pause.been_used, NULL }, - {SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, NULL }, - {SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, NULL }, - {SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE, &_opt.landscape, &_cheats.switch_climate.been_used, &ClickChangeClimateCheat}, - {SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, + {SLE_INT32, STR_CHEAT_MONEY, &_money_cheat_amount, &_cheats.money.been_used, &ClickMoneyCheat }, + {SLE_UINT8, STR_CHEAT_CHANGE_PLAYER, &_local_player, &_cheats.switch_player.been_used, &ClickChangePlayerCheat }, + {SLE_BOOL, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, NULL }, + {SLE_BOOL, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value, &_cheats.crossing_tunnels.been_used, NULL }, + {SLE_BOOL, STR_CHEAT_BUILD_IN_PAUSE, &_cheats.build_in_pause.value, &_cheats.build_in_pause.been_used, NULL }, + {SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, NULL }, + {SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, NULL }, + {SLE_UINT8, STR_CHEAT_SWITCH_CLIMATE, &_settings.game_creation.landscape, &_cheats.switch_climate.been_used, &ClickChangeClimateCheat}, + {SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, }; @@ -125,6 +125,7 @@ CheatWindow(const WindowDesc *desc) : Window(desc) { + this->FindWindowPlacementAndResize(desc); } virtual void OnPaint() @@ -226,7 +227,6 @@ WC_CHEATS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _cheat_widgets, - NULL }; diff -r 68a692eacf22 -r 67db0d431d5e src/clear_cmd.cpp --- a/src/clear_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/clear_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -218,7 +218,7 @@ { TileLoopClearHelper(tile); - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_TROPIC: TileLoopClearDesert(tile); break; case LT_ARCTIC: TileLoopClearAlps(tile); break; } @@ -336,7 +336,7 @@ } else { td->str = _clear_land_str[GetClearGround(tile)]; } - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); } static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player) @@ -346,7 +346,7 @@ void InitializeClearLand() { - _opt.snow_line = _patches.snow_line_height * TILE_HEIGHT; + _settings.game_creation.snow_line = _settings.game_creation.snow_line_height * TILE_HEIGHT; } static CommandCost TerraformTile_Clear(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) diff -r 68a692eacf22 -r 67db0d431d5e src/command.cpp --- a/src/command.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/command.cpp Tue May 27 00:50:55 2008 +0000 @@ -152,7 +152,6 @@ DEF_COMMAND(CmdSetRoadDriveSide); -DEF_COMMAND(CmdChangeDifficultyLevel); DEF_COMMAND(CmdChangePatchSetting); DEF_COMMAND(CmdStartStopShip); @@ -304,7 +303,6 @@ {CmdDoTownAction, 0}, /* CMD_DO_TOWN_ACTION */ {CmdSetRoadDriveSide, CMD_SERVER}, /* CMD_SET_ROAD_DRIVE_SIDE */ - {CmdChangeDifficultyLevel, CMD_SERVER}, /* CMD_CHANGE_DIFFICULTY_LEVEL */ {CmdStartStopShip, 0}, /* CMD_START_STOP_SHIP */ {CmdSellShip, 0}, /* CMD_SELL_SHIP */ diff -r 68a692eacf22 -r 67db0d431d5e src/command_type.h --- a/src/command_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/command_type.h Tue May 27 00:50:55 2008 +0000 @@ -233,8 +233,6 @@ CMD_SET_ROAD_DRIVE_SIDE, ///< set the side where the road vehicles drive - CMD_CHANGE_DIFFICULTY_LEVEL, ///< change the difficult of a game (each setting for it own) - CMD_START_STOP_SHIP, ///< start/stop a ship CMD_SELL_SHIP, ///< sell a ship CMD_BUILD_SHIP, ///< build a new ship diff -r 68a692eacf22 -r 67db0d431d5e src/console.cpp --- a/src/console.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/console.cpp Tue May 27 00:50:55 2008 +0000 @@ -3,23 +3,15 @@ /** @file console.cpp Handling of the in-game console. */ #include "stdafx.h" -#include "openttd.h" -#include "gui.h" -#include "textbuf_gui.h" -#include "window_gui.h" -#include "variables.h" -#include -#include -#include "console.h" -#include "network/network.h" +#include "console_internal.h" #include "network/network_data.h" #include "network/network_server.h" #include "core/alloc_func.hpp" -#include "window_func.h" #include "string_func.h" -#include "gfx_func.h" #include "rev.h" +#include + #include "table/strings.h" #define ICON_BUFFER 79 @@ -35,265 +27,21 @@ IConsoleVar *_iconsole_vars; ///< list of registred vars IConsoleAlias *_iconsole_aliases; ///< list of registred aliases -/* console colors/modes */ -byte _icolour_def; -byte _icolour_err; -byte _icolour_warn; -byte _icolour_dbg; -byte _icolour_cmd; -IConsoleModes _iconsole_mode; - -/* ** main console ** */ -static char *_iconsole_buffer[ICON_BUFFER + 1]; -static uint16 _iconsole_cbuffer[ICON_BUFFER + 1]; -static Textbuf _iconsole_cmdline; - /* ** stdlib ** */ byte _stdlib_developer = 1; bool _stdlib_con_developer = false; FILE *_iconsole_output_file; -/* ** main console cmd buffer ** */ -static char *_iconsole_history[ICON_HISTORY_SIZE]; -static byte _iconsole_historypos; - -/* *************** * - * end of header * - * *************** */ - -static void IConsoleClearCommand() -{ - memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE); - _iconsole_cmdline.length = 0; - _iconsole_cmdline.width = 0; - _iconsole_cmdline.caretpos = 0; - _iconsole_cmdline.caretxoffs = 0; - SetWindowDirty(FindWindowById(WC_CONSOLE, 0)); -} - -static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;} - - -static void IConsoleHistoryAdd(const char *cmd); -static void IConsoleHistoryNavigate(int direction); - -struct IConsoleWindow : Window -{ - static byte scroll; - - IConsoleWindow(const WindowDesc *desc) : Window(desc) - { - _iconsole_mode = ICONSOLE_OPENED; - SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll - - this->height = _screen.height / 3; - this->width = _screen.width; - } - - ~IConsoleWindow() - { - _iconsole_mode = ICONSOLE_CLOSED; - ClrBit(_no_scroll, SCROLL_CON); - } - - virtual void OnPaint() - { - int i = IConsoleWindow::scroll; - int max = (this->height / ICON_LINE_HEIGHT) - 1; - int delta = 0; - GfxFillRect(this->left, this->top, this->width, this->height - 1, 0); - while ((i > 0) && (i > IConsoleWindow::scroll - max) && (_iconsole_buffer[i] != NULL)) { - DoDrawString(_iconsole_buffer[i], 5, - this->height - (IConsoleWindow::scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]); - i--; - } - /* If the text is longer than the window, don't show the starting ']' */ - delta = this->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH; - if (delta > 0) { - DoDrawString("]", 5, this->height - ICON_LINE_HEIGHT, _icolour_cmd); - delta = 0; - } - - DoDrawString(_iconsole_cmdline.buf, 10 + delta, this->height - ICON_LINE_HEIGHT, _icolour_cmd); - - if (_iconsole_cmdline.caret) { - DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, this->height - ICON_LINE_HEIGHT, TC_WHITE); - } - } - - virtual void OnMouseLoop() - { - if (HandleCaret(&_iconsole_cmdline)) this->SetDirty(); - } - - virtual bool OnKeyPress(uint16 key, uint16 keycode) - { - switch (keycode) { - case WKC_UP: - IConsoleHistoryNavigate(+1); - this->SetDirty(); - break; - - case WKC_DOWN: - IConsoleHistoryNavigate(-1); - this->SetDirty(); - break; - - case WKC_SHIFT | WKC_PAGEUP: - if (IConsoleWindow::scroll - (this->height / ICON_LINE_HEIGHT) - 1 < 0) { - IConsoleWindow::scroll = 0; - } else { - IConsoleWindow::scroll -= (this->height / ICON_LINE_HEIGHT) - 1; - } - this->SetDirty(); - break; - - case WKC_SHIFT | WKC_PAGEDOWN: - if (IConsoleWindow::scroll + (this->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) { - IConsoleWindow::scroll = ICON_BUFFER; - } else { - IConsoleWindow::scroll += (this->height / ICON_LINE_HEIGHT) - 1; - } - this->SetDirty(); - break; - - case WKC_SHIFT | WKC_UP: - if (IConsoleWindow::scroll <= 0) { - IConsoleWindow::scroll = 0; - } else { - --IConsoleWindow::scroll; - } - this->SetDirty(); - break; - - case WKC_SHIFT | WKC_DOWN: - if (IConsoleWindow::scroll >= ICON_BUFFER) { - IConsoleWindow::scroll = ICON_BUFFER; - } else { - ++IConsoleWindow::scroll; - } - this->SetDirty(); - break; - - case WKC_BACKQUOTE: - IConsoleSwitch(); - break; - - case WKC_RETURN: case WKC_NUM_ENTER: - IConsolePrintF(_icolour_cmd, "] %s", _iconsole_cmdline.buf); - IConsoleHistoryAdd(_iconsole_cmdline.buf); - - IConsoleCmdExec(_iconsole_cmdline.buf); - IConsoleClearCommand(); - break; - - case WKC_CTRL | WKC_RETURN: - _iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL; - IConsoleResize(this); - MarkWholeScreenDirty(); - break; - - case (WKC_CTRL | 'V'): - if (InsertTextBufferClipboard(&_iconsole_cmdline)) { - IConsoleResetHistoryPos(); - this->SetDirty(); - } - break; - - case (WKC_CTRL | 'L'): - IConsoleCmdExec("clear"); - break; - - case (WKC_CTRL | 'U'): - DeleteTextBufferAll(&_iconsole_cmdline); - this->SetDirty(); - break; - - case WKC_BACKSPACE: case WKC_DELETE: - if (DeleteTextBufferChar(&_iconsole_cmdline, keycode)) { - IConsoleResetHistoryPos(); - this->SetDirty(); - } - break; - - case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME: - if (MoveTextBufferPos(&_iconsole_cmdline, keycode)) { - IConsoleResetHistoryPos(); - this->SetDirty(); - } - break; - - default: - if (IsValidChar(key, CS_ALPHANUMERAL)) { - IConsoleWindow::scroll = ICON_BUFFER; - InsertTextBufferChar(&_iconsole_cmdline, key); - IConsoleResetHistoryPos(); - this->SetDirty(); - } else { - return true; - } - } - return false; - } -}; - -byte IConsoleWindow::scroll = ICON_BUFFER; - -static const Widget _iconsole_window_widgets[] = { - {WIDGETS_END} -}; - -static const WindowDesc _iconsole_window_desc = { - 0, 0, 2, 2, 2, 2, - WC_CONSOLE, WC_NONE, - WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, - _iconsole_window_widgets, - NULL, -}; - void IConsoleInit() { _iconsole_output_file = NULL; - _icolour_def = 1; - _icolour_err = 3; - _icolour_warn = 13; - _icolour_dbg = 5; - _icolour_cmd = TC_GOLD; - _iconsole_historypos = ICON_HISTORY_SIZE - 1; - _iconsole_mode = ICONSOLE_CLOSED; - #ifdef ENABLE_NETWORK /* Initialize network only variables */ _redirect_console_to_client = 0; #endif - memset(_iconsole_history, 0, sizeof(_iconsole_history)); - memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer)); - memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer)); - _iconsole_cmdline.buf = CallocT(ICON_CMDLN_SIZE); // create buffer and zero it - _iconsole_cmdline.maxlength = ICON_CMDLN_SIZE; + IConsoleGUIInit(); - IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision); - IConsolePrint(12, "------------------------------------"); - IConsolePrint(12, "use \"help\" for more information"); - IConsolePrint(12, ""); IConsoleStdLibRegister(); - IConsoleClearCommand(); - IConsoleHistoryAdd(""); -} - -void IConsoleClearBuffer() -{ - uint i; - for (i = 0; i <= ICON_BUFFER; i++) { - free(_iconsole_buffer[i]); - _iconsole_buffer[i] = NULL; - } -} - -static void IConsoleClear() -{ - free(_iconsole_cmdline.buf); - IConsoleClearBuffer(); } static void IConsoleWriteToLogFile(const char *string) @@ -304,7 +52,7 @@ fwrite("\n", 1, 1, _iconsole_output_file) != 1) { fclose(_iconsole_output_file); _iconsole_output_file = NULL; - IConsolePrintF(_icolour_def, "cannot write to log file"); + IConsolePrintF(CC_DEFAULT, "cannot write to log file"); } } } @@ -312,7 +60,7 @@ bool CloseConsoleLogIfActive() { if (_iconsole_output_file != NULL) { - IConsolePrintF(_icolour_def, "file output complete"); + IConsolePrintF(CC_DEFAULT, "file output complete"); fclose(_iconsole_output_file); _iconsole_output_file = NULL; return true; @@ -323,86 +71,10 @@ void IConsoleFree() { - IConsoleClear(); + IConsoleGUIFree(); CloseConsoleLogIfActive(); } -void IConsoleResize(Window *w) -{ - switch (_iconsole_mode) { - case ICONSOLE_OPENED: - w->height = _screen.height / 3; - w->width = _screen.width; - break; - case ICONSOLE_FULL: - w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH; - w->width = _screen.width; - break; - default: return; - } - - MarkWholeScreenDirty(); -} - -void IConsoleSwitch() -{ - switch (_iconsole_mode) { - case ICONSOLE_CLOSED: - new IConsoleWindow(&_iconsole_window_desc); - break; - - case ICONSOLE_OPENED: case ICONSOLE_FULL: - DeleteWindowById(WC_CONSOLE, 0); - break; - } - - MarkWholeScreenDirty(); -} - -void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();} -void IConsoleOpen() {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();} - -/** - * Add the entered line into the history so you can look it back - * scroll, etc. Put it to the beginning as it is the latest text - * @param cmd Text to be entered into the 'history' - */ -static void IConsoleHistoryAdd(const char *cmd) -{ - free(_iconsole_history[ICON_HISTORY_SIZE - 1]); - - memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1)); - _iconsole_history[0] = strdup(cmd); - IConsoleResetHistoryPos(); -} - -/** - * Navigate Up/Down in the history of typed commands - * @param direction Go further back in history (+1), go to recently typed commands (-1) - */ -static void IConsoleHistoryNavigate(int direction) -{ - int i = _iconsole_historypos + direction; - - /* watch out for overflows, just wrap around */ - if (i < 0) i = ICON_HISTORY_SIZE - 1; - if (i >= ICON_HISTORY_SIZE) i = 0; - - if (direction > 0) - if (_iconsole_history[i] == NULL) i = 0; - - if (direction < 0) { - while (i > 0 && _iconsole_history[i] == NULL) i--; - } - - _iconsole_historypos = i; - IConsoleClearCommand(); - /* copy history to 'command prompt / bash' */ - assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE)); - ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength); - UpdateTextBufferSize(&_iconsole_cmdline); -} - /** * Handle the printing of text entered into the console or redirected there * by any other means. Text can be redirected to other players in a network game @@ -412,7 +84,7 @@ * @param color_code the colour of the command. Red in case of errors, etc. * @param string the message entered or output on the console (notice, error, etc.) */ -void IConsolePrint(uint16 color_code, const char *string) +void IConsolePrint(ConsoleColour color_code, const char *string) { char *str; #ifdef ENABLE_NETWORK @@ -437,18 +109,8 @@ return; } - /* move up all the strings in the buffer one place and do the same for colour - * to accomodate for the new command/message */ - free(_iconsole_buffer[0]); - memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER); - _iconsole_buffer[ICON_BUFFER] = str; - - memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER); - _iconsole_cbuffer[ICON_BUFFER] = color_code; - - IConsoleWriteToLogFile(_iconsole_buffer[ICON_BUFFER]); - - SetWindowDirty(FindWindowById(WC_CONSOLE, 0)); + IConsoleWriteToLogFile(str); + IConsoleGUIPrint(color_code, str); } /** @@ -456,7 +118,7 @@ * by any other means. Uses printf() style format, for more information look * at IConsolePrint() */ -void CDECL IConsolePrintF(uint16 color_code, const char *s, ...) +void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...) { va_list va; char buf[ICON_MAX_STREAMSIZE]; @@ -479,7 +141,7 @@ void IConsoleDebug(const char *dbg, const char *string) { if (_stdlib_developer > 1) - IConsolePrintF(_icolour_dbg, "dbg: [%s] %s", dbg, string); + IConsolePrintF(CC_DEBUG, "dbg: [%s] %s", dbg, string); } /** @@ -490,7 +152,7 @@ void IConsoleWarning(const char *string) { if (_stdlib_developer > 0) - IConsolePrintF(_icolour_warn, "WARNING: %s", string); + IConsolePrintF(CC_WARNING, "WARNING: %s", string); } /** @@ -499,7 +161,7 @@ */ void IConsoleError(const char *string) { - IConsolePrintF(_icolour_err, "ERROR: %s", string); + IConsolePrintF(CC_ERROR, "ERROR: %s", string); } /** @@ -748,7 +410,7 @@ memset(&aliasstream, 0, sizeof(aliasstream)); if (_stdlib_con_developer) - IConsolePrintF(_icolour_dbg, "condbg: requested command is an alias; parsing..."); + IConsolePrintF(CC_DEBUG, "condbg: requested command is an alias; parsing..."); aliases[0] = aliasstream; for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; cmdptr++) { @@ -788,7 +450,7 @@ if (param < 0 || param >= tokencount) { IConsoleError("too many or wrong amount of parameters passed to alias, aborting"); - IConsolePrintF(_icolour_warn, "Usage of alias '%s': %s", alias->name, alias->cmdline); + IConsolePrintF(CC_WARNING, "Usage of alias '%s': %s", alias->name, alias->cmdline); return; } @@ -1001,7 +663,7 @@ } value = IConsoleVarGetStringValue(var); - IConsolePrintF(_icolour_warn, "Current value for '%s' is: %s", var->name, value); + IConsolePrintF(CC_WARNING, "Current value for '%s' is: %s", var->name, value); } /** @@ -1011,7 +673,7 @@ void IConsoleVarPrintSetValue(const IConsoleVar *var) { char *value = IConsoleVarGetStringValue(var); - IConsolePrintF(_icolour_warn, "'%s' changed to: %s", var->name, value); + IConsolePrintF(CC_WARNING, "'%s' changed to: %s", var->name, value); } /** @@ -1028,7 +690,7 @@ uint32 value; if (_stdlib_con_developer) - IConsolePrintF(_icolour_dbg, "condbg: requested command is a variable"); + IConsolePrintF(CC_DEBUG, "condbg: requested command is a variable"); if (tokencount == 0) { /* Just print out value */ IConsoleVarPrintGetValue(var); @@ -1105,13 +767,13 @@ for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) { if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) { IConsoleError("command contains malformed characters, aborting"); - IConsolePrintF(_icolour_err, "ERROR: command was: '%s'", cmdstr); + IConsolePrintF(CC_ERROR, "ERROR: command was: '%s'", cmdstr); return; } } if (_stdlib_con_developer) - IConsolePrintF(_icolour_dbg, "condbg: executing cmdline: '%s'", cmdstr); + IConsolePrintF(CC_DEBUG, "condbg: executing cmdline: '%s'", cmdstr); memset(&tokens, 0, sizeof(tokens)); memset(&tokenstream, 0, sizeof(tokenstream)); @@ -1159,7 +821,7 @@ uint i; for (i = 0; tokens[i] != NULL; i++) { - IConsolePrintF(_icolour_dbg, "condbg: token %d is: '%s'", i, tokens[i]); + IConsolePrintF(CC_DEBUG, "condbg: token %d is: '%s'", i, tokens[i]); } } diff -r 68a692eacf22 -r 67db0d431d5e src/console.h --- a/src/console.h Mon May 26 20:45:25 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* $Id$ */ - -/** @file console.h In-game console. */ - -#ifndef CONSOLE_H -#define CONSOLE_H - -#include "window_type.h" - -/* maximum length of a typed in command */ -#define ICON_CMDLN_SIZE 255 -/* maximum length of a totally expanded command */ -#define ICON_MAX_STREAMSIZE 1024 - -enum IConsoleVarTypes { - ICONSOLE_VAR_BOOLEAN, - ICONSOLE_VAR_BYTE, - ICONSOLE_VAR_UINT16, - ICONSOLE_VAR_UINT32, - ICONSOLE_VAR_INT16, - ICONSOLE_VAR_INT32, - ICONSOLE_VAR_STRING -}; - -enum IConsoleModes { - ICONSOLE_FULL, - ICONSOLE_OPENED, - ICONSOLE_CLOSED -}; - -enum IConsoleHookTypes { - ICONSOLE_HOOK_ACCESS, - ICONSOLE_HOOK_PRE_ACTION, - ICONSOLE_HOOK_POST_ACTION -}; - -/** --Hooks-- - * Hooks are certain triggers get get accessed/executed on either - * access, before execution/change or after execution/change. This allows - * for general flow of permissions or special action needed in some cases - */ -typedef bool IConsoleHook(); -struct IConsoleHooks{ - IConsoleHook *access; ///< trigger when accessing the variable/command - IConsoleHook *pre; ///< trigger before the variable/command is changed/executed - IConsoleHook *post; ///< trigger after the variable/command is changed/executed -}; - -/** --Commands-- - * Commands are commands, or functions. They get executed once and any - * effect they produce are carried out. The arguments to the commands - * are given to them, each input word seperated by a double-quote (") is an argument - * If you want to handle multiple words as one, enclose them in double-quotes - * eg. 'say "hello sexy boy"' - */ -typedef bool (IConsoleCmdProc)(byte argc, char *argv[]); - -struct IConsoleCmd { - char *name; ///< name of command - IConsoleCmd *next; ///< next command in list - - IConsoleCmdProc *proc; ///< process executed when command is typed - IConsoleHooks hook; ///< any special trigger action that needs executing -}; - -/** --Variables-- - * Variables are pointers to real ingame variables which allow for - * changing while ingame. After changing they keep their new value - * and can be used for debugging, gameplay, etc. It accepts: - * - no arguments; just print out current value - * - '= ' to assign a new value to the variable - * - '++' to increase value by one - * - '--' to decrease value by one - */ -struct IConsoleVar { - char *name; ///< name of the variable - IConsoleVar *next; ///< next variable in list - - void *addr; ///< the address where the variable is pointing at - uint32 size; ///< size of the variable, used for strings - char *help; ///< the optional help string shown when requesting information - IConsoleVarTypes type; ///< type of variable (for correct assignment/output) - IConsoleCmdProc *proc; ///< some variables need really special handling, use a callback function for that - IConsoleHooks hook; ///< any special trigger action that needs executing -}; - -/** --Aliases-- - * Aliases are like shortcuts for complex functions, variable assignments, - * etc. You can use a simple alias to rename a longer command (eg 'lv' for - * 'list_vars' for example), or concatenate more commands into one - * (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments - * given to them in the command line. - * - "%A - %Z" substitute arguments 1 t/m 26 - * - "%+" lists all parameters keeping them seperated - * - "%!" also lists all parameters but presenting them to the aliased command as one argument - * - ";" allows for combining commands (see example 'ng') - */ -struct IConsoleAlias { - char *name; ///< name of the alias - IConsoleAlias *next; ///< next alias in list - - char *cmdline; ///< command(s) that is/are being aliased -}; - -/* console parser */ -extern IConsoleCmd *_iconsole_cmds; ///< list of registred commands -extern IConsoleVar *_iconsole_vars; ///< list of registred vars -extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases - -/* console colors/modes */ -extern byte _icolour_def; -extern byte _icolour_err; -extern byte _icolour_warn; -extern byte _icolour_dbg; -extern byte _icolour_cmd; -extern IConsoleModes _iconsole_mode; - -/* console functions */ -void IConsoleInit(); -void IConsoleFree(); -void IConsoleClearBuffer(); -void IConsoleResize(Window *w); -void IConsoleSwitch(); -void IConsoleClose(); -void IConsoleOpen(); - -/* console output */ -void IConsolePrint(uint16 color_code, const char *string); -void CDECL IConsolePrintF(uint16 color_code, const char *s, ...); -void IConsoleDebug(const char *dbg, const char *string); -void IConsoleWarning(const char *string); -void IConsoleError(const char *string); - -/* Commands */ -void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc); -void IConsoleAliasRegister(const char *name, const char *cmd); -IConsoleCmd *IConsoleCmdGet(const char *name); -IConsoleAlias *IConsoleAliasGet(const char *name); - -/* Variables */ -void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help); -void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help); -IConsoleVar* IConsoleVarGet(const char *name); -void IConsoleVarPrintGetValue(const IConsoleVar *var); -void IConsoleVarPrintSetValue(const IConsoleVar *var); - -/* Parser */ -void IConsoleCmdExec(const char *cmdstr); -void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]); - -/* console std lib (register ingame commands/aliases/variables) */ -void IConsoleStdLibRegister(); - -/* Hooking code */ -void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc); -void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc); -void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc); - -/* Supporting functions */ -bool GetArgumentInteger(uint32 *value, const char *arg); -#endif /* CONSOLE_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/console_cmds.cpp --- a/src/console_cmds.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/console_cmds.cpp Tue May 27 00:50:55 2008 +0000 @@ -4,7 +4,7 @@ #include "stdafx.h" #include "openttd.h" -#include "console.h" +#include "console_internal.h" #include "debug.h" #include "engine_func.h" #include "landscape.h" @@ -107,7 +107,7 @@ static void IConsoleHelp(const char *str) { - IConsolePrintF(_icolour_warn, "- %s", str); + IConsolePrintF(CC_WARNING, "- %s", str); } DEF_CONSOLE_CMD(ConResetEngines) @@ -165,7 +165,7 @@ uint32 result; if (GetArgumentInteger(&result, argv[1])) { if (result >= MapSize()) { - IConsolePrint(_icolour_err, "Tile does not exist"); + IConsolePrint(CC_ERROR, "Tile does not exist"); return true; } ScrollMainWindowToTile((TileIndex)result); @@ -189,12 +189,12 @@ if (argc == 2) { char *filename = str_fmt("%s.sav", argv[1]); - IConsolePrint(_icolour_def, "Saving map..."); + IConsolePrint(CC_DEFAULT, "Saving map..."); if (SaveOrLoad(filename, SL_SAVE, SAVE_DIR) != SL_OK) { - IConsolePrint(_icolour_err, "Saving map failed"); + IConsolePrint(CC_ERROR, "Saving map failed"); } else { - IConsolePrintF(_icolour_def, "Map sucessfully saved to %s", filename); + IConsolePrintF(CC_DEFAULT, "Map sucessfully saved to %s", filename); } free(filename); return true; @@ -212,7 +212,7 @@ } SaveToConfig(); - IConsolePrint(_icolour_def, "Saved config."); + IConsolePrint(CC_DEFAULT, "Saved config."); return true; } @@ -262,10 +262,10 @@ ttd_strlcpy(_file_to_saveload.name, FiosBrowseTo(item), sizeof(_file_to_saveload.name)); ttd_strlcpy(_file_to_saveload.title, item->title, sizeof(_file_to_saveload.title)); } break; - default: IConsolePrintF(_icolour_err, "%s: Not a savegame.", file); + default: IConsolePrintF(CC_ERROR, "%s: Not a savegame.", file); } } else { - IConsolePrintF(_icolour_err, "%s: No such file or directory.", file); + IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file); } FiosFreeSavegameList(); @@ -289,9 +289,9 @@ item = GetFiosItem(file); if (item != NULL) { if (!FiosDelete(item->name)) - IConsolePrintF(_icolour_err, "%s: Failed to delete file", file); + IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file); } else { - IConsolePrintF(_icolour_err, "%s: No such file or directory.", file); + IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file); } FiosFreeSavegameList(); @@ -313,7 +313,7 @@ for (i = 0; i < _fios_num; i++) { const FiosItem *item = &_fios_list[i]; - IConsolePrintF(_icolour_def, "%d) %s", i, item->title); + IConsolePrintF(CC_DEFAULT, "%d) %s", i, item->title); } FiosFreeSavegameList(); @@ -340,10 +340,10 @@ case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT: FiosBrowseTo(item); break; - default: IConsolePrintF(_icolour_err, "%s: Not a directory.", file); + default: IConsolePrintF(CC_ERROR, "%s: Not a directory.", file); } } else { - IConsolePrintF(_icolour_err, "%s: No such file or directory.", file); + IConsolePrintF(CC_ERROR, "%s: No such file or directory.", file); } FiosFreeSavegameList(); @@ -364,7 +364,7 @@ FiosFreeSavegameList(); FiosGetDescText(&path, NULL); - IConsolePrint(_icolour_def, path); + IConsolePrint(CC_DEFAULT, path); return true; } @@ -427,9 +427,9 @@ if (ci != NULL) { banip = inet_ntoa(*(struct in_addr *)&ci->client_ip); SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED); - IConsolePrint(_icolour_def, "Client banned"); + IConsolePrint(CC_DEFAULT, "Client banned"); } else { - IConsolePrint(_icolour_def, "Client not online, banned IP"); + IConsolePrint(CC_DEFAULT, "Client not online, banned IP"); } /* Add user to ban-list */ @@ -464,12 +464,12 @@ if (strcmp(_network_ban_list[i], argv[1]) == 0 || index == i) { free(_network_ban_list[i]); _network_ban_list[i] = NULL; - IConsolePrint(_icolour_def, "IP unbanned."); + IConsolePrint(CC_DEFAULT, "IP unbanned."); return true; } } - IConsolePrint(_icolour_def, "IP not in ban-list."); + IConsolePrint(CC_DEFAULT, "IP not in ban-list."); return true; } @@ -482,11 +482,11 @@ return true; } - IConsolePrint(_icolour_def, "Banlist: "); + IConsolePrint(CC_DEFAULT, "Banlist: "); for (i = 0; i < lengthof(_network_ban_list); i++) { if (_network_ban_list[i] != NULL) - IConsolePrintF(_icolour_def, " %d) %s", i + 1, _network_ban_list[i]); + IConsolePrintF(CC_DEFAULT, " %d) %s", i + 1, _network_ban_list[i]); } return true; @@ -501,9 +501,9 @@ if (_pause_game == 0) { DoCommandP(0, 1, 0, NULL, CMD_PAUSE); - IConsolePrint(_icolour_def, "Game paused."); + IConsolePrint(CC_DEFAULT, "Game paused."); } else { - IConsolePrint(_icolour_def, "Game is already paused."); + IConsolePrint(CC_DEFAULT, "Game is already paused."); } return true; @@ -518,9 +518,9 @@ if (_pause_game != 0) { DoCommandP(0, 0, 0, NULL, CMD_PAUSE); - IConsolePrint(_icolour_def, "Game unpaused."); + IConsolePrint(CC_DEFAULT, "Game unpaused."); } else { - IConsolePrint(_icolour_def, "Game is already unpaused."); + IConsolePrint(CC_DEFAULT, "Game is already unpaused."); } return true; @@ -570,7 +570,7 @@ const char* status; status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown"); - IConsolePrintF(8, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s unique-id: '%s'", + IConsolePrintF(CC_INFO, "Client #%1d name: '%s' status: '%s' frame-lag: %3d company: %1d IP: %s unique-id: '%s'", cs->index, ci->client_name, status, lag, ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0), GetPlayerIP(ci), ci->unique_id); @@ -590,9 +590,9 @@ } gi = &_network_game_info; - IConsolePrintF(_icolour_def, "Current/maximum clients: %2d/%2d", gi->clients_on, gi->clients_max); - IConsolePrintF(_icolour_def, "Current/maximum companies: %2d/%2d", ActivePlayerCount(), gi->companies_max); - IConsolePrintF(_icolour_def, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max); + IConsolePrintF(CC_DEFAULT, "Current/maximum clients: %2d/%2d", gi->clients_on, gi->clients_max); + IConsolePrintF(CC_DEFAULT, "Current/maximum companies: %2d/%2d", ActivePlayerCount(), gi->companies_max); + IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max); return true; } @@ -693,7 +693,7 @@ /* Check valid range */ if (!IsValidPlayer(index)) { - IConsolePrintF(_icolour_err, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS); + IConsolePrintF(CC_ERROR, "Company does not exist. Company-id must be between 1 and %d.", MAX_PLAYERS); return true; } @@ -725,7 +725,7 @@ /* It is safe to remove this company */ DoCommandP(0, 2, index, NULL, CMD_PLAYER_CTRL); - IConsolePrint(_icolour_def, "Company deleted."); + IConsolePrint(CC_DEFAULT, "Company deleted."); return true; } @@ -740,7 +740,7 @@ } FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { - IConsolePrintF(8, "Client #%1d name: '%s' company: %1d IP: %s", + IConsolePrintF(CC_INFO, "Client #%1d name: '%s' company: %1d IP: %s", ci->client_index, ci->client_name, ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0), GetPlayerIP(ci)); @@ -773,10 +773,10 @@ ParseConnectionString(&player, &port, ip); - IConsolePrintF(_icolour_def, "Connecting to %s...", ip); + IConsolePrintF(CC_DEFAULT, "Connecting to %s...", ip); if (player != NULL) { _network_playas = (PlayerID)atoi(player); - IConsolePrintF(_icolour_def, " player-no: %d", _network_playas); + IConsolePrintF(CC_DEFAULT, " player-no: %d", _network_playas); /* From a user pov 0 is a new player, internally it's different and all * players are offset by one to ease up on users (eg players 1-8 not 0-7) */ @@ -787,7 +787,7 @@ } if (port != NULL) { rport = atoi(port); - IConsolePrintF(_icolour_def, " port: %s", port); + IConsolePrintF(CC_DEFAULT, " port: %s", port); } NetworkClientConnectGame(ip, rport); @@ -870,7 +870,7 @@ if (!CloseConsoleLogIfActive()) { if (argc < 2) return false; - IConsolePrintF(_icolour_def, "file output started to: %s", argv[1]); + IConsolePrintF(CC_DEFAULT, "file output started to: %s", argv[1]); _iconsole_output_file = fopen(argv[1], "ab"); if (_iconsole_output_file == NULL) IConsoleError("could not open file"); } @@ -887,7 +887,7 @@ } if (argc < 2) return false; - IConsolePrint(_icolour_def, argv[1]); + IConsolePrint(CC_DEFAULT, argv[1]); return true; } @@ -899,7 +899,7 @@ } if (argc < 3) return false; - IConsolePrint(atoi(argv[1]), argv[2]); + IConsolePrint((ConsoleColour)atoi(argv[1]), argv[2]); return true; } @@ -926,8 +926,8 @@ } /* Don't copy the _newgame pointers to the real pointers, so call SwitchMode directly */ - _patches.map_x = MapLogX(); - _patches.map_y = FindFirstBit(MapSizeY()); + _settings.game_creation.map_x = MapLogX(); + _settings.game_creation.map_y = FindFirstBit(MapSizeY()); SwitchMode(SM_NEWGAME); return true; } @@ -940,7 +940,7 @@ return true; } - IConsolePrintF(_icolour_def, "Generation Seed: %u", _patches.generation_seed); + IConsolePrintF(CC_DEFAULT, "Generation Seed: %u", _settings.game_creation.generation_seed); return true; } @@ -953,7 +953,7 @@ YearMonthDay ymd; ConvertDateToYMD(_date, &ymd); - IConsolePrintF(_icolour_def, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year); + IConsolePrintF(CC_DEFAULT, "Date: %d-%d-%d", ymd.day, ymd.month + 1, ymd.year); return true; } @@ -1019,9 +1019,9 @@ return true; } - IConsolePrintF(_icolour_def, "variable name: %s", var->name); - IConsolePrintF(_icolour_def, "variable type: %s", _icon_vartypes[var->type]); - IConsolePrintF(_icolour_def, "variable addr: 0x%X", var->addr); + IConsolePrintF(CC_DEFAULT, "variable name: %s", var->name); + IConsolePrintF(CC_DEFAULT, "variable type: %s", _icon_vartypes[var->type]); + IConsolePrintF(CC_DEFAULT, "variable addr: 0x%X", var->addr); if (var->hook.access) IConsoleWarning("variable is access hooked"); if (var->hook.pre) IConsoleWarning("variable is pre hooked"); @@ -1047,8 +1047,8 @@ return true; } - IConsolePrintF(_icolour_def, "command name: %s", cmd->name); - IConsolePrintF(_icolour_def, "command proc: 0x%X", cmd->proc); + IConsolePrintF(CC_DEFAULT, "command name: %s", cmd->name); + IConsolePrintF(CC_DEFAULT, "command proc: 0x%X", cmd->proc); if (cmd->hook.access) IConsoleWarning("command is access hooked"); if (cmd->hook.pre) IConsoleWarning("command is pre hooked"); @@ -1068,7 +1068,7 @@ if (argc > 2) return false; if (argc == 1) { - IConsolePrintF(_icolour_def, "Current debug-level: '%s'", GetDebugString()); + IConsolePrintF(CC_DEFAULT, "Current debug-level: '%s'", GetDebugString()); } else { SetDebugString(argv[1]); } @@ -1083,7 +1083,7 @@ return true; } - if (_game_mode == GM_NORMAL && _patches.autosave_on_exit) DoExitSave(); + if (_game_mode == GM_NORMAL && _settings.gui.autosave_on_exit) DoExitSave(); _exit_game = true; return true; @@ -1122,7 +1122,7 @@ cmd->proc(0, NULL); return true; } - IConsolePrintF(_icolour_err, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline); + IConsolePrintF(CC_ERROR, "ERROR: alias is of special type, please see its execution-line: '%s'", alias->cmdline); return true; } @@ -1136,18 +1136,18 @@ return true; } - IConsolePrint(13, " ---- OpenTTD Console Help ---- "); - IConsolePrint( 1, " - variables: [command to list all variables: list_vars]"); - IConsolePrint( 1, " set value with ' = ', use '++/--' to in-or decrement"); - IConsolePrint( 1, " or omit '=' and just ' '. get value with typing ''"); - IConsolePrint( 1, " - commands: [command to list all commands: list_cmds]"); - IConsolePrint( 1, " call commands with ' ...'"); - IConsolePrint( 1, " - to assign strings, or use them as arguments, enclose it within quotes"); - IConsolePrint( 1, " like this: ' \"string argument with spaces\"'"); - IConsolePrint( 1, " - use 'help | ' to get specific information"); - IConsolePrint( 1, " - scroll console output with shift + (up | down) | (pageup | pagedown))"); - IConsolePrint( 1, " - scroll console input history with the up | down arrows"); - IConsolePrint( 1, ""); + IConsolePrint(CC_WARNING, " ---- OpenTTD Console Help ---- "); + IConsolePrint(CC_DEFAULT, " - variables: [command to list all variables: list_vars]"); + IConsolePrint(CC_DEFAULT, " set value with ' = ', use '++/--' to in-or decrement"); + IConsolePrint(CC_DEFAULT, " or omit '=' and just ' '. get value with typing ''"); + IConsolePrint(CC_DEFAULT, " - commands: [command to list all commands: list_cmds]"); + IConsolePrint(CC_DEFAULT, " call commands with ' ...'"); + IConsolePrint(CC_DEFAULT, " - to assign strings, or use them as arguments, enclose it within quotes"); + IConsolePrint(CC_DEFAULT, " like this: ' \"string argument with spaces\"'"); + IConsolePrint(CC_DEFAULT, " - use 'help | ' to get specific information"); + IConsolePrint(CC_DEFAULT, " - scroll console output with shift + (up | down) | (pageup | pagedown))"); + IConsolePrint(CC_DEFAULT, " - scroll console input history with the up | down arrows"); + IConsolePrint(CC_DEFAULT, ""); return true; } @@ -1165,7 +1165,7 @@ for (cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) { if (argv[1] == NULL || strncmp(cmd->name, argv[1], l) == 0) { - IConsolePrintF(_icolour_def, "%s", cmd->name); + IConsolePrintF(CC_DEFAULT, "%s", cmd->name); } } @@ -1186,7 +1186,7 @@ for (var = _iconsole_vars; var != NULL; var = var->next) { if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0) - IConsolePrintF(_icolour_def, "%s", var->name); + IConsolePrintF(CC_DEFAULT, "%s", var->name); } return true; @@ -1206,7 +1206,7 @@ for (alias = _iconsole_aliases; alias != NULL; alias = alias->next) { if (argv[1] == NULL || strncmp(alias->name, argv[1], l) == 0) - IConsolePrintF(_icolour_def, "%s => %s", alias->name, alias->cmdline); + IConsolePrintF(CC_DEFAULT, "%s => %s", alias->name, alias->cmdline); } return true; @@ -1250,7 +1250,7 @@ const NetworkPlayerInfo *npi = &_network_player_info[p->index]; GetString(buffer, STR_00D1_DARK_BLUE + _player_colors[p->index], lastof(buffer)); - IConsolePrintF(8, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: %" OTTD_PRINTF64 "d Loan: %" OTTD_PRINTF64 "d Value: %" OTTD_PRINTF64 "d (T:%d, R:%d, P:%d, S:%d) %sprotected", + IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: %" OTTD_PRINTF64 "d Loan: %" OTTD_PRINTF64 "d Value: %" OTTD_PRINTF64 "d (T:%d, R:%d, P:%d, S:%d) %sprotected", p->index + 1, buffer, npi->company_name, p->inaugurated_year, (int64)p->player_money, (int64)p->current_loan, (int64)CalculateCompanyValue(p), /* trains */ npi->num_vehicle[0], /* lorry + bus */ npi->num_vehicle[1] + npi->num_vehicle[2], @@ -1273,7 +1273,7 @@ if (argc != 3) return false; if (atoi(argv[1]) < 1 || atoi(argv[1]) > MAX_PLAYERS) { - IConsolePrintF(_icolour_def, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS); + IConsolePrintF(CC_DEFAULT, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS); return true; } @@ -1335,7 +1335,7 @@ { if (argc == 0) { if (!IsValidPlayer(_local_player)) return true; // dedicated server - IConsolePrintF(_icolour_warn, "Current value for 'company_pw': %s", _network_player_info[_local_player].password); + IConsolePrintF(CC_WARNING, "Current value for 'company_pw': %s", _network_player_info[_local_player].password); return true; } @@ -1356,7 +1356,7 @@ HashCurrentCompanyPassword(); } - IConsolePrintF(_icolour_warn, "'company_pw' changed to: %s", _network_player_info[_local_player].password); + IConsolePrintF(CC_WARNING, "'company_pw' changed to: %s", _network_player_info[_local_player].password); return true; } @@ -1373,7 +1373,7 @@ SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name); } else { if (NetworkFindName(_network_player_name)) { - NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", _network_player_name); + NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _network_player_name); ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name)); NetworkUpdateClientInfo(NETWORK_SERVER_INDEX); } @@ -1400,7 +1400,7 @@ DEF_CONSOLE_CMD(ConProcServerIP) { if (argc == 0) { - IConsolePrintF(_icolour_warn, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip)); + IConsolePrintF(CC_WARNING, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip)); return true; } @@ -1408,7 +1408,7 @@ _network_server_bind_ip = (strcmp(argv[0], "all") == 0) ? inet_addr("0.0.0.0") : inet_addr(argv[0]); snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip)); - IConsolePrintF(_icolour_warn, "'server_ip' changed to: %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip)); + IConsolePrintF(CC_WARNING, "'server_ip' changed to: %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip)); return true; } #endif /* ENABLE_NETWORK */ diff -r 68a692eacf22 -r 67db0d431d5e src/console_func.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/console_func.h Tue May 27 00:50:55 2008 +0000 @@ -0,0 +1,26 @@ +/* $Id$ */ + +/** @file console_func.h Console functions used outside of the console code. */ + +#ifndef CONSOLE_FUNC_H +#define CONSOLE_FUNC_H + +#include "console_type.h" + +/* console modes */ +extern IConsoleModes _iconsole_mode; + +/* console functions */ +void IConsoleInit(); +void IConsoleFree(); +void IConsoleClose(); + +/* console output */ +void IConsolePrint(ConsoleColour color_code, const char *string); +void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...); +void IConsoleDebug(const char *dbg, const char *string); + +/* Parser */ +void IConsoleCmdExec(const char *cmdstr); + +#endif /* CONSOLE_FUNC_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/console_gui.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/console_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -0,0 +1,366 @@ +/* $Id$ */ + +/** @file console.cpp Handling of the in-game console. */ + +#include "stdafx.h" +#include "openttd.h" +#include "textbuf_gui.h" +#include "window_gui.h" +#include "console_gui.h" +#include +#include +#include "console_internal.h" +#include "window_func.h" +#include "string_func.h" +#include "gfx_func.h" +#include "core/math_func.hpp" +#include "rev.h" + +#include "table/strings.h" + +#define ICON_BUFFER 79 +#define ICON_HISTORY_SIZE 20 +#define ICON_LINE_HEIGHT 12 +#define ICON_RIGHT_BORDERWIDTH 10 +#define ICON_BOTTOM_BORDERWIDTH 12 +#define ICON_MAX_ALIAS_LINES 40 +#define ICON_TOKEN_COUNT 20 + +/* console modes */ +IConsoleModes _iconsole_mode; + +/* ** main console ** */ +static char *_iconsole_buffer[ICON_BUFFER + 1]; +static uint16 _iconsole_cbuffer[ICON_BUFFER + 1]; +static Textbuf _iconsole_cmdline; + +/* ** main console cmd buffer ** */ +static char *_iconsole_history[ICON_HISTORY_SIZE]; +static byte _iconsole_historypos; + +/* *************** * + * end of header * + * *************** */ + +static void IConsoleClearCommand() +{ + memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE); + _iconsole_cmdline.length = 0; + _iconsole_cmdline.width = 0; + _iconsole_cmdline.caretpos = 0; + _iconsole_cmdline.caretxoffs = 0; + SetWindowDirty(FindWindowById(WC_CONSOLE, 0)); +} + +static inline void IConsoleResetHistoryPos() {_iconsole_historypos = ICON_HISTORY_SIZE - 1;} + + +static void IConsoleHistoryAdd(const char *cmd); +static void IConsoleHistoryNavigate(int direction); + +struct IConsoleWindow : Window +{ + static byte scroll; + + IConsoleWindow(const WindowDesc *desc) : Window(desc) + { + _iconsole_mode = ICONSOLE_OPENED; + SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll + + this->height = _screen.height / 3; + this->width = _screen.width; + } + + ~IConsoleWindow() + { + _iconsole_mode = ICONSOLE_CLOSED; + ClrBit(_no_scroll, SCROLL_CON); + } + + virtual void OnPaint() + { + int i = IConsoleWindow::scroll; + int max = (this->height / ICON_LINE_HEIGHT) - 1; + int delta = 0; + GfxFillRect(this->left, this->top, this->width, this->height - 1, 0); + while ((i > 0) && (i > IConsoleWindow::scroll - max) && (_iconsole_buffer[i] != NULL)) { + DoDrawString(_iconsole_buffer[i], 5, + this->height - (IConsoleWindow::scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]); + i--; + } + /* If the text is longer than the window, don't show the starting ']' */ + delta = this->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH; + if (delta > 0) { + DoDrawString("]", 5, this->height - ICON_LINE_HEIGHT, CC_COMMAND); + delta = 0; + } + + DoDrawString(_iconsole_cmdline.buf, 10 + delta, this->height - ICON_LINE_HEIGHT, CC_COMMAND); + + if (_iconsole_cmdline.caret) { + DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, this->height - ICON_LINE_HEIGHT, TC_WHITE); + } + } + + virtual void OnMouseLoop() + { + if (HandleCaret(&_iconsole_cmdline)) this->SetDirty(); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + switch (keycode) { + case WKC_UP: + IConsoleHistoryNavigate(+1); + this->SetDirty(); + break; + + case WKC_DOWN: + IConsoleHistoryNavigate(-1); + this->SetDirty(); + break; + + case WKC_SHIFT | WKC_PAGEUP: + if (IConsoleWindow::scroll - (this->height / ICON_LINE_HEIGHT) - 1 < 0) { + IConsoleWindow::scroll = 0; + } else { + IConsoleWindow::scroll -= (this->height / ICON_LINE_HEIGHT) - 1; + } + this->SetDirty(); + break; + + case WKC_SHIFT | WKC_PAGEDOWN: + if (IConsoleWindow::scroll + (this->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) { + IConsoleWindow::scroll = ICON_BUFFER; + } else { + IConsoleWindow::scroll += (this->height / ICON_LINE_HEIGHT) - 1; + } + this->SetDirty(); + break; + + case WKC_SHIFT | WKC_UP: + if (IConsoleWindow::scroll <= 0) { + IConsoleWindow::scroll = 0; + } else { + --IConsoleWindow::scroll; + } + this->SetDirty(); + break; + + case WKC_SHIFT | WKC_DOWN: + if (IConsoleWindow::scroll >= ICON_BUFFER) { + IConsoleWindow::scroll = ICON_BUFFER; + } else { + ++IConsoleWindow::scroll; + } + this->SetDirty(); + break; + + case WKC_BACKQUOTE: + IConsoleSwitch(); + break; + + case WKC_RETURN: case WKC_NUM_ENTER: + IConsolePrintF(CC_COMMAND, "] %s", _iconsole_cmdline.buf); + IConsoleHistoryAdd(_iconsole_cmdline.buf); + + IConsoleCmdExec(_iconsole_cmdline.buf); + IConsoleClearCommand(); + break; + + case WKC_CTRL | WKC_RETURN: + _iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL; + IConsoleResize(this); + MarkWholeScreenDirty(); + break; + + case (WKC_CTRL | 'V'): + if (InsertTextBufferClipboard(&_iconsole_cmdline)) { + IConsoleResetHistoryPos(); + this->SetDirty(); + } + break; + + case (WKC_CTRL | 'L'): + IConsoleCmdExec("clear"); + break; + + case (WKC_CTRL | 'U'): + DeleteTextBufferAll(&_iconsole_cmdline); + this->SetDirty(); + break; + + case WKC_BACKSPACE: case WKC_DELETE: + if (DeleteTextBufferChar(&_iconsole_cmdline, keycode)) { + IConsoleResetHistoryPos(); + this->SetDirty(); + } + break; + + case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME: + if (MoveTextBufferPos(&_iconsole_cmdline, keycode)) { + IConsoleResetHistoryPos(); + this->SetDirty(); + } + break; + + default: + if (IsValidChar(key, CS_ALPHANUMERAL)) { + IConsoleWindow::scroll = ICON_BUFFER; + InsertTextBufferChar(&_iconsole_cmdline, key); + IConsoleResetHistoryPos(); + this->SetDirty(); + } else { + return ES_NOT_HANDLED; + } + } + return ES_HANDLED; + } +}; + +byte IConsoleWindow::scroll = ICON_BUFFER; + +static const Widget _iconsole_window_widgets[] = { + {WIDGETS_END} +}; + +static const WindowDesc _iconsole_window_desc = { + 0, 0, 2, 2, 2, 2, + WC_CONSOLE, WC_NONE, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _iconsole_window_widgets, +}; + +void IConsoleGUIInit() +{ + _iconsole_historypos = ICON_HISTORY_SIZE - 1; + _iconsole_mode = ICONSOLE_CLOSED; + + memset(_iconsole_history, 0, sizeof(_iconsole_history)); + memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer)); + memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer)); + _iconsole_cmdline.buf = CallocT(ICON_CMDLN_SIZE); // create buffer and zero it + _iconsole_cmdline.maxlength = ICON_CMDLN_SIZE; + + IConsolePrintF(CC_WARNING, "OpenTTD Game Console Revision 7 - %s", _openttd_revision); + IConsolePrint(CC_WHITE, "------------------------------------"); + IConsolePrint(CC_WHITE, "use \"help\" for more information"); + IConsolePrint(CC_WHITE, ""); + IConsoleClearCommand(); + IConsoleHistoryAdd(""); +} + +void IConsoleClearBuffer() +{ + uint i; + for (i = 0; i <= ICON_BUFFER; i++) { + free(_iconsole_buffer[i]); + _iconsole_buffer[i] = NULL; + } +} + +void IConsoleGUIFree() +{ + free(_iconsole_cmdline.buf); + IConsoleClearBuffer(); +} + +void IConsoleResize(Window *w) +{ + switch (_iconsole_mode) { + case ICONSOLE_OPENED: + w->height = _screen.height / 3; + w->width = _screen.width; + break; + case ICONSOLE_FULL: + w->height = _screen.height - ICON_BOTTOM_BORDERWIDTH; + w->width = _screen.width; + break; + default: return; + } + + MarkWholeScreenDirty(); +} + +void IConsoleSwitch() +{ + switch (_iconsole_mode) { + case ICONSOLE_CLOSED: + new IConsoleWindow(&_iconsole_window_desc); + break; + + case ICONSOLE_OPENED: case ICONSOLE_FULL: + DeleteWindowById(WC_CONSOLE, 0); + break; + } + + MarkWholeScreenDirty(); +} + +void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();} +void IConsoleOpen() {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();} + +/** + * Add the entered line into the history so you can look it back + * scroll, etc. Put it to the beginning as it is the latest text + * @param cmd Text to be entered into the 'history' + */ +static void IConsoleHistoryAdd(const char *cmd) +{ + free(_iconsole_history[ICON_HISTORY_SIZE - 1]); + + memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1)); + _iconsole_history[0] = strdup(cmd); + IConsoleResetHistoryPos(); +} + +/** + * Navigate Up/Down in the history of typed commands + * @param direction Go further back in history (+1), go to recently typed commands (-1) + */ +static void IConsoleHistoryNavigate(int direction) +{ + int i = _iconsole_historypos + direction; + + /* watch out for overflows, just wrap around */ + if (i < 0) i = ICON_HISTORY_SIZE - 1; + if (i >= ICON_HISTORY_SIZE) i = 0; + + if (direction > 0) { + if (_iconsole_history[i] == NULL) i = 0; + } + + if (direction < 0) { + while (i > 0 && _iconsole_history[i] == NULL) i--; + } + + _iconsole_historypos = i; + IConsoleClearCommand(); + /* copy history to 'command prompt / bash' */ + assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE)); + ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength); + UpdateTextBufferSize(&_iconsole_cmdline); +} + +/** + * Handle the printing of text entered into the console or redirected there + * by any other means. Text can be redirected to other players in a network game + * as well as to a logfile. If the network server is a dedicated server, all activities + * are also logged. All lines to print are added to a temporary buffer which can be + * used as a history to print them onscreen + * @param color_code the colour of the command. Red in case of errors, etc. + * @param string the message entered or output on the console (notice, error, etc.) + */ +void IConsoleGUIPrint(ConsoleColour color_code, char *str) +{ + /* move up all the strings in the buffer one place and do the same for colour + * to accomodate for the new command/message */ + free(_iconsole_buffer[0]); + memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER); + _iconsole_buffer[ICON_BUFFER] = str; + + memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER); + _iconsole_cbuffer[ICON_BUFFER] = color_code; + + SetWindowDirty(FindWindowById(WC_CONSOLE, 0)); +} diff -r 68a692eacf22 -r 67db0d431d5e src/console_gui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/console_gui.h Tue May 27 00:50:55 2008 +0000 @@ -0,0 +1,13 @@ +/* $Id$ */ + +/** @file console_gui.h GUI related functions in the console. */ + +#ifndef CONSOLE_GUI_H +#define CONSOLE_GUI_H + +#include "window_type.h" + +void IConsoleResize(Window *w); +void IConsoleSwitch(); + +#endif /* CONSOLE_GUI_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/console_internal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/console_internal.h Tue May 27 00:50:55 2008 +0000 @@ -0,0 +1,143 @@ +/* $Id$ */ + +/** @file console_internal.h Internally used functions for the console. */ + +#ifndef CONSOLE_INTERNAL_H +#define CONSOLE_INTERNAL_H + +#include "console_func.h" + +/* maximum length of a typed in command */ +#define ICON_CMDLN_SIZE 255 +/* maximum length of a totally expanded command */ +#define ICON_MAX_STREAMSIZE 1024 + +enum IConsoleVarTypes { + ICONSOLE_VAR_BOOLEAN, + ICONSOLE_VAR_BYTE, + ICONSOLE_VAR_UINT16, + ICONSOLE_VAR_UINT32, + ICONSOLE_VAR_INT16, + ICONSOLE_VAR_INT32, + ICONSOLE_VAR_STRING +}; + +enum IConsoleHookTypes { + ICONSOLE_HOOK_ACCESS, + ICONSOLE_HOOK_PRE_ACTION, + ICONSOLE_HOOK_POST_ACTION +}; + +/** --Hooks-- + * Hooks are certain triggers get get accessed/executed on either + * access, before execution/change or after execution/change. This allows + * for general flow of permissions or special action needed in some cases + */ +typedef bool IConsoleHook(); +struct IConsoleHooks{ + IConsoleHook *access; ///< trigger when accessing the variable/command + IConsoleHook *pre; ///< trigger before the variable/command is changed/executed + IConsoleHook *post; ///< trigger after the variable/command is changed/executed +}; + +/** --Commands-- + * Commands are commands, or functions. They get executed once and any + * effect they produce are carried out. The arguments to the commands + * are given to them, each input word seperated by a double-quote (") is an argument + * If you want to handle multiple words as one, enclose them in double-quotes + * eg. 'say "hello sexy boy"' + */ +typedef bool (IConsoleCmdProc)(byte argc, char *argv[]); + +struct IConsoleCmd { + char *name; ///< name of command + IConsoleCmd *next; ///< next command in list + + IConsoleCmdProc *proc; ///< process executed when command is typed + IConsoleHooks hook; ///< any special trigger action that needs executing +}; + +/** --Variables-- + * Variables are pointers to real ingame variables which allow for + * changing while ingame. After changing they keep their new value + * and can be used for debugging, gameplay, etc. It accepts: + * - no arguments; just print out current value + * - '= ' to assign a new value to the variable + * - '++' to increase value by one + * - '--' to decrease value by one + */ +struct IConsoleVar { + char *name; ///< name of the variable + IConsoleVar *next; ///< next variable in list + + void *addr; ///< the address where the variable is pointing at + uint32 size; ///< size of the variable, used for strings + char *help; ///< the optional help string shown when requesting information + IConsoleVarTypes type; ///< type of variable (for correct assignment/output) + IConsoleCmdProc *proc; ///< some variables need really special handling, use a callback function for that + IConsoleHooks hook; ///< any special trigger action that needs executing +}; + +/** --Aliases-- + * Aliases are like shortcuts for complex functions, variable assignments, + * etc. You can use a simple alias to rename a longer command (eg 'lv' for + * 'list_vars' for example), or concatenate more commands into one + * (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments + * given to them in the command line. + * - "%A - %Z" substitute arguments 1 t/m 26 + * - "%+" lists all parameters keeping them seperated + * - "%!" also lists all parameters but presenting them to the aliased command as one argument + * - ";" allows for combining commands (see example 'ng') + */ +struct IConsoleAlias { + char *name; ///< name of the alias + IConsoleAlias *next; ///< next alias in list + + char *cmdline; ///< command(s) that is/are being aliased +}; + +/* console parser */ +extern IConsoleCmd *_iconsole_cmds; ///< list of registred commands +extern IConsoleVar *_iconsole_vars; ///< list of registred vars +extern IConsoleAlias *_iconsole_aliases; ///< list of registred aliases + +/* console functions */ +void IConsoleClearBuffer(); +void IConsoleOpen(); + +/* console output */ +void IConsoleWarning(const char *string); +void IConsoleError(const char *string); + +/* Commands */ +void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc); +void IConsoleAliasRegister(const char *name, const char *cmd); +IConsoleCmd *IConsoleCmdGet(const char *name); +IConsoleAlias *IConsoleAliasGet(const char *name); + +/* Variables */ +void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help); +void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help); +IConsoleVar* IConsoleVarGet(const char *name); +void IConsoleVarPrintGetValue(const IConsoleVar *var); +void IConsoleVarPrintSetValue(const IConsoleVar *var); + +/* Parser */ +void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]); + +/* console std lib (register ingame commands/aliases/variables) */ +void IConsoleStdLibRegister(); + +/* Hooking code */ +void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc); +void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc); +void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc); + +/* Supporting functions */ +bool GetArgumentInteger(uint32 *value, const char *arg); + +void IConsoleGUIInit(); +void IConsoleGUIFree(); +void IConsoleGUIPrint(ConsoleColour color_code, char *string); + +#endif /* CONSOLE_INTERNAL_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/console_type.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/console_type.h Tue May 27 00:50:55 2008 +0000 @@ -0,0 +1,24 @@ +/* $Id$ */ + +/** @file console_type.h Globally used console related types. */ + +#ifndef CONSOLE_TYPE_H +#define CONSOLE_TYPE_H + +enum IConsoleModes { + ICONSOLE_FULL, + ICONSOLE_OPENED, + ICONSOLE_CLOSED +}; + +enum ConsoleColour { + CC_DEFAULT = 1, + CC_ERROR = 3, + CC_WARNING = 13, + CC_INFO = 8, + CC_DEBUG = 5, + CC_COMMAND = 2, + CC_WHITE = 12, +}; + +#endif /* CONSOLE_TYPE_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/core/bitmath_func.hpp --- a/src/core/bitmath_func.hpp Mon May 26 20:45:25 2008 +0000 +++ b/src/core/bitmath_func.hpp Tue May 27 00:50:55 2008 +0000 @@ -97,7 +97,7 @@ * @param y The second value * @return True if at least one bit is set in both values, false else. */ -#define HASBITS(x, y) ((x) & (y)) +#define HASBITS(x, y) (((x) & (y)) != 0) /** * Set a bit in a variable. diff -r 68a692eacf22 -r 67db0d431d5e src/currency.cpp --- a/src/currency.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/currency.cpp Tue May 27 00:50:55 2008 +0000 @@ -150,10 +150,10 @@ **/ void CheckSwitchToEuro() { - if (_currency_specs[_opt.currency].to_euro != CF_NOEURO && - _currency_specs[_opt.currency].to_euro != CF_ISEURO && - _cur_year >= _currency_specs[_opt.currency].to_euro) { - _opt.currency = 2; // this is the index of euro above. + if (_currency_specs[_settings.gui.currency].to_euro != CF_NOEURO && + _currency_specs[_settings.gui.currency].to_euro != CF_ISEURO && + _cur_year >= _currency_specs[_settings.gui.currency].to_euro) { + _settings.gui.currency = 2; // this is the index of euro above. AddNewsItem(STR_EURO_INTRODUCE, NS_ECONOMY, 0, 0); } } diff -r 68a692eacf22 -r 67db0d431d5e src/currency.h --- a/src/currency.h Mon May 26 20:45:25 2008 +0000 +++ b/src/currency.h Tue May 27 00:50:55 2008 +0000 @@ -39,7 +39,7 @@ // XXX small hack, but makes the rest of the code a bit nicer to read #define _custom_currency (_currency_specs[CUSTOM_CURRENCY_ID]) -#define _currency ((const CurrencySpec*)&_currency_specs[_opt_ptr->currency]) +#define _currency ((const CurrencySpec*)&_currency_specs[(_game_mode == GM_MENU) ? _settings_newgame.gui.currency : _settings.gui.currency]) uint GetMaskOfAllowedCurrencies(); void CheckSwitchToEuro(); diff -r 68a692eacf22 -r 67db0d431d5e src/date.cpp --- a/src/date.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/date.cpp Tue May 27 00:50:55 2008 +0000 @@ -257,7 +257,7 @@ SaveOrLoad(name, SL_SAVE, AUTOSAVE_DIR); DebugDumpCommands("ddc:save:%s\n", name); #endif /* DUMP_COMMANDS */ - if (_opt.autosave != 0 && (_cur_month % _autosave_months[_opt.autosave]) == 0) { + if (_settings.gui.autosave != 0 && (_cur_month % _autosave_months[_settings.gui.autosave]) == 0) { _do_autosave = true; RedrawAutosave(); } @@ -283,10 +283,10 @@ ShipsYearlyLoop(); if (_network_server) NetworkServerYearlyLoop(); - if (_cur_year == _patches.semaphore_build_before) ResetSignalVariant(); + if (_cur_year == _settings.gui.semaphore_build_before) ResetSignalVariant(); /* check if we reached end of the game */ - if (_cur_year == _patches.ending_year) { + if (_cur_year == _settings.gui.ending_year) { ShowEndGameChart(); /* check if we reached the maximum year, decrement dates by a year */ } else if (_cur_year == MAX_YEAR + 1) { @@ -303,5 +303,5 @@ InitChatMessage(); } - if (_patches.auto_euro) CheckSwitchToEuro(); + if (_settings.gui.auto_euro) CheckSwitchToEuro(); } diff -r 68a692eacf22 -r 67db0d431d5e src/debug.cpp --- a/src/debug.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/debug.cpp Tue May 27 00:50:55 2008 +0000 @@ -6,7 +6,7 @@ #include #include #include "openttd.h" -#include "console.h" +#include "console_func.h" #include "debug.h" #include "string_func.h" #include "network/core/core.h" diff -r 68a692eacf22 -r 67db0d431d5e src/depot_gui.cpp --- a/src/depot_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/depot_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -107,7 +107,6 @@ WC_VEHICLE_DEPOT, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _depot_widgets, - NULL }; static const WindowDesc _road_depot_desc = { @@ -115,7 +114,6 @@ WC_VEHICLE_DEPOT, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _depot_widgets, - NULL }; static const WindowDesc _ship_depot_desc = { @@ -123,7 +121,6 @@ WC_VEHICLE_DEPOT, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _depot_widgets, - NULL }; static const WindowDesc _aircraft_depot_desc = { @@ -131,11 +128,10 @@ WC_VEHICLE_DEPOT, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _depot_widgets, - NULL }; extern int WagonLengthToPixels(int len); -extern void DepotSortList(Vehicle **v, uint16 length); +extern void DepotSortList(VehicleList *list); /** * This is the Callback method after the cloning attempt of a vehicle @@ -148,16 +144,14 @@ { if (!success) return; - Vehicle *v = GetVehicle(_new_vehicle_id); + const Vehicle *v = GetVehicle(_new_vehicle_id); ShowVehicleViewWindow(v); } -static void TrainDepotMoveVehicle(Vehicle *wagon, VehicleID sel, Vehicle *head) +static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Vehicle *head) { - Vehicle *v; - - v = GetVehicle(sel); + const Vehicle *v = GetVehicle(sel); if (v == wagon) return; @@ -246,20 +240,12 @@ VehicleID sel; VehicleType type; bool generate_list; - uint16 engine_list_length; - uint16 wagon_list_length; - uint16 engine_count; - uint16 wagon_count; - Vehicle **vehicle_list; - Vehicle **wagon_list; + VehicleList vehicle_list; + VehicleList wagon_list; DepotWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) { this->sel = INVALID_VEHICLE; - this->vehicle_list = NULL; - this->wagon_list = NULL; - this->engine_count = 0; - this->wagon_count = 0; this->generate_list = true; this->FindWindowPlacementAndResize(desc); @@ -268,8 +254,6 @@ ~DepotWindow() { DeleteWindowById(WC_BUILD_VEHICLE, this->window_number); - free((void*)this->vehicle_list); - free((void*)this->wagon_list); } /** Draw a vehicle in the depot window in the box with the top left corner at x,y @@ -320,11 +304,9 @@ void DrawDepotWindow(Window *w) { - Vehicle **vl = this->vehicle_list; TileIndex tile = this->window_number; int x, y, i, maxval; uint16 hnum; - uint16 num = this->engine_count; /* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */ uint16 rows_in_display = this->widget[DEPOT_WIDGET_MATRIX].data >> 8; @@ -345,15 +327,15 @@ /* determine amount of items for scroller */ if (this->type == VEH_TRAIN) { hnum = 8; - for (num = 0; num < this->engine_count; num++) { - const Vehicle *v = vl[num]; + for (uint num = 0; num < this->vehicle_list.Length(); num++) { + const Vehicle *v = this->vehicle_list[num]; hnum = max(hnum, v->u.rail.cached_total_length); } /* Always have 1 empty row, so people can change the setting of the train */ - SetVScrollCount(w, this->engine_count + this->wagon_count + 1); + SetVScrollCount(w, this->vehicle_list.Length() + this->wagon_list.Length() + 1); SetHScrollCount(w, WagonLengthToPixels(hnum)); } else { - SetVScrollCount(w, (num + this->hscroll.cap - 1) / this->hscroll.cap); + SetVScrollCount(w, (this->vehicle_list.Length() + this->hscroll.cap - 1) / this->hscroll.cap); } /* locate the depot struct */ @@ -368,24 +350,24 @@ w->DrawWidgets(); - num = this->vscroll.pos * boxes_in_each_row; - maxval = min(this->engine_count, num + (rows_in_display * boxes_in_each_row)); + uint16 num = this->vscroll.pos * boxes_in_each_row; + maxval = min(this->vehicle_list.Length(), num + (rows_in_display * boxes_in_each_row)); for (x = 2, y = 15; num < maxval; y += this->resize.step_height, x = 2) { // Draw the rows byte i; for (i = 0; i < boxes_in_each_row && num < maxval; i++, num++, x += this->resize.step_width) { /* Draw all vehicles in the current row */ - const Vehicle *v = vl[num]; + const Vehicle *v = this->vehicle_list[num]; DrawVehicleInDepot(w, v, x, y); } } - maxval = min(this->engine_count + this->wagon_count, (this->vscroll.pos * boxes_in_each_row) + (rows_in_display * boxes_in_each_row)); + maxval = min(this->vehicle_list.Length() + this->wagon_list.Length(), (this->vscroll.pos * boxes_in_each_row) + (rows_in_display * boxes_in_each_row)); /* draw the train wagons, that do not have an engine in front */ for (; num < maxval; num++, y += 14) { - const Vehicle *v = this->wagon_list[num - this->engine_count]; + const Vehicle *v = this->wagon_list[num - this->vehicle_list.Length()]; const Vehicle *u; DrawTrainImage(v, x + 50, y, this->sel, this->hscroll.cap - 29, 0); @@ -401,8 +383,8 @@ } struct GetDepotVehiclePtData { - Vehicle *head; - Vehicle *wagon; + const Vehicle *head; + const Vehicle *wagon; }; enum DepotGUIAction { @@ -412,9 +394,8 @@ MODE_START_STOP, }; - DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, Vehicle **veh, GetDepotVehiclePtData *d) const + DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, const Vehicle **veh, GetDepotVehiclePtData *d) const { - Vehicle **vl = this->vehicle_list; uint xt, row, xm = 0, ym = 0; int pos, skip = 0; uint16 boxes_in_each_row = this->widget[DEPOT_WIDGET_MATRIX].data & 0xFF; @@ -435,7 +416,7 @@ pos = ((row + this->vscroll.pos) * boxes_in_each_row) + xt; - if (this->engine_count + this->wagon_count <= pos) { + if ((int)(this->vehicle_list.Length() + this->wagon_list.Length()) <= pos) { if (this->type == VEH_TRAIN) { d->head = NULL; d->wagon = NULL; @@ -445,20 +426,19 @@ } } - if (this->engine_count > pos) { - *veh = vl[pos]; + if ((int)this->vehicle_list.Length() > pos) { + *veh = this->vehicle_list[pos]; skip = this->hscroll.pos; } else { - vl = this->wagon_list; - pos -= this->engine_count; - *veh = vl[pos]; + pos -= this->vehicle_list.Length(); + *veh = this->wagon_list[pos]; /* free wagons don't have an initial loco. */ x -= _traininfo_vehicle_width; } switch (this->type) { case VEH_TRAIN: { - Vehicle *v = *veh; + const Vehicle *v = *veh; d->head = d->wagon = v; /* either pressed the flag or the number, but only when it's a loco */ @@ -505,7 +485,7 @@ void DepotClick(int x, int y) { GetDepotVehiclePtData gdvp = { NULL, NULL }; - Vehicle *v = NULL; + const Vehicle *v = NULL; DepotGUIAction mode = this->GetVehicleFromDepotWndPt(x, y, &v, &gdvp); /* share / copy orders */ @@ -765,11 +745,9 @@ if (this->generate_list) { /* Generate the vehicle list * It's ok to use the wagon pointers for non-trains as they will be ignored */ - BuildDepotVehicleList(this->type, this->window_number, - &this->vehicle_list, &this->engine_list_length, &this->engine_count, - &this->wagon_list, &this->wagon_list_length, &this->wagon_count); + BuildDepotVehicleList(this->type, this->window_number, &this->vehicle_list, &this->wagon_list); this->generate_list = false; - DepotSortList(this->vehicle_list, this->engine_count); + DepotSortList(&this->vehicle_list); } DrawDepotWindow(this); } @@ -818,7 +796,7 @@ case DEPOT_WIDGET_SELL_ALL: /* Only open the confimation window if there are anything to sell */ - if (this->engine_count != 0 || this->wagon_count != 0) { + if (this->vehicle_list.Length() != 0 || this->wagon_list.Length() != 0) { static const StringID confirm_captions[] = { STR_8800_TRAIN_DEPOT, STR_9003_ROAD_VEHICLE_DEPOT, @@ -883,7 +861,7 @@ { switch (widget) { case DEPOT_WIDGET_MATRIX: { - Vehicle *v; + const Vehicle *v = NULL; VehicleID sel = this->sel; this->sel = INVALID_VEHICLE; @@ -912,23 +890,20 @@ case DEPOT_WIDGET_SELL: case DEPOT_WIDGET_SELL_CHAIN: if (!this->IsWidgetDisabled(DEPOT_WIDGET_SELL) && this->sel != INVALID_VEHICLE) { - Vehicle *v; uint command; - int sell_cmd; - bool is_engine; if (this->IsWidgetDisabled(widget)) return; if (this->sel == INVALID_VEHICLE) return; this->HandleButtonClick(widget); - v = GetVehicle(this->sel); + const Vehicle *v = GetVehicle(this->sel); this->sel = INVALID_VEHICLE; this->SetDirty(); - sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0; + int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0; - is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v))); + bool is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v))); if (is_engine) { _backup_orders_tile = v->tile; @@ -961,14 +936,14 @@ ResizeDepotButtons(this); } - virtual bool OnCTRLStateChange() + virtual EventState OnCTRLStateChange() { if (this->sel != INVALID_VEHICLE) { _cursor.vehchain = _ctrl_pressed; this->InvalidateWidget(DEPOT_WIDGET_MATRIX); } - return true; + return ES_HANDLED; } }; diff -r 68a692eacf22 -r 67db0d431d5e src/disaster_cmd.cpp --- a/src/disaster_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/disaster_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -1053,7 +1053,7 @@ ResetDisasterDelay(); - if (_opt.diff.disasters != 0) DoDisaster(); + if (_settings.difficulty.disasters != 0) DoDisaster(); } void StartupDisasters() diff -r 68a692eacf22 -r 67db0d431d5e src/dock_gui.cpp --- a/src/dock_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/dock_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -25,8 +25,8 @@ #include "table/sprites.h" #include "table/strings.h" -static void ShowBuildDockStationPicker(); -static void ShowBuildDocksDepotPicker(); +static void ShowBuildDockStationPicker(Window *parent); +static void ShowBuildDocksDepotPicker(Window *parent); static Axis _ship_depot_direction; @@ -69,14 +69,21 @@ DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_MSG(STR_CANT_BUILD_LOCKS)); } - -enum { - DTW_CANAL = 3, - DTW_LOCK = 4, - DTW_DEMOLISH = 6, - DTW_DEPOT = 7, - DTW_STATION = 8, - DTW_BUOY = 9 +/** Enum referring to the widgets of the build dock toolbar */ +enum DockToolbarWidgets { + DTW_BEGIN = 0, ///< Start of toolbar widgets + DTW_CLOSEBOX = DTW_BEGIN, ///< Close window button + DTW_CAPTION, ///< Window caption + DTW_STICKY, ///< Sticky window button + DTW_BUTTONS_BEGIN, ///< Begin of clickable buttons (except seperating panel) + DTW_CANAL = DTW_BUTTONS_BEGIN, ///< Build canal button + DTW_LOCK, ///< Build lock button + DTW_SEPERATOR, ///< Seperating panel between lock and demolish + DTW_DEMOLISH, ///< Demolish aka dynamite button + DTW_DEPOT, ///< Build depot button + DTW_STATION, ///< Build station button + DTW_BUOY, ///< Build buoy button + DTW_END, ///< End of toolbar widgets }; @@ -98,13 +105,13 @@ static void BuildDocksClick_Depot(Window *w) { if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; - if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, VHM_RECT, PlaceDocks_Depot)) ShowBuildDocksDepotPicker(); + if (HandlePlacePushButton(w, DTW_DEPOT, SPR_CURSOR_SHIP_DEPOT, VHM_RECT, PlaceDocks_Depot)) ShowBuildDocksDepotPicker(w); } static void BuildDocksClick_Dock(Window *w) { if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; - if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, VHM_SPECIAL, PlaceDocks_Dock)) ShowBuildDockStationPicker(); + if (HandlePlacePushButton(w, DTW_STATION, SPR_CURSOR_DOCK, VHM_SPECIAL, PlaceDocks_Dock)) ShowBuildDockStationPicker(w); } static void BuildDocksClick_Buoy(Window *w) @@ -125,91 +132,99 @@ BuildDocksClick_Buoy }; -static void BuildDocksToolbWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: - w->DrawWidgets(); - w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), 7, 8, 9, WIDGET_LIST_END); - break; - - case WE_CLICK: - if (e->we.click.widget - 3 >= 0 && e->we.click.widget != 5) _build_docks_button_proc[e->we.click.widget - 3](w); - break; - - case WE_KEYPRESS: - switch (e->we.keypress.keycode) { - case '1': BuildDocksClick_Canal(w); break; - case '2': BuildDocksClick_Lock(w); break; - case '3': BuildDocksClick_Demolish(w); break; - case '4': BuildDocksClick_Depot(w); break; - case '5': BuildDocksClick_Dock(w); break; - case '6': BuildDocksClick_Buoy(w); break; - default: return; - } - break; - - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - break; - - case WE_PLACE_DRAG: { - VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); - return; +struct BuildDocksToolbarWindow : Window { + BuildDocksToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this); } - case WE_PLACE_MOUSEUP: - if (e->we.place.pt.x != -1) { - switch (e->we.place.select_proc) { + ~BuildDocksToolbarWindow() + { + if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); + } + + virtual void OnPaint() + { + this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_SHIP), DTW_DEPOT, DTW_STATION, DTW_BUOY, WIDGET_LIST_END); + this->DrawWidgets(); + } + + virtual void OnClick(Point pt, int widget) + { + if (widget >= DTW_BUTTONS_BEGIN && widget != DTW_SEPERATOR) _build_docks_button_proc[widget - DTW_BUTTONS_BEGIN](this); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + switch (keycode) { + case '1': BuildDocksClick_Canal(this); break; + case '2': BuildDocksClick_Lock(this); break; + case '3': BuildDocksClick_Demolish(this); break; + case '4': BuildDocksClick_Depot(this); break; + case '5': BuildDocksClick_Dock(this); break; + case '6': BuildDocksClick_Buoy(this); break; + default: return ES_NOT_HANDLED; + } + return ES_HANDLED; + } + + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } + + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) + { + VpSelectTilesWithMethod(pt.x, pt.y, select_method); + } + + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + { + if (pt.x != -1) { + switch (select_proc) { case DDSP_DEMOLISH_AREA: - GUIPlaceProcDragXY(e); + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; case DDSP_CREATE_WATER: - DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_MSG(STR_CANT_BUILD_CANALS)); + DoCommandP(end_tile, start_tile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_MSG(STR_CANT_BUILD_CANALS)); break; + default: break; } } - break; + } - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); delete FindWindowById(WC_BUILD_STATION, 0); delete FindWindowById(WC_BUILD_DEPOT, 0); - break; + } - case WE_PLACE_PRESIZE: { - TileIndex tile_from; - TileIndex tile_to; - - tile_from = e->we.place.tile; - + virtual void OnPlacePresize(Point pt, TileIndex tile_from) + { DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from, NULL)); - tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from); + TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile_from, ReverseDiagDir(dir)) : tile_from); VpSetPresizeRange(tile_from, tile_to); - } break; - - case WE_DESTROY: - if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); - break; } -} +}; static const Widget _build_docks_toolb_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 7, 11, 123, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_STICKYBOX, RESIZE_NONE, 7, 124, 135, 0, 13, 0x0, STR_STICKY_BUTTON}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP}, +{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // DTW_CLOSEBOX +{ WWT_CAPTION, RESIZE_NONE, 7, 11, 123, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // DTW_CAPTION +{ WWT_STICKYBOX, RESIZE_NONE, 7, 124, 135, 0, 13, 0x0, STR_STICKY_BUTTON}, // DTW_STICKY +{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP}, // DTW_CANAL +{ WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP}, // DTW_LOCK -{ WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL}, +{ WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL}, // DTW_SEPERATOR -{ WWT_IMGBTN, RESIZE_NONE, 7, 48, 69, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_SHIP_DEPOT, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_SHIP_DOCK, STR_981D_BUILD_SHIP_DOCK}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_BOUY, STR_9834_POSITION_BUOY_WHICH_CAN}, +{ WWT_IMGBTN, RESIZE_NONE, 7, 48, 69, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, // DTW_DEMOLISH +{ WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_SHIP_DEPOT, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING}, // DTW_DEPOT +{ WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_SHIP_DOCK, STR_981D_BUILD_SHIP_DOCK}, // DTW_STATION +{ WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_BOUY, STR_9834_POSITION_BUOY_WHICH_CAN}, // DTW_BUOY { WIDGETS_END}, }; @@ -218,7 +233,6 @@ WC_BUILD_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _build_docks_toolb_widgets, - BuildDocksToolbWndProc }; void ShowBuildDocksToolbar() @@ -226,19 +240,32 @@ if (!IsValidPlayer(_current_player)) return; DeleteWindowByClass(WC_BUILD_TOOLBAR); - Window *w = AllocateWindowDescFront(&_build_docks_toolbar_desc, TRANSPORT_WATER); - if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w); + AllocateWindowDescFront(&_build_docks_toolbar_desc, TRANSPORT_WATER); } -static void BuildDockStationWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: w->LowerWidget(_station_show_coverage + 3); break; +struct BuildDocksStationWindow : public PickerWindowBase { +private: + enum BuildDockStationWidgets { + BDSW_CLOSE, + BDSW_CAPTION, + BDSW_BACKGROUND, + BDSW_LT_OFF, + BDSW_LT_ON, + BDSW_INFO, + }; - case WE_PAINT: { - int rad = (_patches.modified_catchment) ? CA_DOCK : CA_UNMODIFIED; +public: + BuildDocksStationWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) + { + this->LowerWidget(_station_show_coverage + BDSW_LT_OFF); + this->FindWindowPlacementAndResize(desc); + } - w->DrawWidgets(); + virtual void OnPaint() + { + int rad = (_settings.station.modified_catchment) ? CA_DOCK : CA_UNMODIFIED; + + this->DrawWidgets(); if (_station_show_coverage) { SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); @@ -253,44 +280,40 @@ int text_end = DrawStationCoverageAreaText(4, 50, SCT_ALL, rad, false); text_end = DrawStationCoverageAreaText(4, text_end + 4, SCT_ALL, rad, true) + 4; - if (text_end != w->widget[2].bottom) { - w->SetDirty(); - ResizeWindowForWidget(w, 2, 0, text_end - w->widget[2].bottom); - w->SetDirty(); + if (text_end != this->widget[BDSW_BACKGROUND].bottom) { + this->SetDirty(); + ResizeWindowForWidget(this, 2, 0, text_end - this->widget[BDSW_BACKGROUND].bottom); + this->SetDirty(); } - break; } - case WE_CLICK: - switch (e->we.click.widget) { - case 3: - case 4: - w->RaiseWidget(_station_show_coverage + 3); - _station_show_coverage = (e->we.click.widget != 3); - w->LowerWidget(_station_show_coverage + 3); + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case BDSW_LT_OFF: + case BDSW_LT_ON: + this->RaiseWidget(_station_show_coverage + BDSW_LT_OFF); + _station_show_coverage = (widget != BDSW_LT_OFF); + this->LowerWidget(_station_show_coverage + BDSW_LT_OFF); SndPlayFx(SND_15_BEEP); - w->SetDirty(); + this->SetDirty(); break; } - break; + } - case WE_TICK: - CheckRedrawStationCoverage(w); - break; - - case WE_DESTROY: - ResetObjectToPlace(); - break; + virtual void OnTick() + { + CheckRedrawStationCoverage(this); } -} +}; static const Widget _build_dock_station_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 74, 0x0, STR_NULL}, -{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, -{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, -{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 17, 30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL}, +{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // BDSW_CLOSE +{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS}, // BDSW_CAPTION +{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 74, 0x0, STR_NULL}, // BDSW_BACKGROUND +{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE}, // BDSW_LT_OFF +{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA}, // BDSW_LT_ON +{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 17, 30, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL}, // BDSW_INFO { WIDGETS_END}, }; @@ -299,63 +322,72 @@ WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_dock_station_widgets, - BuildDockStationWndProc }; -static void ShowBuildDockStationPicker() +static void ShowBuildDockStationPicker(Window *parent) { - new Window(&_build_dock_station_desc); + new BuildDocksStationWindow(&_build_dock_station_desc, parent); } -static void UpdateDocksDirection() -{ - if (_ship_depot_direction != AXIS_X) { - SetTileSelectSize(1, 2); - } else { - SetTileSelectSize(2, 1); +struct BuildDocksDepotWindow : public PickerWindowBase { +private: + enum BuildDockDepotWidgets { + BDDW_CLOSE, + BDDW_CAPTION, + BDDW_BACKGROUND, + BDDW_X, + BDDW_Y, + }; + + static void UpdateDocksDirection() + { + if (_ship_depot_direction != AXIS_X) { + SetTileSelectSize(1, 2); + } else { + SetTileSelectSize(2, 1); + } } -} -static void BuildDocksDepotWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: w->LowerWidget(_ship_depot_direction + 3); break; +public: + BuildDocksDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) + { + this->LowerWidget(_ship_depot_direction + BDDW_X); + UpdateDocksDirection(); + this->FindWindowPlacementAndResize(desc); + } - case WE_PAINT: - w->DrawWidgets(); + virtual void OnPaint() + { + this->DrawWidgets(); DrawShipDepotSprite(67, 35, 0); DrawShipDepotSprite(35, 51, 1); DrawShipDepotSprite(135, 35, 2); DrawShipDepotSprite(167, 51, 3); - return; + } - case WE_CLICK: { - switch (e->we.click.widget) { - case 3: - case 4: - w->RaiseWidget(_ship_depot_direction + 3); - _ship_depot_direction = (e->we.click.widget == 3 ? AXIS_X : AXIS_Y); - w->LowerWidget(_ship_depot_direction + 3); - SndPlayFx(SND_15_BEEP); - UpdateDocksDirection(); - w->SetDirty(); - break; + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case BDDW_X: + case BDDW_Y: + this->RaiseWidget(_ship_depot_direction + BDDW_X); + _ship_depot_direction = (widget == BDDW_X ? AXIS_X : AXIS_Y); + this->LowerWidget(_ship_depot_direction + BDDW_X); + SndPlayFx(SND_15_BEEP); + UpdateDocksDirection(); + this->SetDirty(); + break; } - } break; - - case WE_DESTROY: - ResetObjectToPlace(); - break; } -} +}; static const Widget _build_docks_depot_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 85, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, -{ WWT_PANEL, RESIZE_NONE, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, +{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // BDDW_CLOSE +{ WWT_CAPTION, RESIZE_NONE, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // BDDW_CAPTION +{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 85, 0x0, STR_NULL}, // BDDW_BACKGROUND +{ WWT_PANEL, RESIZE_NONE, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, // BDDW_X +{ WWT_PANEL, RESIZE_NONE, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION}, // BDDW_Y { WIDGETS_END}, }; @@ -364,14 +396,12 @@ WC_BUILD_DEPOT, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_docks_depot_widgets, - BuildDocksDepotWndProc }; -static void ShowBuildDocksDepotPicker() +static void ShowBuildDocksDepotPicker(Window *parent) { - new Window(&_build_docks_depot_desc); - UpdateDocksDirection(); + new BuildDocksDepotWindow(&_build_docks_depot_desc, parent); } diff -r 68a692eacf22 -r 67db0d431d5e src/dummy_land.cpp --- a/src/dummy_land.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/dummy_land.cpp Tue May 27 00:50:55 2008 +0000 @@ -41,7 +41,7 @@ static void GetTileDesc_Dummy(TileIndex tile, TileDesc *td) { td->str = STR_EMPTY; - td->owner = OWNER_NONE; + td->owner[0] = OWNER_NONE; } static void AnimateTile_Dummy(TileIndex tile) diff -r 68a692eacf22 -r 67db0d431d5e src/economy.cpp --- a/src/economy.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/economy.cpp Tue May 27 00:50:55 2008 +0000 @@ -29,7 +29,6 @@ #include "newgrf_station.h" #include "unmovable.h" #include "cargotype.h" -#include "player_face.h" #include "group.h" #include "strings_func.h" #include "tile_cmd.h" @@ -46,7 +45,6 @@ #include "gfx_func.h" #include "autoreplace_func.h" #include "player_gui.h" -#include "window_gui.h" #include "table/strings.h" #include "table/sprites.h" @@ -589,67 +587,6 @@ } } -void DrawNewsBankrupcy(Window *w, const NewsItem *ni) -{ - Player *p = GetPlayer((PlayerID)(ni->data_b)); - DrawPlayerFace(p->face, p->player_color, 2, 23); - GfxFillRect(3, 23, 3 + 91, 23 + 118, PALETTE_TO_STRUCT_GREY | (1 << USE_COLORTABLE)); - - SetDParam(0, p->index); - - DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94); - - switch (ni->subtype) { - case NS_COMPANY_TROUBLE: - DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING); - - SetDParam(0, p->index); - - DrawStringMultiCenter( - ((w->width - 101) >> 1) + 98, - 90, - STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED, - w->width - 101); - break; - - case NS_COMPANY_MERGER: - DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING); - SetDParam(0, ni->params[2]); - SetDParam(1, p->index); - SetDParam(2, ni->params[4]); - DrawStringMultiCenter( - ((w->width - 101) >> 1) + 98, - 90, - ni->params[4] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR, - w->width - 101); - break; - - case NS_COMPANY_BANKRUPT: - DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING); - SetDParam(0, p->index); - DrawStringMultiCenter( - ((w->width - 101) >> 1) + 98, - 90, - STR_705D_HAS_BEEN_CLOSED_DOWN_BY, - w->width - 101); - break; - - case NS_COMPANY_NEW: - DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING); - SetDParam(0, p->index); - SetDParam(1, ni->params[3]); - DrawStringMultiCenter( - ((w->width - 101) >> 1) + 98, - 90, - STR_705F_STARTS_CONSTRUCTION_NEAR, - w->width - 101); - break; - - default: - NOT_REACHED(); - } -} - static void PlayersGenStatistics() { Station *st; @@ -717,7 +654,7 @@ * inflation doesn't add anything after that either; it even makes playing * it impossible due to the diverging cost and income rates. */ - if ((_cur_year - _patches.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return; + if ((_cur_year - _settings.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return; /* Approximation for (100 + infl_amount)% ** (1 / 12) - 100% * scaled by 65536 @@ -767,7 +704,7 @@ static void HandleEconomyFluctuations() { - if (_opt.diff.economy == 0) return; + if (_settings.difficulty.economy == 0) return; if (--_economy.fluct == 0) { _economy.fluct = -(int)GB(Random(), 0, 2); @@ -876,7 +813,7 @@ for (i = 0; i != NUM_PRICES; i++) { Money price = _price_base[i]; if (_price_category[i] != 0) { - uint mod = _price_category[i] == 1 ? _opt.diff.vehicle_costs : _opt.diff.construction_cost; + uint mod = _price_category[i] == 1 ? _settings.difficulty.vehicle_costs : _settings.difficulty.construction_cost; if (mod < 1) { price = price * 3 >> 2; } else if (mod > 1) { @@ -892,10 +829,10 @@ _price_frac[i] = 0; } - _economy.interest_rate = _opt.diff.initial_interest; - _economy.infl_amount = _opt.diff.initial_interest; - _economy.infl_amount_pr = max(0, _opt.diff.initial_interest - 1); - _economy.max_loan_unround = _economy.max_loan = _opt.diff.max_loan * 1000; + _economy.interest_rate = _settings.difficulty.initial_interest; + _economy.infl_amount = _settings.difficulty.initial_interest; + _economy.infl_amount_pr = max(0, _settings.difficulty.initial_interest - 1); + _economy.max_loan_unround = _economy.max_loan = _settings.difficulty.max_loan; _economy.fluct = GB(Random(), 0, 8) + 168; } @@ -1225,7 +1162,7 @@ } /* zero the distance (thus income) if it's the bank and very short transport. */ - if (_opt.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0; + if (_settings.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0; static const int MIN_TIME_FACTOR = 31; @@ -1271,7 +1208,7 @@ * XXX - Think of something better to * 1) Only deliver to industries which are withing the catchment radius * 2) Distribute between industries if more then one is present */ - best_dist = (_patches.station_spread + 8) * 2; + best_dist = (_settings.station.station_spread + 8) * 2; FOR_ALL_INDUSTRIES(ind) { indspec = GetIndustrySpec(ind->type); uint i; @@ -1376,7 +1313,7 @@ SetDParam(0, _current_player); AddNewsItem( - STR_2031_SERVICE_SUBSIDY_AWARDED + _opt.diff.subsidy_multiplier, + STR_2031_SERVICE_SUBSIDY_AWARDED + _settings.difficulty.subsidy_multiplier, NS_SUBSIDIES, pair.a, pair.b ); @@ -1423,7 +1360,7 @@ /* Modify profit if a subsidy is in effect */ if (subsidised) { - switch (_opt.diff.subsidy_multiplier) { + switch (_settings.difficulty.subsidy_multiplier) { case 0: profit += profit >> 1; break; case 1: profit *= 2; break; case 2: profit *= 3; break; @@ -1544,7 +1481,7 @@ /* We have not waited enough time till the next round of loading/unloading */ if (--v->load_unload_time_rem != 0) { - if (_patches.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) { + if (_settings.order.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) { /* 'Reserve' this cargo for this vehicle, because we were first. */ for (; v != NULL; v = v->Next()) { if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); @@ -1580,7 +1517,7 @@ if (v->cargo_cap == 0) continue; byte load_amount = EngInfo(v->engine_type)->load_amount; - if (_patches.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { + if (_settings.order.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v); if (cb_load_amount != CALLBACK_FAILED && GB(cb_load_amount, 0, 8) != 0) load_amount = GB(cb_load_amount, 0, 8); } @@ -1589,7 +1526,7 @@ if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (u->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) { uint cargo_count = v->cargo.Count(); - uint amount_unloaded = _patches.gradual_loading ? min(cargo_count, load_amount) : cargo_count; + uint amount_unloaded = _settings.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count; bool remaining; // Are there cargo entities in this vehicle that can still be unloaded here? if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) { @@ -1615,7 +1552,7 @@ unloading_time += amount_unloaded; anything_unloaded = true; - if (_patches.gradual_loading && remaining) { + if (_settings.order.gradual_loading && remaining) { completely_emptied = false; } else { /* We have finished unloading (cargo count == 0) */ @@ -1649,14 +1586,14 @@ /* Skip loading this vehicle if another train/vehicle is already handling * the same cargo type at this station */ - if (_patches.improved_load && cargo_left[v->cargo_type] <= 0) { + if (_settings.order.improved_load && cargo_left[v->cargo_type] <= 0) { SetBit(cargo_not_full, v->cargo_type); continue; } if (cap > count) cap = count; - if (_patches.gradual_loading) cap = min(cap, load_amount); - if (_patches.improved_load) { + if (_settings.order.gradual_loading) cap = min(cap, load_amount); + if (_settings.order.improved_load) { /* Don't load stuff that is already 'reserved' for other vehicles */ cap = min((uint)cargo_left[v->cargo_type], cap); cargo_left[v->cargo_type] -= cap; @@ -1700,7 +1637,7 @@ * all wagons at the same time instead of using the same 'improved' * loading algorithm for the wagons (only fill wagon when there is * enough to fill the previous wagons) */ - if (_patches.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) { + if (_settings.order.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) { /* Update left cargo */ for (v = u; v != NULL; v = v->Next()) { if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); @@ -1710,7 +1647,7 @@ v = u; if (anything_loaded || anything_unloaded) { - if (_patches.gradual_loading) { + if (_settings.order.gradual_loading) { /* The time it takes to load one 'slice' of cargo or passengers depends * on the vehicle type - the values here are those found in TTDPatch */ const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 }; @@ -1747,11 +1684,11 @@ /* Calculate the loading indicator fill percent and display * In the Game Menu do not display indicators - * If _patches.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 ) - * if _patches.loading_indicators == 1, _local_player must be the owner or must be a spectator to show ind., so 1 > 0 - * if _patches.loading_indicators == 0, do not display indicators ... 0 is never greater than anything + * If _settings.gui.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 ) + * if _settings.gui.loading_indicators == 1, _local_player must be the owner or must be a spectator to show ind., so 1 > 0 + * if _settings.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything */ - if (_game_mode != GM_MENU && (_patches.loading_indicators > (uint)(v->owner != _local_player && _local_player != PLAYER_SPECTATOR))) { + if (_game_mode != GM_MENU && (_settings.gui.loading_indicators > (uint)(v->owner != _local_player && _local_player != PLAYER_SPECTATOR))) { StringID percent_up_down = STR_NULL; int percent = CalcPercentVehicleFilled(v, &percent_up_down); if (v->fill_percent_te_id == INVALID_TE_ID) { @@ -1799,7 +1736,7 @@ void PlayersMonthlyLoop() { PlayersGenStatistics(); - if (_patches.inflation && _cur_year < MAX_YEAR) + if (_settings.economy.inflation && _cur_year < MAX_YEAR) AddInflation(); PlayersPayInterest(); /* Reset the _current_player flag */ @@ -1844,7 +1781,10 @@ p->is_active = false; DeletePlayerWindows(pi); - RebuildVehicleLists(); //Updates the open windows to add the newly acquired vehicles to the lists + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); + InvalidateWindowClassesData(WC_SHIPS_LIST, 0); + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); + InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0); } extern int GetAmountOwnedBy(const Player *p, PlayerID owner); @@ -1862,7 +1802,7 @@ /* Check if buying shares is allowed (protection against modified clients) */ /* Cannot buy own shares */ - if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; + if (!IsValidPlayer((PlayerID)p1) || !_settings.economy.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; p = GetPlayer((PlayerID)p1); @@ -1911,7 +1851,7 @@ /* Check if selling shares is allowed (protection against modified clients) */ /* Cannot sell own shares */ - if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; + if (!IsValidPlayer((PlayerID)p1) || !_settings.economy.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; p = GetPlayer((PlayerID)p1); diff -r 68a692eacf22 -r 67db0d431d5e src/elrail_func.h --- a/src/elrail_func.h Mon May 26 20:45:25 2008 +0000 +++ b/src/elrail_func.h Tue May 27 00:50:55 2008 +0000 @@ -25,7 +25,7 @@ */ static inline bool HasCatenaryDrawn(RailType rt) { - return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_patches.disable_elrails; + return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_settings.vehicle.disable_elrails; } /** @@ -37,6 +37,6 @@ void DrawCatenaryOnTunnel(const TileInfo *ti); void DrawCatenaryOnBridge(const TileInfo *ti); -int32 SettingsDisableElrail(int32 p1); ///< _patches.disable_elrail callback +int32 SettingsDisableElrail(int32 p1); ///< _settings.disable_elrail callback #endif /* ELRAIL_FUNC_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/engine.cpp --- a/src/engine.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/engine.cpp Tue May 27 00:50:55 2008 +0000 @@ -138,6 +138,7 @@ { assert(begin <= (uint)el->size()); assert(begin + num_items <= (uint)el->size()); + if (num_items < 2) return; qsort(&((*el)[begin]), num_items, sizeof(EngineID), compare); } @@ -216,7 +217,7 @@ uint age = e->age; /* Check for early retirement */ - if (e->player_avail != 0 && !_patches.never_expire_vehicles) { + if (e->player_avail != 0 && !_settings.vehicle.never_expire_vehicles) { int retire_early = e->info.retire_early; uint retire_early_max_age = max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12); if (retire_early != 0 && age >= retire_early_max_age) { @@ -229,7 +230,7 @@ if (age < e->duration_phase_1) { uint start = e->reliability_start; e->reliability = age * (e->reliability_max - start) / e->duration_phase_1 + start; - } else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _patches.never_expire_vehicles) { + } else if ((age -= e->duration_phase_1) < e->duration_phase_2 || _settings.vehicle.never_expire_vehicles) { /* We are at the peak of this engines life. It will have max reliability. * This is also true if the engines never expire. They will not go bad over time */ e->reliability = e->reliability_max; @@ -292,10 +293,10 @@ CalcEngineReliability(e); } - e->lifelength = ei->lifelength + _patches.extend_vehicle_life; + e->lifelength = ei->lifelength + _settings.vehicle.extend_vehicle_life; /* prevent certain engines from ever appearing. */ - if (!HasBit(ei->climates, _opt.landscape)) { + if (!HasBit(ei->climates, _settings.game_creation.landscape)) { e->flags |= ENGINE_AVAILABLE; e->player_avail = 0; } diff -r 68a692eacf22 -r 67db0d431d5e src/engine_gui.cpp --- a/src/engine_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/engine_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -66,55 +66,54 @@ { DrawAircraftEngine, DrawAircraftEngineInfo }, }; -static void EnginePreviewWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - EngineID engine = w->window_number; - const DrawEngineInfo* dei; - int width; +struct EnginePreviewWindow : Window { + EnginePreviewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + } - w->DrawWidgets(); + virtual void OnPaint() + { + this->DrawWidgets(); + EngineID engine = this->window_number; SetDParam(0, GetEngineCategoryName(engine)); DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296); SetDParam(0, engine); - DrawStringCentered(w->width >> 1, 80, STR_ENGINE_NAME, TC_BLACK); + DrawStringCentered(this->width >> 1, 80, STR_ENGINE_NAME, TC_BLACK); - dei = &_draw_engine_list[GetEngine(engine)->type]; + const DrawEngineInfo *dei = &_draw_engine_list[GetEngine(engine)->type]; - width = w->width; + int width = this->width; dei->engine_proc(width >> 1, 100, engine, 0); dei->info_proc(engine, width >> 1, 130, width - 52); - break; } - case WE_CLICK: - switch (e->we.click.widget) { + virtual void OnClick(Point pt, int widget) + { + switch (widget) { case 4: - DoCommandP(0, w->window_number, 0, NULL, CMD_WANT_ENGINE_PREVIEW); + DoCommandP(0, this->window_number, 0, NULL, CMD_WANT_ENGINE_PREVIEW); /* Fallthrough */ case 3: - delete w; + delete this; break; } - break; } -} +}; static const WindowDesc _engine_preview_desc = { WDP_CENTER, WDP_CENTER, 300, 192, 300, 192, WC_ENGINE_PREVIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _engine_preview_widgets, - EnginePreviewWndProc }; void ShowEnginePreviewWindow(EngineID engine) { - AllocateWindowDescFront(&_engine_preview_desc, engine); + AllocateWindowDescFront(&_engine_preview_desc, engine); } static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw) diff -r 68a692eacf22 -r 67db0d431d5e src/genworld.cpp --- a/src/genworld.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/genworld.cpp Tue May 27 00:50:55 2008 +0000 @@ -91,8 +91,8 @@ _generating_world = true; if (_network_dedicated) DEBUG(net, 0, "Generating map, please wait..."); /* Set the Random() seed to generation_seed so we produce the same map with the same seed */ - if (_patches.generation_seed == GENERATE_NEW_SEED) _patches.generation_seed = _patches_newgame.generation_seed = InteractiveRandom(); - _random.SetSeed(_patches.generation_seed); + if (_settings.game_creation.generation_seed == GENERATE_NEW_SEED) _settings.game_creation.generation_seed = _settings_newgame.game_creation.generation_seed = InteractiveRandom(); + _random.SetSeed(_settings.game_creation.generation_seed); SetGeneratingWorldProgress(GWP_MAP_INIT, 2); SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, VHM_NONE, WC_MAIN_WINDOW, 0); @@ -105,7 +105,7 @@ SetGeneratingWorldProgress(GWP_UNMOVABLE, 1); /* Make the map the height of the patch setting */ - if (_game_mode != GM_MENU) FlatEmptyWorld(_patches.se_flat_world_height); + if (_game_mode != GM_MENU) FlatEmptyWorld(_settings.game_creation.se_flat_world_height); ConvertGroundTilesIntoWaterTiles(); IncreaseGeneratingWorldProgress(GWP_UNMOVABLE); @@ -165,7 +165,7 @@ if (_network_dedicated) DEBUG(net, 0, "Map generated, starting game"); - if (_patches.pause_on_newgame && _game_mode == GM_NORMAL) DoCommandP(0, 1, 0, NULL, CMD_PAUSE); + if (_settings.gui.pause_on_newgame && _game_mode == GM_NORMAL) DoCommandP(0, 1, 0, NULL, CMD_PAUSE); } catch (...) { _generating_world = false; throw; @@ -273,7 +273,7 @@ _current_player = OWNER_NONE; /* Set the date before loading sprites as some newgrfs check it */ - SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1)); + SetDate(ConvertYMDToDate(_settings.game_creation.starting_year, 0, 1)); /* Load the right landscape stuff */ GfxLoadSprites(); diff -r 68a692eacf22 -r 67db0d431d5e src/genworld_gui.cpp --- a/src/genworld_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/genworld_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -48,7 +48,7 @@ static inline void SetNewLandscapeType(byte landscape) { - _opt_newgame.landscape = landscape; + _settings_newgame.game_creation.landscape = landscape; InvalidateWindowClasses(WC_SELECT_GAME); InvalidateWindowClasses(WC_GENERATE_LANDSCAPE); } @@ -205,9 +205,7 @@ DeleteAllNonVitalWindows(); /* Copy all XXX_newgame to XXX when coming from outside the editor */ - UpdatePatches(); - _opt = _opt_newgame; - _opt_ptr = &_opt; + _settings = _settings_newgame; ResetGRFConfig(true); SndPlayFx(SND_15_BEEP); @@ -255,9 +253,9 @@ GenerateLandscapeWindow(const WindowDesc *desc, WindowNumber number = 0) : QueryStringBaseWindow(desc, number) { - this->LowerWidget(_opt_newgame.landscape + GLAND_TEMPERATE); + this->LowerWidget(_settings_newgame.game_creation.landscape + GLAND_TEMPERATE); - snprintf(this->edit_str_buf, sizeof(this->edit_str_buf), "%u", _patches_newgame.generation_seed); + snprintf(this->edit_str_buf, sizeof(this->edit_str_buf), "%u", _settings_newgame.game_creation.generation_seed); InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120); this->caption = STR_NULL; this->afilter = CS_NUMERAL; @@ -271,49 +269,49 @@ { /* You can't select smoothness if not terragenesis */ if (mode == GLWP_GENERATE) { - this->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _patches_newgame.land_generator == 0); + this->SetWidgetDisabledState(GLAND_SMOOTHNESS_PULLDOWN, _settings_newgame.game_creation.land_generator == 0); } /* Disable snowline if not hilly */ - this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _opt_newgame.landscape != LT_ARCTIC); + this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_TEXT, _settings_newgame.game_creation.landscape != LT_ARCTIC); /* Disable town, industry and trees in SE */ this->SetWidgetDisabledState(GLAND_TOWN_PULLDOWN, _game_mode == GM_EDITOR); this->SetWidgetDisabledState(GLAND_INDUSTRY_PULLDOWN, _game_mode == GM_EDITOR); this->SetWidgetDisabledState(GLAND_TREE_PULLDOWN, _game_mode == GM_EDITOR); - this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR); - this->SetWidgetDisabledState(GLAND_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR); - this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_ARCTIC); - this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP, _patches_newgame.snow_line_height >= MAX_SNOWLINE_HEIGHT || _opt_newgame.landscape != LT_ARCTIC); + this->SetWidgetDisabledState(GLAND_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR); + this->SetWidgetDisabledState(GLAND_START_DATE_UP, _settings_newgame.game_creation.starting_year >= MAX_YEAR); + this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_DOWN, _settings_newgame.game_creation.snow_line_height <= 2 || _settings_newgame.game_creation.landscape != LT_ARCTIC); + this->SetWidgetDisabledState(GLAND_SNOW_LEVEL_UP, _settings_newgame.game_creation.snow_line_height >= MAX_SNOWLINE_HEIGHT || _settings_newgame.game_creation.landscape != LT_ARCTIC); - this->SetWidgetLoweredState(GLAND_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE); - this->SetWidgetLoweredState(GLAND_ARCTIC, _opt_newgame.landscape == LT_ARCTIC); - this->SetWidgetLoweredState(GLAND_TROPICAL, _opt_newgame.landscape == LT_TROPIC); - this->SetWidgetLoweredState(GLAND_TOYLAND, _opt_newgame.landscape == LT_TOYLAND); + this->SetWidgetLoweredState(GLAND_TEMPERATE, _settings_newgame.game_creation.landscape == LT_TEMPERATE); + this->SetWidgetLoweredState(GLAND_ARCTIC, _settings_newgame.game_creation.landscape == LT_ARCTIC); + this->SetWidgetLoweredState(GLAND_TROPICAL, _settings_newgame.game_creation.landscape == LT_TROPIC); + this->SetWidgetLoweredState(GLAND_TOYLAND, _settings_newgame.game_creation.landscape == LT_TOYLAND); if (_game_mode == GM_EDITOR) { this->widget[GLAND_TOWN_PULLDOWN].data = STR_6836_OFF; this->widget[GLAND_INDUSTRY_PULLDOWN].data = STR_6836_OFF; } else { - this->widget[GLAND_TOWN_PULLDOWN].data = _num_towns[_opt_newgame.diff.number_towns]; - this->widget[GLAND_INDUSTRY_PULLDOWN].data = _num_inds[_opt_newgame.diff.number_industries]; + this->widget[GLAND_TOWN_PULLDOWN].data = _num_towns[_settings_newgame.difficulty.number_towns]; + this->widget[GLAND_INDUSTRY_PULLDOWN].data = _num_inds[_settings_newgame.difficulty.number_industries]; } if (mode == GLWP_GENERATE) { - this->widget[GLAND_LANDSCAPE_PULLDOWN].data = _landscape[_patches_newgame.land_generator]; - this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_patches_newgame.tree_placer]; - this->widget[GLAND_TERRAIN_PULLDOWN].data = _elevations[_opt_newgame.diff.terrain_type]; - this->widget[GLAND_WATER_PULLDOWN].data = _sea_lakes[_opt_newgame.diff.quantity_sea_lakes]; - this->widget[GLAND_SMOOTHNESS_PULLDOWN].data = _smoothness[_patches_newgame.tgen_smoothness]; + this->widget[GLAND_LANDSCAPE_PULLDOWN].data = _landscape[_settings_newgame.game_creation.land_generator]; + this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_settings_newgame.game_creation.tree_placer]; + this->widget[GLAND_TERRAIN_PULLDOWN].data = _elevations[_settings_newgame.difficulty.terrain_type]; + this->widget[GLAND_WATER_PULLDOWN].data = _sea_lakes[_settings_newgame.difficulty.quantity_sea_lakes]; + this->widget[GLAND_SMOOTHNESS_PULLDOWN].data = _smoothness[_settings_newgame.game_creation.tgen_smoothness]; } else { - this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_patches_newgame.tree_placer]; - this->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = _rotation[_patches_newgame.heightmap_rotation]; + this->widget[GLAND_TREE_PULLDOWN].data = _tree_placer[_settings_newgame.game_creation.tree_placer]; + this->widget[GLAND_HEIGHTMAP_ROTATION_PULLDOWN].data = _rotation[_settings_newgame.game_creation.heightmap_rotation]; } /* Set parameters for widget text that requires them. */ - SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // GLAND_START_DATE_TEXT - SetDParam(1, 1 << _patches_newgame.map_x); // GLAND_MAPSIZE_X_PULLDOWN - SetDParam(2, 1 << _patches_newgame.map_y); // GLAND_MAPSIZE_Y_PULLDOWN - SetDParam(3, _patches_newgame.snow_line_height); // GLAND_SNOW_LEVEL_TEXT + SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); // GLAND_START_DATE_TEXT + SetDParam(1, 1 << _settings_newgame.game_creation.map_x); // GLAND_MAPSIZE_X_PULLDOWN + SetDParam(2, 1 << _settings_newgame.game_creation.map_y); // GLAND_MAPSIZE_Y_PULLDOWN + SetDParam(3, _settings_newgame.game_creation.snow_line_height); // GLAND_SNOW_LEVEL_TEXT this->DrawWidgets(); @@ -322,7 +320,7 @@ if (mode != GLWP_GENERATE) { char buffer[512]; - if (_patches_newgame.heightmap_rotation == HM_CLOCKWISE) { + if (_settings_newgame.game_creation.heightmap_rotation == HM_CLOCKWISE) { SetDParam(0, this->y); SetDParam(1, this->x); } else { @@ -347,29 +345,29 @@ case GLAND_ARCTIC: case GLAND_TROPICAL: case GLAND_TOYLAND: - this->RaiseWidget(_opt_newgame.landscape + GLAND_TEMPERATE); + this->RaiseWidget(_settings_newgame.game_creation.landscape + GLAND_TEMPERATE); SetNewLandscapeType(widget - GLAND_TEMPERATE); break; case GLAND_MAPSIZE_X_PULLDOWN: // Mapsize X - ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, GLAND_MAPSIZE_X_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, GLAND_MAPSIZE_X_PULLDOWN); break; case GLAND_MAPSIZE_Y_PULLDOWN: // Mapsize Y - ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, GLAND_MAPSIZE_Y_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, GLAND_MAPSIZE_Y_PULLDOWN); break; case GLAND_TOWN_PULLDOWN: // Number of towns - ShowDropDownMenu(this, _num_towns, _opt_newgame.diff.number_towns, GLAND_TOWN_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _num_towns, _settings_newgame.difficulty.number_towns, GLAND_TOWN_PULLDOWN, 0, 0); break; case GLAND_INDUSTRY_PULLDOWN: // Number of industries - ShowDropDownMenu(this, _num_inds, _opt_newgame.diff.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _num_inds, _settings_newgame.difficulty.number_industries, GLAND_INDUSTRY_PULLDOWN, 0, 0); break; case GLAND_RANDOM_BUTTON: // Random seed - _patches_newgame.generation_seed = InteractiveRandom(); - snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "%u", _patches_newgame.generation_seed); + _settings_newgame.game_creation.generation_seed = InteractiveRandom(); + snprintf(this->edit_str_buf, lengthof(this->edit_str_buf), "%u", _settings_newgame.game_creation.generation_seed); UpdateTextBufferSize(&this->text); this->SetDirty(); break; @@ -379,19 +377,19 @@ break; case GLAND_GENERATE_BUTTON: // Generate - UpdatePatches(); + _settings = _settings_newgame; - if (_patches.town_layout == TL_NO_ROADS) { + if (_settings.economy.town_layout == TL_NO_ROADS) { ShowQuery( STR_TOWN_LAYOUT_WARNING_CAPTION, STR_TOWN_LAYOUT_WARNING_MESSAGE, this, LandscapeGenerationCallback); } else if (mode == GLWP_HEIGHTMAP && - (this->x * 2 < (1U << _patches_newgame.map_x) || - this->x / 2 > (1U << _patches_newgame.map_x) || - this->y * 2 < (1U << _patches_newgame.map_y) || - this->y / 2 > (1U << _patches_newgame.map_y))) { + (this->x * 2 < (1U << _settings_newgame.game_creation.map_x) || + this->x / 2 > (1U << _settings_newgame.game_creation.map_x) || + this->y * 2 < (1U << _settings_newgame.game_creation.map_y) || + this->y / 2 > (1U << _settings_newgame.game_creation.map_y))) { ShowQuery( STR_HEIGHTMAP_SCALE_WARNING_CAPTION, STR_HEIGHTMAP_SCALE_WARNING_MESSAGE, @@ -409,14 +407,14 @@ this->HandleButtonClick(widget); this->SetDirty(); - _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR); + _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - GLAND_START_DATE_TEXT, MIN_YEAR, MAX_YEAR); } _left_button_clicked = false; break; case GLAND_START_DATE_TEXT: // Year text this->widget_id = GLAND_START_DATE_TEXT; - SetDParam(0, _patches_newgame.starting_year); + SetDParam(0, _settings_newgame.game_creation.starting_year); ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL); break; @@ -427,40 +425,40 @@ this->HandleButtonClick(widget); this->SetDirty(); - _patches_newgame.snow_line_height = Clamp(_patches_newgame.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT); + _settings_newgame.game_creation.snow_line_height = Clamp(_settings_newgame.game_creation.snow_line_height + widget - GLAND_SNOW_LEVEL_TEXT, 2, MAX_SNOWLINE_HEIGHT); } _left_button_clicked = false; break; case GLAND_SNOW_LEVEL_TEXT: // Snow line text this->widget_id = GLAND_SNOW_LEVEL_TEXT; - SetDParam(0, _patches_newgame.snow_line_height); + SetDParam(0, _settings_newgame.game_creation.snow_line_height); ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_SNOW_LINE_QUERY_CAPT, 3, 100, this, CS_NUMERAL); break; case GLAND_TREE_PULLDOWN: // Tree placer - ShowDropDownMenu(this, _tree_placer, _patches_newgame.tree_placer, GLAND_TREE_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _tree_placer, _settings_newgame.game_creation.tree_placer, GLAND_TREE_PULLDOWN, 0, 0); break; case GLAND_LANDSCAPE_PULLDOWN: // Landscape generator OR Heightmap rotation /* case GLAND_HEIGHTMAP_ROTATION_TEXT: case GLAND_HEIGHTMAP_ROTATION_PULLDOWN:*/ if (mode == GLWP_HEIGHTMAP) { - ShowDropDownMenu(this, _rotation, _patches_newgame.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _rotation, _settings_newgame.game_creation.heightmap_rotation, GLAND_HEIGHTMAP_ROTATION_PULLDOWN, 0, 0); } else { - ShowDropDownMenu(this, _landscape, _patches_newgame.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _landscape, _settings_newgame.game_creation.land_generator, GLAND_LANDSCAPE_PULLDOWN, 0, 0); } break; case GLAND_TERRAIN_PULLDOWN: // Terrain type - ShowDropDownMenu(this, _elevations, _opt_newgame.diff.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _elevations, _settings_newgame.difficulty.terrain_type, GLAND_TERRAIN_PULLDOWN, 0, 0); break; case GLAND_WATER_PULLDOWN: // Water quantity - ShowDropDownMenu(this, _sea_lakes, _opt_newgame.diff.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _sea_lakes, _settings_newgame.difficulty.quantity_sea_lakes, GLAND_WATER_PULLDOWN, 0, 0); break; case GLAND_SMOOTHNESS_PULLDOWN: // Map smoothness - ShowDropDownMenu(this, _smoothness, _patches_newgame.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0); + ShowDropDownMenu(this, _smoothness, _settings_newgame.game_creation.tgen_smoothness, GLAND_SMOOTHNESS_PULLDOWN, 0, 0); break; } } @@ -470,58 +468,58 @@ this->HandleEditBox(GLAND_RANDOM_EDITBOX); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont; - this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, cont); + EventState state; + this->HandleEditBoxKey(GLAND_RANDOM_EDITBOX, key, keycode, state); /* the seed is unsigned, therefore atoi cannot be used. * As 2^32 - 1 (MAX_UVALUE(uint32)) is a 'magic' value * (use random seed) it should not be possible to be * entered into the input field; the generate seed * button can be used instead. */ - _patches_newgame.generation_seed = minu(strtoul(this->edit_str_buf, NULL, sizeof(this->edit_str_buf) - 1), MAX_UVALUE(uint32) - 1); - return cont; + _settings_newgame.game_creation.generation_seed = minu(strtoul(this->edit_str_buf, NULL, sizeof(this->edit_str_buf) - 1), MAX_UVALUE(uint32) - 1); + return state; } virtual void OnDropdownSelect(int widget, int index) { switch (widget) { - case GLAND_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break; - case GLAND_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break; - case GLAND_TREE_PULLDOWN: _patches_newgame.tree_placer = index; break; - case GLAND_SMOOTHNESS_PULLDOWN: _patches_newgame.tgen_smoothness = index; break; + case GLAND_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break; + case GLAND_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break; + case GLAND_TREE_PULLDOWN: _settings_newgame.game_creation.tree_placer = index; break; + case GLAND_SMOOTHNESS_PULLDOWN: _settings_newgame.game_creation.tgen_smoothness = index; break; case GLAND_TOWN_PULLDOWN: - _opt_newgame.diff.number_towns = index; - if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); - DoCommandP(0, 2, _opt_newgame.diff.number_towns, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + _settings_newgame.difficulty.number_towns = index; + if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); + IConsoleSetPatchSetting("difficulty.number_towns", _settings_newgame.difficulty.number_towns); break; case GLAND_INDUSTRY_PULLDOWN: - _opt_newgame.diff.number_industries = index; - if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); - DoCommandP(0, 3, _opt_newgame.diff.number_industries, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + _settings_newgame.difficulty.number_industries = index; + if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); + IConsoleSetPatchSetting("difficulty.number_industries", _settings_newgame.difficulty.number_industries); break; case GLAND_LANDSCAPE_PULLDOWN: /* case GLAND_HEIGHTMAP_PULLDOWN: */ if (mode == GLWP_HEIGHTMAP) { - _patches_newgame.heightmap_rotation = index; + _settings_newgame.game_creation.heightmap_rotation = index; } else { - _patches_newgame.land_generator = index; + _settings_newgame.game_creation.land_generator = index; } break; case GLAND_TERRAIN_PULLDOWN: - _opt_newgame.diff.terrain_type = index; - if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); - DoCommandP(0, 12, _opt_newgame.diff.terrain_type, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + _settings_newgame.difficulty.terrain_type = index; + if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); + IConsoleSetPatchSetting("difficulty.terrain_type", _settings_newgame.difficulty.terrain_type); break; case GLAND_WATER_PULLDOWN: - _opt_newgame.diff.quantity_sea_lakes = index; - if (_opt_newgame.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); - DoCommandP(0, 13, _opt_newgame.diff.quantity_sea_lakes, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + _settings_newgame.difficulty.quantity_sea_lakes = index; + if (_settings_newgame.difficulty.diff_level != 3) ShowErrorMessage(INVALID_STRING_ID, STR_DIFFICULTY_TO_CUSTOM, 0, 0); + IConsoleSetPatchSetting("difficulty.quantity_sea_lakes", _settings_newgame.difficulty.quantity_sea_lakes); break; } this->SetDirty(); @@ -535,12 +533,12 @@ switch (this->widget_id) { case GLAND_START_DATE_TEXT: this->InvalidateWidget(GLAND_START_DATE_TEXT); - _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR); + _settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR); break; case GLAND_SNOW_LEVEL_TEXT: this->InvalidateWidget(GLAND_SNOW_LEVEL_TEXT); - _patches_newgame.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT); + _settings_newgame.game_creation.snow_line_height = Clamp(value, 2, MAX_SNOWLINE_HEIGHT); break; } @@ -554,7 +552,6 @@ WC_GENERATE_LANDSCAPE, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _generate_landscape_widgets, - NULL, }; static const WindowDesc _heightmap_load_desc = { @@ -562,7 +559,6 @@ WC_GENERATE_LANDSCAPE, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, _heightmap_load_widgets, - NULL, }; static void _ShowGenerateLandscape(glwp_modes mode) @@ -573,7 +569,7 @@ DeleteWindowByClass(WC_GENERATE_LANDSCAPE); /* Always give a new seed if not editor */ - if (_game_mode != GM_EDITOR) _patches_newgame.generation_seed = InteractiveRandom(); + if (_game_mode != GM_EDITOR) _settings_newgame.game_creation.generation_seed = InteractiveRandom(); if (mode == GLWP_HEIGHTMAP) { /* If the function returns negative, it means there was a problem loading the heightmap */ @@ -603,8 +599,8 @@ void StartScenarioEditor() { - if (_patches_newgame.town_layout == TL_NO_ROADS) { - _patches_newgame.town_layout = TL_ORIGINAL; + if (_settings_newgame.economy.town_layout == TL_NO_ROADS) { + _settings_newgame.economy.town_layout = TL_ORIGINAL; } StartGeneratingLandscape(GLWP_SCENARIO); @@ -613,7 +609,7 @@ void StartNewGameWithoutGUI(uint seed) { /* GenerateWorld takes care of the possible GENERATE_NEW_SEED value in 'seed' */ - _patches_newgame.generation_seed = seed; + _settings_newgame.game_creation.generation_seed = seed; StartGeneratingLandscape(GLWP_GENERATE); } @@ -646,26 +642,27 @@ CreateScenarioWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) { - this->LowerWidget(_opt_newgame.landscape + CSCEN_TEMPERATE); + this->LowerWidget(_settings_newgame.game_creation.landscape + CSCEN_TEMPERATE); + this->FindWindowPlacementAndResize(desc); } virtual void OnPaint() { - this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN, _patches_newgame.starting_year <= MIN_YEAR); - this->SetWidgetDisabledState(CSCEN_START_DATE_UP, _patches_newgame.starting_year >= MAX_YEAR); - this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _patches_newgame.se_flat_world_height <= 0); - this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP, _patches_newgame.se_flat_world_height >= MAX_TILE_HEIGHT); + this->SetWidgetDisabledState(CSCEN_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR); + this->SetWidgetDisabledState(CSCEN_START_DATE_UP, _settings_newgame.game_creation.starting_year >= MAX_YEAR); + this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_DOWN, _settings_newgame.game_creation.se_flat_world_height <= 0); + this->SetWidgetDisabledState(CSCEN_FLAT_LAND_HEIGHT_UP, _settings_newgame.game_creation.se_flat_world_height >= MAX_TILE_HEIGHT); - this->SetWidgetLoweredState(CSCEN_TEMPERATE, _opt_newgame.landscape == LT_TEMPERATE); - this->SetWidgetLoweredState(CSCEN_ARCTIC, _opt_newgame.landscape == LT_ARCTIC); - this->SetWidgetLoweredState(CSCEN_TROPICAL, _opt_newgame.landscape == LT_TROPIC); - this->SetWidgetLoweredState(CSCEN_TOYLAND, _opt_newgame.landscape == LT_TOYLAND); + this->SetWidgetLoweredState(CSCEN_TEMPERATE, _settings_newgame.game_creation.landscape == LT_TEMPERATE); + this->SetWidgetLoweredState(CSCEN_ARCTIC, _settings_newgame.game_creation.landscape == LT_ARCTIC); + this->SetWidgetLoweredState(CSCEN_TROPICAL, _settings_newgame.game_creation.landscape == LT_TROPIC); + this->SetWidgetLoweredState(CSCEN_TOYLAND, _settings_newgame.game_creation.landscape == LT_TOYLAND); /* Set parameters for widget text that requires them */ - SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT - SetDParam(1, 1 << _patches_newgame.map_x); // CSCEN_MAPSIZE_X_PULLDOWN - SetDParam(2, 1 << _patches_newgame.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN - SetDParam(3, _patches_newgame.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT + SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); // CSCEN_START_DATE_TEXT + SetDParam(1, 1 << _settings_newgame.game_creation.map_x); // CSCEN_MAPSIZE_X_PULLDOWN + SetDParam(2, 1 << _settings_newgame.game_creation.map_y); // CSCEN_MAPSIZE_Y_PULLDOWN + SetDParam(3, _settings_newgame.game_creation.se_flat_world_height); // CSCEN_FLAT_LAND_HEIGHT_TEXT this->DrawWidgets(); } @@ -677,16 +674,16 @@ case CSCEN_ARCTIC: case CSCEN_TROPICAL: case CSCEN_TOYLAND: - this->RaiseWidget(_opt_newgame.landscape + CSCEN_TEMPERATE); + this->RaiseWidget(_settings_newgame.game_creation.landscape + CSCEN_TEMPERATE); SetNewLandscapeType(widget - CSCEN_TEMPERATE); break; case CSCEN_MAPSIZE_X_PULLDOWN: // Mapsize X - ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_x, CSCEN_MAPSIZE_X_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_x, CSCEN_MAPSIZE_X_PULLDOWN); break; case CSCEN_MAPSIZE_Y_PULLDOWN: // Mapsize Y - ShowDropDownList(this, BuildMapsizeDropDown(), _patches_newgame.map_y, CSCEN_MAPSIZE_Y_PULLDOWN); + ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, CSCEN_MAPSIZE_Y_PULLDOWN); break; case CSCEN_EMPTY_WORLD: // Empty world / flat world @@ -704,14 +701,14 @@ this->HandleButtonClick(widget); this->SetDirty(); - _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR); + _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - CSCEN_START_DATE_TEXT, MIN_YEAR, MAX_YEAR); } _left_button_clicked = false; break; case CSCEN_START_DATE_TEXT: // Year text this->widget_id = CSCEN_START_DATE_TEXT; - SetDParam(0, _patches_newgame.starting_year); + SetDParam(0, _settings_newgame.game_creation.starting_year); ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_START_DATE_QUERY_CAPT, 8, 100, this, CS_NUMERAL); break; @@ -722,14 +719,14 @@ this->HandleButtonClick(widget); this->SetDirty(); - _patches_newgame.se_flat_world_height = Clamp(_patches_newgame.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT); + _settings_newgame.game_creation.se_flat_world_height = Clamp(_settings_newgame.game_creation.se_flat_world_height + widget - CSCEN_FLAT_LAND_HEIGHT_TEXT, 0, MAX_TILE_HEIGHT); } _left_button_clicked = false; break; case CSCEN_FLAT_LAND_HEIGHT_TEXT: // Height level text this->widget_id = CSCEN_FLAT_LAND_HEIGHT_TEXT; - SetDParam(0, _patches_newgame.se_flat_world_height); + SetDParam(0, _settings_newgame.game_creation.se_flat_world_height); ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_FLAT_WORLD_HEIGHT_QUERY_CAPT, 3, 100, this, CS_NUMERAL); break; } @@ -738,8 +735,8 @@ virtual void OnDropdownSelect(int widget, int index) { switch (widget) { - case CSCEN_MAPSIZE_X_PULLDOWN: _patches_newgame.map_x = index; break; - case CSCEN_MAPSIZE_Y_PULLDOWN: _patches_newgame.map_y = index; break; + case CSCEN_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break; + case CSCEN_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break; } this->SetDirty(); } @@ -752,12 +749,12 @@ switch (this->widget_id) { case CSCEN_START_DATE_TEXT: this->InvalidateWidget(CSCEN_START_DATE_TEXT); - _patches_newgame.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR); + _settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR); break; case CSCEN_FLAT_LAND_HEIGHT_TEXT: this->InvalidateWidget(CSCEN_FLAT_LAND_HEIGHT_TEXT); - _patches_newgame.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT); + _settings_newgame.game_creation.se_flat_world_height = Clamp(value, 0, MAX_TILE_HEIGHT); break; } @@ -801,7 +798,6 @@ WC_GENERATE_LANDSCAPE, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS, _create_scenario_widgets, - NULL, }; void ShowCreateScenario() @@ -823,7 +819,6 @@ WC_GENERATE_PROGRESS_WINDOW, WC_NONE, WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _generate_progress_widgets, - NULL }; struct tp_info { @@ -854,7 +849,10 @@ }; public: - GenerateProgressWindow() : Window(&_generate_progress_desc) {}; + GenerateProgressWindow() : Window(&_generate_progress_desc) + { + this->FindWindowPlacementAndResize(&_generate_progress_desc); + } virtual void OnClick(Point pt, int widget) { diff -r 68a692eacf22 -r 67db0d431d5e src/gfx.cpp --- a/src/gfx.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/gfx.cpp Tue May 27 00:50:55 2008 +0000 @@ -427,9 +427,9 @@ } } -/** Draw a given string with the centre around the given x coordinates +/** Draw a given string with the centre around the given (x,y) coordinates * @param x Centre the string around this pixel width - * @param y Draw the string at this pixel height (first line's bottom) + * @param y Centre the string around this pixel height * @param str String to draw * @param maxw Maximum width the string can have before it is wrapped */ void DrawStringMultiCenter(int x, int y, StringID str, int maxw) @@ -807,7 +807,7 @@ memcpy(old_val, d, c * sizeof(*old_val)); /* Dark blue water */ - s = (_opt.landscape == LT_TOYLAND) ? ev->ac : ev->a; + s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->ac : ev->a; j = EXTR(320, 5); for (i = 0; i != 5; i++) { *d++ = s[j]; @@ -816,7 +816,7 @@ } /* Glittery water */ - s = (_opt.landscape == LT_TOYLAND) ? ev->bc : ev->b; + s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->bc : ev->b; j = EXTR(128, 15); for (i = 0; i != 5; i++) { *d++ = s[j]; @@ -876,7 +876,7 @@ /* Animate water for old DOS graphics */ if (_use_dos_palette) { /* Dark blue water DOS */ - s = (_opt.landscape == LT_TOYLAND) ? ev->ac : ev->a; + s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->ac : ev->a; j = EXTR(320, 5); for (i = 0; i != 5; i++) { *d++ = s[j]; @@ -885,7 +885,7 @@ } /* Glittery water DOS */ - s = (_opt.landscape == LT_TOYLAND) ? ev->bc : ev->b; + s = (_settings.game_creation.landscape == LT_TOYLAND) ? ev->bc : ev->b; j = EXTR(128, 15); for (i = 0; i != 5; i++) { *d++ = s[j]; diff -r 68a692eacf22 -r 67db0d431d5e src/gfxinit.cpp --- a/src/gfxinit.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/gfxinit.cpp Tue May 27 00:50:55 2008 +0000 @@ -214,10 +214,10 @@ * This overwrites some of the temperate sprites, such as foundations * and the ground sprites. */ - if (_opt.landscape != LT_TEMPERATE) { + if (_settings.game_creation.landscape != LT_TEMPERATE) { LoadGrfIndexed( - files->landscape[_opt.landscape - 1].filename, - _landscape_spriteindexes[_opt.landscape - 1], + files->landscape[_settings.game_creation.landscape - 1].filename, + _landscape_spriteindexes[_settings.game_creation.landscape - 1], i++ ); } @@ -248,7 +248,7 @@ void GfxLoadSprites() { - DEBUG(sprite, 2, "Loading sprite set %d", _opt.landscape); + DEBUG(sprite, 2, "Loading sprite set %d", _settings.game_creation.landscape); GfxInitSpriteMem(); LoadSpriteTables(); diff -r 68a692eacf22 -r 67db0d431d5e src/graph_gui.cpp --- a/src/graph_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/graph_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -24,295 +24,62 @@ static uint _legend_excluded_players; static uint _legend_excluded_cargo; -/************************/ -/* GENERIC GRAPH DRAWER */ -/************************/ - -enum { - GRAPH_MAX_DATASETS = 32, - GRAPH_AXIS_LABEL_COLOUR = TC_BLACK, - GRAPH_AXIS_LINE_COLOUR = 215, - - GRAPH_X_POSITION_BEGINNING = 44, ///< Start the graph 44 pixels from gw->left - GRAPH_X_POSITION_SEPARATION = 22, ///< There are 22 pixels between each X value - - GRAPH_NUM_LINES_Y = 9, ///< How many horizontal lines to draw. - /* 9 is convenient as that means the distance between them is the height of the graph / 8, - * which is the same - * as height >> 3. */ -}; - /* Apparently these don't play well with enums. */ static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn. static const uint INVALID_DATAPOINT_POS = UINT_MAX; // Used to determine if the previous point was drawn. -struct GraphDrawer { - uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed. - byte num_dataset; - byte num_on_x_axis; - bool has_negative_values; - byte num_vert_lines; - - /* The starting month and year that values are plotted against. If month is - * 0xFF, use x_values_start and x_values_increment below instead. */ - byte month; - Year year; - - /* These values are used if the graph is being plotted against values - * rather than the dates specified by month and year. */ - uint16 x_values_start; - uint16 x_values_increment; - - int left, top; ///< Where to start drawing the graph, in pixels. - uint height; ///< The height of the graph in pixels. - StringID format_str_y_axis; - byte colors[GRAPH_MAX_DATASETS]; - OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][24]; ///< last 2 years -}; - -static void DrawGraph(const GraphDrawer *gw) -{ - uint x, y; ///< Reused whenever x and y coordinates are needed. - OverflowSafeInt64 highest_value; ///< Highest value to be drawn. - int x_axis_offset; ///< Distance from the top of the graph to the x axis. - - /* the colors and cost array of GraphDrawer must accomodate - * both values for cargo and players. So if any are higher, quit */ - assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_PLAYERS); - assert(gw->num_vert_lines > 0); - - byte grid_colour = _colour_gradient[14][4]; - - /* The coordinates of the opposite edges of the graph. */ - int bottom = gw->top + gw->height - 1; - int right = gw->left + GRAPH_X_POSITION_BEGINNING + gw->num_vert_lines * GRAPH_X_POSITION_SEPARATION - 1; - - /* Draw the vertical grid lines. */ - - /* Don't draw the first line, as that's where the axis will be. */ - x = gw->left + GRAPH_X_POSITION_BEGINNING + GRAPH_X_POSITION_SEPARATION; - - for (int i = 0; i < gw->num_vert_lines; i++) { - GfxFillRect(x, gw->top, x, bottom, grid_colour); - x += GRAPH_X_POSITION_SEPARATION; - } - - /* Draw the horizontal grid lines. */ - x = gw->left + GRAPH_X_POSITION_BEGINNING; - y = gw->height + gw->top; - - for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) { - GfxFillRect(x, y, right, y, grid_colour); - y -= (gw->height / (GRAPH_NUM_LINES_Y - 1)); - } - - /* Draw the y axis. */ - GfxFillRect(x, gw->top, x, bottom, GRAPH_AXIS_LINE_COLOUR); - - /* Find the distance from the top of the graph to the x axis. */ - x_axis_offset = gw->height; - - /* The graph is currently symmetrical about the x axis. */ - if (gw->has_negative_values) x_axis_offset /= 2; - - /* Draw the x axis. */ - y = x_axis_offset + gw->top; - GfxFillRect(x, y, right, y, GRAPH_AXIS_LINE_COLOUR); - - /* Find the largest value that will be drawn. */ - if (gw->num_on_x_axis == 0) - return; - - assert(gw->num_on_x_axis > 0); - assert(gw->num_dataset > 0); - - /* Start of with a value of twice the height of the graph in pixels. It's a - * bit arbitrary, but it makes the cargo payment graph look a little nicer, - * and prevents division by zero when calculating where the datapoint - * should be drawn. */ - highest_value = x_axis_offset * 2; - - for (int i = 0; i < gw->num_dataset; i++) { - if (!HasBit(gw->excluded_data, i)) { - for (int j = 0; j < gw->num_on_x_axis; j++) { - OverflowSafeInt64 datapoint = gw->cost[i][j]; - - if (datapoint != INVALID_DATAPOINT) { - /* For now, if the graph has negative values the scaling is - * symmetrical about the x axis, so take the absolute value - * of each data point. */ - highest_value = max(highest_value, abs(datapoint)); - } - } - } - } - - /* Round up highest_value so that it will divide cleanly into the number of - * axis labels used. */ - int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1); - if (round_val != 0) highest_value += (GRAPH_NUM_LINES_Y - 1 - round_val); - - /* draw text strings on the y axis */ - int64 y_label = highest_value; - int64 y_label_separation = highest_value / (GRAPH_NUM_LINES_Y - 1); - - /* If there are negative values, the graph goes from highest_value to - * -highest_value, not highest_value to 0. */ - if (gw->has_negative_values) y_label_separation *= 2; - - x = gw->left + GRAPH_X_POSITION_BEGINNING + 1; - y = gw->top - 3; - - for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) { - SetDParam(0, gw->format_str_y_axis); - SetDParam(1, y_label); - DrawStringRightAligned(x, y, STR_0170, GRAPH_AXIS_LABEL_COLOUR); - - y_label -= y_label_separation; - y += (gw->height / (GRAPH_NUM_LINES_Y - 1)); - } - - /* draw strings on the x axis */ - if (gw->month != 0xFF) { - x = gw->left + GRAPH_X_POSITION_BEGINNING; - y = gw->top + gw->height + 1; - byte month = gw->month; - Year year = gw->year; - for (int i = 0; i < gw->num_on_x_axis; i++) { - SetDParam(0, month + STR_0162_JAN); - SetDParam(1, month + STR_0162_JAN + 2); - SetDParam(2, year); - DrawString(x, y, month == 0 ? STR_016F : STR_016E, GRAPH_AXIS_LABEL_COLOUR); - - month += 3; - if (month >= 12) { - month = 0; - year++; - } - x += GRAPH_X_POSITION_SEPARATION; - } - } else { - /* Draw the label under the data point rather than on the grid line. */ - x = gw->left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2) + 1; - y = gw->top + gw->height + 1; - uint16 label = gw->x_values_start; - - for (int i = 0; i < gw->num_on_x_axis; i++) { - SetDParam(0, label); - DrawStringCentered(x, y, STR_01CB, GRAPH_AXIS_LABEL_COLOUR); - - label += gw->x_values_increment; - x += GRAPH_X_POSITION_SEPARATION; - } - } - - /* draw lines and dots */ - for (int i = 0; i < gw->num_dataset; i++) { - if (!HasBit(gw->excluded_data, i)) { - /* Centre the dot between the grid lines. */ - x = gw->left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2); - - byte color = gw->colors[i]; - uint prev_x = INVALID_DATAPOINT_POS; - uint prev_y = INVALID_DATAPOINT_POS; - - for (int j = 0; j < gw->num_on_x_axis; j++) { - OverflowSafeInt64 datapoint = gw->cost[i][j]; - - if (datapoint != INVALID_DATAPOINT) { - /* - * Check whether we need to reduce the 'accuracy' of the - * datapoint value and the highest value to splut overflows. - * And when 'drawing' 'one million' or 'one million and one' - * there is no significant difference, so the least - * significant bits can just be removed. - * - * If there are more bits needed than would fit in a 32 bits - * integer, so at about 31 bits because of the sign bit, the - * least significant bits are removed. - */ - int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint)); - int reduce_range = max(mult_range - 31, 0); - - /* Handle negative values differently (don't shift sign) */ - if (datapoint < 0) { - datapoint = -(abs(datapoint) >> reduce_range); - } else { - datapoint >>= reduce_range; - } - - y = gw->top + x_axis_offset - (x_axis_offset * datapoint) / (highest_value >> reduce_range); - - /* Draw the point. */ - GfxFillRect(x - 1, y - 1, x + 1, y + 1, color); - - /* Draw the line connected to the previous point. */ - if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, color); - - prev_x = x; - prev_y = y; - } else { - prev_x = INVALID_DATAPOINT_POS; - prev_y = INVALID_DATAPOINT_POS; - } - - x += GRAPH_X_POSITION_SEPARATION; - } - } - } -} - /****************/ /* GRAPH LEGEND */ /****************/ -static void GraphLegendWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: - for (uint i = 3; i < w->widget_count; i++) { - if (!HasBit(_legend_excluded_players, i - 3)) w->LowerWidget(i); - } - break; - - case WE_PAINT: { - const Player *p; - - FOR_ALL_PLAYERS(p) { - if (p->is_active) continue; - - SetBit(_legend_excluded_players, p->index); - w->RaiseWidget(p->index + 3); - } - - w->DrawWidgets(); - - FOR_ALL_PLAYERS(p) { - if (!p->is_active) continue; - - DrawPlayerIcon(p->index, 4, 18 + p->index * 12); - - SetDParam(0, p->index); - SetDParam(1, p->index); - DrawString(21, 17 + p->index * 12, STR_7021, HasBit(_legend_excluded_players, p->index) ? TC_BLACK : TC_WHITE); - } - break; +struct GraphLegendWindow : Window { + GraphLegendWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + for (uint i = 3; i < this->widget_count; i++) { + if (!HasBit(_legend_excluded_players, i - 3)) this->LowerWidget(i); } - case WE_CLICK: - if (!IsInsideMM(e->we.click.widget, 3, 11)) return; + this->FindWindowPlacementAndResize(desc); + } - ToggleBit(_legend_excluded_players, e->we.click.widget - 3); - w->ToggleWidgetLoweredState(e->we.click.widget); - w->SetDirty(); - InvalidateWindow(WC_INCOME_GRAPH, 0); - InvalidateWindow(WC_OPERATING_PROFIT, 0); - InvalidateWindow(WC_DELIVERED_CARGO, 0); - InvalidateWindow(WC_PERFORMANCE_HISTORY, 0); - InvalidateWindow(WC_COMPANY_VALUE, 0); - break; + virtual void OnPaint() + { + const Player *p; + + FOR_ALL_PLAYERS(p) { + if (p->is_active) continue; + + SetBit(_legend_excluded_players, p->index); + this->RaiseWidget(p->index + 3); + } + + this->DrawWidgets(); + + FOR_ALL_PLAYERS(p) { + if (!p->is_active) continue; + + DrawPlayerIcon(p->index, 4, 18 + p->index * 12); + + SetDParam(0, p->index); + SetDParam(1, p->index); + DrawString(21, 17 + p->index * 12, STR_7021, HasBit(_legend_excluded_players, p->index) ? TC_BLACK : TC_WHITE); + } } -} + + virtual void OnClick(Point pt, int widget) + { + if (!IsInsideMM(widget, 3, 11)) return; + + ToggleBit(_legend_excluded_players, widget - 3); + this->ToggleWidgetLoweredState(widget); + this->SetDirty(); + InvalidateWindow(WC_INCOME_GRAPH, 0); + InvalidateWindow(WC_OPERATING_PROFIT, 0); + InvalidateWindow(WC_DELIVERED_CARGO, 0); + InvalidateWindow(WC_PERFORMANCE_HISTORY, 0); + InvalidateWindow(WC_COMPANY_VALUE, 0); + } +}; static const Widget _graph_legend_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -334,90 +101,332 @@ WC_GRAPH_LEGEND, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _graph_legend_widgets, - GraphLegendWndProc }; static void ShowGraphLegend() { - AllocateWindowDescFront(&_graph_legend_desc, 0); + AllocateWindowDescFront(&_graph_legend_desc, 0); } +/******************/ +/* BASE OF GRAPHS */ +/*****************/ + +struct BaseGraphWindow : Window { +protected: + enum { + GRAPH_MAX_DATASETS = 32, + GRAPH_AXIS_LABEL_COLOUR = TC_BLACK, + GRAPH_AXIS_LINE_COLOUR = 215, + + GRAPH_X_POSITION_BEGINNING = 44, ///< Start the graph 44 pixels from gd_left + GRAPH_X_POSITION_SEPARATION = 22, ///< There are 22 pixels between each X value + + GRAPH_NUM_LINES_Y = 9, ///< How many horizontal lines to draw. + /* 9 is convenient as that means the distance between them is the gd_height of the graph / 8, + * which is the same + * as height >> 3. */ + }; + + uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed. + byte num_dataset; + byte num_on_x_axis; + bool has_negative_values; + byte num_vert_lines; + + /* The starting month and year that values are plotted against. If month is + * 0xFF, use x_values_start and x_values_increment below instead. */ + byte month; + Year year; + + /* These values are used if the graph is being plotted against values + * rather than the dates specified by month and year. */ + uint16 x_values_start; + uint16 x_values_increment; + + int gd_left, gd_top; ///< Where to start drawing the graph, in pixels. + uint gd_height; ///< The height of the graph in pixels. + StringID format_str_y_axis; + byte colors[GRAPH_MAX_DATASETS]; + OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][24]; ///< last 2 years + + void DrawGraph() const + { + uint x, y; ///< Reused whenever x and y coordinates are needed. + OverflowSafeInt64 highest_value; ///< Highest value to be drawn. + int x_axis_offset; ///< Distance from the top of the graph to the x axis. + + /* the colors and cost array of GraphDrawer must accomodate + * both values for cargo and players. So if any are higher, quit */ + assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_PLAYERS); + assert(this->num_vert_lines > 0); + + byte grid_colour = _colour_gradient[14][4]; + + /* The coordinates of the opposite edges of the graph. */ + int bottom = this->gd_top + this->gd_height - 1; + int right = this->gd_left + GRAPH_X_POSITION_BEGINNING + this->num_vert_lines * GRAPH_X_POSITION_SEPARATION - 1; + + /* Draw the vertical grid lines. */ + + /* Don't draw the first line, as that's where the axis will be. */ + x = this->gd_left + GRAPH_X_POSITION_BEGINNING + GRAPH_X_POSITION_SEPARATION; + + for (int i = 0; i < this->num_vert_lines; i++) { + GfxFillRect(x, this->gd_top, x, bottom, grid_colour); + x += GRAPH_X_POSITION_SEPARATION; + } + + /* Draw the horizontal grid lines. */ + x = this->gd_left + GRAPH_X_POSITION_BEGINNING; + y = this->gd_height + this->gd_top; + + for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) { + GfxFillRect(x, y, right, y, grid_colour); + y -= (this->gd_height / (GRAPH_NUM_LINES_Y - 1)); + } + + /* Draw the y axis. */ + GfxFillRect(x, this->gd_top, x, bottom, GRAPH_AXIS_LINE_COLOUR); + + /* Find the distance from the gd_top of the graph to the x axis. */ + x_axis_offset = this->gd_height; + + /* The graph is currently symmetrical about the x axis. */ + if (this->has_negative_values) x_axis_offset /= 2; + + /* Draw the x axis. */ + y = x_axis_offset + this->gd_top; + GfxFillRect(x, y, right, y, GRAPH_AXIS_LINE_COLOUR); + + /* Find the largest value that will be drawn. */ + if (this->num_on_x_axis == 0) + return; + + assert(this->num_on_x_axis > 0); + assert(this->num_dataset > 0); + + /* Start of with a value of twice the gd_height of the graph in pixels. It's a + * bit arbitrary, but it makes the cargo payment graph look a little nicer, + * and prevents division by zero when calculating where the datapoint + * should be drawn. */ + highest_value = x_axis_offset * 2; + + for (int i = 0; i < this->num_dataset; i++) { + if (!HasBit(this->excluded_data, i)) { + for (int j = 0; j < this->num_on_x_axis; j++) { + OverflowSafeInt64 datapoint = this->cost[i][j]; + + if (datapoint != INVALID_DATAPOINT) { + /* For now, if the graph has negative values the scaling is + * symmetrical about the x axis, so take the absolute value + * of each data point. */ + highest_value = max(highest_value, abs(datapoint)); + } + } + } + } + + /* Round up highest_value so that it will divide cleanly into the number of + * axis labels used. */ + int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1); + if (round_val != 0) highest_value += (GRAPH_NUM_LINES_Y - 1 - round_val); + + /* draw text strings on the y axis */ + int64 y_label = highest_value; + int64 y_label_separation = highest_value / (GRAPH_NUM_LINES_Y - 1); + + /* If there are negative values, the graph goes from highest_value to + * -highest_value, not highest_value to 0. */ + if (this->has_negative_values) y_label_separation *= 2; + + x = this->gd_left + GRAPH_X_POSITION_BEGINNING + 1; + y = this->gd_top - 3; + + for (int i = 0; i < GRAPH_NUM_LINES_Y; i++) { + SetDParam(0, this->format_str_y_axis); + SetDParam(1, y_label); + DrawStringRightAligned(x, y, STR_0170, GRAPH_AXIS_LABEL_COLOUR); + + y_label -= y_label_separation; + y += (this->gd_height / (GRAPH_NUM_LINES_Y - 1)); + } + + /* draw strings on the x axis */ + if (this->month != 0xFF) { + x = this->gd_left + GRAPH_X_POSITION_BEGINNING; + y = this->gd_top + this->gd_height + 1; + byte month = this->month; + Year year = this->year; + for (int i = 0; i < this->num_on_x_axis; i++) { + SetDParam(0, month + STR_0162_JAN); + SetDParam(1, month + STR_0162_JAN + 2); + SetDParam(2, year); + DrawString(x, y, month == 0 ? STR_016F : STR_016E, GRAPH_AXIS_LABEL_COLOUR); + + month += 3; + if (month >= 12) { + month = 0; + year++; + } + x += GRAPH_X_POSITION_SEPARATION; + } + } else { + /* Draw the label under the data point rather than on the grid line. */ + x = this->gd_left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2) + 1; + y = this->gd_top + this->gd_height + 1; + uint16 label = this->x_values_start; + + for (int i = 0; i < this->num_on_x_axis; i++) { + SetDParam(0, label); + DrawStringCentered(x, y, STR_01CB, GRAPH_AXIS_LABEL_COLOUR); + + label += this->x_values_increment; + x += GRAPH_X_POSITION_SEPARATION; + } + } + + /* draw lines and dots */ + for (int i = 0; i < this->num_dataset; i++) { + if (!HasBit(this->excluded_data, i)) { + /* Centre the dot between the grid lines. */ + x = this->gd_left + GRAPH_X_POSITION_BEGINNING + (GRAPH_X_POSITION_SEPARATION / 2); + + byte color = this->colors[i]; + uint prev_x = INVALID_DATAPOINT_POS; + uint prev_y = INVALID_DATAPOINT_POS; + + for (int j = 0; j < this->num_on_x_axis; j++) { + OverflowSafeInt64 datapoint = this->cost[i][j]; + + if (datapoint != INVALID_DATAPOINT) { + /* + * Check whether we need to reduce the 'accuracy' of the + * datapoint value and the highest value to splut overflows. + * And when 'drawing' 'one million' or 'one million and one' + * there is no significant difference, so the least + * significant bits can just be removed. + * + * If there are more bits needed than would fit in a 32 bits + * integer, so at about 31 bits because of the sign bit, the + * least significant bits are removed. + */ + int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint)); + int reduce_range = max(mult_range - 31, 0); + + /* Handle negative values differently (don't shift sign) */ + if (datapoint < 0) { + datapoint = -(abs(datapoint) >> reduce_range); + } else { + datapoint >>= reduce_range; + } + + y = this->gd_top + x_axis_offset - (x_axis_offset * datapoint) / (highest_value >> reduce_range); + + /* Draw the point. */ + GfxFillRect(x - 1, y - 1, x + 1, y + 1, color); + + /* Draw the line connected to the previous point. */ + if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, color); + + prev_x = x; + prev_y = y; + } else { + prev_x = INVALID_DATAPOINT_POS; + prev_y = INVALID_DATAPOINT_POS; + } + + x += GRAPH_X_POSITION_SEPARATION; + } + } + } + } + + + BaseGraphWindow(const WindowDesc *desc, WindowNumber window_number, int left, + int top, int height, bool has_negative_values, StringID format_str_y_axis) : + Window(desc, window_number), has_negative_values(has_negative_values), + gd_left(left), gd_top(top), gd_height(height), format_str_y_axis(format_str_y_axis) + { + InvalidateWindow(WC_GRAPH_LEGEND, 0); + } + +public: + virtual void OnPaint() + { + this->DrawWidgets(); + + uint excluded_players = _legend_excluded_players; + + /* Exclude the players which aren't valid */ + const Player* p; + FOR_ALL_PLAYERS(p) { + if (!p->is_active) SetBit(excluded_players, p->index); + } + this->excluded_data = excluded_players; + this->num_vert_lines = 24; + + byte nums = 0; + FOR_ALL_PLAYERS(p) { + if (p->is_active) nums = max(nums, p->num_valid_stat_ent); + } + this->num_on_x_axis = min(nums, 24); + + int mo = (_cur_month / 3 - nums) * 3; + int yr = _cur_year; + while (mo < 0) { + yr--; + mo += 12; + } + + this->year = yr; + this->month = mo; + + int numd = 0; + FOR_ALL_PLAYERS(p) { + if (p->is_active) { + this->colors[numd] = _colour_gradient[p->player_color][6]; + for (int j = this->num_on_x_axis, i = 0; --j >= 0;) { + this->cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : GetGraphData(p, j); + i++; + } + } + numd++; + } + + this->num_dataset = numd; + + this->DrawGraph(); + } + + virtual OverflowSafeInt64 GetGraphData(const Player *p, int j) + { + return INVALID_DATAPOINT; + } + + virtual void OnClick(Point pt, int widget) + { + /* Clicked on legend? */ + if (widget == 2) ShowGraphLegend(); + } +}; + /********************/ /* OPERATING PROFIT */ /********************/ -static void SetupGraphDrawerForPlayers(GraphDrawer *gd) -{ - const Player* p; - uint excluded_players = _legend_excluded_players; - byte nums; - int mo, yr; - - /* Exclude the players which aren't valid */ - FOR_ALL_PLAYERS(p) { - if (!p->is_active) SetBit(excluded_players, p->index); - } - gd->excluded_data = excluded_players; - gd->num_vert_lines = 24; - - nums = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) nums = max(nums, p->num_valid_stat_ent); - } - gd->num_on_x_axis = min(nums, 24); - - mo = (_cur_month / 3 - nums) * 3; - yr = _cur_year; - while (mo < 0) { - yr--; - mo += 12; +struct OperatingProfitGraphWindow : BaseGraphWindow { + OperatingProfitGraphWindow(const WindowDesc *desc, WindowNumber window_number) : + BaseGraphWindow(desc, window_number, 2, 18, 136, true, STR_CURRCOMPACT) + { + this->FindWindowPlacementAndResize(desc); } - gd->year = yr; - gd->month = mo; -} - -static void OperatingProfitWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - GraphDrawer gd; - const Player* p; - - w->DrawWidgets(); - - gd.left = 2; - gd.top = 18; - gd.height = 136; - gd.has_negative_values = true; - gd.format_str_y_axis = STR_CURRCOMPACT; - - SetupGraphDrawerForPlayers(&gd); - - int numd = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - gd.colors[numd] = _colour_gradient[p->player_color][6]; - for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) { - gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : (p->old_economy[j].income + p->old_economy[j].expenses); - i++; - } - } - numd++; - } - - gd.num_dataset = numd; - - DrawGraph(&gd); - break; - } - - case WE_CLICK: - /* Clicked on legend? */ - if (e->we.click.widget == 2) ShowGraphLegend(); - break; + virtual OverflowSafeInt64 GetGraphData(const Player *p, int j) + { + return p->old_economy[j].income + p->old_economy[j].expenses; } -} +}; static const Widget _operating_profit_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -432,15 +441,12 @@ WC_OPERATING_PROFIT, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _operating_profit_widgets, - OperatingProfitWndProc }; void ShowOperatingProfitGraph() { - if (AllocateWindowDescFront(&_operating_profit_desc, 0)) { - InvalidateWindow(WC_GRAPH_LEGEND, 0); - } + AllocateWindowDescFront(&_operating_profit_desc, 0); } @@ -448,45 +454,18 @@ /* INCOME GRAPH */ /****************/ -static void IncomeGraphWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - GraphDrawer gd; - const Player* p; - - w->DrawWidgets(); - - gd.left = 2; - gd.top = 18; - gd.height = 104; - gd.has_negative_values = false; - gd.format_str_y_axis = STR_CURRCOMPACT; - SetupGraphDrawerForPlayers(&gd); +struct IncomeGraphWindow : BaseGraphWindow { + IncomeGraphWindow(const WindowDesc *desc, WindowNumber window_number) : + BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_CURRCOMPACT) + { + this->FindWindowPlacementAndResize(desc); + } - int numd = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - gd.colors[numd] = _colour_gradient[p->player_color][6]; - for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) { - gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : p->old_economy[j].income; - i++; - } - } - numd++; - } - - gd.num_dataset = numd; - - DrawGraph(&gd); - break; - } - - case WE_CLICK: - if (e->we.click.widget == 2) ShowGraphLegend(); - break; + virtual OverflowSafeInt64 GetGraphData(const Player *p, int j) + { + return p->old_economy[j].income; } -} +}; static const Widget _income_graph_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -501,59 +480,29 @@ WC_INCOME_GRAPH, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _income_graph_widgets, - IncomeGraphWndProc }; void ShowIncomeGraph() { - if (AllocateWindowDescFront(&_income_graph_desc, 0)) { - InvalidateWindow(WC_GRAPH_LEGEND, 0); - } + AllocateWindowDescFront(&_income_graph_desc, 0); } /*******************/ /* DELIVERED CARGO */ /*******************/ -static void DeliveredCargoGraphWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - GraphDrawer gd; - const Player* p; - - w->DrawWidgets(); - - gd.left = 2; - gd.top = 18; - gd.height = 104; - gd.has_negative_values = false; - gd.format_str_y_axis = STR_7024; - SetupGraphDrawerForPlayers(&gd); +struct DeliveredCargoGraphWindow : BaseGraphWindow { + DeliveredCargoGraphWindow(const WindowDesc *desc, WindowNumber window_number) : + BaseGraphWindow(desc, window_number, 2, 18, 104, false, STR_7024) + { + this->FindWindowPlacementAndResize(desc); + } - int numd = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - gd.colors[numd] = _colour_gradient[p->player_color][6]; - for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) { - gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : (OverflowSafeInt64)p->old_economy[j].delivered_cargo; - i++; - } - } - numd++; - } - - gd.num_dataset = numd; - - DrawGraph(&gd); - break; - } - - case WE_CLICK: - if (e->we.click.widget == 2) ShowGraphLegend(); - break; + virtual OverflowSafeInt64 GetGraphData(const Player *p, int j) + { + return p->old_economy[j].delivered_cargo; } -} +}; static const Widget _delivered_cargo_graph_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -568,60 +517,35 @@ WC_DELIVERED_CARGO, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _delivered_cargo_graph_widgets, - DeliveredCargoGraphWndProc }; void ShowDeliveredCargoGraph() { - if (AllocateWindowDescFront(&_delivered_cargo_graph_desc, 0)) { - InvalidateWindow(WC_GRAPH_LEGEND, 0); - } + AllocateWindowDescFront(&_delivered_cargo_graph_desc, 0); } /***********************/ /* PERFORMANCE HISTORY */ /***********************/ -static void PerformanceHistoryWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - GraphDrawer gd; - const Player* p; - - w->DrawWidgets(); - - gd.left = 2; - gd.top = 18; - gd.height = 200; - gd.has_negative_values = false; - gd.format_str_y_axis = STR_7024; - SetupGraphDrawerForPlayers(&gd); +struct PerformanceHistoryGraphWindow : BaseGraphWindow { + PerformanceHistoryGraphWindow(const WindowDesc *desc, WindowNumber window_number) : + BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_7024) + { + this->FindWindowPlacementAndResize(desc); + } - int numd = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - gd.colors[numd] = _colour_gradient[p->player_color][6]; - for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) { - gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : (OverflowSafeInt64)p->old_economy[j].performance_history; - i++; - } - } - numd++; - } + virtual OverflowSafeInt64 GetGraphData(const Player *p, int j) + { + return p->old_economy[j].performance_history; + } - gd.num_dataset = numd; - - DrawGraph(&gd); - break; - } - - case WE_CLICK: - if (e->we.click.widget == 2) ShowGraphLegend(); - if (e->we.click.widget == 3) ShowPerformanceRatingDetail(); - break; + virtual void OnClick(Point pt, int widget) + { + if (widget == 3) ShowPerformanceRatingDetail(); + this->BaseGraphWindow::OnClick(pt, widget); } -} +}; static const Widget _performance_history_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -637,59 +561,29 @@ WC_PERFORMANCE_HISTORY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _performance_history_widgets, - PerformanceHistoryWndProc }; void ShowPerformanceHistoryGraph() { - if (AllocateWindowDescFront(&_performance_history_desc, 0)) { - InvalidateWindow(WC_GRAPH_LEGEND, 0); - } + AllocateWindowDescFront(&_performance_history_desc, 0); } /*****************/ /* COMPANY VALUE */ /*****************/ -static void CompanyValueGraphWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - GraphDrawer gd; - const Player* p; - - w->DrawWidgets(); - - gd.left = 2; - gd.top = 18; - gd.height = 200; - gd.has_negative_values = false; - gd.format_str_y_axis = STR_CURRCOMPACT; - SetupGraphDrawerForPlayers(&gd); +struct CompanyValueGraphWindow : BaseGraphWindow { + CompanyValueGraphWindow(const WindowDesc *desc, WindowNumber window_number) : + BaseGraphWindow(desc, window_number, 2, 18, 200, false, STR_CURRCOMPACT) + { + this->FindWindowPlacementAndResize(desc); + } - int numd = 0; - FOR_ALL_PLAYERS(p) { - if (p->is_active) { - gd.colors[numd] = _colour_gradient[p->player_color][6]; - for (int j = gd.num_on_x_axis, i = 0; --j >= 0;) { - gd.cost[numd][i] = (j >= p->num_valid_stat_ent) ? INVALID_DATAPOINT : p->old_economy[j].company_value; - i++; - } - } - numd++; - } - - gd.num_dataset = numd; - - DrawGraph(&gd); - break; - } - - case WE_CLICK: - if (e->we.click.widget == 2) ShowGraphLegend(); - break; + virtual OverflowSafeInt64 GetGraphData(const Player *p, int j) + { + return p->old_economy[j].company_value; } -} +}; static const Widget _company_value_graph_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -704,90 +598,117 @@ WC_COMPANY_VALUE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _company_value_graph_widgets, - CompanyValueGraphWndProc }; void ShowCompanyValueGraph() { - if (AllocateWindowDescFront(&_company_value_graph_desc, 0)) { - InvalidateWindow(WC_GRAPH_LEGEND, 0); - } + AllocateWindowDescFront(&_company_value_graph_desc, 0); } /*****************/ /* PAYMENT RATES */ /*****************/ -static void CargoPaymentRatesWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - GraphDrawer gd; - - w->DrawWidgets(); - - int x = 495; - int y = 24; - - gd.excluded_data = _legend_excluded_cargo; - gd.left = 2; - gd.top = 24; - gd.height = w->height - 38; - gd.has_negative_values = false; - gd.format_str_y_axis = STR_CURRCOMPACT; - gd.num_on_x_axis = 20; - gd.num_vert_lines = 20; - gd.month = 0xFF; - gd.x_values_start = 10; - gd.x_values_increment = 10; - - uint i = 0; - for (CargoID c = 0; c < NUM_CARGO; c++) { - const CargoSpec *cs = GetCargo(c); - if (!cs->IsValid()) continue; - - /* Only draw labels for widgets that exist. If the widget doesn't - * exist then the local player has used the climate cheat or - * changed the NewGRF configuration with this window open. */ - if (i + 3 < w->widget_count) { - /* Since the buttons have no text, no images, - * both the text and the colored box have to be manually painted. - * clk_dif will move one pixel down and one pixel to the right - * when the button is clicked */ - byte clk_dif = w->IsWidgetLowered(i + 3) ? 1 : 0; - - GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0); - GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour); - SetDParam(0, cs->name); - DrawString(x + 14 + clk_dif, y + clk_dif, STR_7065, TC_FROMSTRING); - y += 8; - } - - gd.colors[i] = cs->legend_colour; - for (uint j = 0; j != 20; j++) { - gd.cost[i][j] = GetTransportedGoodsIncome(10, 20, j * 6 + 6, c); - } - - i++; - } - gd.num_dataset = i; - - DrawGraph(&gd); - - DrawString(2 + 46, 24 + gd.height + 7, STR_7062_DAYS_IN_TRANSIT, TC_FROMSTRING); - DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, TC_FROMSTRING); - break; +struct PaymentRatesGraphWindow : BaseGraphWindow { + PaymentRatesGraphWindow(const WindowDesc *desc, WindowNumber window_number) : + BaseGraphWindow(desc, window_number, 2, 24, 200, false, STR_CURRCOMPACT) + { + uint num_active = 0; + for (CargoID c = 0; c < NUM_CARGO; c++) { + if (GetCargo(c)->IsValid()) num_active++; } - case WE_CLICK: - if (e->we.click.widget >= 3) { - ToggleBit(_legend_excluded_cargo, e->we.click.widget - 3); - w->ToggleWidgetLoweredState(e->we.click.widget); - w->SetDirty(); + /* Resize the window to fit the cargo types */ + ResizeWindow(this, 0, max(num_active, 12U) * 8); + + /* Add widgets for each cargo type */ + this->widget_count += num_active; + this->widget = ReallocT(this->widget, this->widget_count + 1); + this->widget[this->widget_count].type = WWT_LAST; + + /* Set the properties of each widget */ + for (uint i = 0; i != num_active; i++) { + Widget *wi = &this->widget[3 + i]; + wi->type = WWT_PANEL; + wi->display_flags = RESIZE_NONE; + wi->color = 12; + wi->left = 493; + wi->right = 562; + wi->top = 24 + i * 8; + wi->bottom = wi->top + 7; + wi->data = 0; + wi->tooltips = STR_7064_TOGGLE_GRAPH_FOR_CARGO; + + if (!HasBit(_legend_excluded_cargo, i)) this->LowerWidget(i + 3); + } + + this->SetDirty(); + + this->gd_height = this->height - 38; + this->num_on_x_axis = 20; + this->num_vert_lines = 20; + this->month = 0xFF; + this->x_values_start = 10; + this->x_values_increment = 10; + + this->FindWindowPlacementAndResize(desc); + } + + virtual void OnPaint() + { + this->DrawWidgets(); + + this->excluded_data = _legend_excluded_cargo; + + int x = 495; + int y = 24; + + uint i = 0; + for (CargoID c = 0; c < NUM_CARGO; c++) { + const CargoSpec *cs = GetCargo(c); + if (!cs->IsValid()) continue; + + /* Only draw labels for widgets that exist. If the widget doesn't + * exist then the local player has used the climate cheat or + * changed the NewGRF configuration with this window open. */ + if (i + 3 < this->widget_count) { + /* Since the buttons have no text, no images, + * both the text and the colored box have to be manually painted. + * clk_dif will move one pixel down and one pixel to the right + * when the button is clicked */ + byte clk_dif = this->IsWidgetLowered(i + 3) ? 1 : 0; + + GfxFillRect(x + clk_dif, y + clk_dif, x + 8 + clk_dif, y + 5 + clk_dif, 0); + GfxFillRect(x + 1 + clk_dif, y + 1 + clk_dif, x + 7 + clk_dif, y + 4 + clk_dif, cs->legend_colour); + SetDParam(0, cs->name); + DrawString(x + 14 + clk_dif, y + clk_dif, STR_7065, TC_FROMSTRING); + y += 8; } - break; + + this->colors[i] = cs->legend_colour; + for (uint j = 0; j != 20; j++) { + this->cost[i][j] = GetTransportedGoodsIncome(10, 20, j * 6 + 6, c); + } + + i++; + } + this->num_dataset = i; + + this->DrawGraph(); + + DrawString(2 + 46, 24 + this->gd_height + 7, STR_7062_DAYS_IN_TRANSIT, TC_FROMSTRING); + DrawString(2 + 84, 24 - 9, STR_7063_PAYMENT_FOR_DELIVERING, TC_FROMSTRING); } -} + + virtual void OnClick(Point pt, int widget) + { + if (widget >= 3) { + ToggleBit(_legend_excluded_cargo, widget - 3); + this->ToggleWidgetLoweredState(widget); + this->SetDirty(); + } + } +}; static const Widget _cargo_payment_rates_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -801,46 +722,12 @@ WC_PAYMENT_RATES, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _cargo_payment_rates_widgets, - CargoPaymentRatesWndProc }; void ShowCargoPaymentRates() { - Window *w = AllocateWindowDescFront(&_cargo_payment_rates_desc, 0); - if (w == NULL) return; - - /* Count the number of active cargo types */ - uint num_active = 0; - for (CargoID c = 0; c < NUM_CARGO; c++) { - if (GetCargo(c)->IsValid()) num_active++; - } - - /* Resize the window to fit the cargo types */ - ResizeWindow(w, 0, max(num_active, 12U) * 8); - - /* Add widgets for each cargo type */ - w->widget_count += num_active; - w->widget = ReallocT(w->widget, w->widget_count + 1); - w->widget[w->widget_count].type = WWT_LAST; - - /* Set the properties of each widget */ - for (uint i = 0; i != num_active; i++) { - Widget *wi = &w->widget[3 + i]; - wi->type = WWT_PANEL; - wi->display_flags = RESIZE_NONE; - wi->color = 12; - wi->left = 493; - wi->right = 562; - wi->top = 24 + i * 8; - wi->bottom = wi->top + 7; - wi->data = 0; - wi->tooltips = STR_7064_TOGGLE_GRAPH_FOR_CARGO; - - if (!HasBit(_legend_excluded_cargo, i)) w->LowerWidget(i + 3); - } - - w->SetDirty(); + AllocateWindowDescFront(&_cargo_payment_rates_desc, 0); } /************************/ @@ -879,35 +766,36 @@ return p2->old_economy[1].performance_history - p1->old_economy[1].performance_history; } -static void CompanyLeagueWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - const Player* plist[MAX_PLAYERS]; - const Player* p; - - w->DrawWidgets(); - - uint pl_num = 0; - FOR_ALL_PLAYERS(p) if (p->is_active) plist[pl_num++] = p; +struct CompanyLeagueWindow : Window { + CompanyLeagueWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + } - qsort((void*)plist, pl_num, sizeof(*plist), PerfHistComp); + virtual void OnPaint() + { + const Player *plist[MAX_PLAYERS]; + const Player *p; - for (uint i = 0; i != pl_num; i++) { - p = plist[i]; - SetDParam(0, i + STR_01AC_1ST); - SetDParam(1, p->index); - SetDParam(2, p->index); - SetDParam(3, GetPerformanceTitleFromValue(p->old_economy[1].performance_history)); + this->DrawWidgets(); - DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING); - DrawPlayerIcon(p->index, 27, 16 + i * 10); - } + uint pl_num = 0; + FOR_ALL_PLAYERS(p) if (p->is_active) plist[pl_num++] = p; - break; + qsort((void*)plist, pl_num, sizeof(*plist), PerfHistComp); + + for (uint i = 0; i != pl_num; i++) { + p = plist[i]; + SetDParam(0, i + STR_01AC_1ST); + SetDParam(1, p->index); + SetDParam(2, p->index); + SetDParam(3, GetPerformanceTitleFromValue(p->old_economy[1].performance_history)); + + DrawString(2, 15 + i * 10, i == 0 ? STR_7054 : STR_7055, TC_FROMSTRING); + DrawPlayerIcon(p->index, 27, 16 + i * 10); } } -} +}; static const Widget _company_league_widgets[] = { @@ -923,12 +811,11 @@ WC_COMPANY_LEAGUE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _company_league_widgets, - CompanyLeagueWndProc }; void ShowCompanyLeagueTable() { - AllocateWindowDescFront(&_company_league_desc, 0); + AllocateWindowDescFront(&_company_league_desc, 0); } /*****************************/ @@ -949,7 +836,8 @@ this->UpdatePlayerStats(); if (player != INVALID_PLAYER) this->LowerWidget(player + 13); - this->SetDirty(); + + this->FindWindowPlacementAndResize(desc); } void UpdatePlayerStats() @@ -1154,7 +1042,6 @@ WC_PERFORMANCE_DETAIL, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _performance_rating_detail_widgets, - NULL }; void ShowPerformanceRatingDetail() diff -r 68a692eacf22 -r 67db0d431d5e src/group_gui.cpp --- a/src/group_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/group_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -30,70 +30,6 @@ typedef GUIList GUIGroupList; -static void BuildGroupList(GUIGroupList *gl, PlayerID owner, VehicleType vehicle_type) -{ - uint n = 0; - - if (!(gl->flags & VL_REBUILD)) return; - - const Group **list = MallocT(GetGroupArraySize()); - - const Group *g; - FOR_ALL_GROUPS(g) { - if (g->owner == owner && g->vehicle_type == vehicle_type) list[n++] = g; - } - - gl->sort_list = ReallocT(gl->sort_list, n); - gl->list_length = n; - - for (uint i = 0; i < n; ++i) gl->sort_list[i] = list[i]; - free(list); - - gl->flags &= ~VL_REBUILD; - gl->flags |= VL_RESORT; -} - - -static int CDECL GroupNameSorter(const void *a, const void *b) -{ - static const Group *last_group[2] = { NULL, NULL }; - static char last_name[2][64] = { "", "" }; - - const Group *ga = *(const Group**)a; - const Group *gb = *(const Group**)b; - int r; - - if (ga != last_group[0]) { - last_group[0] = ga; - SetDParam(0, ga->index); - GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0])); - } - - if (gb != last_group[1]) { - last_group[1] = gb; - SetDParam(0, gb->index); - GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1])); - } - - r = strcmp(last_name[0], last_name[1]); // sort by name - - if (r == 0) return ga->index - gb->index; - - return r; -} - - -static void SortGroupList(GUIGroupList *gl) -{ - if (!(gl->flags & VL_RESORT)) return; - - qsort((void*)gl->sort_list, gl->list_length, sizeof(gl->sort_list[0]), GroupNameSorter); - - gl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; - gl->flags &= ~VL_RESORT; -} - - enum GroupListWidgets { GRP_WIDGET_CLOSEBOX = 0, GRP_WIDGET_CAPTION, @@ -182,11 +118,58 @@ }; -struct VehicleGroupWindow : public Window, public VehicleListBase { +class VehicleGroupWindow : public Window, public VehicleListBase { +private: GroupID group_sel; VehicleID vehicle_sel; GUIGroupList groups; + /** + * (Re)Build the group list. + * + * @param owner The owner of the window + */ + void BuildGroupList(PlayerID owner) + { + if (!this->groups.NeedRebuild()) return; + + this->groups.Clear(); + + const Group *g; + FOR_ALL_GROUPS(g) { + if (g->owner == owner && g->vehicle_type == this->vehicle_type) { + *this->groups.Append() = g; + } + } + + this->groups.Compact(); + this->groups.RebuildDone(); + } + + /** Sort the groups by their name */ + static int CDECL GroupNameSorter(const Group* const *a, const Group* const *b) + { + static const Group *last_group[2] = { NULL, NULL }; + static char last_name[2][64] = { "", "" }; + + if (*a != last_group[0]) { + last_group[0] = *a; + SetDParam(0, (*a)->index); + GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0])); + } + + if (*b != last_group[1]) { + last_group[1] = *b; + SetDParam(0, (*b)->index); + GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1])); + } + + int r = strcmp(last_name[0], last_name[1]); // sort by name + if (r == 0) return (*a)->index - (*b)->index; + return r; + } + +public: VehicleGroupWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) { const PlayerID owner = (PlayerID)GB(this->window_number, 0, 8); @@ -223,14 +206,12 @@ case VEH_AIRCRAFT: this->sorting = &_sorting.aircraft; break; } - this->vehicles.sort_list = NULL; this->vehicles.sort_type = this->sorting->criteria; this->vehicles.flags = VL_REBUILD | (this->sorting->order ? VL_DESC : VL_NONE); this->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer - this->groups.sort_list = NULL; - this->groups.flags = VL_REBUILD | VL_NONE; - this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; // Set up resort timer + this->groups.ForceRebuild(); + this->groups.NeedResort(); this->group_sel = ALL_GROUP; this->vehicle_sel = INVALID_VEHICLE; @@ -280,14 +261,18 @@ ~VehicleGroupWindow() { - free((void*)this->vehicles.sort_list); - free((void*)this->groups.sort_list); } virtual void OnInvalidateData(int data) { - this->vehicles.flags |= VL_REBUILD; - this->groups.flags |= VL_REBUILD; + this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT); + + if (data == 0) { + this->groups.ForceRebuild(); + } else { + this->groups.ForceResort(); + } + if (!(IsAllGroupID(this->group_sel) || IsDefaultGroupID(this->group_sel) || IsValidGroupID(this->group_sel))) { this->group_sel = ALL_GROUP; HideDropDownMenu(this); @@ -309,21 +294,20 @@ BuildVehicleList(this, owner, this->group_sel, IsAllGroupID(this->group_sel) ? VLW_STANDARD : VLW_GROUP_LIST); SortVehicleList(this); + this->BuildGroupList(owner); + this->groups.Sort(&GroupNameSorter); - BuildGroupList(&this->groups, owner, this->vehicle_type); - SortGroupList(&this->groups); - - SetVScrollCount(this, this->groups.list_length); - SetVScroll2Count(this, this->vehicles.list_length); + SetVScrollCount(this, this->groups.Length()); + SetVScroll2Count(this, this->vehicles.Length()); /* The drop down menu is out, *but* it may not be used, retract it. */ - if (this->vehicles.list_length == 0 && this->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) { + if (this->vehicles.Length() == 0 && this->IsWidgetLowered(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN)) { this->RaiseWidget(GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN); HideDropDownMenu(this); } /* Disable all lists management button when the list is empty */ - this->SetWidgetsDisabledState(this->vehicles.list_length == 0 || _local_player != owner, + this->SetWidgetsDisabledState(this->vehicles.Length() == 0 || _local_player != owner, GRP_WIDGET_STOP_ALL, GRP_WIDGET_START_ALL, GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN, @@ -352,7 +336,7 @@ We list all vehicles or ungrouped vehicles */ if (IsDefaultGroupID(this->group_sel) || IsAllGroupID(this->group_sel)) { SetDParam(0, owner); - SetDParam(1, this->vehicles.list_length); + SetDParam(1, this->vehicles.Length()); switch (this->vehicle_type) { case VEH_TRAIN: @@ -434,9 +418,9 @@ DrawString(10, y1, str_no_group_veh, IsDefaultGroupID(this->group_sel) ? TC_WHITE : TC_BLACK); - max = min(this->vscroll.pos + this->vscroll.cap, this->groups.list_length); + max = min(this->vscroll.pos + this->vscroll.cap, this->groups.Length()); for (i = this->vscroll.pos ; i < max ; ++i) { - const Group *g = this->groups.sort_list[i]; + const Group *g = this->groups[i]; assert(g->owner == owner); @@ -454,9 +438,9 @@ this->DrawSortButtonState(GRP_WIDGET_SORT_BY_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP); /* Draw Matrix Vehicle according to the vehicle list built before */ - max = min(this->vscroll2.pos + this->vscroll2.cap, this->vehicles.list_length); + max = min(this->vscroll2.pos + this->vscroll2.cap, this->vehicles.Length()); for (i = this->vscroll2.pos ; i < max ; ++i) { - const Vehicle* v = this->vehicles.sort_list[i]; + const Vehicle* v = this->vehicles[i]; assert(v->type == this->vehicle_type && v->owner == owner); @@ -521,9 +505,9 @@ id_g += this->vscroll.pos; - if (id_g >= this->groups.list_length) return; + if (id_g >= this->groups.Length()) return; - this->group_sel = this->groups.sort_list[id_g]->index;; + this->group_sel = this->groups[id_g]->index;; this->vehicles.flags |= VL_REBUILD; this->SetDirty(); @@ -538,9 +522,9 @@ id_v += this->vscroll2.pos; - if (id_v >= this->vehicles.list_length) return; // click out of list bound + if (id_v >= this->vehicles.Length()) return; // click out of list bound - v = this->vehicles.sort_list[id_v]; + v = this->vehicles[id_v]; this->vehicle_sel = v->index; @@ -628,9 +612,9 @@ id_g += this->vscroll.pos; - if (id_g >= this->groups.list_length) return; + if (id_g >= this->groups.Length()) return; - DoCommandP(0, this->groups.sort_list[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE)); + DoCommandP(0, this->groups[id_g]->index, vindex, NULL, CMD_ADD_VEHICLE_GROUP | CMD_MSG(STR_GROUP_CAN_T_ADD_VEHICLE)); break; } @@ -648,9 +632,9 @@ id_v += this->vscroll2.pos; - if (id_v >= this->vehicles.list_length) return; // click out of list bound + if (id_v >= this->vehicles.Length()) return; // click out of list bound - v = this->vehicles.sort_list[id_v]; + v = this->vehicles[id_v]; if (vindex == v->index) { ShowVehicleViewWindow(v); @@ -693,7 +677,7 @@ break; case GRP_WIDGET_MANAGE_VEHICLES_DROPDOWN: - assert(this->vehicles.list_length != 0); + assert(this->vehicles.Length() != 0); switch (index) { case GALF_REPLACE: // Replace window @@ -736,9 +720,7 @@ this->vehicles.flags |= VL_RESORT; this->SetDirty(); } - if (--this->groups.resort_timer == 0) { - this->groups.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; - this->groups.flags |= VL_RESORT; + if (this->groups.NeedResort()) { this->SetDirty(); } } @@ -757,7 +739,6 @@ WC_TRAINS_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _group_widgets, - NULL }; void ShowPlayerGroup(PlayerID player, VehicleType vehicle_type) diff -r 68a692eacf22 -r 67db0d431d5e src/heightmap.cpp --- a/src/heightmap.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/heightmap.cpp Tue May 27 00:50:55 2008 +0000 @@ -297,7 +297,7 @@ TileIndex tile; /* Get map size and calculate scale and padding values */ - switch (_patches.heightmap_rotation) { + switch (_settings.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: width = MapSizeX(); @@ -322,7 +322,7 @@ /* Form the landscape */ for (row = 0; row < height - 1; row++) { for (col = 0; col < width - 1; col++) { - switch (_patches.heightmap_rotation) { + switch (_settings.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break; case HM_CLOCKWISE: tile = TileXY(row, col); break; @@ -337,7 +337,7 @@ /* Use nearest neighbor resizing to scale map data. * We rotate the map 45 degrees (counter)clockwise */ img_row = (((row - row_pad) * num_div) / img_scale); - switch (_patches.heightmap_rotation) { + switch (_settings.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: img_col = (((width - 1 - col - col_pad) * num_div) / img_scale); diff -r 68a692eacf22 -r 67db0d431d5e src/industry.h --- a/src/industry.h Mon May 26 20:45:25 2008 +0000 +++ b/src/industry.h Tue May 27 00:50:55 2008 +0000 @@ -354,9 +354,6 @@ #define FOR_ALL_INDUSTRIES_FROM(i, start) for (i = GetIndustry(start); i != NULL; i = (i->index + 1U < GetIndustryPoolSize()) ? GetIndustry(i->index + 1U) : NULL) if (i->IsValid()) #define FOR_ALL_INDUSTRIES(i) FOR_ALL_INDUSTRIES_FROM(i, 0) -extern const Industry **_industry_sort; -extern bool _industry_sort_dirty; - static const uint8 IT_INVALID = 255; #endif /* INDUSTRY_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/industry_cmd.cpp --- a/src/industry_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/industry_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -55,9 +55,6 @@ int _total_industries; //general counter uint16 _industry_counts[NUM_INDUSTRYTYPES]; // Number of industries per type ingame -const Industry **_industry_sort; -bool _industry_sort_dirty; - IndustrySpec _industry_specs[NUM_INDUSTRYTYPES]; IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES]; @@ -73,7 +70,7 @@ /* once performed, enable only the current climate industries */ for (IndustryType i = 0; i < NUM_INDUSTRYTYPES; i++) { _industry_specs[i].enabled = i < NEW_INDUSTRYOFFSET && - HasBit(_origin_industry_specs[i].climate_availability, _opt.landscape); + HasBit(_origin_industry_specs[i].climate_availability, _settings.game_creation.landscape); } memset(&_industry_tile_specs, 0, sizeof(_industry_tile_specs)); @@ -87,7 +84,7 @@ void ResetIndustryCreationProbility(IndustryType type) { assert(type < INVALID_INDUSTRYTYPE); - _industry_specs[type].appear_creation[_opt.landscape] = 0; + _industry_specs[type].appear_creation[_settings.game_creation.landscape] = 0; } DEFINE_OLD_POOL_GENERIC(Industry, Industry) @@ -168,12 +165,11 @@ } END_TILE_LOOP(tile_cur, 42, 42, this->xy - TileDiff(21, 21)) } - _industry_sort_dirty = true; DecIndustryTypeCount(this->type); DeleteSubsidyWithIndustry(this->index); DeleteWindowById(WC_INDUSTRY_VIEW, this->index); - InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); + InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0); this->xy = 0; } @@ -381,7 +377,7 @@ { const Industry *i = GetIndustryByTile(tile); - td->owner = i->owner; + td->owner[0] = i->owner; td->str = GetIndustrySpec(i->type)->name; if (!IsIndustryCompleted(tile)) { SetDParamX(td->dparam, 0, td->str); @@ -892,14 +888,14 @@ uint field_type; int type; - if (_opt.landscape == LT_ARCTIC) { + if (_settings.game_creation.landscape == LT_ARCTIC) { if (GetTileZ(tile) + TILE_HEIGHT * 2 >= GetSnowLine()) return; } /* determine field size */ r = (Random() & 0x303) + 0x404; - if (_opt.landscape == LT_ARCTIC) r += 0x404; + if (_settings.game_creation.landscape == LT_ARCTIC) r += 0x404; size_x = GB(r, 0, 8); size_y = GB(r, 8, 8); @@ -930,7 +926,7 @@ END_TILE_LOOP(cur_tile, size_x, size_y, tile) type = 3; - if (_opt.landscape != LT_ARCTIC && _opt.landscape != LT_TROPIC) { + if (_settings.game_creation.landscape != LT_ARCTIC && _settings.game_creation.landscape != LT_TROPIC) { type = _plantfarmfield_type[Random() & 0xF]; } @@ -1067,7 +1063,7 @@ static bool CheckNewIndustry_Forest(TileIndex tile) { - if (_opt.landscape == LT_ARCTIC) { + if (_settings.game_creation.landscape == LT_ARCTIC) { if (GetTileZ(tile) < HighestSnowLine() + TILE_HEIGHT * 2U) { _error_message = STR_4831_FOREST_CAN_ONLY_BE_PLANTED; return false; @@ -1079,7 +1075,7 @@ static bool CheckNewIndustry_OilRefinery(TileIndex tile) { if (_game_mode == GM_EDITOR) return true; - if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true; + if (DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings.game_creation.oil_refinery_limit) return true; _error_message = STR_483B_CAN_ONLY_BE_POSITIONED; return false; @@ -1091,7 +1087,7 @@ { if (_game_mode == GM_EDITOR && _ignore_restrictions) return true; if (TileHeight(tile) == 0 && - DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _patches.oil_refinery_limit) return true; + DistanceFromEdge(TILE_ADDXY(tile, 1, 1)) < _settings.game_creation.oil_refinery_limit) return true; _error_message = STR_483B_CAN_ONLY_BE_POSITIONED; return false; @@ -1099,7 +1095,7 @@ static bool CheckNewIndustry_Farm(TileIndex tile) { - if (_opt.landscape == LT_ARCTIC) { + if (_settings.game_creation.landscape == LT_ARCTIC) { if (GetTileZ(tile) + TILE_HEIGHT * 2 >= HighestSnowLine()) { _error_message = STR_0239_SITE_UNSUITABLE; return false; @@ -1175,7 +1171,7 @@ t = ClosestTownFromTile(tile, (uint)-1); - if (_patches.multiple_industry_per_town) return t; + if (_settings.economy.multiple_industry_per_town) return t; FOR_ALL_INDUSTRIES(i) { if (i->type == (byte)type && @@ -1261,7 +1257,7 @@ /* It is almost impossible to have a fully flat land in TG, so what we * do is that we check if we can make the land flat later on. See * CheckIfCanLevelIndustryPlatform(). */ - return !refused_slope || (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions); + return !refused_slope || (_settings.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !custom_shape && !_ignore_restrictions); } static bool CheckIfIndustryIsAllowed(TileIndex tile, int type, const Town *t) @@ -1391,7 +1387,7 @@ const IndustrySpec *indspec = GetIndustrySpec(type); const Industry *i; - if (_patches.same_industry_close && indspec->IsRawIndustry()) + if (_settings.economy.same_industry_close && indspec->IsRawIndustry()) /* Allow primary industries to be placed close to any other industry */ return true; @@ -1405,8 +1401,8 @@ indspec->accepts_cargo[0] == i->accepts_cargo[0] && ( /* at least one of those options must be true */ _game_mode != GM_EDITOR || // editor must not be stopped - !_patches.same_industry_close || - !_patches.multiple_industry_per_town)) { + !_settings.economy.same_industry_close || + !_settings.economy.multiple_industry_per_town)) { _error_message = STR_INDUSTRY_TOO_CLOSE; return false; } @@ -1453,7 +1449,7 @@ i->production_rate[1] = indspec->production_rate[1]; /* don't use smooth economy for industries using production related callbacks */ - if (_patches.smooth_economy && + if (_settings.economy.smooth_economy && !(HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_256_TICKS) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks !(HasBit(indspec->callback_flags, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CHANGE)) // production change callbacks ) { @@ -1556,8 +1552,7 @@ if (GetIndustrySpec(i->type)->behaviour & INDUSTRYBEH_PLANT_ON_BUILT) { for (j = 0; j != 50; j++) PlantRandomFarmField(i); } - _industry_sort_dirty = true; - InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); + InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 0); } /** Helper function for Build/Fund an industry @@ -1582,7 +1577,7 @@ if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL; } - if (!custom_shape_check && _patches.land_generator == LG_TERRAGENESIS && _generating_world && !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL; + if (!custom_shape_check && _settings.game_creation.land_generator == LG_TERRAGENESIS && _generating_world && !_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL; if (!CheckIfFarEnoughFromIndustry(tile, type)) return NULL; const Town *t = CheckMultipleIndustryInTown(tile, type); @@ -1626,11 +1621,11 @@ /* If the patch for raw-material industries is not on, you cannot build raw-material industries. * Raw material industries are industries that do not accept cargo (at least for now) */ - if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 0 && indspec->IsRawIndustry()) { + if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) { return CMD_ERROR; } - if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indspec->IsRawIndustry()) { + if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && indspec->IsRawIndustry()) { if (flags & DC_EXEC) { /* Prospecting has a chance to fail, however we cannot guarantee that something can * be built on the map, so the chance gets lower when the map is fuller, but there @@ -1705,13 +1700,13 @@ { /* We need to bypass the amount given in parameter if it exceeds the maximum dimension of the * _numof_industry_table. newgrf can specify a big amount */ - int num = (amount > NB_NUMOFINDUSTRY) ? amount : _numof_industry_table[_opt.diff.number_industries][amount]; + int num = (amount > NB_NUMOFINDUSTRY) ? amount : _numof_industry_table[_settings.difficulty.number_industries][amount]; const IndustrySpec *ind_spc = GetIndustrySpec(type); /* These are always placed next to the coastline, so we scale by the perimeter instead. */ num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); - if (_opt.diff.number_industries != 0) { + if (_settings.difficulty.number_industries != 0) { PlayerID old_player = _current_player; _current_player = OWNER_NONE; assert(num > 0); @@ -1740,7 +1735,7 @@ const IndustrySpec *ind_spc; /* Find the total amount of industries */ - if (_opt.diff.number_industries > 0) { + if (_settings.difficulty.number_industries > 0) { for (it = 0; it < NUM_INDUSTRYTYPES; it++) { ind_spc = GetIndustrySpec(it); @@ -1749,12 +1744,12 @@ ResetIndustryCreationProbility(it); } - chance = ind_spc->appear_creation[_opt.landscape]; + chance = ind_spc->appear_creation[_settings.game_creation.landscape]; if (ind_spc->enabled && chance > 0) { /* once the chance of appearance is determind, it have to be scaled by * the difficulty level. The "chance" in question is more an index into * the _numof_industry_table,in fact */ - int num = (chance > NB_NUMOFINDUSTRY) ? chance : _numof_industry_table[_opt.diff.number_industries][chance]; + int num = (chance > NB_NUMOFINDUSTRY) ? chance : _numof_industry_table[_settings.difficulty.number_industries][chance]; /* These are always placed next to the coastline, so we scale by the perimeter instead. */ num = (ind_spc->check_proc == CHECK_REFINERY || ind_spc->check_proc == CHECK_OIL_RIG) ? ScaleByMapSize1D(num) : ScaleByMapSize(num); @@ -1765,7 +1760,7 @@ SetGeneratingWorldProgress(GWP_INDUSTRY, i); - if (_opt.diff.number_industries > 0) { + if (_settings.difficulty.number_industries > 0) { for (it = 0; it < NUM_INDUSTRYTYPES; it++) { /* Once the number of industries has been determined, let's really create them. * The test for chance allows us to try create industries that are available only @@ -1774,7 +1769,7 @@ * processed that scaling above? No, don't think so. Will find a way. */ ind_spc = GetIndustrySpec(it); if (ind_spc->enabled) { - chance = ind_spc->appear_creation[_opt.landscape]; + chance = ind_spc->appear_creation[_settings.game_creation.landscape]; if (chance > 0) PlaceInitialIndustry(it, chance); } } @@ -1828,7 +1823,7 @@ /* Generate a list of all possible industries that can be built. */ for (j = 0; j < NUM_INDUSTRYTYPES; j++) { ind_spc = GetIndustrySpec(j); - byte chance = ind_spc->appear_ingame[_opt.landscape]; + byte chance = ind_spc->appear_ingame[_settings.game_creation.landscape]; if (!ind_spc->enabled || chance == 0) continue; @@ -1886,7 +1881,7 @@ const IndustrySpec *indspec = GetIndustrySpec(type); /* oil wells (or the industries with that flag set) are always allowed to closedown */ - if (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD && _opt.landscape == LT_TEMPERATE) return false; + if (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD && _settings.game_creation.landscape == LT_TEMPERATE) return false; return (indspec->behaviour & INDUSTRYBEH_CANCLOSE_LASTINSTANCE) == 0 && GetIndustryTypeCount(type) <= 1; } @@ -1958,10 +1953,9 @@ bool c_accepts = false; bool c_produces = false; if (v->type == VEH_TRAIN && IsFrontEngine(v)) { - const Vehicle *u = v; - BEGIN_ENUM_WAGONS(u) + for (const Vehicle *u = v; u != NULL; u = u->Next()) { CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces); - END_ENUM_WAGONS(u) + } } else if (v->type == VEH_ROAD || v->type == VEH_SHIP || v->type == VEH_AIRCRAFT) { CanCargoServiceIndustry(v->cargo_type, ind, &c_accepts, &c_produces); } else { @@ -2037,7 +2031,7 @@ bool standard = true; bool suppress_message = false; /* don't use smooth economy for industries using production related callbacks */ - bool smooth_economy = _patches.smooth_economy && + bool smooth_economy = _settings.economy.smooth_economy && !(HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_256_TICKS) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks !(HasBit(indspec->callback_flags, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(indspec->callback_flags, CBM_IND_PRODUCTION_CHANGE)); // production change callbacks byte div = 0; @@ -2078,7 +2072,7 @@ if (standard && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) { /* decrease or increase */ - bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE; + bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings.game_creation.landscape == LT_TEMPERATE; if (smooth_economy) { closeit = true; @@ -2240,8 +2234,7 @@ _current_player = old_player; /* production-change */ - _industry_sort_dirty = true; - InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0); + InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, 1); } @@ -2251,7 +2244,6 @@ _Industry_pool.AddBlockToPool(); ResetIndustryCounts(); - _industry_sort_dirty = true; _industry_sound_tile = 0; } @@ -2265,7 +2257,7 @@ Money IndustrySpec::GetConstructionCost() const { return (_price.build_industry * - (_patches.raw_industry_construction == 1 && this->IsRawIndustry() ? + (_settings.construction.raw_industry_construction == 1 && this->IsRawIndustry() ? this->raw_industry_cost_multiplier : this->cost_multiplier )) >> 8; diff -r 68a692eacf22 -r 67db0d431d5e src/industry_gui.cpp --- a/src/industry_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/industry_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -26,6 +26,7 @@ #include "settings_type.h" #include "tilehighlight_func.h" #include "string_func.h" +#include "sortlist_type.h" #include "table/strings.h" #include "table/sprites.h" @@ -90,7 +91,6 @@ WC_BUILD_INDUSTRY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE, _build_industry_widgets, - NULL, }; class BuildIndustryWindow : public Window { @@ -131,7 +131,7 @@ /* Rule is that editor mode loads all industries. * In game mode, all non raw industries are loaded too * and raw ones are loaded only when setting allows it */ - if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _patches.raw_industry_construction == 0) { + if (_game_mode != GM_EDITOR && indsp->IsRawIndustry() && _settings.construction.raw_industry_construction == 0) { /* Unselect if the industry is no longer in the list */ if (this->selected_type == ind) this->selected_index = -1; continue; @@ -195,10 +195,10 @@ * In Editor, you just build, while ingame, or you fund or you prospect */ if (_game_mode == GM_EDITOR) { /* We've chosen many random industries but no industries have been specified */ - if (indsp == NULL) this->enabled[this->selected_index] = _opt.diff.number_industries != 0; + if (indsp == NULL) this->enabled[this->selected_index] = _settings.difficulty.number_industries != 0; this->widget[DPIW_FUND_WIDGET].data = STR_BUILD_NEW_INDUSTRY; } else { - this->widget[DPIW_FUND_WIDGET].data = (_patches.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY; + this->widget[DPIW_FUND_WIDGET].data = (_settings.construction.raw_industry_construction == 2 && indsp->IsRawIndustry()) ? STR_PROSPECT_NEW_INDUSTRY : STR_FUND_NEW_INDUSTRY; } this->SetWidgetDisabledState(DPIW_FUND_WIDGET, !this->enabled[this->selected_index]); @@ -304,7 +304,7 @@ this->SetDirty(); - if ((_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) || + if ((_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && indsp != NULL && indsp->IsRawIndustry()) || this->selected_type == INVALID_INDUSTRYTYPE) { /* Reset the button state if going to prospecting or "build many industries" */ this->RaiseButtons(); @@ -325,7 +325,7 @@ GenerateIndustries(); _generating_world = false; } - } else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) { + } else if (_game_mode != GM_EDITOR && _settings.construction.raw_industry_construction == 2 && GetIndustrySpec(this->selected_type)->IsRawIndustry()) { DoCommandP(0, this->selected_type, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY)); this->HandleButtonClick(DPIW_FUND_WIDGET); } else { @@ -679,7 +679,6 @@ WC_INDUSTRY_VIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _industry_view_widgets, - NULL }; void ShowIndustryViewWindow(int industry) @@ -697,7 +696,7 @@ IDW_SORTBYPROD, IDW_SORTBYTRANSPORT, IDW_SPACER, - IDW_INDUSRTY_LIST, + IDW_INDUSTRY_LIST, IDW_SCROLLBAR, IDW_RESIZE, }; @@ -718,12 +717,37 @@ { WIDGETS_END}, }; -static uint _num_industry_sort; - static char _bufcache[96]; static const Industry* _last_industry; +static int _internal_sort_order; -static byte _industry_sort_order; +/** Returns percents of cargo transported if industry produces this cargo, else -1 + * @param i industry to check + * @param id cargo slot + * @return percents of cargo transported, or -1 if industry doesn't use this cargo slot + */ +static inline int GetCargoTransportedPercentsIfValid(const Industry *i, uint id) +{ + assert(id < lengthof(i->produced_cargo)); + + if (i->produced_cargo[id] == CT_INVALID) return 101; + return i->last_month_pct_transported[id] * 100 >> 8; +} + +/** Returns value representing industry's transported cargo + * percentage for industry sorting + * @param i industry to check + * @return value used for sorting + */ +static int GetCargoTransportedSortValue(const Industry *i) +{ + int p1 = GetCargoTransportedPercentsIfValid(i, 0); + int p2 = GetCargoTransportedPercentsIfValid(i, 1); + + if (p1 > p2) Swap(p1, p2); // lower value has higher priority + + return (p1 << 8) + p2; +} static int CDECL GeneralIndustrySorter(const void *a, const void *b) { @@ -731,7 +755,7 @@ const Industry* j = *(const Industry**)b; int r; - switch (_industry_sort_order >> 1) { + switch (_internal_sort_order >> 1) { default: NOT_REACHED(); case 0: /* Sort by Name (handled later) */ r = 0; @@ -756,30 +780,7 @@ break; case 3: /* Sort by transported fraction */ - if (i->produced_cargo[0] == CT_INVALID) { - r = (j->produced_cargo[0] == CT_INVALID ? 0 : -1); - } else { - if (j->produced_cargo[0] == CT_INVALID) { - r = 1; - } else { - int pi; - int pj; - - pi = i->last_month_pct_transported[0] * 100 >> 8; - if (i->produced_cargo[1] != CT_INVALID) { - int p = i->last_month_pct_transported[1] * 100 >> 8; - if (p < pi) pi = p; - } - - pj = j->last_month_pct_transported[0] * 100 >> 8; - if (j->produced_cargo[1] != CT_INVALID) { - int p = j->last_month_pct_transported[1] * 100 >> 8; - if (p < pj) pj = p; - } - - r = pi - pj; - } - } + r = GetCargoTransportedSortValue(i) - GetCargoTransportedSortValue(j); break; } @@ -798,138 +799,164 @@ r = strcmp(buf1, _bufcache); } - if (_industry_sort_order & 1) r = -r; + if (_internal_sort_order & 1) r = -r; return r; } +typedef GUIList GUIIndustryList; + /** - * Makes a sorted industry list. - * When there are no industries, the list has to be made. This so when one - * starts a new game without industries after playing a game with industries - * the list is not populated with invalid industries from the previous game. + * Rebuild industries list if the VL_REBUILD flag is set + * + * @param sl pointer to industry list */ -static void MakeSortedIndustryList() +static void BuildIndustriesList(GUIIndustryList *sl) { - const Industry* i; - int n = 0; + if (!(sl->flags & VL_REBUILD)) return; - /* Create array for sorting */ - _industry_sort = ReallocT(_industry_sort, GetMaxIndustryIndex() + 1); + sl->Clear(); - /* Don't attempt a sort if there are no industries */ - if (GetNumIndustries() != 0) { - FOR_ALL_INDUSTRIES(i) _industry_sort[n++] = i; - qsort((void*)_industry_sort, n, sizeof(_industry_sort[0]), GeneralIndustrySorter); + DEBUG(misc, 3, "Building industry list"); + + const Industry *i; + FOR_ALL_INDUSTRIES(i) { + *sl->Append() = i; } - _num_industry_sort = n; - _last_industry = NULL; // used for "cache" + sl->Compact(); - DEBUG(misc, 3, "Resorting industries list"); + sl->flags &= ~VL_REBUILD; + sl->flags |= VL_RESORT; } -static void IndustryDirectoryWndProc(Window *w, WindowEvent *e) +/** + * Sort industry list if the VL_RESORT flag is set + * + * @param sl pointer to industry list + */ +static void SortIndustriesList(GUIIndustryList *sl) { - switch (e->event) { - case WE_PAINT: { - if (_industry_sort_dirty) { - _industry_sort_dirty = false; - MakeSortedIndustryList(); + if (!(sl->flags & VL_RESORT)) return; + + _internal_sort_order = (sl->sort_type << 1) | (sl->flags & VL_DESC); + _last_industry = NULL; // used for "cache" in namesorting + qsort((void*)sl->Begin(), sl->Length(), sizeof(sl->Begin()), &GeneralIndustrySorter); + + sl->flags &= ~VL_RESORT; +} + +/** + * The list of industries. + */ +struct IndustryDirectoryWindow : public Window, public GUIIndustryList { + static Listing industry_sort; + + IndustryDirectoryWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number) + { + this->vscroll.cap = 16; + this->resize.height = this->height - 6 * 10; // minimum 10 items + this->resize.step_height = 10; + this->FindWindowPlacementAndResize(desc); + + this->flags = VL_REBUILD; + this->sort_type = industry_sort.criteria; + if (industry_sort.order) this->flags |= VL_DESC; + } + + virtual void OnPaint() + { + BuildIndustriesList(this); + SortIndustriesList(this); + + SetVScrollCount(this, this->Length()); + + this->DrawWidgets(); + this->DrawSortButtonState(IDW_SORTBYNAME + this->sort_type, this->flags & VL_DESC ? SBS_DOWN : SBS_UP); + + int max = min(this->vscroll.pos + this->vscroll.cap, this->Length()); + int y = 28; // start of the list-widget + + for (int n = this->vscroll.pos; n < max; ++n) { + const Industry* i = *this->Get(n); + const IndustrySpec *indsp = GetIndustrySpec(i->type); + byte p = 0; + + /* Industry name */ + SetDParam(p++, i->index); + + /* Industry productions */ + for (byte j = 0; j < lengthof(i->produced_cargo); j++) { + if (i->produced_cargo[j] == CT_INVALID) continue; + SetDParam(p++, i->produced_cargo[j]); + SetDParam(p++, i->last_month_production[j]); + SetDParam(p++, GetCargoSuffix(j + 3, CST_DIR, (Industry*)i, i->type, indsp)); } - SetVScrollCount(w, _num_industry_sort); - - w->DrawWidgets(); - w->DrawSortButtonState(IDW_SORTBYNAME + (_industry_sort_order >> 1), _industry_sort_order & 1 ? SBS_DOWN : SBS_UP); - - uint pos = w->vscroll.pos; - int n = 0; - - while (pos < _num_industry_sort) { - const Industry* i = _industry_sort[pos]; - const IndustrySpec *indsp = GetIndustrySpec(i->type); - byte p = 0; - - /* Industry name */ - SetDParam(p++, i->index); - - /* Industry productions */ - for (byte j = 0; j < lengthof(i->produced_cargo); j++) { - if (i->produced_cargo[j] == CT_INVALID) continue; - SetDParam(p++, i->produced_cargo[j]); - SetDParam(p++, i->last_month_production[j]); - SetDParam(p++, GetCargoSuffix(j + 3, CST_DIR, (Industry*)i, i->type, indsp)); - } - - /* Transported productions */ - for (byte j = 0; j < lengthof(i->produced_cargo); j++) { - if (i->produced_cargo[j] == CT_INVALID) continue; - SetDParam(p++, i->last_month_pct_transported[j] * 100 >> 8); - } - - /* Drawing the right string */ - StringID str = STR_INDUSTRYDIR_ITEM_NOPROD; - if (p != 1) str = (p == 5) ? STR_INDUSTRYDIR_ITEM : STR_INDUSTRYDIR_ITEM_TWO; - DrawStringTruncated(4, 28 + n * 10, str, TC_FROMSTRING, w->widget[IDW_INDUSRTY_LIST].right - 4); - - pos++; - if (++n == w->vscroll.cap) break; + /* Transported productions */ + for (byte j = 0; j < lengthof(i->produced_cargo); j++) { + if (i->produced_cargo[j] == CT_INVALID) continue; + SetDParam(p++, i->last_month_pct_transported[j] * 100 >> 8); } - } break; - case WE_CLICK: - switch (e->we.click.widget) { - case IDW_SORTBYNAME: { - _industry_sort_order = _industry_sort_order == 0 ? 1 : 0; - _industry_sort_dirty = true; - w->SetDirty(); - } break; - - case IDW_SORTBYTYPE: { - _industry_sort_order = _industry_sort_order == 2 ? 3 : 2; - _industry_sort_dirty = true; - w->SetDirty(); - } break; - - case IDW_SORTBYPROD: { - _industry_sort_order = _industry_sort_order == 4 ? 5 : 4; - _industry_sort_dirty = true; - w->SetDirty(); - } break; - - case IDW_SORTBYTRANSPORT: { - _industry_sort_order = _industry_sort_order == 6 ? 7 : 6; - _industry_sort_dirty = true; - w->SetDirty(); - } break; + /* Drawing the right string */ + StringID str = STR_INDUSTRYDIR_ITEM_NOPROD; + if (p != 1) str = (p == 5) ? STR_INDUSTRYDIR_ITEM : STR_INDUSTRYDIR_ITEM_TWO; + DrawStringTruncated(4, y, str, TC_FROMSTRING, this->widget[IDW_INDUSTRY_LIST].right - 4); - case IDW_INDUSRTY_LIST: { - int y = (e->we.click.pt.y - 28) / 10; - uint16 p; + y += 10; + } + } - if (!IsInsideMM(y, 0, w->vscroll.cap)) return; - p = y + w->vscroll.pos; - if (p < _num_industry_sort) { - if (_ctrl_pressed) { - ShowExtraViewPortWindow(_industry_sort[p]->xy); - } else { - ScrollMainWindowToTile(_industry_sort[p]->xy); - } + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case IDW_SORTBYNAME: + case IDW_SORTBYTYPE: + case IDW_SORTBYPROD: + case IDW_SORTBYTRANSPORT: + if (this->sort_type == (widget - IDW_SORTBYNAME)) { + this->flags ^= VL_DESC; + } else { + this->sort_type = widget - IDW_SORTBYNAME; + this->flags &= ~VL_DESC; + } + industry_sort.criteria = this->sort_type; + industry_sort.order = HasBit(this->flags, 0); + this->flags |= VL_RESORT; + this->SetDirty(); + break; + + case IDW_INDUSTRY_LIST: { + int y = (pt.y - 28) / 10; + uint16 p; + + if (!IsInsideMM(y, 0, this->vscroll.cap)) return; + p = y + this->vscroll.pos; + if (p < this->Length()) { + if (_ctrl_pressed) { + ShowExtraViewPortWindow((*this->Get(p))->xy); + } else { + ScrollMainWindowToTile((*this->Get(p))->xy); } - } break; - } - break; + } + } break; + } + } - case WE_100_TICKS: - w->SetDirty(); - break; + virtual void OnResize(Point new_size, Point delta) + { + this->vscroll.cap += delta.y / 10; + } - case WE_RESIZE: - w->vscroll.cap += e->we.sizing.diff.y / 10; - break; + virtual void OnInvalidateData(int data) + { + this->flags |= (data == 0 ? VL_REBUILD : VL_RESORT); + this->InvalidateWidget(IDW_INDUSTRY_LIST); } -} +}; + +Listing IndustryDirectoryWindow::industry_sort = {0, 0}; /** Window definition of the industy directory gui */ static const WindowDesc _industry_directory_desc = { @@ -937,17 +964,9 @@ WC_INDUSTRY_DIRECTORY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _industry_directory_widgets, - IndustryDirectoryWndProc }; void ShowIndustryDirectory() { - Window *w = AllocateWindowDescFront(&_industry_directory_desc, 0); - - if (w != NULL) { - w->vscroll.cap = 16; - w->resize.height = w->height - 6 * 10; // minimum 10 items - w->resize.step_height = 10; - w->SetDirty(); - } + AllocateWindowDescFront(&_industry_directory_desc, 0); } diff -r 68a692eacf22 -r 67db0d431d5e src/intro_gui.cpp --- a/src/intro_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/intro_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -49,91 +49,95 @@ static inline void SetNewLandscapeType(byte landscape) { - _opt_newgame.landscape = landscape; + _settings_newgame.game_creation.landscape = landscape; InvalidateWindowClasses(WC_SELECT_GAME); } -enum SelectGameIntroWidgets { - SGI_GENERATE_GAME = 2, - SGI_LOAD_GAME, - SGI_PLAY_SCENARIO, - SGI_PLAY_HEIGHTMAP, - SGI_EDIT_SCENARIO, - SGI_PLAY_NETWORK, - SGI_TEMPERATE_LANDSCAPE, - SGI_ARCTIC_LANDSCAPE, - SGI_TROPIC_LANDSCAPE, - SGI_TOYLAND_LANDSCAPE, - SGI_OPTIONS, - SGI_DIFFICULTIES, - SGI_PATCHES_OPTIONS, - SGI_GRF_SETTINGS, - SGI_EXIT, -}; +struct SelectGameWindow : public Window { +private: + enum SelectGameIntroWidgets { + SGI_GENERATE_GAME = 2, + SGI_LOAD_GAME, + SGI_PLAY_SCENARIO, + SGI_PLAY_HEIGHTMAP, + SGI_EDIT_SCENARIO, + SGI_PLAY_NETWORK, + SGI_TEMPERATE_LANDSCAPE, + SGI_ARCTIC_LANDSCAPE, + SGI_TROPIC_LANDSCAPE, + SGI_TOYLAND_LANDSCAPE, + SGI_OPTIONS, + SGI_DIFFICULTIES, + SGI_PATCHES_OPTIONS, + SGI_GRF_SETTINGS, + SGI_EXIT, + }; -static void SelectGameWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: w->LowerWidget(_opt_newgame.landscape + 8); break; +public: + SelectGameWindow(const WindowDesc *desc) : Window(desc) + { + this->LowerWidget(_settings_newgame.game_creation.landscape + SGI_TEMPERATE_LANDSCAPE); + this->FindWindowPlacementAndResize(desc); + } - case WE_PAINT: - w->SetWidgetLoweredState(SGI_TEMPERATE_LANDSCAPE, _opt_newgame.landscape == LT_TEMPERATE); - w->SetWidgetLoweredState(SGI_ARCTIC_LANDSCAPE, _opt_newgame.landscape == LT_ARCTIC); - w->SetWidgetLoweredState(SGI_TROPIC_LANDSCAPE, _opt_newgame.landscape == LT_TROPIC); - w->SetWidgetLoweredState(SGI_TOYLAND_LANDSCAPE, _opt_newgame.landscape == LT_TOYLAND); - SetDParam(0, STR_6801_EASY + _opt_newgame.diff_level); - w->DrawWidgets(); - break; + virtual void OnPaint() + { + this->SetWidgetLoweredState(SGI_TEMPERATE_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_TEMPERATE); + this->SetWidgetLoweredState(SGI_ARCTIC_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_ARCTIC); + this->SetWidgetLoweredState(SGI_TROPIC_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_TROPIC); + this->SetWidgetLoweredState(SGI_TOYLAND_LANDSCAPE, _settings_newgame.game_creation.landscape == LT_TOYLAND); + SetDParam(0, STR_6801_EASY + _settings_newgame.difficulty.diff_level); + this->DrawWidgets(); + } - case WE_CLICK: + virtual void OnClick(Point pt, int widget) + { #ifdef ENABLE_NETWORK - /* Do not create a network server when you (just) have closed one of the game - * creation/load windows for the network server. */ - if (SGI_GENERATE_GAME <= e->we.click.widget && e->we.click.widget <= SGI_EDIT_SCENARIO) _is_network_server = false; + /* Do not create a network server when you (just) have closed one of the game + * creation/load windows for the network server. */ + if (IsInsideMM(widget, SGI_GENERATE_GAME, SGI_EDIT_SCENARIO + 1)) _is_network_server = false; #endif /* ENABLE_NETWORK */ - switch (e->we.click.widget) { - case SGI_GENERATE_GAME: ShowGenerateLandscape(); break; - case SGI_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break; - case SGI_PLAY_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break; - case SGI_PLAY_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break; - case SGI_EDIT_SCENARIO: StartScenarioEditor(); break; - - case SGI_PLAY_NETWORK: - if (!_network_available) { - ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0); - } else { - ShowNetworkGameWindow(); - } - break; + switch (widget) { + case SGI_GENERATE_GAME: ShowGenerateLandscape(); break; + case SGI_LOAD_GAME: ShowSaveLoadDialog(SLD_LOAD_GAME); break; + case SGI_PLAY_SCENARIO: ShowSaveLoadDialog(SLD_LOAD_SCENARIO); break; + case SGI_PLAY_HEIGHTMAP: ShowSaveLoadDialog(SLD_LOAD_HEIGHTMAP); break; + case SGI_EDIT_SCENARIO: StartScenarioEditor(); break; - case SGI_TEMPERATE_LANDSCAPE: case SGI_ARCTIC_LANDSCAPE: - case SGI_TROPIC_LANDSCAPE: case SGI_TOYLAND_LANDSCAPE: - w->RaiseWidget(_opt_newgame.landscape + SGI_TEMPERATE_LANDSCAPE); - SetNewLandscapeType(e->we.click.widget - SGI_TEMPERATE_LANDSCAPE); - break; + case SGI_PLAY_NETWORK: + if (!_network_available) { + ShowErrorMessage(INVALID_STRING_ID, STR_NETWORK_ERR_NOTAVAILABLE, 0, 0); + } else { + ShowNetworkGameWindow(); + } + break; - case SGI_OPTIONS: ShowGameOptions(); break; - case SGI_DIFFICULTIES: ShowGameDifficulty(); break; - case SGI_PATCHES_OPTIONS: ShowPatchesSelection(); break; - case SGI_GRF_SETTINGS: ShowNewGRFSettings(true, true, false, &_grfconfig_newgame); break; - case SGI_EXIT: HandleExitGameRequest(); break; - } - break; + case SGI_TEMPERATE_LANDSCAPE: case SGI_ARCTIC_LANDSCAPE: + case SGI_TROPIC_LANDSCAPE: case SGI_TOYLAND_LANDSCAPE: + this->RaiseWidget(_settings_newgame.game_creation.landscape + SGI_TEMPERATE_LANDSCAPE); + SetNewLandscapeType(widget - SGI_TEMPERATE_LANDSCAPE); + break; + + case SGI_OPTIONS: ShowGameOptions(); break; + case SGI_DIFFICULTIES: ShowGameDifficulty(); break; + case SGI_PATCHES_OPTIONS: ShowPatchesSelection(); break; + case SGI_GRF_SETTINGS: ShowNewGRFSettings(true, true, false, &_grfconfig_newgame); break; + case SGI_EXIT: HandleExitGameRequest(); break; + } } -} +}; static const WindowDesc _select_game_desc = { WDP_CENTER, WDP_CENTER, 336, 195, 336, 195, WC_SELECT_GAME, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _select_game_widgets, - SelectGameWndProc }; void ShowSelectGameWindow() { - new Window(&_select_game_desc); + new SelectGameWindow(&_select_game_desc); } static void AskExitGameCallback(Window *w, bool confirmed) diff -r 68a692eacf22 -r 67db0d431d5e src/landscape.cpp --- a/src/landscape.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/landscape.cpp Tue May 27 00:50:55 2008 +0000 @@ -526,7 +526,7 @@ */ byte GetSnowLine(void) { - if (_snow_line == NULL) return _opt.snow_line; + if (_snow_line == NULL) return _settings.game_creation.snow_line; YearMonthDay ymd; ConvertDateToYMD(_date, &ymd); @@ -539,7 +539,7 @@ */ byte HighestSnowLine(void) { - return _snow_line == NULL ? _opt.snow_line : _snow_line->highest_value; + return _snow_line == NULL ? _settings.game_creation.snow_line : _snow_line->highest_value; } /** @@ -818,14 +818,14 @@ static const int gwp_desert_amount = 4 + 8; if (mode == GW_HEIGHTMAP) { - SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1); + SetGeneratingWorldProgress(GWP_LANDSCAPE, (_settings.game_creation.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1); LoadHeightmap(_file_to_saveload.name); IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); - } else if (_patches.land_generator == LG_TERRAGENESIS) { - SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3); + } else if (_settings.game_creation.land_generator == LG_TERRAGENESIS) { + SetGeneratingWorldProgress(GWP_LANDSCAPE, (_settings.game_creation.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3); GenerateTerrainPerlin(); } else { - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_ARCTIC: { SetGeneratingWorldProgress(GWP_LANDSCAPE, 2); @@ -872,9 +872,9 @@ uint32 r = Random(); - uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100); + uint i = ScaleByMapSize(GB(r, 0, 7) + (3 - _settings.difficulty.quantity_sea_lakes) * 256 + 100); for (; i != 0; --i) { - GenerateTerrain(_opt.diff.terrain_type, 0); + GenerateTerrain(_settings.difficulty.terrain_type, 0); } IncreaseGeneratingWorldProgress(GWP_LANDSCAPE); } break; @@ -883,7 +883,7 @@ ConvertGroundTilesIntoWaterTiles(); - if (_opt.landscape == LT_TROPIC) CreateDesertOrRainForest(); + if (_settings.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest(); } void OnTick_Town(); diff -r 68a692eacf22 -r 67db0d431d5e src/lang/english.txt --- a/src/lang/english.txt Mon May 26 20:45:25 2008 +0000 +++ b/src/lang/english.txt Tue May 27 00:50:55 2008 +0000 @@ -486,6 +486,9 @@ STR_01A5_COST_TO_CLEAR :{BLACK}Cost to clear: {LTBLUE}{CURRENCY} STR_01A6_N_A :N/A STR_01A7_OWNER :{BLACK}Owner: {LTBLUE}{STRING1} +STR_ROAD_OWNER :{BLACK}Road owner: {LTBLUE}{STRING1} +STR_TRAM_OWNER :{BLACK}Tramway owner: {LTBLUE}{STRING1} +STR_RAIL_OWNER :{BLACK}Railroad owner: {LTBLUE}{STRING1} STR_01A8_LOCAL_AUTHORITY :{BLACK}Local authority: {LTBLUE}{STRING1} STR_01A9_NONE :None STR_01AA_NAME :{BLACK}Name @@ -1714,6 +1717,7 @@ STR_1816_TREE_LINED_ROAD :Tree-lined road STR_1817_ROAD_VEHICLE_DEPOT :Road vehicle depot STR_1818_ROAD_RAIL_LEVEL_CROSSING :Road/rail level crossing +STR_TRAMWAY :Tramway STR_CAN_T_REMOVE_BUS_STATION :{WHITE}Can't remove bus station... STR_CAN_T_REMOVE_TRUCK_STATION :{WHITE}Can't remove lorry station... STR_CAN_T_REMOVE_PASSENGER_TRAM_STATION :{WHITE}Can't remove passenger tram station... @@ -3549,3 +3553,9 @@ STR_OSK_KEYBOARD_LAYOUT :`1234567890-=\qwertyuiop[]asdfghjkl;' zxcvbnm,./ . STR_OSK_KEYBOARD_LAYOUT_CAPS :~!@#$%^&*()_+|QWERTYUIOP{{}}ASDFGHJKL:" ZXCVBNM<>? . ######## + +############ town controlled noise level +STR_CONFIG_PATCHES_NOISE_LEVEL :{LTBLUE}Allow town controlled noise level for airports: {ORANGE}{STRING} +STR_NOISE_IN_TOWN :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA} +STR_STATION_NOISE :{BLACK}Noise generated: {GOLD}{COMMA} +######## diff -r 68a692eacf22 -r 67db0d431d5e src/main_gui.cpp --- a/src/main_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/main_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -13,7 +13,7 @@ #include "viewport_func.h" #include "command_func.h" #include "news_gui.h" -#include "console.h" +#include "console_gui.h" #include "waypoint.h" #include "genworld.h" #include "transparency_gui.h" @@ -48,7 +48,7 @@ void CcGiveMoney(bool success, TileIndex tile, uint32 p1, uint32 p2) { #ifdef ENABLE_NETWORK - if (!success || !_patches.give_money) return; + if (!success || !_settings.economy.give_money) return; char msg[20]; /* Inform the player of this action */ @@ -217,7 +217,7 @@ struct MainWindow : Window { - MainWindow(int width, int height) : Window(0, 0, width, height, NULL, WC_MAIN_WINDOW, NULL) + MainWindow(int width, int height) : Window(0, 0, width, height, WC_MAIN_WINDOW, NULL) { InitializeWindowViewport(this, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT); } @@ -239,34 +239,34 @@ } } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { switch (keycode) { case 'Q' | WKC_CTRL: case 'Q' | WKC_META: HandleExitGameRequest(); - return true; + return ES_HANDLED; } /* Disable all key shortcuts, except quit shortcuts when * generating the world, otherwise they create threading * problem during the generating, resulting in random * assertions that are hard to trigger and debug */ - if (IsGeneratingWorld()) return true; + if (IsGeneratingWorld()) return ES_NOT_HANDLED; if (keycode == WKC_BACKQUOTE) { IConsoleSwitch(); - return false; + return ES_HANDLED; } if (keycode == ('B' | WKC_CTRL)) { extern bool _draw_bounding_boxes; _draw_bounding_boxes = !_draw_bounding_boxes; MarkWholeScreenDirty(); - return false; + return ES_HANDLED; } - if (_game_mode == GM_MENU) return true; + if (_game_mode == GM_MENU) return ES_NOT_HANDLED; switch (keycode) { case 'C': @@ -344,7 +344,7 @@ if (cio == NULL) break; /* Only players actually playing can speak to team. Eg spectators cannot */ - if (_patches.prefer_teamchat && IsValidPlayer(cio->client_playas)) { + if (_settings.gui.prefer_teamchat && IsValidPlayer(cio->client_playas)) { const NetworkClientInfo *ci; FOR_ALL_ACTIVE_CLIENT_INFOS(ci) { if (ci->client_playas == cio->client_playas && ci != cio) { @@ -372,9 +372,9 @@ break; #endif - default: return true; + default: return ES_NOT_HANDLED; } - return false; + return ES_HANDLED; } virtual void OnScroll(Point delta) diff -r 68a692eacf22 -r 67db0d431d5e src/misc.cpp --- a/src/misc.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/misc.cpp Tue May 27 00:50:55 2008 +0000 @@ -27,6 +27,7 @@ #include "core/alloc_type.hpp" #include "animated_tile_func.h" #include "tilehighlight_func.h" +#include "core/bitmath_func.hpp" #include "table/strings.h" #include "table/sprites.h" @@ -66,9 +67,10 @@ _realtime_tick = 0; _date_fract = 0; _cur_tileloop_tile = 0; + _settings = _settings_newgame; if ((mode & IG_DATE_RESET) == IG_DATE_RESET) { - SetDate(ConvertYMDToDate(_patches.starting_year, 0, 1)); + SetDate(ConvertYMDToDate(_settings.game_creation.starting_year, 0, 1)); InitializeOldNames(); } diff -r 68a692eacf22 -r 67db0d431d5e src/misc/smallvec.h --- a/src/misc/smallvec.h Mon May 26 20:45:25 2008 +0000 +++ b/src/misc/smallvec.h Tue May 27 00:50:55 2008 +0000 @@ -1,11 +1,12 @@ /* $Id$ */ -/** @file smallvec.h Simple vector class that allows allocating an item without the need to copy data needlessly. */ +/** @file smallvec.h Simple vector class that allows allocating an item without the need to copy this->data needlessly. */ #ifndef SMALLVEC_H #define SMALLVEC_H -template struct SmallVector { +template +struct SmallVector { T *data; uint items; uint capacity; @@ -14,7 +15,30 @@ ~SmallVector() { - free(data); + free(this->data); + } + + /** + * Remove all items from the list. + */ + void Clear() + { + /* In fact we just reset the item counter avoiding the need to + * probably reallocate the same amount of memory the list was + * previously using. */ + this->items = 0; + } + + /** + * Compact the list down to the smallest block size boundary. + */ + void Compact() + { + uint capacity = Align(this->items, S); + if (capacity >= this->capacity) return; + + this->capacity = capacity; + this->data = ReallocT(this->data, this->capacity); } /** @@ -22,42 +46,60 @@ */ T *Append() { - if (items == capacity) { - capacity += S; - data = ReallocT(data, capacity); + if (this->items == this->capacity) { + this->capacity += S; + this->data = ReallocT(this->data, this->capacity); } - return &data[items++]; + return &this->data[this->items++]; + } + + /** + * Get the number of items in the list. + */ + uint Length() const + { + return this->items; } const T *Begin() const { - return data; + return this->data; } T *Begin() { - return data; + return this->data; } const T *End() const { - return &data[items]; + return &this->data[this->items]; } T *End() { - return &data[items]; + return &this->data[this->items]; } - const T *Get(size_t index) const + const T *Get(uint index) const { - return &data[index]; + return &this->data[index]; } - T *Get(size_t index) + T *Get(uint index) { - return &data[index]; + return &this->data[index]; + } + + const T &operator[](uint index) const + { + return this->data[index]; + } + + T &operator[](uint index) + { + return this->data[index]; } }; diff -r 68a692eacf22 -r 67db0d431d5e src/misc_cmd.cpp --- a/src/misc_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/misc_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -145,7 +145,7 @@ switch (p2) { default: return CMD_ERROR; // Invalid method case 0: // Take some extra loan - loan = (IsHumanPlayer(_current_player) || _patches.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI; + loan = (IsHumanPlayer(_current_player) || _settings.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI; break; case 1: // Take a loan as big as possible loan = _economy.max_loan - p->current_loan; @@ -181,7 +181,7 @@ switch (p2) { default: return CMD_ERROR; // Invalid method case 0: // Pay back one step - loan = min(p->current_loan, (Money)(IsHumanPlayer(_current_player) || _patches.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI); + loan = min(p->current_loan, (Money)(IsHumanPlayer(_current_player) || _settings.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI); break; case 1: // Pay back as much as possible loan = max(min(p->current_loan, p->player_money), (Money)LOAN_INTERVAL); @@ -359,7 +359,7 @@ */ CommandCost CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - if (!_patches.give_money) return CMD_ERROR; + if (!_settings.economy.give_money) return CMD_ERROR; const Player *p = GetPlayer(_current_player); CommandCost amount(EXPENSES_OTHER, min((Money)p1, (Money)20000000LL)); @@ -379,35 +379,3 @@ /* Subtract money from local-player */ return amount; } - -/** Change difficulty level/settings (server-only). - * We cannot really check for valid values of p2 (too much work mostly); stored - * in file 'settings_gui.c' _game_setting_info[]; we'll just trust the server it knows - * what to do and does this correctly - * @param tile unused - * @param flags operation to perform - * @param p1 the difficulty setting being changed. If it is -1, the difficulty level - * itself is changed. The new value is inside p2 - * @param p2 new value for a difficulty setting or difficulty level - */ -CommandCost CmdChangeDifficultyLevel(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) -{ - if (p1 != (uint32)-1L && ((int32)p1 >= GAME_DIFFICULTY_NUM || (int32)p1 < 0)) return CMD_ERROR; - - if (flags & DC_EXEC) { - if (p1 != (uint32)-1L) { - ((GDType*)&_opt_ptr->diff)[p1] = p2; - _opt_ptr->diff_level = 3; // custom difficulty level - } else { - _opt_ptr->diff_level = p2; - } - - /* If we are a network-client, update the difficult setting (if it is open). - * Use this instead of just dirtying the window because we need to load in - * the new difficulty settings */ - if (_networking && !_network_server && FindWindowById(WC_GAME_OPTIONS, 0) != NULL) { - ShowGameDifficulty(); - } - } - return CommandCost(); -} diff -r 68a692eacf22 -r 67db0d431d5e src/misc_gui.cpp --- a/src/misc_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/misc_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -69,34 +69,40 @@ WC_LAND_INFO, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _land_info_widgets, - NULL }; class LandInfoWindow : public Window { enum { - LAND_INFO_LINES = 7, + LAND_INFO_CENTERED_LINES = 9, ///< Up to 9 centered lines + LAND_INFO_MULTICENTER_LINE = LAND_INFO_CENTERED_LINES, ///< One multicenter line + LAND_INFO_LINE_END, + LAND_INFO_LINE_BUFF_SIZE = 512, }; public: - char landinfo_data[LAND_INFO_LINES][LAND_INFO_LINE_BUFF_SIZE]; + char landinfo_data[LAND_INFO_LINE_END][LAND_INFO_LINE_BUFF_SIZE]; virtual void OnPaint() { this->DrawWidgets(); - DoDrawStringCentered(140, 16, this->landinfo_data[0], TC_LIGHT_BLUE); - DoDrawStringCentered(140, 27, this->landinfo_data[1], TC_FROMSTRING); - DoDrawStringCentered(140, 38, this->landinfo_data[2], TC_FROMSTRING); - DoDrawStringCentered(140, 49, this->landinfo_data[3], TC_FROMSTRING); - DoDrawStringCentered(140, 60, this->landinfo_data[4], TC_FROMSTRING); - if (!StrEmpty(this->landinfo_data[5])) DrawStringMultiCenter(140, 76, BindCString(this->landinfo_data[5]), this->width - 4); - if (!StrEmpty(this->landinfo_data[6])) DoDrawStringCentered(140, 71, this->landinfo_data[6], TC_FROMSTRING); + uint y = 16; + for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) { + if (StrEmpty(this->landinfo_data[i])) continue; + + DoDrawStringCentered(140, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING); + y += 11; + } + + y += 5; + + if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) DrawStringMultiCenter(140, y, BindCString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]), this->width - 4); } LandInfoWindow(TileIndex tile) : Window(&_land_info_desc) { Player *p = GetPlayer(IsValidPlayer(_local_player) ? _local_player : PLAYER_FIRST); - Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); + Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority); Money old_money = p->player_money; p->player_money = INT64_MAX; @@ -108,38 +114,81 @@ AcceptedCargo ac; td.build_date = 0; + + /* Most tiles have only one owner, but + * - drivethrough roadstops can be build on town owned roads (up to 2 owners) and + * - roads can have up to four owners (railroad, road, tram, 3rd-roadtype "highway"). + */ + td.owner_type[0] = STR_01A7_OWNER; // At least one owner is displayed, though it might be "N/A". + td.owner_type[1] = STR_NULL; // STR_NULL results in skipping the owner + td.owner_type[2] = STR_NULL; + td.owner_type[3] = STR_NULL; + td.owner[0] = OWNER_NONE; + td.owner[1] = OWNER_NONE; + td.owner[2] = OWNER_NONE; + td.owner[3] = OWNER_NONE; + GetAcceptedCargo(tile, ac); GetTileDesc(tile, &td); - SetDParam(0, td.dparam[0]); - GetString(this->landinfo_data[0], td.str, lastof(this->landinfo_data[0])); + uint line_nr = 0; - SetDParam(0, STR_01A6_N_A); - if (td.owner != OWNER_NONE && td.owner != OWNER_WATER) GetNameOfOwner(td.owner, tile); - GetString(this->landinfo_data[1], STR_01A7_OWNER, lastof(this->landinfo_data[1])); + /* Tiletype */ + SetDParam(0, td.dparam[0]); + GetString(this->landinfo_data[line_nr], td.str, lastof(this->landinfo_data[line_nr])); + line_nr++; + /* Up to four owners */ + for (uint i = 0; i < 4; i++) { + if (td.owner_type[i] == STR_NULL) continue; + + SetDParam(0, STR_01A6_N_A); + if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile); + GetString(this->landinfo_data[line_nr], td.owner_type[i], lastof(this->landinfo_data[line_nr])); + line_nr++; + } + + /* Cost to clear */ StringID str = STR_01A4_COST_TO_CLEAR_N_A; if (CmdSucceeded(costclear)) { SetDParam(0, costclear.GetCost()); str = STR_01A5_COST_TO_CLEAR; } - GetString(this->landinfo_data[2], str, lastof(this->landinfo_data[2])); + GetString(this->landinfo_data[line_nr], str, lastof(this->landinfo_data[line_nr])); + line_nr++; + /* Location */ snprintf(_userstring, lengthof(_userstring), "0x%.4X", tile); SetDParam(0, TileX(tile)); SetDParam(1, TileY(tile)); SetDParam(2, TileHeight(tile)); SetDParam(3, STR_SPEC_USERSTRING); - GetString(this->landinfo_data[3], STR_LANDINFO_COORDS, lastof(this->landinfo_data[3])); + GetString(this->landinfo_data[line_nr], STR_LANDINFO_COORDS, lastof(this->landinfo_data[line_nr])); + line_nr++; + /* Local authority */ SetDParam(0, STR_01A9_NONE); if (t != NULL && t->IsValid()) { SetDParam(0, STR_TOWN); SetDParam(1, t->index); } - GetString(this->landinfo_data[4], STR_01A8_LOCAL_AUTHORITY, lastof(this->landinfo_data[4])); + GetString(this->landinfo_data[line_nr], STR_01A8_LOCAL_AUTHORITY, lastof(this->landinfo_data[line_nr])); + line_nr++; - char *strp = GetString(this->landinfo_data[5], STR_01CE_CARGO_ACCEPTED, lastof(this->landinfo_data[5])); + /* Build date */ + if (td.build_date != 0) { + SetDParam(0, td.build_date); + GetString(this->landinfo_data[line_nr], STR_BUILD_DATE, lastof(this->landinfo_data[line_nr])); + line_nr++; + } + + /* Remaining lines stay empty */ + for (; line_nr < LAND_INFO_CENTERED_LINES; line_nr++) { + this->landinfo_data[line_nr][0] = '\0'; + } + + /* Cargo acceptance is displayed in a extra multiline */ + char *strp = GetString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE], STR_01CE_CARGO_ACCEPTED, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); bool found = false; for (CargoID i = 0; i < NUM_CARGO; ++i) { @@ -155,20 +204,13 @@ if (ac[i] < 8) { SetDParam(0, ac[i]); SetDParam(1, GetCargo(i)->name); - strp = GetString(strp, STR_01D1_8, lastof(this->landinfo_data[5])); + strp = GetString(strp, STR_01D1_8, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); } else { - strp = GetString(strp, GetCargo(i)->name, lastof(this->landinfo_data[5])); + strp = GetString(strp, GetCargo(i)->name, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); } } } - if (!found) this->landinfo_data[5][0] = '\0'; - - if (td.build_date != 0) { - SetDParam(0, td.build_date); - GetString(this->landinfo_data[6], STR_BUILD_DATE, lastof(this->landinfo_data[6])); - } else { - this->landinfo_data[6][0] = '\0'; - } + if (!found) this->landinfo_data[LAND_INFO_MULTICENTER_LINE][0] = '\0'; #if defined(_DEBUG) # define LANDINFOD_LEVEL 0 @@ -219,7 +261,6 @@ WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _about_widgets, - NULL }; struct AboutWindow : public Window { @@ -352,10 +393,10 @@ public: ErrmsgWindow(Point pt, int width, int height, StringID msg1, StringID msg2, const Widget *widget, bool show_player_face) : - Window(pt.x, pt.y, width, height, NULL, WC_ERRMSG, widget), + Window(pt.x, pt.y, width, height, WC_ERRMSG, widget), show_player_face(show_player_face) { - this->duration = _patches.errmsg_duration; + this->duration = _settings.gui.errmsg_duration; CopyOutDParam(this->decode_params, 0, lengthof(this->decode_params)); this->message_1 = msg1; this->message_2 = msg2; @@ -412,11 +453,11 @@ _switch_mode_errorstr = INVALID_STRING_ID; } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - if (keycode != WKC_SPACE) return true; + if (keycode != WKC_SPACE) return ES_NOT_HANDLED; delete this; - return false; + return ES_HANDLED; } }; @@ -424,7 +465,7 @@ { DeleteWindowById(WC_ERRMSG, 0); - if (!_patches.errmsg_duration) return; + if (!_settings.gui.errmsg_duration) return; if (msg_2 == STR_NULL) msg_2 = STR_EMPTY; @@ -532,7 +573,7 @@ TooltipsWindow(int x, int y, int width, int height, const Widget *widget, StringID str, uint paramcount, const uint64 params[]) : - Window(x, y, width, height, NULL, WC_TOOLTIPS, widget) + Window(x, y, width, height, WC_TOOLTIPS, widget) { this->string_id = str; assert(sizeof(this->params[0]) == sizeof(params[0])); @@ -579,7 +620,7 @@ DeleteWindowById(WC_TOOLTIPS, 0); /* We only show measurement tooltips with patch setting on */ - if (str == STR_NULL || (paramcount != 0 && !_patches.measure_tooltip)) return; + if (str == STR_NULL || (paramcount != 0 && !_settings.gui.measure_tooltip)) return; for (uint i = 0; i != paramcount; i++) SetDParam(i, params[i]); char buffer[512]; @@ -883,9 +924,9 @@ return false; } -int QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont) +int QueryString::HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, Window::EventState &state) { - cont = false; + state = Window::ES_HANDLED; switch (keycode) { case WKC_ESC: return 2; @@ -913,7 +954,7 @@ if (IsValidChar(key, this->afilter)) { if (InsertTextBufferChar(&this->text, key)) w->InvalidateWidget(wid); } else { // key wasn't caught. Continue only if standard entry specified - cont = (this->afilter == CS_ALPHANUMERAL); + state = (this->afilter == CS_ALPHANUMERAL) ? Window::ES_HANDLED : Window::ES_NOT_HANDLED; } } @@ -963,9 +1004,9 @@ _cur_dpi = old_dpi; } -int QueryStringBaseWindow::HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont) +int QueryStringBaseWindow::HandleEditBoxKey(int wid, uint16 key, uint16 keycode, EventState &state) { - return this->QueryString::HandleEditBoxKey(this, wid, key, keycode, cont); + return this->QueryString::HandleEditBoxKey(this, wid, key, keycode, state); } void QueryStringBaseWindow::HandleEditBox(int wid) @@ -1038,15 +1079,15 @@ this->HandleEditBox(QUERY_STR_WIDGET_TEXT); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont; - switch (this->HandleEditBoxKey(QUERY_STR_WIDGET_TEXT, key, keycode, cont)) { + EventState state; + switch (this->HandleEditBoxKey(QUERY_STR_WIDGET_TEXT, key, keycode, state)) { case 1: this->OnOk(); // Enter pressed, confirms change /* FALL THROUGH */ case 2: delete this; break; // ESC pressed, closes window, abandons changes } - return cont; + return state; } ~QueryStringWindow() @@ -1074,17 +1115,16 @@ WC_QUERY_STRING, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _query_string_widgets, - NULL }; /** Show a query popup window with a textbox in it. * @param str StringID for the text shown in the textbox * @param caption StringID of text shown in caption of querywindow * @param maxlen maximum length in characters allowed. If bit 12 is set we - * will not check the resulting string against to original string to return success + * will not check the resulting string against to original string to return success * @param maxwidth maximum width in pixels allowed * @param parent pointer to a Window that will handle the events (ok/cancel) of this - * window. If NULL, results are handled by global function HandleOnEditText + * window. If NULL, results are handled by global function HandleOnEditText * @param afilter filters out unwanted character input */ void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, Window *parent, CharSetFilter afilter) { @@ -1124,11 +1164,11 @@ * Window used for asking the user a YES/NO question. */ struct QueryWindow : public Window { - void (*proc)(Window*, bool); ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise - uint64 params[10]; ///< local copy of _decode_parameters - StringID message; ///< message shown for query window + QueryCallbackProc *proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise + uint64 params[10]; ///< local copy of _decode_parameters + StringID message; ///< message shown for query window - QueryWindow(const WindowDesc *desc, StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool)) : Window(desc) + QueryWindow(const WindowDesc *desc, StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) : Window(desc) { if (parent == NULL) parent = FindWindowById(WC_MAIN_WINDOW, 0); this->parent = parent; @@ -1162,19 +1202,24 @@ virtual void OnClick(Point pt, int widget) { switch (widget) { - case QUERY_WIDGET_YES: - if (this->proc != NULL) { - this->proc(this->parent, true); - this->proc = NULL; + case QUERY_WIDGET_YES: { + /* in the Generate New World window, clicking 'Yes' causes + * DeleteNonVitalWindows() to be called - we shouldn't be in a window then */ + QueryCallbackProc *proc = this->proc; + Window *parent = this->parent; + delete this; + if (proc != NULL) { + proc(parent, true); + proc = NULL; } - /* Fallthrough */ + } break; case QUERY_WIDGET_NO: delete this; break; } } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { /* ESC closes the window, Enter confirms the action */ switch (keycode) { @@ -1187,9 +1232,9 @@ /* Fallthrough */ case WKC_ESC: delete this; - return false; + return ES_HANDLED; } - return true; + return ES_NOT_HANDLED; } }; @@ -1208,7 +1253,6 @@ WC_CONFIRM_POPUP_QUERY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_DEF_WIDGET | WDF_MODAL, _query_widgets, - NULL }; /** Show a modal confirmation window with standard 'yes' and 'no' buttons @@ -1219,7 +1263,7 @@ * @param parent pointer to parent window, if this pointer is NULL the parent becomes * the main window WC_MAIN_WINDOW * @param callback callback function pointer to set in the window descriptor*/ -void ShowQuery(StringID caption, StringID message, Window *parent, void (*callback)(Window*, bool)) +void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) { new QueryWindow(&_query_desc, caption, message, parent, callback); } @@ -1523,20 +1567,20 @@ } } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { if (keycode == WKC_ESC) { delete this; - return false; + return ES_HANDLED; } - bool cont = true; + EventState state = ES_NOT_HANDLED; if ((_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) && - this->HandleEditBoxKey(10, key, keycode, cont) == 1) { // Press Enter + this->HandleEditBoxKey(10, key, keycode, state) == 1) { // Press Enter this->HandleButtonClick(12); } - return cont; + return state; } virtual void OnTimeout() @@ -1589,7 +1633,6 @@ WC_SAVELOAD, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _load_dialog_widgets, - NULL, }; static const WindowDesc _save_dialog_desc = { @@ -1597,7 +1640,6 @@ WC_SAVELOAD, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _save_dialog_widgets, - NULL, }; /** These values are used to convert the file/operations mode into a corresponding file type. diff -r 68a692eacf22 -r 67db0d431d5e src/music_gui.cpp --- a/src/music_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/music_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -193,18 +193,40 @@ } } -static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { +struct MusicTrackSelectionWindow : public Window { +private: + enum MusicTrackSelectionWidgets { + MTSW_CLOSE, + MTSW_CAPTION, + MTSW_BACKGROUND, + MTSW_LIST_LEFT, + MTSW_LIST_RIGHT, + MTSW_ALL, + MTSW_OLD, + MTSW_NEW, + MTSW_EZY, + MTSW_CUSTOM1, + MTSW_CUSTOM2, + MTSW_CLEAR, + MTSW_SAVE, + }; + +public: + MusicTrackSelectionWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number) + { + this->FindWindowPlacementAndResize(desc); + } + + virtual void OnPaint() + { const byte* p; uint i; int y; - w->SetWidgetDisabledState(11, msf.playlist <= 3); - w->LowerWidget(3); - w->LowerWidget(4); - w->DrawWidgets(); + this->SetWidgetDisabledState(MTSW_CLEAR, msf.playlist <= 3); + this->LowerWidget(MTSW_LIST_LEFT); + this->LowerWidget(MTSW_LIST_RIGHT); + this->DrawWidgets(); GfxFillRect(3, 23, 3 + 177, 23 + 191, 0); GfxFillRect(251, 23, 251 + 177, 23 + 191, 0); @@ -238,88 +260,88 @@ DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, TC_FROMSTRING); y += 6; } - break; } - case WE_CLICK: - switch (e->we.click.widget) { - case 3: { // add to playlist - int y = (e->we.click.pt.y - 23) / 6; - uint i; - byte *p; - - if (msf.playlist < 4) return; - if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return; + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case MTSW_LIST_LEFT: { // add to playlist + int y = (pt.y - 23) / 6; + uint i; + byte *p; - p = _playlists[msf.playlist]; - for (i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) { - if (p[i] == 0) { - p[i] = y + 1; - p[i + 1] = 0; - w->SetDirty(); - SelectSongToPlay(); - break; + if (msf.playlist < 4) return; + if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return; + + p = _playlists[msf.playlist]; + for (i = 0; i != NUM_SONGS_PLAYLIST - 1; i++) { + if (p[i] == 0) { + p[i] = y + 1; + p[i + 1] = 0; + this->SetDirty(); + SelectSongToPlay(); + break; + } } - } - } break; + } break; - case 4: { // remove from playlist - int y = (e->we.click.pt.y - 23) / 6; - uint i; - byte *p; + case MTSW_LIST_RIGHT: { // remove from playlist + int y = (pt.y - 23) / 6; + uint i; + byte *p; - if (msf.playlist < 4) return; - if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return; + if (msf.playlist < 4) return; + if (!IsInsideMM(y, 0, NUM_SONGS_AVAILABLE)) return; - p = _playlists[msf.playlist]; - for (i = y; i != NUM_SONGS_PLAYLIST - 1; i++) { - p[i] = p[i + 1]; + p = _playlists[msf.playlist]; + for (i = y; i != NUM_SONGS_PLAYLIST - 1; i++) { + p[i] = p[i + 1]; } - w->SetDirty(); - SelectSongToPlay(); - } break; + this->SetDirty(); + SelectSongToPlay(); + } break; - case 11: // clear - _playlists[msf.playlist][0] = 0; - w->SetDirty(); - StopMusic(); - SelectSongToPlay(); - break; + case MTSW_CLEAR: // clear + _playlists[msf.playlist][0] = 0; + this->SetDirty(); + StopMusic(); + SelectSongToPlay(); + break; #if 0 - case 12: // save - ShowInfo("MusicTrackSelectionWndProc:save not implemented"); - break; + case MTSW_SAVE: // save + ShowInfo("MusicTrackSelectionWndProc:save not implemented"); + break; #endif - case 5: case 6: case 7: case 8: case 9: case 10: /* set playlist */ - msf.playlist = e->we.click.widget - 5; - w->SetDirty(); - InvalidateWindow(WC_MUSIC_WINDOW, 0); - StopMusic(); - SelectSongToPlay(); - break; + case MTSW_ALL: case MTSW_OLD: case MTSW_NEW: + case MTSW_EZY: case MTSW_CUSTOM1: case MTSW_CUSTOM2: // set playlist + msf.playlist = widget - MTSW_ALL; + this->SetDirty(); + InvalidateWindow(WC_MUSIC_WINDOW, 0); + StopMusic(); + SelectSongToPlay(); + break; } - break; } -} +}; static const Widget _music_track_selection_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 14, 11, 431, 0, 13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PANEL, RESIZE_NONE, 14, 0, 431, 14, 217, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 14, 2, 181, 22, 215, 0x0, STR_01FA_CLICK_ON_MUSIC_TRACK_TO}, -{ WWT_PANEL, RESIZE_NONE, 14, 250, 429, 22, 215, 0x0, STR_CLICK_ON_TRACK_TO_REMOVE}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 44, 51, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 52, 59, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 60, 67, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 68, 75, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 76, 83, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 84, 91, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 108, 115, 0x0, STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1}, +{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // MTSW_CLOSE +{ WWT_CAPTION, RESIZE_NONE, 14, 11, 431, 0, 13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // MTSW_CAPTION +{ WWT_PANEL, RESIZE_NONE, 14, 0, 431, 14, 217, 0x0, STR_NULL}, // MTSW_BACKGROUND +{ WWT_PANEL, RESIZE_NONE, 14, 2, 181, 22, 215, 0x0, STR_01FA_CLICK_ON_MUSIC_TRACK_TO}, // MTSW_LIST_LEFT +{ WWT_PANEL, RESIZE_NONE, 14, 250, 429, 22, 215, 0x0, STR_CLICK_ON_TRACK_TO_REMOVE}, // MTSW_LIST_RIGHT +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 44, 51, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, // MTSW_ALL +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 52, 59, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, // MTSW_OLD +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 60, 67, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, // MTSW_NEW +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 68, 75, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, // MTSW_EZY +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 76, 83, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, // MTSW_CUSTOM1 +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 84, 91, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, // MTSW_CUSTOM2 +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 108, 115, 0x0, STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1}, // MTSW_CLEAR #if 0 -{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 124, 131, 0x0, STR_01F9_SAVE_MUSIC_SETTINGS}, +{ WWT_PUSHBTN, RESIZE_NONE, 14, 186, 245, 124, 131, 0x0, STR_01F9_SAVE_MUSIC_SETTINGS}, // MTSW_SAVE #endif { WIDGETS_END}, }; @@ -329,24 +351,50 @@ WC_MUSIC_TRACK_SELECTION, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _music_track_selection_widgets, - MusicTrackSelectionWndProc }; static void ShowMusicTrackSelection() { - AllocateWindowDescFront(&_music_track_selection_desc, 0); + AllocateWindowDescFront(&_music_track_selection_desc, 0); } -static void MusicWindowWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { +struct MusicWindow : public Window { +private: + enum MusicWidgets { + MW_CLOSE, + MW_CAPTION, + MW_PREV, + MW_NEXT, + MW_STOP, + MW_PLAY, + MW_SLIDERS, + MW_GAUGE, + MW_BACKGROUND, + MW_INFO, + MW_SHUFFLE, + MW_PROGRAMME, + MW_ALL, + MW_OLD, + MW_NEW, + MW_EZY, + MW_CUSTOM1, + MW_CUSTOM2, + }; + +public: + MusicWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number) + { + this->FindWindowPlacementAndResize(desc); + } + + virtual void OnPaint() + { uint i; StringID str; - w->RaiseWidget(7); - w->RaiseWidget(9); - w->DrawWidgets(); + this->RaiseWidget(MW_GAUGE); + this->RaiseWidget(MW_INFO); + this->DrawWidgets(); GfxFillRect(187, 16, 200, 33, 0); @@ -403,92 +451,99 @@ DrawFrameRect( 214 + msf.effect_vol / 2, 22, 217 + msf.effect_vol / 2, 28, 14, FR_NONE ); - } break; - - case WE_CLICK: - switch (e->we.click.widget) { - case 2: // skip to prev - if (!_song_is_active) - return; - SkipToPrevSong(); - break; - case 3: // skip to next - if (!_song_is_active) - return; - SkipToNextSong(); - break; - case 4: // stop playing - msf.playing = false; - break; - case 5: // start playing - msf.playing = true; - break; - case 6: { // volume sliders - byte *vol, new_vol; - int x = e->we.click.pt.x - 88; - - if (x < 0) return; - - vol = &msf.music_vol; - if (x >= 106) { - vol = &msf.effect_vol; - x -= 106; - } - - new_vol = min(max(x - 21, 0) * 2, 127); - if (new_vol != *vol) { - *vol = new_vol; - if (vol == &msf.music_vol) - MusicVolumeChanged(new_vol); - w->SetDirty(); - } - - _left_button_clicked = false; - } break; - case 10: //toggle shuffle - msf.shuffle ^= 1; - StopMusic(); - SelectSongToPlay(); - break; - case 11: //show track selection - ShowMusicTrackSelection(); - break; - case 12: case 13: case 14: case 15: case 16: case 17: // playlist - msf.playlist = e->we.click.widget - 12; - w->SetDirty(); - InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0); - StopMusic(); - SelectSongToPlay(); - break; - } - break; - - case WE_TICK: - InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7); - break; } -} + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case MW_PREV: // skip to prev + if (!_song_is_active) return; + SkipToPrevSong(); + break; + + case MW_NEXT: // skip to next + if (!_song_is_active) return; + SkipToNextSong(); + break; + + case MW_STOP: // stop playing + msf.playing = false; + break; + + case MW_PLAY: // start playing + msf.playing = true; + break; + + case MW_SLIDERS: { // volume sliders + byte *vol, new_vol; + int x = pt.x - 88; + + if (x < 0) return; + + vol = &msf.music_vol; + if (x >= 106) { + vol = &msf.effect_vol; + x -= 106; + } + + new_vol = min(max(x - 21, 0) * 2, 127); + if (new_vol != *vol) { + *vol = new_vol; + if (vol == &msf.music_vol) MusicVolumeChanged(new_vol); + this->SetDirty(); + } + + _left_button_clicked = false; + } break; + + case MW_SHUFFLE: //toggle shuffle + msf.shuffle ^= 1; + StopMusic(); + SelectSongToPlay(); + break; + + case MW_PROGRAMME: //show track selection + ShowMusicTrackSelection(); + break; + + case MW_ALL: case MW_OLD: case MW_NEW: + case MW_EZY: case MW_CUSTOM1: case MW_CUSTOM2: // playlist + msf.playlist = widget - MW_ALL; + this->SetDirty(); + InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0); + StopMusic(); + SelectSongToPlay(); + break; + } + } + +#if 0 + virtual void OnTick() + { + this->InvalidateWidget(MW_GAUGE); + } +#endif +}; static const Widget _music_window_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 14, 11, 299, 0, 13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 0, 21, 14, 35, SPR_IMG_SKIP_TO_PREV, STR_01DE_SKIP_TO_PREVIOUS_TRACK}, -{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 22, 43, 14, 35, SPR_IMG_SKIP_TO_NEXT, STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION}, -{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 44, 65, 14, 35, SPR_IMG_STOP_MUSIC, STR_01E0_STOP_PLAYING_MUSIC}, -{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 66, 87, 14, 35, SPR_IMG_PLAY_MUSIC, STR_01E1_START_PLAYING_MUSIC}, -{ WWT_PANEL, RESIZE_NONE, 14, 88, 299, 14, 35, 0x0, STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC}, -{ WWT_PANEL, RESIZE_NONE, 14, 186, 201, 15, 34, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 14, 0, 299, 36, 57, 0x0, STR_NULL}, -{ WWT_PANEL, RESIZE_NONE, 14, 59, 240, 45, 53, 0x0, STR_NULL}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 6, 55, 42, 49, 0x0, STR_01FB_TOGGLE_PROGRAM_SHUFFLE}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 244, 293, 42, 49, 0x0, STR_01FC_SHOW_MUSIC_TRACK_SELECTION}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 0, 49, 58, 65, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 50, 99, 58, 65, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 100, 149, 58, 65, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 150, 199, 58, 65, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 200, 249, 58, 65, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, -{ WWT_PUSHBTN, RESIZE_NONE, 14, 250, 299, 58, 65, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, +{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // MW_CLOSE +{ WWT_CAPTION, RESIZE_NONE, 14, 11, 299, 0, 13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS}, // MW_CAPTION +{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 0, 21, 14, 35, SPR_IMG_SKIP_TO_PREV, STR_01DE_SKIP_TO_PREVIOUS_TRACK}, // MW_PREV +{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 22, 43, 14, 35, SPR_IMG_SKIP_TO_NEXT, STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION}, // MW_NEXT +{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 44, 65, 14, 35, SPR_IMG_STOP_MUSIC, STR_01E0_STOP_PLAYING_MUSIC}, // MW_STOP +{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 66, 87, 14, 35, SPR_IMG_PLAY_MUSIC, STR_01E1_START_PLAYING_MUSIC}, // MW_PLAY +{ WWT_PANEL, RESIZE_NONE, 14, 88, 299, 14, 35, 0x0, STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC}, // MW_SLIDERS +{ WWT_PANEL, RESIZE_NONE, 14, 186, 201, 15, 34, 0x0, STR_NULL}, // MW_GAUGE +{ WWT_PANEL, RESIZE_NONE, 14, 0, 299, 36, 57, 0x0, STR_NULL}, // MW_BACKGROUND +{ WWT_PANEL, RESIZE_NONE, 14, 59, 240, 45, 53, 0x0, STR_NULL}, // MW_INFO +{ WWT_PUSHBTN, RESIZE_NONE, 14, 6, 55, 42, 49, 0x0, STR_01FB_TOGGLE_PROGRAM_SHUFFLE}, // MW_SHUFFLE +{ WWT_PUSHBTN, RESIZE_NONE, 14, 244, 293, 42, 49, 0x0, STR_01FC_SHOW_MUSIC_TRACK_SELECTION}, // MW_PROGRAMME +{ WWT_PUSHBTN, RESIZE_NONE, 14, 0, 49, 58, 65, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM}, // MW_ALL +{ WWT_PUSHBTN, RESIZE_NONE, 14, 50, 99, 58, 65, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC}, // MW_OLD +{ WWT_PUSHBTN, RESIZE_NONE, 14, 100, 149, 58, 65, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC}, // MW_NEW +{ WWT_PUSHBTN, RESIZE_NONE, 14, 150, 199, 58, 65, 0x0, STR_0330_SELECT_EZY_STREET_STYLE}, // MW_EZY +{ WWT_PUSHBTN, RESIZE_NONE, 14, 200, 249, 58, 65, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED}, // MW_CUSTOM1 +{ WWT_PUSHBTN, RESIZE_NONE, 14, 250, 299, 58, 65, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED}, // MW_CUSTOM2 { WIDGETS_END}, }; @@ -497,10 +552,9 @@ WC_MUSIC_WINDOW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _music_window_widgets, - MusicWindowWndProc }; void ShowMusicWindow() { - AllocateWindowDescFront(&_music_window_desc, 0); + AllocateWindowDescFront(&_music_window_desc, 0); } diff -r 68a692eacf22 -r 67db0d431d5e src/network/network.cpp --- a/src/network/network.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/network/network.cpp Tue May 27 00:50:55 2008 +0000 @@ -23,7 +23,7 @@ #include "core/tcp.h" #include "core/core.h" #include "network_gui.h" -#include "../console.h" /* IConsoleCmdExec */ +#include "../console_func.h" #include /* va_list */ #include "../md5.h" #include "../fileio.h" @@ -141,7 +141,7 @@ // This puts a text-message to the console, or in the future, the chat-box, // (to keep it all a bit more general) // If 'self_send' is true, this is the client who is sending the message -void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...) +void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...) { char buf[1024]; va_list va; @@ -155,16 +155,16 @@ switch (action) { case NETWORK_ACTION_SERVER_MESSAGE: - color = 1; + color = CC_DEFAULT; snprintf(message, sizeof(message), "*** %s", buf); break; case NETWORK_ACTION_JOIN: - color = 1; + color = CC_DEFAULT; GetString(temp, STR_NETWORK_CLIENT_JOINED, lastof(temp)); snprintf(message, sizeof(message), "*** %s %s", name, temp); break; case NETWORK_ACTION_LEAVE: - color = 1; + color = CC_DEFAULT; GetString(temp, STR_NETWORK_ERR_LEFT, lastof(temp)); snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf); break; @@ -651,7 +651,7 @@ GetNetworkErrorMsg(str, errorno, lastof(str)); - NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str); // Inform other clients of this... strange leaving ;) FOR_ALL_CLIENTS(new_cs) { @@ -1009,10 +1009,10 @@ _network_game_info.spectators_on = 0; _network_game_info.game_date = _date; - _network_game_info.start_date = ConvertYMDToDate(_patches.starting_year, 0, 1); + _network_game_info.start_date = ConvertYMDToDate(_settings.game_creation.starting_year, 0, 1); _network_game_info.map_width = MapSizeX(); _network_game_info.map_height = MapSizeY(); - _network_game_info.map_set = _opt.landscape; + _network_game_info.map_set = _settings.game_creation.landscape; _network_game_info.use_password = (_network_server_password[0] != '\0'); diff -r 68a692eacf22 -r 67db0d431d5e src/network/network_client.cpp --- a/src/network/network_client.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/network/network_client.cpp Tue May 27 00:50:55 2008 +0000 @@ -14,7 +14,7 @@ #include "network_gui.h" #include "../saveload.h" #include "../command_func.h" -#include "../console.h" +#include "../console_func.h" #include "../variables.h" #include "../ai/ai.h" #include "../core/alloc_func.hpp" @@ -83,7 +83,7 @@ { if (StrEmpty(_network_player_info[_local_player].password)) return; - _password_game_seed = _patches.generation_seed; + _password_game_seed = _settings.game_creation.generation_seed; ttd_strlcpy(_password_server_unique_id, _network_unique_id, sizeof(_password_server_unique_id)); const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password); @@ -414,7 +414,7 @@ if (ci != NULL) { if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) { // Client name changed, display the change - NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name); + NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", name); } else if (playas != ci->client_playas) { // The player changed from client-player.. // Do not display that for now @@ -622,8 +622,6 @@ /* If the savegame has successfully loaded, ALL windows have been removed, * only toolbar/statusbar and gamefield are visible */ - _opt_ptr = &_opt; // during a network game you are always in-game - // Say we received the map and loaded it correctly! SEND_COMMAND(PACKET_CLIENT_MAP_OK)(); @@ -761,7 +759,7 @@ } if (ci != NULL) - NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg); + NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg); return NETWORK_RECV_STATUS_OKAY; } @@ -776,7 +774,7 @@ ci = NetworkFindClientInfoFromIndex(index); if (ci != NULL) { - NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str); // The client is gone, give the NetworkClientInfo free ci->client_index = NETWORK_EMPTY_INDEX; @@ -798,7 +796,7 @@ ci = NetworkFindClientInfoFromIndex(index); if (ci != NULL) { - NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, ci->client_name, "%s", str); // The client is gone, give the NetworkClientInfo free ci->client_index = NETWORK_EMPTY_INDEX; @@ -821,7 +819,7 @@ ci = NetworkFindClientInfoFromIndex(index); if (ci != NULL) - NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, ci->client_name, ""); + NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, ci->client_name, ""); InvalidateWindow(WC_CLIENT_LIST, 0); @@ -850,9 +848,8 @@ DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON) { char rcon_out[NETWORK_RCONCOMMAND_LENGTH]; - uint16 color_code; - color_code = p->Recv_uint16(); + ConsoleColour color_code = (ConsoleColour)p->Recv_uint16(); p->Recv_string(rcon_out, sizeof(rcon_out)); IConsolePrint(color_code, rcon_out); diff -r 68a692eacf22 -r 67db0d431d5e src/network/network_data.h --- a/src/network/network_data.h Mon May 26 20:45:25 2008 +0000 +++ b/src/network/network_data.h Tue May 27 00:50:55 2008 +0000 @@ -6,6 +6,7 @@ #define NETWORK_DATA_H #include "../openttd.h" +#include "../console_type.h" #include "network.h" #include "network_internal.h" @@ -105,7 +106,7 @@ // from network.c void NetworkCloseClient(NetworkTCPSocketHandler *cs); -void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...); +void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...); void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs); uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs); byte NetworkGetCurrentLanguageIndex(); diff -r 68a692eacf22 -r 67db0d431d5e src/network/network_gui.cpp --- a/src/network/network_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/network/network_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -190,7 +190,6 @@ this->field = NGWW_PLAYER; this->server = NULL; - this->servers.sort_list = NULL; this->servers.flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE); this->servers.sort_type = _ng_sorting.criteria; @@ -199,7 +198,6 @@ ~NetworkGameWindow() { - free(this->servers.sort_list); } /** @@ -208,23 +206,17 @@ */ void BuildNetworkGameList() { - NetworkGameList *ngl_temp; - uint n = 0; - if (!(this->servers.flags & VL_REBUILD)) return; - /* Count the number of games in the list */ - for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++; - if (n == 0) return; - /* Create temporary array of games to use for listing */ - this->servers.sort_list = ReallocT(this->servers.sort_list, n); - this->servers.list_length = n; + this->servers.Clear(); - for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) { - this->servers.sort_list[n++] = ngl_temp; + for (NetworkGameList *ngl = _network_game_list; ngl != NULL; ngl = ngl->next) { + *this->servers.Append() = ngl; } + this->servers.Compact(); + /* Force resort */ this->servers.flags &= ~VL_REBUILD; this->servers.flags |= VL_RESORT; @@ -242,17 +234,17 @@ uint i; if (!(this->servers.flags & VL_RESORT)) return; - if (this->servers.list_length == 0) return; + if (this->servers.Length() == 0) return; _internal_sort_order = !!(this->servers.flags & VL_DESC); - qsort(this->servers.sort_list, this->servers.list_length, sizeof(this->servers.sort_list[0]), ngame_sorter[this->servers.sort_type]); + qsort(this->servers.Begin(), this->servers.Length(), sizeof(this->servers.Begin()), ngame_sorter[this->servers.sort_type]); /* After sorting ngl->sort_list contains the sorted items. Put these back * into the original list. Basically nothing has changed, we are only * shuffling the ->next pointers */ - _network_game_list = this->servers.sort_list[0]; - for (item = _network_game_list, i = 1; i != this->servers.list_length; i++) { - item->next = this->servers.sort_list[i]; + _network_game_list = this->servers[0]; + for (item = _network_game_list, i = 1; i != this->servers.Length(); i++) { + item->next = this->servers[i]; item = item->next; } item->next = NULL; @@ -300,7 +292,7 @@ if (this->servers.flags & VL_REBUILD) { this->BuildNetworkGameList(); - SetVScrollCount(this, this->servers.list_length); + SetVScrollCount(this, this->servers.Length()); } if (this->servers.flags & VL_RESORT) this->SortNetworkGameList(); @@ -543,9 +535,9 @@ this->SetDirty(); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont = true; + EventState state = ES_NOT_HANDLED; if (this->field != NGWW_PLAYER) { if (this->server != NULL) { if (keycode == WKC_DELETE) { // Press 'delete' to remove servers @@ -554,10 +546,10 @@ this->server = NULL; } } - return cont; + return state; } - if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, cont) == 1) return cont; // enter pressed + if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, state) == 1) return state; // enter pressed /* The name is only allowed when it starts with a letter! */ if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') { @@ -565,7 +557,7 @@ } else { ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name)); } - return cont; + return state; } virtual void OnQueryTextFinished(char *str) @@ -582,7 +574,7 @@ this->widget[NGWW_MATRIX].data = (this->vscroll.cap << 8) + 1; - SetVScrollCount(this, this->servers.list_length); + SetVScrollCount(this, this->servers.Length()); int widget_width = this->widget[NGWW_FIND].right - this->widget[NGWW_FIND].left; int space = (this->width - 4 * widget_width - 25) / 3; @@ -642,7 +634,6 @@ WC_NETWORK_WINDOW, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _network_game_window_widgets, - NULL, }; void ShowNetworkGameWindow() @@ -892,16 +883,16 @@ if (this->field == NSSW_GAMENAME) this->HandleEditBox(NSSW_GAMENAME); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont = true; + EventState state = ES_NOT_HANDLED; if (this->field == NSSW_GAMENAME) { - if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, cont) == 1) return cont; // enter pressed + if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, state) == 1) return state; // enter pressed ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name)); } - return cont; + return state; } virtual void OnQueryTextFinished(char *str) @@ -977,7 +968,6 @@ WC_NETWORK_WINDOW, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _network_start_server_window_widgets, - NULL, }; static void ShowNetworkStartServerWindow() @@ -1191,7 +1181,6 @@ WC_NETWORK_WINDOW, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _network_lobby_window_widgets, - NULL, }; /* Show the networklobbywindow with the selected server @@ -1237,12 +1226,11 @@ { WIDGETS_END}, }; -static WindowDesc _client_list_desc = { +static const WindowDesc _client_list_desc = { WDP_AUTO, WDP_AUTO, 250, 1, 250, 1, WC_CLIENT_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _client_list_widgets, - NULL }; // Finds the Xth client-info that is active @@ -1321,7 +1309,7 @@ ClientList_Action_Proc *proc[MAX_CLIENTLIST_ACTION]; NetworkClientListPopupWindow(int x, int y, const Widget *widgets, int client_no) : - Window(x, y, 150, 100, NULL, WC_TOOLBAR_MENU, widgets), + Window(x, y, 150, 100, WC_TOOLBAR_MENU, widgets), sel_index(0), client_no(client_no) { /* @@ -1346,7 +1334,7 @@ if (_network_own_client_index != ci->client_index) { /* We are no spectator and the player we want to give money to is no spectator and money gifts are allowed */ - if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _patches.give_money) { + if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas) && _settings.economy.give_money) { GetString(this->action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(this->action[i])); this->proc[i++] = &ClientList_GiveMoney; } @@ -1665,7 +1653,6 @@ WC_NETWORK_STATUS_WINDOW, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL, _network_join_status_window_widget, - NULL, }; void ShowJoinStatusWindow() @@ -1878,21 +1865,21 @@ this->HandleEditBox(2); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont = true; + EventState state = ES_NOT_HANDLED; if (keycode == WKC_TAB) { ChatTabCompletion(); } else { _chat_tab_completion_active = false; - switch (this->HandleEditBoxKey(2, key, keycode, cont)) { + switch (this->HandleEditBoxKey(2, key, keycode, state)) { case 1: /* Return */ SendChat(this->text.buf, this->dtype, this->dest); /* FALLTHROUGH */ case 2: /* Escape */ delete this; break; } } - return cont; + return state; } }; @@ -1909,7 +1896,6 @@ WC_SEND_NETWORK_MSG, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET, _chat_window_widgets, - NULL }; void ShowNetworkChatQueryWindow(DestType type, int dest) @@ -1985,10 +1971,10 @@ this->HandleEditBox(4); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont; - switch (this->HandleEditBoxKey(4, key, keycode, cont)) { + EventState state; + switch (this->HandleEditBoxKey(4, key, keycode, state)) { case 1: // Return this->OnOk(); /* FALL THROUGH */ @@ -1997,7 +1983,7 @@ delete this; break; } - return cont; + return state; } }; @@ -2018,7 +2004,6 @@ WC_COMPANY_PASSWORD_WINDOW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, _ncp_window_widgets, - NULL }; void ShowNetworkCompanyPasswordWindow(Window *parent) diff -r 68a692eacf22 -r 67db0d431d5e src/network/network_server.cpp --- a/src/network/network_server.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/network/network_server.cpp Tue May 27 00:50:55 2008 +0000 @@ -15,7 +15,7 @@ #include "../date_func.h" #include "network_server.h" #include "network_udp.h" -#include "../console.h" +#include "../console_func.h" #include "../command_func.h" #include "../saveload.h" #include "../station_base.h" @@ -160,7 +160,7 @@ DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str); - NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str); FOR_ALL_CLIENTS(new_cs) { if (new_cs->status > STATUS_AUTH && new_cs != cs) { @@ -229,7 +229,7 @@ Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD); p->Send_uint8(type); - p->Send_uint32(_patches.generation_seed); + p->Send_uint32(_settings.game_creation.generation_seed); p->Send_string(_network_unique_id); cs->Send_Packet(p); } @@ -254,7 +254,7 @@ p = NetworkSend_Init(PACKET_SERVER_WELCOME); p->Send_uint16(cs->index); - p->Send_uint32(_patches.generation_seed); + p->Send_uint32(_settings.game_creation.generation_seed); p->Send_string(_network_unique_id); cs->Send_Packet(p); @@ -779,7 +779,7 @@ NetworkGetClientName(client_name, sizeof(client_name), cs); - NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, ""); + NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, ""); // Mark the client as pre-active, and wait for an ACK // so we know he is done loading and in sync with us @@ -822,17 +822,17 @@ byte flags = GetCommandFlags(cp->cmd); if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) { - IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci)); + IConsolePrintF(CC_ERROR, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci)); return false; } if (flags & CMD_OFFLINE) { - IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci)); + IConsolePrintF(CC_ERROR, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci)); return false; } if (cp->cmd != CMD_PLAYER_CTRL && !IsValidPlayer(cp->player) && ci->client_index != NETWORK_SERVER_INDEX) { - IConsolePrintF(_icolour_err, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci)); + IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci)); return false; } @@ -875,7 +875,7 @@ /* Check if cp->cmd is valid */ if (!IsValidCommand(cp->cmd)) { - IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); + IConsolePrintF(CC_ERROR, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); free(cp); return; @@ -892,7 +892,7 @@ * something pretty naughty (or a bug), and will be kicked */ if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) { - IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", + IConsolePrintF(CC_ERROR, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1); SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH); free(cp); @@ -969,7 +969,7 @@ DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str); - NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str); FOR_ALL_CLIENTS(new_cs) { if (new_cs->status > STATUS_AUTH) { @@ -998,7 +998,7 @@ NetworkGetClientName(client_name, sizeof(client_name), cs); - NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str); + NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, "%s", str); FOR_ALL_CLIENTS(new_cs) { if (new_cs->status > STATUS_AUTH) { @@ -1052,7 +1052,7 @@ ci = NetworkFindClientInfoFromIndex(from_index); /* Display the text locally, and that is it */ if (ci != NULL) - NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg); + NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg); } else { /* Else find the client to send the message to */ FOR_ALL_CLIENTS(cs) { @@ -1069,7 +1069,7 @@ ci = NetworkFindClientInfoFromIndex(from_index); ci_to = NetworkFindClientInfoFromIndex(dest); if (ci != NULL && ci_to != NULL) - NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg); + NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg); } else { FOR_ALL_CLIENTS(cs) { if (cs->index == from_index) { @@ -1097,7 +1097,7 @@ ci = NetworkFindClientInfoFromIndex(from_index); ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX); if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) { - NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg); + NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg); if (from_index == NETWORK_SERVER_INDEX) show_local = false; ci_to = ci_own; } @@ -1112,7 +1112,7 @@ StringID str = IsValidPlayer(ci_to->client_playas) ? STR_COMPANY_NAME : STR_NETWORK_SPECTATORS; SetDParam(0, ci_to->client_playas); GetString(name, str, lastof(name)); - NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg); + NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg); } else { FOR_ALL_CLIENTS(cs) { if (cs->index == from_index) { @@ -1132,7 +1132,7 @@ } ci = NetworkFindClientInfoFromIndex(from_index); if (ci != NULL) - NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg); + NetworkTextMessage(action, (ConsoleColour)GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg); break; } } @@ -1175,7 +1175,7 @@ if (ci != NULL) { // Display change if (NetworkFindName(client_name)) { - NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name); + NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", client_name); ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name)); NetworkUpdateClientInfo(ci->client_index); } @@ -1412,13 +1412,13 @@ if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') { /* Shut the company down */ DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL); - IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1); + IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d", p->index + 1); } /* Is the compnay empty for autoclean_protected-months, and there is a protection? */ if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') { /* Unprotect the company */ _network_player_info[p->index].password[0] = '\0'; - IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1); + IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", p->index+1); _network_player_info[p->index].months_empty = 0; } } else { @@ -1527,14 +1527,14 @@ if (lag > 3) { // Client did still not report in after 4 game-day, drop him // (that is, the 3 of above, + 1 before any lag is counted) - IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index); + IConsolePrintF(CC_ERROR,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index); NetworkCloseClient(cs); continue; } // Report once per time we detect the lag if (cs->lag_test == 0) { - IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index); + IConsolePrintF(CC_WARNING,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index); cs->lag_test = 1; } } else { @@ -1543,13 +1543,13 @@ } else if (cs->status == STATUS_PRE_ACTIVE) { int lag = NetworkCalculateLag(cs); if (lag > _network_max_join_time) { - IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time); + IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time); NetworkCloseClient(cs); } } else if (cs->status == STATUS_INACTIVE) { int lag = NetworkCalculateLag(cs); if (lag > 4 * DAY_TICKS) { - IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS); + IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks to start the joining process", cs->index, 4 * DAY_TICKS); NetworkCloseClient(cs); } } diff -r 68a692eacf22 -r 67db0d431d5e src/network/network_udp.cpp --- a/src/network/network_udp.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/network/network_udp.cpp Tue May 27 00:50:55 2008 +0000 @@ -77,7 +77,7 @@ _network_game_info.game_date = _date; _network_game_info.map_width = MapSizeX(); _network_game_info.map_height = MapSizeY(); - _network_game_info.map_set = _opt.landscape; + _network_game_info.map_set = _settings.game_creation.landscape; _network_game_info.companies_on = ActivePlayerCount(); _network_game_info.spectators_on = NetworkSpectatorCount(); _network_game_info.grfconfig = _grfconfig; diff -r 68a692eacf22 -r 67db0d431d5e src/newgrf.cpp --- a/src/newgrf.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/newgrf.cpp Tue May 27 00:50:55 2008 +0000 @@ -328,7 +328,7 @@ /* Hack for add-on GRFs that need to modify another GRF's engines. This lets * them use the same engine slots. */ const GRFFile *grf_match = NULL; - if (_patches.dynamic_engines) { + if (_settings.vehicle.dynamic_engines) { uint32 override = _grf_id_overrides[file->grfid]; if (override != 0) { grf_match = GetFileByGRFID(override); @@ -343,7 +343,7 @@ /* Check if this vehicle is already defined... */ Engine *e = NULL; FOR_ALL_ENGINES(e) { - if (_patches.dynamic_engines && e->grffile != NULL && e->grffile != file && e->grffile != grf_match) continue; + if (_settings.vehicle.dynamic_engines && e->grffile != NULL && e->grffile != file && e->grffile != grf_match) continue; if (e->type != type) continue; if (e->internal_id != internal_id) continue; @@ -379,14 +379,14 @@ extern uint32 GetNewGRFOverride(uint32 grfid); const GRFFile *grf_match = NULL; - if (_patches.dynamic_engines) { + if (_settings.vehicle.dynamic_engines) { uint32 override = _grf_id_overrides[file->grfid]; if (override != 0) grf_match = GetFileByGRFID(override); } const Engine *e = NULL; FOR_ALL_ENGINES(e) { - if (_patches.dynamic_engines && e->grffile != file && (grf_match == NULL || e->grffile != grf_match)) continue; + if (_settings.vehicle.dynamic_engines && e->grffile != file && (grf_match == NULL || e->grffile != grf_match)) continue; if (e->type != type) continue; if (e->internal_id != internal_id) continue; @@ -1447,8 +1447,8 @@ /* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance. * Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */ - CargoID cid = (goods >= 0) ? ((_opt.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) : - ((_opt.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD); + CargoID cid = (goods >= 0) ? ((_settings.game_creation.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) : + ((_settings.game_creation.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD); /* Make sure the cargo type is valid in this climate. */ if (!GetCargo(cid)->IsValid()) goods = 0; @@ -2177,11 +2177,11 @@ break; case 0x17: // Probability in random game - indsp->appear_creation[_opt.landscape] = grf_load_byte(&buf); + indsp->appear_creation[_settings.game_creation.landscape] = grf_load_byte(&buf); break; case 0x18: // Probability during gameplay - indsp->appear_ingame[_opt.landscape] = grf_load_byte(&buf); + indsp->appear_ingame[_settings.game_creation.landscape] = grf_load_byte(&buf); break; case 0x19: // Map color @@ -2567,6 +2567,10 @@ } break; + case 0x24: // Noise of airport + fsmportspec->portFSM->noise_level = grf_load_byte(&buf); + break; + default: ret = true; break; @@ -3984,11 +3988,11 @@ return true; case 0x03: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland - *value = _opt.landscape; + *value = _settings.game_creation.landscape; return true; case 0x06: // road traffic side, bit 4 clear=left, set=right - *value = _opt.road_side << 4; + *value = _settings.vehicle.road_side << 4; return true; case 0x09: // date fraction @@ -4019,7 +4023,7 @@ case 0x0F: // Rail track type cost factors *value = 0; SB(*value, 0, 8, _railtype_cost_multiplier[0]); // normal rail - if (_patches.disable_elrails) { + if (_settings.vehicle.disable_elrails) { /* skip elrail multiplier - disabled */ SB(*value, 8, 8, _railtype_cost_multiplier[2]); // monorail } else { @@ -4062,7 +4066,7 @@ /* case 0x1F: // locale dependent settings not implemented */ case 0x20: // snow line height - *value = _opt.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF; + *value = _settings.game_creation.landscape == LT_ARCTIC ? GetSnowLine() : 0xFF; return true; case 0x21: // OpenTTD version @@ -4070,7 +4074,7 @@ return true; case 0x22: // difficulty level - *value = _opt.diff_level; + *value = _settings.difficulty.diff_level; return true; default: return false; @@ -4615,10 +4619,10 @@ { switch (param) { /* start year - 1920 */ - case 0x0B: return max(_patches.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR; + case 0x0B: return max(_settings.game_creation.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR; /* freight trains weight factor */ - case 0x0E: return _patches.freight_trains; + case 0x0E: return _settings.vehicle.freight_trains; /* empty wagon speed increase */ case 0x0F: return 0; @@ -4627,7 +4631,7 @@ * the following is good for 1x, 2x and 4x (most common?) and... * well not really for 3x. */ case 0x10: - switch (_patches.plane_speed) { + switch (_settings.vehicle.plane_speed) { default: case 4: return 1; case 3: return 2; @@ -4809,7 +4813,7 @@ case 0x01: // Road Vehicles case 0x02: // Ships case 0x03: // Aircraft - if (!_patches.dynamic_engines) { + if (!_settings.vehicle.dynamic_engines) { src1 = PerformGRM(&_grm_engines[_engine_offsets[feature]], _engine_counts[feature], count, op, target, "vehicles"); if (_skip_sprites == -1) return; } else { @@ -4971,7 +4975,7 @@ case 0x8F: // Rail track type cost factors _railtype_cost_multiplier[0] = GB(res, 0, 8); - if (_patches.disable_elrails) { + if (_settings.vehicle.disable_elrails) { _railtype_cost_multiplier[1] = GB(res, 0, 8); _railtype_cost_multiplier[2] = GB(res, 8, 8); } else { @@ -5506,84 +5510,84 @@ static void InitializeGRFSpecial() { - _ttdpatch_flags[0] = ((_patches.always_small_airport ? 1 : 0) << 0x0C) // keepsmallairport - | (1 << 0x0D) // newairports - | (1 << 0x0E) // largestations - | ((_patches.longbridges ? 1 : 0) << 0x0F) // longbridges - | (0 << 0x10) // loadtime - | (1 << 0x12) // presignals - | (1 << 0x13) // extpresignals - | ((_patches.never_expire_vehicles ? 1 : 0) << 0x16) // enginespersist - | (1 << 0x1B) // multihead - | (1 << 0x1D) // lowmemory - | (1 << 0x1E); // generalfixes - - _ttdpatch_flags[1] = (0 << 0x07) // moreairports - based on units of noise - | ((_patches.mammoth_trains ? 1 : 0) << 0x08) // mammothtrains - | (1 << 0x09) // trainrefit - | (0 << 0x0B) // subsidiaries - | ((_patches.gradual_loading ? 1 : 0) << 0x0C) // gradualloading - | (1 << 0x12) // unifiedmaglevmode - set bit 0 mode. Not revelant to OTTD - | (1 << 0x13) // unifiedmaglevmode - set bit 1 mode - | (1 << 0x14) // bridgespeedlimits - | (1 << 0x16) // eternalgame - | (1 << 0x17) // newtrains - | (1 << 0x18) // newrvs - | (1 << 0x19) // newships - | (1 << 0x1A) // newplanes - | ((_patches.signal_side ? 1 : 0) << 0x1B) // signalsontrafficside - | ((_patches.disable_elrails ? 0 : 1) << 0x1C); // electrifiedrailway - - _ttdpatch_flags[2] = (1 << 0x01) // loadallgraphics - obsolote - | (1 << 0x03) // semaphores - | (0 << 0x0B) // enhancedgui - | (0 << 0x0C) // newagerating - | ((_patches.build_on_slopes ? 1 : 0) << 0x0D) // buildonslopes - | (1 << 0x0E) // fullloadany - | (1 << 0x0F) // planespeed - | (0 << 0x10) // moreindustriesperclimate - obsolete - | (0 << 0x11) // moretoylandfeatures - | (1 << 0x12) // newstations - | (1 << 0x13) // tracktypecostdiff - | (1 << 0x14) // manualconvert - | ((_patches.build_on_slopes ? 1 : 0) << 0x15) // buildoncoasts - | (1 << 0x16) // canals - | (1 << 0x17) // newstartyear - | ((_patches.freight_trains > 1 ? 1 : 0) << 0x18) // freighttrains - | (1 << 0x19) // newhouses - | (1 << 0x1A) // newbridges - | (1 << 0x1B) // newtownnames - | (1 << 0x1C) // moreanimation - | ((_patches.wagon_speed_limits ? 1 : 0) << 0x1D) // wagonspeedlimits - | (1 << 0x1E) // newshistory - | (0 << 0x1F); // custombridgeheads - - _ttdpatch_flags[3] = (0 << 0x00) // newcargodistribution - | (1 << 0x01) // windowsnap - | (0 << 0x02) // townbuildnoroad - | (0 << 0x03) // pathbasedsignalling. To enable if ever pbs is back - | (0 << 0x04) // aichoosechance - | (1 << 0x05) // resolutionwidth - | (1 << 0x06) // resolutionheight - | (1 << 0x07) // newindustries - | ((_patches.improved_load ? 1 : 0) << 0x08) // fifoloading - | (0 << 0x09) // townroadbranchprob - | (0 << 0x0A) // tempsnowline - | (1 << 0x0B) // newcargo - | (1 << 0x0C) // enhancemultiplayer - | (1 << 0x0D) // onewayroads - | ((_patches.nonuniform_stations ? 1 : 0) << 0x0E) // irregularstations - | (1 << 0x0F) // statistics - | (1 << 0x10) // newsounds - | (1 << 0x11) // autoreplace - | (1 << 0x12) // autoslope - | (0 << 0x13) // followvehicle - | (1 << 0x14) // trams - | (0 << 0x15) // enhancetunnels - | (1 << 0x16) // shortrvs - | (1 << 0x17) // articulatedrvs - | ((_patches.dynamic_engines ? 1 : 0) << 0x18) // dynamic engines - | (1 << 0x1E); // variablerunningcosts + _ttdpatch_flags[0] = ((_settings.station.always_small_airport ? 1 : 0) << 0x0C) // keepsmallairport + | (1 << 0x0D) // newairports + | (1 << 0x0E) // largestations + | ((_settings.construction.longbridges ? 1 : 0) << 0x0F) // longbridges + | (0 << 0x10) // loadtime + | (1 << 0x12) // presignals + | (1 << 0x13) // extpresignals + | ((_settings.vehicle.never_expire_vehicles ? 1 : 0) << 0x16) // enginespersist + | (1 << 0x1B) // multihead + | (1 << 0x1D) // lowmemory + | (1 << 0x1E); // generalfixes + + _ttdpatch_flags[1] = ((_settings.economy.station_noise_level ? 1 : 0) << 0x07) // moreairports - based on units of noise + | ((_settings.vehicle.mammoth_trains ? 1 : 0) << 0x08) // mammothtrains + | (1 << 0x09) // trainrefit + | (0 << 0x0B) // subsidiaries + | ((_settings.order.gradual_loading ? 1 : 0) << 0x0C) // gradualloading + | (1 << 0x12) // unifiedmaglevmode - set bit 0 mode. Not revelant to OTTD + | (1 << 0x13) // unifiedmaglevmode - set bit 1 mode + | (1 << 0x14) // bridgespeedlimits + | (1 << 0x16) // eternalgame + | (1 << 0x17) // newtrains + | (1 << 0x18) // newrvs + | (1 << 0x19) // newships + | (1 << 0x1A) // newplanes + | ((_settings.construction.signal_side ? 1 : 0) << 0x1B) // signalsontrafficside + | ((_settings.vehicle.disable_elrails ? 0 : 1) << 0x1C); // electrifiedrailway + + _ttdpatch_flags[2] = (1 << 0x01) // loadallgraphics - obsolote + | (1 << 0x03) // semaphores + | (0 << 0x0B) // enhancedgui + | (0 << 0x0C) // newagerating + | ((_settings.construction.build_on_slopes ? 1 : 0) << 0x0D) // buildonslopes + | (1 << 0x0E) // fullloadany + | (1 << 0x0F) // planespeed + | (0 << 0x10) // moreindustriesperclimate - obsolete + | (0 << 0x11) // moretoylandfeatures + | (1 << 0x12) // newstations + | (1 << 0x13) // tracktypecostdiff + | (1 << 0x14) // manualconvert + | ((_settings.construction.build_on_slopes ? 1 : 0) << 0x15) // buildoncoasts + | (1 << 0x16) // canals + | (1 << 0x17) // newstartyear + | ((_settings.vehicle.freight_trains > 1 ? 1 : 0) << 0x18) // freighttrains + | (1 << 0x19) // newhouses + | (1 << 0x1A) // newbridges + | (1 << 0x1B) // newtownnames + | (1 << 0x1C) // moreanimation + | ((_settings.vehicle.wagon_speed_limits ? 1 : 0) << 0x1D) // wagonspeedlimits + | (1 << 0x1E) // newshistory + | (0 << 0x1F); // custombridgeheads + + _ttdpatch_flags[3] = (0 << 0x00) // newcargodistribution + | (1 << 0x01) // windowsnap + | (0 << 0x02) // townbuildnoroad + | (0 << 0x03) // pathbasedsignalling. To enable if ever pbs is back + | (0 << 0x04) // aichoosechance + | (1 << 0x05) // resolutionwidth + | (1 << 0x06) // resolutionheight + | (1 << 0x07) // newindustries + | ((_settings.order.improved_load ? 1 : 0) << 0x08) // fifoloading + | (0 << 0x09) // townroadbranchprob + | (0 << 0x0A) // tempsnowline + | (1 << 0x0B) // newcargo + | (1 << 0x0C) // enhancemultiplayer + | (1 << 0x0D) // onewayroads + | ((_settings.station.nonuniform_stations ? 1 : 0) << 0x0E) // irregularstations + | (1 << 0x0F) // statistics + | (1 << 0x10) // newsounds + | (1 << 0x11) // autoreplace + | (1 << 0x12) // autoslope + | (0 << 0x13) // followvehicle + | (1 << 0x14) // trams + | (0 << 0x15) // enhancetunnels + | (1 << 0x16) // shortrvs + | (1 << 0x17) // articulatedrvs + | ((_settings.vehicle.dynamic_engines ? 1 : 0) << 0x18) // dynamic engines + | (1 << 0x1E); // variablerunningcosts } static void ResetCustomStations() @@ -5782,7 +5786,7 @@ ResetNewGRFErrors(); /* Set up the default cargo types */ - SetupCargoForClimate(_opt.landscape); + SetupCargoForClimate(_settings.game_creation.landscape); /* Reset misc GRF features and train list display variables */ _misc_grf_features = 0; diff -r 68a692eacf22 -r 67db0d431d5e src/newgrf_commons.cpp --- a/src/newgrf_commons.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/newgrf_commons.cpp Tue May 27 00:50:55 2008 +0000 @@ -278,7 +278,7 @@ * Terrain type: 0 normal, 1 desert, 2 rainforest, 4 on or above snowline */ uint32 GetTerrainType(TileIndex tile) { - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_TROPIC: return GetTropicZone(tile); case LT_ARCTIC: return GetTileZ(tile) > GetSnowLine() ? 4 : 0; default: return 0; diff -r 68a692eacf22 -r 67db0d431d5e src/newgrf_engine.cpp --- a/src/newgrf_engine.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/newgrf_engine.cpp Tue May 27 00:50:55 2008 +0000 @@ -1107,7 +1107,7 @@ /* Populate map with current list positions */ Engine *e; FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) { - if (!_patches.dynamic_engines || e->grffile == source_e->grffile) { + if (!_settings.vehicle.dynamic_engines || e->grffile == source_e->grffile) { if (e->internal_id == target) target_e = e; lptr_map[e->list_position] = e; } diff -r 68a692eacf22 -r 67db0d431d5e src/newgrf_gui.cpp --- a/src/newgrf_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/newgrf_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -250,7 +250,6 @@ WC_SAVELOAD, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _newgrf_add_dlg_widgets, - NULL, }; @@ -552,7 +551,6 @@ WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _newgrf_widgets, - NULL, }; /** Callback function for the newgrf 'apply changes' confirmation window diff -r 68a692eacf22 -r 67db0d431d5e src/newgrf_town.cpp --- a/src/newgrf_town.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/newgrf_town.cpp Tue May 27 00:50:55 2008 +0000 @@ -21,7 +21,7 @@ switch (variable) { /* Larger towns */ case 0x40: - if (_patches.larger_towns == 0) return 2; + if (_settings.economy.larger_towns == 0) return 2; if (t->larger_town) return 1; return 0; diff -r 68a692eacf22 -r 67db0d431d5e src/news_gui.cpp --- a/src/news_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/news_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -19,6 +19,7 @@ #include "widgets/dropdown_func.h" #include "map_func.h" #include "statusbar_gui.h" +#include "player_face.h" #include "table/sprites.h" #include "table/strings.h" @@ -73,12 +74,68 @@ typedef void DrawNewsCallbackProc(struct Window *w, const NewsItem *ni); void DrawNewsNewVehicleAvail(Window *w, const NewsItem *ni); -void DrawNewsBankrupcy(Window *w, const NewsItem *ni); -static DrawNewsCallbackProc * const _draw_news_callback[] = { - DrawNewsNewVehicleAvail, ///< DNC_VEHICLEAVAIL - DrawNewsBankrupcy, ///< DNC_BANKRUPCY -}; +static void DrawNewsBankrupcy(Window *w, const NewsItem *ni) +{ + Player *p = GetPlayer((PlayerID)(ni->data_b)); + DrawPlayerFace(p->face, p->player_color, 2, 23); + GfxFillRect(3, 23, 3 + 91, 23 + 118, PALETTE_TO_STRUCT_GREY | (1 << USE_COLORTABLE)); + + SetDParam(0, p->index); + + DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94); + + switch (ni->subtype) { + case NS_COMPANY_TROUBLE: + DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING); + + SetDParam(0, p->index); + + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED, + w->width - 101); + break; + + case NS_COMPANY_MERGER: + DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING); + SetDParam(0, ni->params[2]); + SetDParam(1, p->index); + SetDParam(2, ni->params[4]); + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + ni->params[4] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR, + w->width - 101); + break; + + case NS_COMPANY_BANKRUPT: + DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING); + SetDParam(0, p->index); + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + STR_705D_HAS_BEEN_CLOSED_DOWN_BY, + w->width - 101); + break; + + case NS_COMPANY_NEW: + DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING); + SetDParam(0, p->index); + SetDParam(1, ni->params[3]); + DrawStringMultiCenter( + ((w->width - 101) >> 1) + 98, + 90, + STR_705F_STARTS_CONSTRUCTION_NEAR, + w->width - 101); + break; + + default: + NOT_REACHED(); + } +} + /** * Data common to all news items of a given subtype (structure) @@ -87,7 +144,7 @@ NewsType type; ///< News category @see NewsType NewsMode display_mode; ///< Display mode value @see NewsMode NewsFlag flags; ///< Initial NewsFlags bits @see NewsFlag - NewsCallback callback; ///< Call-back function + DrawNewsCallbackProc *callback; ///< Call-back function }; /** @@ -95,24 +152,24 @@ */ static const struct NewsSubtypeData _news_subtype_data[NS_END] = { /* type, display_mode, flags, callback */ - { NT_ARRIVAL_PLAYER, NM_THIN, NF_VIEWPORT|NF_VEHICLE, DNC_NONE }, ///< NS_ARRIVAL_PLAYER - { NT_ARRIVAL_OTHER, NM_THIN, NF_VIEWPORT|NF_VEHICLE, DNC_NONE }, ///< NS_ARRIVAL_OTHER - { NT_ACCIDENT, NM_THIN, NF_VIEWPORT|NF_TILE, DNC_NONE }, ///< NS_ACCIDENT_TILE - { NT_ACCIDENT, NM_THIN, NF_VIEWPORT|NF_VEHICLE, DNC_NONE }, ///< NS_ACCIDENT_VEHICLE - { NT_COMPANY_INFO, NM_CALLBACK, NF_NONE, DNC_BANKRUPCY }, ///< NS_COMPANY_TROUBLE - { NT_COMPANY_INFO, NM_CALLBACK, NF_NONE, DNC_BANKRUPCY }, ///< NS_COMPANY_MERGER - { NT_COMPANY_INFO, NM_CALLBACK, NF_NONE, DNC_BANKRUPCY }, ///< NS_COMPANY_BANKRUPT - { NT_COMPANY_INFO, NM_CALLBACK, NF_TILE, DNC_BANKRUPCY }, ///< NS_COMPANY_NEW - { NT_OPENCLOSE, NM_THIN, NF_VIEWPORT|NF_TILE, DNC_NONE }, ///< NS_OPENCLOSE - { NT_ECONOMY, NM_NORMAL, NF_NONE, DNC_NONE }, ///< NS_ECONOMY - { NT_INDUSTRY_PLAYER, NM_THIN, NF_VIEWPORT|NF_TILE, DNC_NONE }, ///< NS_INDUSTRY_PLAYER - { NT_INDUSTRY_OTHER, NM_THIN, NF_VIEWPORT|NF_TILE, DNC_NONE }, ///< NS_INDUSTRY_OTHER - { NT_INDUSTRY_NOBODY, NM_THIN, NF_VIEWPORT|NF_TILE, DNC_NONE }, ///< NS_INDUSTRY_NOBODY - { NT_ADVICE, NM_SMALL, NF_VIEWPORT|NF_VEHICLE, DNC_NONE }, ///< NS_ADVICE - { NT_NEW_VEHICLES, NM_CALLBACK, NF_NONE, DNC_VEHICLEAVAIL }, ///< NS_NEW_VEHICLES - { NT_ACCEPTANCE, NM_SMALL, NF_VIEWPORT|NF_TILE, DNC_NONE }, ///< NS_ACCEPTANCE - { NT_SUBSIDIES, NM_NORMAL, NF_TILE|NF_TILE2, DNC_NONE }, ///< NS_SUBSIDIES - { NT_GENERAL, NM_NORMAL, NF_TILE, DNC_NONE }, ///< NS_GENERAL + { NT_ARRIVAL_PLAYER, NM_THIN, NF_VIEWPORT|NF_VEHICLE, NULL }, ///< NS_ARRIVAL_PLAYER + { NT_ARRIVAL_OTHER, NM_THIN, NF_VIEWPORT|NF_VEHICLE, NULL }, ///< NS_ARRIVAL_OTHER + { NT_ACCIDENT, NM_THIN, NF_VIEWPORT|NF_TILE, NULL }, ///< NS_ACCIDENT_TILE + { NT_ACCIDENT, NM_THIN, NF_VIEWPORT|NF_VEHICLE, NULL }, ///< NS_ACCIDENT_VEHICLE + { NT_COMPANY_INFO, NM_CALLBACK, NF_NONE, DrawNewsBankrupcy }, ///< NS_COMPANY_TROUBLE + { NT_COMPANY_INFO, NM_CALLBACK, NF_NONE, DrawNewsBankrupcy }, ///< NS_COMPANY_MERGER + { NT_COMPANY_INFO, NM_CALLBACK, NF_NONE, DrawNewsBankrupcy }, ///< NS_COMPANY_BANKRUPT + { NT_COMPANY_INFO, NM_CALLBACK, NF_TILE, DrawNewsBankrupcy }, ///< NS_COMPANY_NEW + { NT_OPENCLOSE, NM_THIN, NF_VIEWPORT|NF_TILE, NULL }, ///< NS_OPENCLOSE + { NT_ECONOMY, NM_NORMAL, NF_NONE, NULL }, ///< NS_ECONOMY + { NT_INDUSTRY_PLAYER, NM_THIN, NF_VIEWPORT|NF_TILE, NULL }, ///< NS_INDUSTRY_PLAYER + { NT_INDUSTRY_OTHER, NM_THIN, NF_VIEWPORT|NF_TILE, NULL }, ///< NS_INDUSTRY_OTHER + { NT_INDUSTRY_NOBODY, NM_THIN, NF_VIEWPORT|NF_TILE, NULL }, ///< NS_INDUSTRY_NOBODY + { NT_ADVICE, NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NULL }, ///< NS_ADVICE + { NT_NEW_VEHICLES, NM_CALLBACK, NF_NONE, DrawNewsNewVehicleAvail }, ///< NS_NEW_VEHICLES + { NT_ACCEPTANCE, NM_SMALL, NF_VIEWPORT|NF_TILE, NULL }, ///< NS_ACCEPTANCE + { NT_SUBSIDIES, NM_NORMAL, NF_TILE|NF_TILE2, NULL }, ///< NS_SUBSIDIES + { NT_GENERAL, NM_NORMAL, NF_TILE, NULL }, ///< NS_GENERAL }; /** Initialize the news-items data structures */ @@ -200,7 +257,7 @@ case NM_CALLBACK: this->DrawNewsBorder(); - _draw_news_callback[_news_subtype_data[this->ni->subtype].callback](this, ni); + (_news_subtype_data[this->ni->subtype].callback)(this, ni); break; default: @@ -246,14 +303,14 @@ } } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { if (keycode == WKC_SPACE) { /* Don't continue. */ delete this; - return false; + return ES_HANDLED; } - return true; + return ES_NOT_HANDLED; } virtual void OnInvalidateData(int data) @@ -341,7 +398,7 @@ ni->flags = _news_subtype_data[subtype].flags; /* show this news message in color? */ - if (_cur_year >= _patches.colored_news_year) ni->flags |= NF_INCOLOR; + if (_cur_year >= _settings.gui.colored_news_year) ni->flags |= NF_INCOLOR; ni->data_a = data_a; ni->data_b = data_b; @@ -388,7 +445,6 @@ WC_NEWS_WINDOW, WC_NONE, WDF_DEF_WIDGET, _news_type13_widgets, - NULL }; static const Widget _news_type2_widgets[] = { @@ -402,7 +458,6 @@ WC_NEWS_WINDOW, WC_NONE, WDF_DEF_WIDGET, _news_type2_widgets, - NULL }; static const Widget _news_type0_widgets[] = { @@ -418,7 +473,6 @@ WC_NEWS_WINDOW, WC_NONE, WDF_DEF_WIDGET, _news_type0_widgets, - NULL }; @@ -640,45 +694,56 @@ } -static void MessageHistoryWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - int y = 19; - - SetVScrollCount(w, _total_news); - w->DrawWidgets(); - - if (_total_news == 0) break; - NewsID show = min(_total_news, w->vscroll.cap); - - for (NewsID p = w->vscroll.pos; p < w->vscroll.pos + show; p++) { - /* get news in correct order */ - const NewsItem *ni = &_news_items[getNews(p)]; - - SetDParam(0, ni->date); - DrawString(4, y, STR_SHORT_DATE, TC_WHITE); +struct MessageHistoryWindow : Window { + MessageHistoryWindow(const WindowDesc *desc) : Window(desc) + { + this->vscroll.cap = 10; + this->vscroll.count = _total_news; + this->resize.step_height = 12; + this->resize.height = this->height - 12 * 6; // minimum of 4 items in the list, each item 12 high + this->resize.step_width = 1; + this->resize.width = 200; // can't make window any smaller than 200 pixel - DrawNewsString(82, y, TC_WHITE, ni, w->width - 95); - y += 12; - } - break; - } + this->FindWindowPlacementAndResize(desc); + } - case WE_CLICK: - if (e->we.click.widget == 3) { - int y = (e->we.click.pt.y - 19) / 12; - NewsID p = getNews(y + w->vscroll.pos); + virtual void OnPaint() + { + int y = 19; - if (p != INVALID_NEWS) ShowNewsMessage(p); - } - break; + SetVScrollCount(this, _total_news); + this->DrawWidgets(); - case WE_RESIZE: - w->vscroll.cap += e->we.sizing.diff.y / 12; - break; + if (_total_news == 0) return; + NewsID show = min(_total_news, this->vscroll.cap); + + for (NewsID p = this->vscroll.pos; p < this->vscroll.pos + show; p++) { + /* get news in correct order */ + const NewsItem *ni = &_news_items[getNews(p)]; + + SetDParam(0, ni->date); + DrawString(4, y, STR_SHORT_DATE, TC_WHITE); + + DrawNewsString(82, y, TC_WHITE, ni, this->width - 95); + y += 12; + } } -} + + virtual void OnClick(Point pt, int widget) + { + if (widget == 3) { + int y = (pt.y - 19) / 12; + NewsID p = getNews(y + this->vscroll.pos); + + if (p != INVALID_NEWS) ShowNewsMessage(p); + } + } + + virtual void OnResize(Point new_size, Point delta) + { + this->vscroll.cap += delta.y / 12; + } +}; static const Widget _message_history_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -695,24 +760,13 @@ WC_MESSAGE_HISTORY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _message_history_widgets, - MessageHistoryWndProc }; /** Display window with news messages history */ void ShowMessageHistory() { DeleteWindowById(WC_MESSAGE_HISTORY, 0); - Window *w = new Window(&_message_history_desc); - - if (w == NULL) return; - - w->vscroll.cap = 10; - w->vscroll.count = _total_news; - w->resize.step_height = 12; - w->resize.height = w->height - 12 * 6; // minimum of 4 items in the list, each item 12 high - w->resize.step_width = 1; - w->resize.width = 200; // can't make window any smaller than 200 pixel - w->SetDirty(); + new MessageHistoryWindow(&_message_history_desc); } @@ -741,6 +795,8 @@ } /* If all values are the same value, the ALL-button will take over this value */ this->state = all_val; + + this->FindWindowPlacementAndResize(desc); } /** @@ -913,7 +969,6 @@ WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _message_options_widgets, - NULL }; void ShowMessageOptions() diff -r 68a692eacf22 -r 67db0d431d5e src/news_type.h --- a/src/news_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/news_type.h Tue May 27 00:50:55 2008 +0000 @@ -82,15 +82,6 @@ /** - * Special news items - */ -enum NewsCallback { - DNC_VEHICLEAVAIL = 0, ///< Show new vehicle available message. StringID is EngineID - DNC_BANKRUPCY = 1, ///< Show bankrupcy message. StringID is PlayerID (0-3) and NewsBankrupcy (4-7) - DNC_NONE = 0xFF, ///< No news callback. -}; - -/** * News display options */ enum NewsDisplay { diff -r 68a692eacf22 -r 67db0d431d5e src/npf.cpp --- a/src/npf.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/npf.cpp Tue May 27 00:50:55 2008 +0000 @@ -213,7 +213,7 @@ if (z2 - z1 > 1) { /* Slope up */ - return _patches.npf_rail_slope_penalty; + return _settings.pf.npf.npf_rail_slope_penalty; } return 0; /* Should we give a bonus for slope down? Probably not, we @@ -260,10 +260,10 @@ cost = _trackdir_length[trackdir]; // Should be different for diagonal tracks if (IsBuoyTile(current->tile) && IsDiagonalTrackdir(trackdir)) - cost += _patches.npf_buoy_penalty; // A small penalty for going over buoys + cost += _settings.pf.npf.npf_buoy_penalty; // A small penalty for going over buoys if (current->direction != NextTrackdir((Trackdir)parent->path.node.direction)) - cost += _patches.npf_water_curve_penalty; + cost += _settings.pf.npf.npf_water_curve_penalty; /* @todo More penalties? */ @@ -285,13 +285,13 @@ case MP_ROAD: cost = NPF_TILE_LENGTH; /* Increase the cost for level crossings */ - if (IsLevelCrossing(tile)) cost += _patches.npf_crossing_penalty; + if (IsLevelCrossing(tile)) cost += _settings.pf.npf.npf_crossing_penalty; break; case MP_STATION: cost = NPF_TILE_LENGTH; /* Increase the cost for drive-through road stops */ - if (IsDriveThroughStopTile(tile)) cost += _patches.npf_road_drive_through_penalty; + if (IsDriveThroughStopTile(tile)) cost += _settings.pf.npf.npf_road_drive_through_penalty; break; default: @@ -306,7 +306,7 @@ /* Check for turns. Road vehicles only really drive diagonal, turns are * represented by non-diagonal tracks */ if (!IsDiagonalTrackdir((Trackdir)current->direction)) - cost += _patches.npf_road_curve_penalty; + cost += _settings.pf.npf.npf_road_curve_penalty; NPFMarkTile(tile); DEBUG(npf, 4, "Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost); @@ -344,7 +344,7 @@ * give any station tile a penalty, because every possible route will get * this penalty exactly once, on its end tile (if it's a station) and it * will therefore not make a difference. */ - cost = NPF_TILE_LENGTH + _patches.npf_rail_station_penalty; + cost = NPF_TILE_LENGTH + _settings.pf.npf.npf_rail_station_penalty; break; default: @@ -366,9 +366,9 @@ SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir)); if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) { /* Penalise exit and combo signals differently (heavier) */ - cost += _patches.npf_rail_firstred_exit_penalty; + cost += _settings.pf.npf.npf_rail_firstred_exit_penalty; } else { - cost += _patches.npf_rail_firstred_penalty; + cost += _settings.pf.npf.npf_rail_firstred_penalty; } } /* Record the state of this signal */ @@ -386,14 +386,14 @@ * of course... */ new_node.path.node = *current; if (as->EndNodeCheck(as, &new_node) == AYSTAR_FOUND_END_NODE && NPFGetFlag(current, NPF_FLAG_LAST_SIGNAL_RED)) - cost += _patches.npf_rail_lastred_penalty; + cost += _settings.pf.npf.npf_rail_lastred_penalty; /* Check for slope */ cost += NPFSlopeCost(current); /* Check for turns */ if (current->direction != NextTrackdir((Trackdir)parent->path.node.direction)) - cost += _patches.npf_rail_curve_penalty; + cost += _settings.pf.npf.npf_rail_curve_penalty; /*TODO, with realistic acceleration, also the amount of straight track between * curves should be taken into account, as this affects the speed limit. */ @@ -402,7 +402,7 @@ /* Penalise any depot tile that is not the last tile in the path. This * _should_ penalise every occurence of reversing in a depot (and only * that) */ - cost += _patches.npf_rail_depot_reverse_penalty; + cost += _settings.pf.npf.npf_rail_depot_reverse_penalty; } /* Check for occupied track */ @@ -634,7 +634,7 @@ trackdirbits &= TrackdirReachesTrackdirs(src_trackdir); /* Filter out trackdirs that would make 90 deg turns for trains */ - if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir); + if (_settings.pf.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir); DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits); @@ -970,7 +970,7 @@ //_npf_aystar.max_search_nodes = 0; /* We will limit the number of nodes for now, until we have a better * solution to really fix performance */ - _npf_aystar.max_search_nodes = _patches.npf_max_search_nodes; + _npf_aystar.max_search_nodes = _settings.pf.npf.npf_max_search_nodes; } void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) diff -r 68a692eacf22 -r 67db0d431d5e src/oldloader.cpp --- a/src/oldloader.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/oldloader.cpp Tue May 27 00:50:55 2008 +0000 @@ -319,8 +319,8 @@ /* Convert town-names if needed */ FOR_ALL_TOWNS(town) { if (IsInsideMM(town->townnametype, 0x20C1, 0x20C3)) { - town->townnametype = SPECSTR_TOWNNAME_ENGLISH + _opt.town_name; - town->townnameparts = GetOldTownName(town->townnameparts, _opt.town_name); + town->townnametype = SPECSTR_TOWNNAME_ENGLISH + _settings.game_creation.town_name; + town->townnameparts = GetOldTownName(town->townnameparts, _settings.game_creation.town_name); } } } @@ -1370,29 +1370,31 @@ } static const OldChunks game_difficulty_chunk[] = { - OCL_SVAR( OC_UINT16, GameDifficulty, max_no_competitors ), - OCL_SVAR( OC_UINT16, GameDifficulty, competitor_start_time ), - OCL_SVAR( OC_UINT16, GameDifficulty, number_towns ), - OCL_SVAR( OC_UINT16, GameDifficulty, number_industries ), - OCL_SVAR( OC_UINT16, GameDifficulty, max_loan ), - OCL_SVAR( OC_UINT16, GameDifficulty, initial_interest ), - OCL_SVAR( OC_UINT16, GameDifficulty, vehicle_costs ), - OCL_SVAR( OC_UINT16, GameDifficulty, competitor_speed ), - OCL_SVAR( OC_UINT16, GameDifficulty, competitor_intelligence ), - OCL_SVAR( OC_UINT16, GameDifficulty, vehicle_breakdowns ), - OCL_SVAR( OC_UINT16, GameDifficulty, subsidy_multiplier ), - OCL_SVAR( OC_UINT16, GameDifficulty, construction_cost ), - OCL_SVAR( OC_UINT16, GameDifficulty, terrain_type ), - OCL_SVAR( OC_UINT16, GameDifficulty, quantity_sea_lakes ), - OCL_SVAR( OC_UINT16, GameDifficulty, economy ), - OCL_SVAR( OC_UINT16, GameDifficulty, line_reverse_mode ), - OCL_SVAR( OC_UINT16, GameDifficulty, disasters ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, max_no_competitors ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, competitor_start_time ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, number_towns ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, number_industries ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, DifficultySettings, max_loan ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, initial_interest ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_costs ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, competitor_speed ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, competitor_intelligence ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, vehicle_breakdowns ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, subsidy_multiplier ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, construction_cost ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, terrain_type ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, quantity_sea_lakes ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, economy ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, line_reverse_mode ), + OCL_SVAR( OC_FILE_U16 | OC_VAR_U8, DifficultySettings, disasters ), OCL_END() }; static inline bool LoadOldGameDifficulty(LoadgameState *ls, int num) { - return LoadChunk(ls, &_opt.diff, game_difficulty_chunk); + bool ret = LoadChunk(ls, &_settings.difficulty, game_difficulty_chunk); + _settings.difficulty.max_loan *= 1000; + return ret; } @@ -1570,8 +1572,8 @@ OCL_VAR ( OC_FILE_U8 | OC_VAR_U16, 1, &_station_tick_ctr ), - OCL_VAR ( OC_UINT8, 1, &_opt.currency ), - OCL_VAR ( OC_UINT8, 1, &_opt.units ), + OCL_VAR ( OC_UINT8, 1, &_settings.gui.currency ), + OCL_VAR ( OC_UINT8, 1, &_settings.gui.units ), OCL_VAR ( OC_FILE_U8 | OC_VAR_U32, 1, &_cur_player_tick_index ), OCL_NULL( 2 ), ///< Date stuff, calculated automatically @@ -1581,19 +1583,19 @@ OCL_VAR ( OC_UINT8, 1, &_economy.infl_amount_pr ), OCL_VAR ( OC_UINT8, 1, &_economy.interest_rate ), OCL_NULL( 1 ), // available airports - OCL_VAR ( OC_UINT8, 1, &_opt.road_side ), - OCL_VAR ( OC_UINT8, 1, &_opt.town_name ), + OCL_VAR ( OC_UINT8, 1, &_settings.vehicle.road_side ), + OCL_VAR ( OC_UINT8, 1, &_settings.game_creation.town_name ), OCL_CHUNK( 1, LoadOldGameDifficulty ), OCL_ASSERT( 0x77130 ), - OCL_VAR ( OC_UINT8, 1, &_opt.diff_level ), - OCL_VAR ( OC_UINT8, 1, &_opt.landscape ), + OCL_VAR ( OC_UINT8, 1, &_settings.difficulty.diff_level ), + OCL_VAR ( OC_UINT8, 1, &_settings.game_creation.landscape ), OCL_VAR ( OC_UINT8, 1, &_trees_tick_ctr ), OCL_NULL( 1 ), ///< Custom vehicle types yes/no, no longer used - OCL_VAR ( OC_UINT8, 1, &_opt.snow_line ), + OCL_VAR ( OC_UINT8, 1, &_settings.game_creation.snow_line ), OCL_NULL( 32 ), ///< new_industry_randtable, no longer used (because of new design) OCL_NULL( 36 ), ///< cargo-stuff, calculated in InitializeLandscapeVariables @@ -1628,7 +1630,7 @@ DEBUG(oldloader, 3, "Done, converting game data..."); /* Fix some general stuff */ - _opt.landscape = _opt.landscape & 0xF; + _settings.game_creation.landscape = _settings.game_creation.landscape & 0xF; /* Remap some pointers */ _cur_town_ctr = REMAP_TOWN_IDX(_old_cur_town_ctr); @@ -1690,7 +1692,7 @@ FixOldVehicles(); /* We have a new difficulty setting */ - _opt.diff.town_council_tolerance = Clamp(_opt.diff_level, 0, 2); + _settings.difficulty.town_council_tolerance = Clamp(_settings.difficulty.diff_level, 0, 2); DEBUG(oldloader, 3, "Finished converting game data"); DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted"); diff -r 68a692eacf22 -r 67db0d431d5e src/openttd.cpp --- a/src/openttd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/openttd.cpp Tue May 27 00:50:55 2008 +0000 @@ -41,7 +41,7 @@ #include "fios.h" #include "airport.h" #include "aircraft.h" -#include "console.h" +#include "console_func.h" #include "screenshot.h" #include "network/network.h" #include "signs_base.h" @@ -100,7 +100,7 @@ void ProcessAsyncSaveFinish(); void CallWindowTickEvent(); -extern void SetDifficultyLevel(int mode, GameOptions *gm_opt); +extern void SetDifficultyLevel(int mode, DifficultySettings *gm_opt); extern Player* DoStartupNewPlayer(bool is_ai); extern void ShowOSErrorBox(const char *buf); extern void InitializeRailGUI(); @@ -284,7 +284,6 @@ { /* Dynamic stuff needs to be initialized somewhere... */ _town_sort = NULL; - _industry_sort = NULL; _industry_mngr.ResetMapping(); _industile_mngr.ResetMapping(); } @@ -318,7 +317,6 @@ _Engine_pool.CleanPool(); free((void*)_town_sort); - free((void*)_industry_sort); free(_config_file); @@ -330,7 +328,6 @@ { _game_mode = GM_MENU; - _opt_ptr = &_opt_newgame; ResetGRFConfig(false); /* Setup main window */ @@ -486,8 +483,8 @@ if (!StrEmpty(videodriver)) ttd_strlcpy(_ini_videodriver, videodriver, sizeof(_ini_videodriver)); if (!StrEmpty(blitter)) ttd_strlcpy(_ini_blitter, blitter, sizeof(_ini_blitter)); if (resolution[0] != 0) { _cur_resolution[0] = resolution[0]; _cur_resolution[1] = resolution[1]; } - if (startyear != INVALID_YEAR) _patches_newgame.starting_year = startyear; - if (generation_seed != GENERATE_NEW_SEED) _patches_newgame.generation_seed = generation_seed; + if (startyear != INVALID_YEAR) _settings_newgame.game_creation.starting_year = startyear; + if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed; /* The width and height must be at least 1 pixel, this * way all internal drawing routines work correctly. */ @@ -581,17 +578,13 @@ ScanNewGRFFiles(); - _opt_ptr = &_opt_newgame; ResetGRFConfig(false); /* XXX - ugly hack, if diff_level is 9, it means we got no setting from the config file */ - if (_opt_newgame.diff_level == 9) SetDifficultyLevel(0, &_opt_newgame); + if (_settings_newgame.difficulty.diff_level == 9) SetDifficultyLevel(0, &_settings_newgame.difficulty); - /* Make sure _patches is filled with _patches_newgame if we switch to a game directly */ - if (_switch_mode != SM_NONE) { - _opt = _opt_newgame; - UpdatePatches(); - } + /* Make sure _settings is filled with _settings_newgame if we switch to a game directly */ + if (_switch_mode != SM_NONE) _settings = _settings_newgame; /* initialize the ingame console */ IConsoleInit(); @@ -651,7 +644,7 @@ { if (_game_mode == GM_MENU) { // do not ask to quit on the main screen _exit_game = true; - } else if (_patches.autosave_on_exit) { + } else if (_settings.gui.autosave_on_exit) { DoExitSave(); _exit_game = true; } else { @@ -683,9 +676,9 @@ SetLocalPlayer(PLAYER_FIRST); _current_player = _local_player; - DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE); + DoCommandP(0, (_settings.gui.autorenew << 15 ) | (_settings.gui.autorenew_months << 16) | 4, _settings.gui.autorenew_money, NULL, CMD_SET_AUTOREPLACE); - SettingsDisableElrail(_patches.disable_elrails); + SettingsDisableElrail(_settings.vehicle.disable_elrails); InitializeRailGUI(); #ifdef ENABLE_NETWORK @@ -710,7 +703,7 @@ _industry_mngr.ResetMapping(); GenerateWorldSetCallback(&MakeNewGameDone); - GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y); + GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y); } static void MakeNewEditorWorldDone() @@ -727,7 +720,7 @@ ResetGRFConfig(true); GenerateWorldSetCallback(&MakeNewEditorWorldDone); - GenerateWorld(GW_EMPTY, 1 << _patches.map_x, 1 << _patches.map_y); + GenerateWorld(GW_EMPTY, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y); } void StartupPlayers(); @@ -766,9 +759,7 @@ ShowErrorMessage(INVALID_STRING_ID, STR_012D, 0, 0); } - _opt_ptr = &_opt; - _opt_ptr->diff = _opt_newgame.diff; - _opt.diff_level = _opt_newgame.diff_level; + _settings.difficulty = _settings_newgame.difficulty; /* Inititalize data */ StartupEconomy(); @@ -778,7 +769,7 @@ SetLocalPlayer(PLAYER_FIRST); _current_player = _local_player; - DoCommandP(0, (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE); + DoCommandP(0, (_settings.gui.autorenew << 15 ) | (_settings.gui.autorenew_months << 16) | 4, _settings.gui.autorenew_money, NULL, CMD_SET_AUTOREPLACE); MarkWholeScreenDirty(); } @@ -837,8 +828,7 @@ /* check if we should reload the config */ if (_network_reload_cfg) { LoadFromConfig(); - _patches = _patches_newgame; - _opt = _opt_newgame; + _settings = _settings_newgame; ResetGRFConfig(false); } NetworkServerStart(); @@ -874,7 +864,6 @@ break; case SM_LOAD: { /* Load game, Play Scenario */ - _opt_ptr = &_opt; ResetGRFConfig(true); ResetWindowSystem(); @@ -912,16 +901,14 @@ case SM_LOAD_HEIGHTMAP: /* Load heightmap from scenario editor */ SetLocalPlayer(OWNER_NONE); - GenerateWorld(GW_HEIGHTMAP, 1 << _patches.map_x, 1 << _patches.map_y); + GenerateWorld(GW_HEIGHTMAP, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y); MarkWholeScreenDirty(); break; case SM_LOAD_SCENARIO: { /* Load scenario from scenario editor */ if (SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_EDITOR, NO_DIRECTORY)) { - _opt_ptr = &_opt; - SetLocalPlayer(OWNER_NONE); - _patches_newgame.starting_year = _cur_year; + _settings_newgame.game_creation.starting_year = _cur_year; } else { SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(INVALID_STRING_ID, STR_012D, 0, 0); @@ -947,7 +934,7 @@ case SM_GENRANDLAND: /* Generate random land within scenario editor */ SetLocalPlayer(OWNER_NONE); - GenerateWorld(GW_RANDOM, 1 << _patches.map_x, 1 << _patches.map_y); + GenerateWorld(GW_RANDOM, 1 << _settings.game_creation.map_x, 1 << _settings.game_creation.map_y); /* XXX: set date */ MarkWholeScreenDirty(); break; @@ -1063,16 +1050,16 @@ if (_networking) return; #endif /* PSP */ - if (_patches.keep_all_autosave && _local_player != PLAYER_SPECTATOR) { + if (_settings.gui.keep_all_autosave && _local_player != PLAYER_SPECTATOR) { SetDParam(0, _local_player); SetDParam(1, _date); GetString(buf, STR_4004, lastof(buf)); ttd_strlcat(buf, ".sav", lengthof(buf)); } else { - /* generate a savegame name and number according to _patches.max_num_autosaves */ + /* generate a savegame name and number according to _settings.gui.max_num_autosaves */ snprintf(buf, sizeof(buf), "autosave%d.sav", _autosave_ctr); - if (++_autosave_ctr >= _patches.max_num_autosaves) _autosave_ctr = 0; + if (++_autosave_ctr >= _settings.gui.max_num_autosaves) _autosave_ctr = 0; } DEBUG(sl, 2, "Autosaving to '%s'", buf); @@ -1262,7 +1249,7 @@ /* since savegame version 4.2 the currencies are arranged differently */ static void UpdateCurrencies() { - _opt.currency = convert_currency[_opt.currency]; + _settings.gui.currency = convert_currency[_settings.gui.currency]; } /* Up to revision 1413 the invisible tiles at the southern border have not been @@ -1370,6 +1357,11 @@ SetCachedEngineCounts(); + /* Towns have a noise controlled number of airports system + * So each airport's noise value must be added to the town->noise_reached value + * Reset each town's noise_reached value to '0' before. */ + UpdateAirportsNoise(); + return true; } @@ -1420,7 +1412,7 @@ Town *t; FOR_ALL_TOWNS(t) { t->name = CopyFromOldName(t->townnametype); - if (t->name != NULL) t->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name; + if (t->name != NULL) t->townnametype = SPECSTR_TOWNNAME_START + _settings.game_creation.town_name; } Waypoint *wp; @@ -1434,7 +1426,7 @@ ResetOldNames(); /* convert road side to my format. */ - if (_opt.road_side) _opt.road_side = 1; + if (_settings.vehicle.road_side) _settings.vehicle.road_side = 1; /* Check if all NewGRFs are present, we are very strict in MP mode */ GRFListCompatibility gcf_res = IsGoodGRFConfigList(); @@ -1454,7 +1446,7 @@ SetDate(_date); /* Force dynamic engines off when loading older savegames */ - if (CheckSavegameVersion(95)) _patches.dynamic_engines = 0; + if (CheckSavegameVersion(95)) _settings.vehicle.dynamic_engines = 0; /* Load the sprites */ GfxLoadSprites(); @@ -1687,9 +1679,9 @@ */ if (!_network_dedicated && IsValidPlayer(PLAYER_FIRST)) { p = GetPlayer(PLAYER_FIRST); - p->engine_renew = _patches.autorenew; - p->engine_renew_months = _patches.autorenew_months; - p->engine_renew_money = _patches.autorenew_money; + p->engine_renew = _settings.gui.autorenew; + p->engine_renew_months = _settings.gui.autorenew_months; + p->engine_renew_money = _settings.gui.autorenew_money; } } @@ -1971,8 +1963,6 @@ } } - if (CheckSavegameVersion(22)) UpdatePatches(); - if (CheckSavegameVersion(25)) { Vehicle *v; FOR_ALL_VEHICLES(v) { @@ -2074,9 +2064,9 @@ /* from version 38 we have optional elrails, since we cannot know the * preference of a user, let elrails enabled; it can be disabled manually */ - if (CheckSavegameVersion(38)) _patches.disable_elrails = false; + if (CheckSavegameVersion(38)) _settings.vehicle.disable_elrails = false; /* do the same as when elrails were enabled/disabled manually just now */ - SettingsDisableElrail(_patches.disable_elrails); + SettingsDisableElrail(_settings.vehicle.disable_elrails); InitializeRailGUI(); /* From version 53, the map array was changed for house tiles to allow @@ -2241,7 +2231,7 @@ Town *t; FOR_ALL_TOWNS(t) { - if (_patches.larger_towns != 0 && (t->index % _patches.larger_towns) == 0) { + if (_settings.economy.larger_towns != 0 && (t->index % _settings.economy.larger_towns) == 0) { t->larger_town = true; } } @@ -2278,12 +2268,12 @@ if (CheckSavegameVersion(58)) { /* patch difficulty number_industries other then zero get bumped to +1 * since a new option (very low at position1) has been added */ - if (_opt.diff.number_industries > 0) { - _opt.diff.number_industries++; + if (_settings.difficulty.number_industries > 0) { + _settings.difficulty.number_industries++; } /* Same goes for number of towns, although no test is needed, just an increment */ - _opt.diff.number_towns++; + _settings.difficulty.number_towns++; } if (CheckSavegameVersion(64)) { @@ -2516,22 +2506,22 @@ } /* Convert old PF settings to new */ - if (_patches.yapf.rail_use_yapf || CheckSavegameVersion(28)) { - _patches.pathfinder_for_trains = VPF_YAPF; + if (_settings.pf.yapf.rail_use_yapf || CheckSavegameVersion(28)) { + _settings.pf.pathfinder_for_trains = VPF_YAPF; } else { - _patches.pathfinder_for_trains = (_patches.new_pathfinding_all ? VPF_NPF : VPF_NTP); + _settings.pf.pathfinder_for_trains = (_settings.pf.new_pathfinding_all ? VPF_NPF : VPF_NTP); } - if (_patches.yapf.road_use_yapf || CheckSavegameVersion(28)) { - _patches.pathfinder_for_roadvehs = VPF_YAPF; + if (_settings.pf.yapf.road_use_yapf || CheckSavegameVersion(28)) { + _settings.pf.pathfinder_for_roadvehs = VPF_YAPF; } else { - _patches.pathfinder_for_roadvehs = (_patches.new_pathfinding_all ? VPF_NPF : VPF_OPF); + _settings.pf.pathfinder_for_roadvehs = (_settings.pf.new_pathfinding_all ? VPF_NPF : VPF_OPF); } - if (_patches.yapf.ship_use_yapf) { - _patches.pathfinder_for_ships = VPF_YAPF; + if (_settings.pf.yapf.ship_use_yapf) { + _settings.pf.pathfinder_for_ships = VPF_YAPF; } else { - _patches.pathfinder_for_ships = (_patches.new_pathfinding_all ? VPF_NPF : VPF_OPF); + _settings.pf.pathfinder_for_ships = (_settings.pf.new_pathfinding_all ? VPF_NPF : VPF_OPF); } } diff -r 68a692eacf22 -r 67db0d431d5e src/order_cmd.cpp --- a/src/order_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/order_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -152,11 +152,15 @@ void Order::ConvertFromOldSavegame() { - /* First handle non-stop, because those bits are going to be reused. */ - if (_patches.sg_new_nonstop) { - this->SetNonStopType((this->flags & 0x08) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + uint8 old_flags = this->flags; + this->flags = 0; + + /* First handle non-stop */ + if (_settings.gui.sg_new_nonstop) { + /* OFB_NON_STOP */ + this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); } else { - this->SetNonStopType((this->flags & 0x08) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE); + this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE); } switch (this->GetType()) { @@ -165,31 +169,31 @@ default: return; } - /* Then the load/depot action flags because those bits are going to be reused too - * and they reuse the non-stop bits. */ if (this->GetType() != OT_GOTO_DEPOT) { - if ((this->flags & 4) == 0) { + /* Then the load flags */ + if ((old_flags & 2) != 0) { // OFB_UNLOAD + this->SetLoadType(OLFB_NO_LOAD); + } else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD this->SetLoadType(OLF_LOAD_IF_POSSIBLE); } else { - this->SetLoadType(_patches.sg_full_load_any ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD); + this->SetLoadType(_settings.gui.sg_full_load_any ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD); + } + + /* Finally fix the unload flags */ + if ((old_flags & 1) != 0) { // OFB_TRANSFER + this->SetUnloadType(OUFB_TRANSFER); + } else if ((old_flags & 2) != 0) { // OFB_UNLOAD + this->SetUnloadType(OUFB_UNLOAD); + } else { + this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE); } } else { - this->SetDepotActionType(((this->flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY); - } + /* Then the depot action flags */ + this->SetDepotActionType(((old_flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY); - /* Finally fix the unload/depot type flags. */ - if (this->GetType() != OT_GOTO_DEPOT) { - uint t = ((this->flags & 1) == 0) ? OUF_UNLOAD_IF_POSSIBLE : OUFB_TRANSFER; - if ((this->flags & 2) != 0) t |= OUFB_UNLOAD; - this->SetUnloadType((OrderUnloadFlags)t); - - if ((this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == (OUFB_UNLOAD | OUFB_TRANSFER)) { - this->SetUnloadType(OUFB_TRANSFER); - this->SetLoadType(OLFB_NO_LOAD); - } - } else { - uint t = ((this->flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL; - if ((this->flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS; + /* Finally fix the depot type flags */ + uint t = ((old_flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL; + if ((old_flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS; this->SetDepotOrderType((OrderDepotTypeFlags)t); } } @@ -451,7 +455,7 @@ if (!HasOrderPoolFree(1)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS); - if (v->type == VEH_SHIP && IsHumanPlayer(v->owner) && _patches.pathfinder_for_ships != VPF_NPF) { + if (v->type == VEH_SHIP && IsHumanPlayer(v->owner) && _settings.pf.pathfinder_for_ships != VPF_NPF) { /* Make sure the new destination is not too far away from the previous */ const Order *prev = NULL; uint n = 0; @@ -546,7 +550,7 @@ } /* Make sure to rebuild the whole list */ - RebuildVehicleLists(); + InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); } return CommandCost(); @@ -561,7 +565,7 @@ if (flags & DC_EXEC) { DeleteVehicleOrders(dst); InvalidateVehicleOrder(dst); - RebuildVehicleLists(); + InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0); } return CommandCost(); } @@ -673,7 +677,7 @@ cur_order_id++; } - RebuildVehicleLists(); + InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); } return CommandCost(); @@ -811,7 +815,7 @@ } /* Make sure to rebuild the whole list */ - RebuildVehicleLists(); + InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); } return CommandCost(); @@ -1075,7 +1079,7 @@ InvalidateVehicleOrder(dst); InvalidateVehicleOrder(src); - RebuildVehicleLists(); + InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0); } } break; @@ -1134,7 +1138,7 @@ InvalidateVehicleOrder(dst); - RebuildVehicleLists(); + InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0); } } break; @@ -1273,7 +1277,7 @@ } /* Copy timetable if enabled */ - if (_patches.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25), + if (_settings.order.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25), bak->order[i].wait_time << 16 | bak->order[i].travel_time, NULL, CMD_CHANGE_TIMETABLE | CMD_NO_TEST_IF_IN_NETWORK)) { break; @@ -1386,13 +1390,13 @@ void CheckOrders(const Vehicle* v) { /* Does the user wants us to check things? */ - if (_patches.order_review_system == 0) return; + if (_settings.gui.order_review_system == 0) return; /* Do nothing for crashed vehicles */ if (v->vehstatus & VS_CRASHED) return; /* Do nothing for stopped vehicles if setting is '1' */ - if (_patches.order_review_system == 1 && v->vehstatus & VS_STOPPED) + if (_settings.gui.order_review_system == 1 && v->vehstatus & VS_STOPPED) return; /* do nothing we we're not the first vehicle in a share-chain */ @@ -1571,7 +1575,7 @@ Date GetServiceIntervalClamped(uint index) { - return (_patches.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS); + return (_settings.vehicle.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS); } /** diff -r 68a692eacf22 -r 67db0d431d5e src/order_gui.cpp --- a/src/order_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/order_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -265,13 +265,13 @@ order.index = 0; /* check depot first */ - if (_patches.gotodepot) { + if (_settings.order.gotodepot) { switch (GetTileType(tile)) { case MP_RAILWAY: if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_player)) { if (IsRailDepot(tile)) { order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS); - if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + if (_settings.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); return order; } } @@ -280,7 +280,7 @@ case MP_ROAD: if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_player)) { order.MakeGoToDepot(GetDepotByTile(tile)->index, ODTFB_PART_OF_ORDERS); - if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + if (_settings.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); return order; } break; @@ -313,7 +313,7 @@ IsTileOwner(tile, _local_player) && IsRailWaypoint(tile)) { order.MakeGoToWaypoint(GetWaypointByTile(tile)->index); - if (_patches.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + if (_settings.gui.new_nonstop) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); return order; } @@ -330,7 +330,7 @@ (facil = FACIL_TRUCK_STOP, 1); if (st->facilities & facil) { order.MakeGoToStation(st_index); - if (_patches.new_nonstop && (v->type == VEH_TRAIN || v->type == VEH_ROAD)) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); + if (_settings.gui.new_nonstop && (v->type == VEH_TRAIN || v->type == VEH_ROAD)) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS); return order; } } @@ -611,7 +611,7 @@ this->resize.step_height = 10; this->selected_order = -1; this->vehicle = v; - if (_patches.timetabling) { + if (_settings.order.timetabling) { this->widget[ORDER_WIDGET_CAPTION].right -= 61; } else { this->HideWidget(ORDER_WIDGET_TIMETABLE_VIEW); @@ -926,7 +926,7 @@ ResetObjectToPlace(); } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { static const KeyToEvent keytoevent[] = { {'D', OrderClick_Skip}, @@ -939,15 +939,15 @@ //('?', OrderClick_Service}, }; - if (this->vehicle->owner != _local_player) return true; + if (this->vehicle->owner != _local_player) return ES_NOT_HANDLED; for (uint i = 0; i < lengthof(keytoevent); i++) { if (keycode == keytoevent[i].keycode) { keytoevent[i].proc(this, -1); - return false; + return ES_HANDLED; } } - return true; + return ES_NOT_HANDLED; } virtual void OnPlaceObject(Point pt, TileIndex tile) @@ -1063,7 +1063,6 @@ WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE, _orders_train_widgets, - NULL }; /** @@ -1104,7 +1103,6 @@ WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE, _orders_widgets, - NULL }; /** @@ -1145,7 +1143,6 @@ WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _other_orders_widgets, - NULL }; void ShowOrdersWindow(const Vehicle *v) diff -r 68a692eacf22 -r 67db0d431d5e src/osk_gui.cpp --- a/src/osk_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/osk_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -283,12 +283,11 @@ { WIDGETS_END}, }; -WindowDesc _osk_desc = { +static const WindowDesc _osk_desc = { WDP_CENTER, WDP_CENTER, 256, 140, 256, 140, WC_OSK, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _osk_widgets, - NULL }; /** @@ -346,7 +345,7 @@ } /** - * Show the osk associated with a given textbox + * Show the on-screen keyboard (osk) associated with a given textbox * @param parent pointer to the Window where this keyboard originated from * @param q querystr_d pointer to the query string of the parent, which is * shared for both windows diff -r 68a692eacf22 -r 67db0d431d5e src/pathfind.cpp --- a/src/pathfind.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/pathfind.cpp Tue May 27 00:50:55 2008 +0000 @@ -778,7 +778,7 @@ tpf->enum_proc = enum_proc; tpf->tracktype = TRANSPORT_RAIL; tpf->railtypes = railtypes; - tpf->maxlength = min(_patches.pf_maxlength * 3, 10000); + tpf->maxlength = min(_settings.pf.opf.pf_maxlength * 3, 10000); tpf->nstack = 0; tpf->new_link = tpf->links; tpf->num_links_left = lengthof(tpf->links); diff -r 68a692eacf22 -r 67db0d431d5e src/player_gui.cpp --- a/src/player_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/player_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -165,6 +165,8 @@ this->top = top; this->left = left; } + + this->FindWindowPlacementAndResize(desc); } virtual void OnPaint() @@ -230,7 +232,6 @@ WC_FINANCES, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, _player_finances_widgets, - NULL }; static const WindowDesc _player_finances_small_desc = { @@ -238,7 +239,6 @@ WC_FINANCES, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, _player_finances_small_widgets, - NULL }; /** @@ -543,7 +543,6 @@ WC_PLAYER_COLOR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _select_player_livery_widgets, - NULL }; /** @@ -758,10 +757,9 @@ } public: - SelectPlayerFaceWindow(const WindowDesc *desc, Window *parent, bool advanced) : Window(desc, parent->window_number) + SelectPlayerFaceWindow(const WindowDesc *desc, Window *parent, bool advanced, int top, int left) : Window(desc, parent->window_number) { this->parent = parent; - this->FindWindowPlacementAndResize(desc); this->caption_color = this->window_number; this->face = GetPlayer((PlayerID)this->window_number)->face; this->advanced = advanced; @@ -773,6 +771,8 @@ this->top = top; this->left = left; } + + this->FindWindowPlacementAndResize(desc); } virtual void OnPaint() @@ -1010,7 +1010,6 @@ WC_PLAYER_FACE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _select_player_face_widgets, - NULL }; /** advanced player face selection window description */ @@ -1019,7 +1018,6 @@ WC_PLAYER_FACE, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _select_player_face_adv_widgets, - NULL }; /** @@ -1037,7 +1035,7 @@ if (!IsValidPlayer((PlayerID)parent->window_number)) return; if (BringWindowToFrontById(WC_PLAYER_FACE, parent->window_number)) return; - new SelectPlayerFaceWindow(adv ? &_select_player_face_adv_desc : &_select_player_face_desc, parent, adv); // simple or advanced window + new SelectPlayerFaceWindow(adv ? &_select_player_face_adv_desc : &_select_player_face_desc, parent, adv, top, left); // simple or advanced window } @@ -1172,6 +1170,7 @@ PlayerCompanyWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) { this->caption_color = this->window_number; + this->FindWindowPlacementAndResize(desc); } virtual void OnPaint() @@ -1192,7 +1191,7 @@ this->SetWidgetHiddenState(PCW_WIDGET_COMPANY_PASSWORD, !local || !_networking); if (!local) { - if (_patches.allow_shares) { // Shares are allowed + if (_settings.economy.allow_shares) { // Shares are allowed /* If all shares are owned by someone (none by nobody), disable buy button */ this->SetWidgetDisabledState(PCW_WIDGET_BUY_SHARE, GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 0 || /* Only 25% left to buy. If the player is human, disable buying it up.. TODO issues! */ @@ -1348,7 +1347,6 @@ WC_COMPANY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _player_company_widgets, - NULL }; void ShowPlayerCompany(PlayerID player) @@ -1360,35 +1358,39 @@ -static void BuyCompanyWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - Player *p = GetPlayer((PlayerID)w->window_number); - SetDParam(0, STR_COMPANY_NAME); - SetDParam(1, p->index); - w->DrawWidgets(); - - DrawPlayerFace(p->face, p->player_color, 2, 16); +struct BuyCompanyWindow : Window { + BuyCompanyWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + } - SetDParam(0, p->index); - SetDParam(1, p->bankrupt_value); - DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238); - } break; + virtual void OnPaint() + { + Player *p = GetPlayer((PlayerID)this->window_number); + SetDParam(0, STR_COMPANY_NAME); + SetDParam(1, p->index); + this->DrawWidgets(); - case WE_CLICK: - switch (e->we.click.widget) { - case 3: - delete w; - break; - case 4: { - DoCommandP(0, w->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY)); - break; - } - } - break; + DrawPlayerFace(p->face, p->player_color, 2, 16); + + SetDParam(0, p->index); + SetDParam(1, p->bankrupt_value); + DrawStringMultiCenter(214, 65, STR_705B_WE_ARE_LOOKING_FOR_A_TRANSPORT, 238); } -} + + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case 3: + delete this; + break; + + case 4: + DoCommandP(0, this->window_number, 0, NULL, CMD_BUY_COMPANY | CMD_MSG(STR_7060_CAN_T_BUY_COMPANY)); + break; + } + } +}; static const Widget _buy_company_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 5, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -1404,13 +1406,12 @@ WC_BUY_COMPANY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _buy_company_widgets, - BuyCompanyWndProc }; void ShowBuyCompanyDialog(uint player) { - AllocateWindowDescFront(&_buy_company_desc, player); + AllocateWindowDescFront(&_buy_company_desc, player); } /********** HIGHSCORE and ENDGAME windows */ @@ -1476,7 +1477,7 @@ } else { /* in single player _local player is always valid */ const Player *p = GetPlayer(_local_player); - this->window_number = _opt.diff_level; + this->window_number = _settings.difficulty.diff_level; this->rank = SaveHighScoreValue(p); } @@ -1544,7 +1545,7 @@ this->SetupHighScoreEndWindow(&x, &y); - SetDParam(0, _patches.ending_year); + SetDParam(0, _settings.gui.ending_year); SetDParam(1, this->window_number + STR_6801_EASY); DrawStringMultiCenter(x + (640 / 2), y + 62, !_networking ? STR_0211_TOP_COMPANIES_WHO_REACHED : STR_TOP_COMPANIES_NETWORK_GAME, 500); @@ -1575,7 +1576,6 @@ WC_HIGHSCORE, WC_NONE, 0, _highscore_widgets, - NULL }; static const WindowDesc _endgame_desc = { @@ -1583,7 +1583,6 @@ WC_ENDSCREEN, WC_NONE, 0, _highscore_widgets, - NULL }; /** Show the highscore table for a given difficulty. When called from diff -r 68a692eacf22 -r 67db0d431d5e src/players.cpp --- a/src/players.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/players.cpp Tue May 27 00:50:55 2008 +0000 @@ -65,9 +65,9 @@ /* Do not update the patches if we are in the intro GUI */ if (IsValidPlayer(new_player) && _game_mode != GM_MENU) { const Player *p = GetPlayer(new_player); - _patches.autorenew = p->engine_renew; - _patches.autorenew_months = p->engine_renew_months; - _patches.autorenew_money = p->engine_renew_money; + _settings.gui.autorenew = p->engine_renew; + _settings.gui.autorenew_months = p->engine_renew_months; + _settings.gui.autorenew_money = p->engine_renew_money; InvalidateWindow(WC_GAME_OPTIONS, 0); } } @@ -541,9 +541,9 @@ /* Engine renewal settings */ p->engine_renew_list = NULL; p->renew_keep_length = false; - p->engine_renew = _patches_newgame.autorenew; - p->engine_renew_months = _patches_newgame.autorenew_months; - p->engine_renew_money = _patches_newgame.autorenew_money; + p->engine_renew = _settings_newgame.gui.autorenew; + p->engine_renew_months = _settings_newgame.gui.autorenew_months; + p->engine_renew_money = _settings_newgame.gui.autorenew_money; GeneratePresidentName(p); @@ -563,7 +563,7 @@ void StartupPlayers() { /* The AI starts like in the setting with +2 month max */ - _next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1; + _next_competitor_start = _settings.difficulty.competitor_start_time * 90 * DAY_TICKS + RandomRange(60 * DAY_TICKS) + 1; } static void MaybeStartNewPlayer() @@ -578,10 +578,10 @@ } /* when there's a lot of computers in game, the probability that a new one starts is lower */ - if (n < (uint)_opt.diff.max_no_competitors && + if (n < (uint)_settings.difficulty.max_no_competitors && n < (_network_server ? - InteractiveRandomRange(_opt.diff.max_no_competitors + 2) : - RandomRange(_opt.diff.max_no_competitors + 2) + InteractiveRandomRange(_settings.difficulty.max_no_competitors + 2) : + RandomRange(_settings.difficulty.max_no_competitors + 2) )) { /* Send a command to all clients to start up a new AI. * Works fine for Multiplayer and Singleplayer */ @@ -589,7 +589,7 @@ } /* The next AI starts like the difficulty setting said, with +2 month max */ - _next_competitor_start = _opt.diff.competitor_start_time * 90 * DAY_TICKS + 1; + _next_competitor_start = _settings.difficulty.competitor_start_time * 90 * DAY_TICKS + 1; _next_competitor_start += _network_server ? InteractiveRandomRange(60 * DAY_TICKS) : RandomRange(60 * DAY_TICKS); } @@ -630,7 +630,7 @@ } } - if (_patches.show_finances && _local_player != PLAYER_SPECTATOR) { + if (_settings.gui.show_finances && _local_player != PLAYER_SPECTATOR) { ShowPlayerFinances(_local_player); p = GetPlayer(_local_player); if (p->num_valid_stat_ent > 5 && p->old_economy[0].performance_history < p->old_economy[4].performance_history) { @@ -695,7 +695,7 @@ if (flags & DC_EXEC) { p->engine_renew = HasBit(p2, 0); if (IsLocalPlayer()) { - _patches.autorenew = p->engine_renew; + _settings.gui.autorenew = p->engine_renew; InvalidateWindow(WC_GAME_OPTIONS, 0); } } @@ -708,7 +708,7 @@ if (flags & DC_EXEC) { p->engine_renew_months = (int16)p2; if (IsLocalPlayer()) { - _patches.autorenew_months = p->engine_renew_months; + _settings.gui.autorenew_months = p->engine_renew_months; InvalidateWindow(WC_GAME_OPTIONS, 0); } } @@ -721,7 +721,7 @@ if (flags & DC_EXEC) { p->engine_renew_money = p2; if (IsLocalPlayer()) { - _patches.autorenew_money = p->engine_renew_money; + _settings.gui.autorenew_money = p->engine_renew_money; InvalidateWindow(WC_GAME_OPTIONS, 0); } } @@ -771,9 +771,9 @@ p->engine_renew_money = p2; if (IsLocalPlayer()) { - _patches.autorenew = p->engine_renew; - _patches.autorenew_months = p->engine_renew_months; - _patches.autorenew_money = p->engine_renew_money; + _settings.gui.autorenew = p->engine_renew; + _settings.gui.autorenew_months = p->engine_renew_months; + _settings.gui.autorenew_money = p->engine_renew_money; InvalidateWindow(WC_GAME_OPTIONS, 0); } } @@ -876,8 +876,8 @@ /* Now that we have a new player, broadcast its autorenew settings to * all clients so everything is in sync */ DoCommand(0, - (_patches.autorenew << 15 ) | (_patches.autorenew_months << 16) | 4, - _patches.autorenew_money, + (_settings.gui.autorenew << 15 ) | (_settings.gui.autorenew_months << 16) | 4, + _settings.gui.autorenew_money, DC_EXEC, CMD_SET_AUTOREPLACE ); @@ -994,7 +994,7 @@ /** Save the highscore for the player */ int8 SaveHighScoreValue(const Player *p) { - HighScore *hs = _highscore_table[_opt.diff_level]; + HighScore *hs = _highscore_table[_settings.difficulty.diff_level]; uint i; uint16 score = p->old_economy[0].performance_history; @@ -1122,7 +1122,7 @@ } /* Initialize end of game variable (when to show highscore chart) */ - _patches.ending_year = 2051; + _settings.gui.ending_year = 2051; } /* Save/load of players */ diff -r 68a692eacf22 -r 67db0d431d5e src/querystring_gui.h --- a/src/querystring_gui.h Mon May 26 20:45:25 2008 +0000 +++ b/src/querystring_gui.h Tue May 27 00:50:55 2008 +0000 @@ -17,7 +17,7 @@ void DrawEditBox(Window *w, int wid); void HandleEditBox(Window *w, int wid); - int HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, bool &cont); + int HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, Window::EventState &state); }; struct QueryStringBaseWindow : public Window, public QueryString { @@ -30,7 +30,7 @@ void DrawEditBox(int wid); void HandleEditBox(int wid); - int HandleEditBoxKey(int wid, uint16 key, uint16 keycode, bool &cont); + int HandleEditBoxKey(int wid, uint16 key, uint16 keycode, EventState &state); }; void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button, int cancel, int ok); diff -r 68a692eacf22 -r 67db0d431d5e src/rail.cpp --- a/src/rail.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/rail.cpp Tue May 27 00:50:55 2008 +0000 @@ -207,7 +207,7 @@ FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) { const EngineInfo *ei = &e->info; - if (HasBit(ei->climates, _opt.landscape) && + if (HasBit(ei->climates, _settings.game_creation.landscape) && (HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) { const RailVehicleInfo *rvi = &e->u.rail; diff -r 68a692eacf22 -r 67db0d431d5e src/rail_cmd.cpp --- a/src/rail_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/rail_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -292,7 +292,7 @@ /* check track/slope combination */ if ((f_new == FOUNDATION_INVALID) || - ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player)) + ((f_new != FOUNDATION_NONE) && (!_settings.construction.build_on_slopes || _is_old_ai_player)) ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); Foundation f_old = GetRailFoundation(tileh, existing); @@ -756,7 +756,7 @@ if (tileh != SLOPE_FLAT && ( _is_old_ai_player || - !_patches.build_on_slopes || + !_settings.construction.build_on_slopes || IsSteepSlope(tileh) || !CanBuildDepotByTileh(dir, tileh) )) { @@ -1224,7 +1224,7 @@ RailType type = GetRailType(tile); /* Converting to the same type or converting 'hidden' elrail -> rail */ - if (type == totype || (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue; + if (type == totype || (_settings.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue; /* Trying to convert other's rail */ if (!CheckTileOwnership(tile)) continue; @@ -1420,7 +1420,7 @@ static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos) { - bool side = (_opt.road_side != 0) && _patches.signal_side; + bool side = (_settings.vehicle.road_side != 0) && _settings.construction.signal_side; static const Point SignalPositions[2][12] = { { /* Signals on the left side */ /* LEFT LEFT RIGHT RIGHT UPPER UPPER */ @@ -1789,7 +1789,7 @@ /* adjust ground tile for desert * don't adjust for snow, because snow in depots looks weird */ - if (IsSnowRailGround(ti->tile) && _opt.landscape == LT_TROPIC) { + if (IsSnowRailGround(ti->tile) && _settings.game_creation.landscape == LT_TROPIC) { if (image != SPR_FLAT_GRASS_TILE) { image += rti->snow_offset; // tile with tracks } else { @@ -1953,7 +1953,7 @@ return; } - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_ARCTIC: { uint z; Slope slope = GetTileSlope(tile, &z); @@ -2173,7 +2173,7 @@ static void GetTileDesc_Track(TileIndex tile, TileDesc *td) { - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); switch (GetRailTileType(tile)) { case RAIL_TILE_NORMAL: td->str = STR_1021_RAILROAD_TRACK; @@ -2329,7 +2329,7 @@ */ static CommandCost TestAutoslopeOnRailTile(TileIndex tile, uint flags, uint z_old, Slope tileh_old, uint z_new, Slope tileh_new, TrackBits rail_bits) { - if (!_patches.build_on_slopes || !AutoslopeEnabled()) return CMD_ERROR; + if (!_settings.construction.build_on_slopes || !AutoslopeEnabled()) return CMD_ERROR; /* Is the slope-rail_bits combination valid in general? I.e. is it save to call GetRailFoundation() ? */ if (CmdFailed(CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile))) return CMD_ERROR; @@ -2405,7 +2405,7 @@ /* allow terraforming */ return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0); } else { - if (_patches.build_on_slopes && AutoslopeEnabled()) { + if (_settings.construction.build_on_slopes && AutoslopeEnabled()) { switch (GetRailTileType(tile)) { case RAIL_TILE_WAYPOINT: { CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); diff -r 68a692eacf22 -r 67db0d431d5e src/rail_gui.cpp --- a/src/rail_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/rail_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -42,33 +42,33 @@ #include "table/sprites.h" #include "table/strings.h" -static RailType _cur_railtype; -static bool _remove_button_clicked; -static DiagDirection _build_depot_direction; -static byte _waypoint_count = 1; -static byte _cur_waypoint_type; -static bool _convert_signal_button; ///< convert signal button in the signal GUI pressed -static SignalVariant _cur_signal_variant; ///< set the signal variant (for signal GUI) -static SignalType _cur_signal_type; ///< set the signal type (for signal GUI) +static RailType _cur_railtype; ///< Rail type of the current build-rail toolbar. +static bool _remove_button_clicked; ///< Flag whether 'remove' toggle-button is currently enabled +static DiagDirection _build_depot_direction; ///< Currently selected depot direction +static byte _waypoint_count = 1; ///< Number of waypoint types +static byte _cur_waypoint_type; ///< Currently selected waypoint type +static bool _convert_signal_button; ///< convert signal button in the signal GUI pressed +static SignalVariant _cur_signal_variant; ///< set the signal variant (for signal GUI) +static SignalType _cur_signal_type; ///< set the signal type (for signal GUI) static struct { - byte orientation; - byte numtracks; - byte platlength; - bool dragdrop; + byte orientation; ///< Currently selected rail station orientation + byte numtracks; ///< Currently selected number of tracks in station (if not \c dragdrop ) + byte platlength; ///< Currently selected platform length of station (if not \c dragdrop ) + bool dragdrop; ///< Use drag & drop to place a station - bool newstations; - StationClassIDByte station_class; - byte station_type; - byte station_count; + bool newstations; ///< Are custom station definitions available? + StationClassIDByte station_class; ///< Currently selected custom station class (if newstations is \c true ) + byte station_type; ///< Station type within the currently selected custom station class (if newstations is \c true ) + byte station_count; ///< Number of custom stations (if newstations is \c true ) } _railstation; static void HandleStationPlacement(TileIndex start, TileIndex end); -static void ShowBuildTrainDepotPicker(); -static void ShowBuildWaypointPicker(); -static void ShowStationBuilder(); -static void ShowSignalBuilder(); +static void ShowBuildTrainDepotPicker(Window *parent); +static void ShowBuildWaypointPicker(Window *parent); +static void ShowStationBuilder(Window *parent); +static void ShowSignalBuilder(Window *parent); void CcPlaySound1E(bool success, TileIndex tile, uint32 p1, uint32 p2) { @@ -111,6 +111,12 @@ VpStartPlaceSizing(tile, VPM_RAILDIRS, DDSP_PLACE_AUTORAIL); } +/** + * Try to add an additional rail-track at the entrance of a depot + * @param tile Tile to use for adding the rail-track + * @param extra Track to add + * @see CcRailDepot() + */ static void PlaceExtraDepotRail(TileIndex tile, uint16 extra) { if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return; @@ -119,10 +125,11 @@ DoCommandP(tile, _cur_railtype, extra & 0xFF, NULL, CMD_BUILD_SINGLE_RAIL | CMD_NO_WATER); } +/** Additional pieces of track to add at the entrance of a depot. */ static const uint16 _place_depot_extra[12] = { - 0x0604, 0x2102, 0x1202, 0x0505, - 0x2400, 0x2801, 0x1800, 0x1401, - 0x2203, 0x0904, 0x0A05, 0x1103, + 0x0604, 0x2102, 0x1202, 0x0505, // First additional track for directions 0..3 + 0x2400, 0x2801, 0x1800, 0x1401, // Second additional track + 0x2203, 0x0904, 0x0A05, 0x1103, // Third additional track }; @@ -175,7 +182,7 @@ VpSetPlaceSizingLimit(-1); } else if (_railstation.dragdrop) { VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_BUILD_STATION); - VpSetPlaceSizingLimit(_patches.station_spread); + VpSetPlaceSizingLimit(_settings.station.station_spread); } else { DoCommandP(tile, _railstation.orientation | (_railstation.numtracks << 8) | (_railstation.platlength << 16) | (_ctrl_pressed << 24), @@ -220,7 +227,7 @@ SB(p1, 7, 1, _convert_signal_button); } else { SB(p1, 3, 1, _ctrl_pressed); - SB(p1, 4, 1, (_cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC)); + SB(p1, 4, 1, (_cur_year < _settings.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC)); SB(p1, 5, 2, SIGTYPE_NORMAL); SB(p1, 7, 1, 0); } @@ -235,6 +242,7 @@ VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_BUILD_BRIDGE); } +/** Command callback for building a tunnel */ void CcBuildRailTunnel(bool success, TileIndex tile, uint32 p1, uint32 p2) { if (success) { @@ -285,7 +293,7 @@ }; -/** Toogles state of the Remove button of Build rail toolbar +/** Toggles state of the Remove button of Build rail toolbar * @param w window the button belongs to */ static void ToggleRailButton_Remove(Window *w) @@ -316,77 +324,143 @@ } +/** + * The "rail N"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_N(Window *w) { HandlePlacePushButton(w, RTW_BUILD_NS, GetRailTypeInfo(_cur_railtype)->cursor.rail_ns, VHM_RECT, PlaceRail_N); } +/** + * The "rail NE"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_NE(Window *w) { HandlePlacePushButton(w, RTW_BUILD_X, GetRailTypeInfo(_cur_railtype)->cursor.rail_swne, VHM_RECT, PlaceRail_NE); } +/** + * The "rail E"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_E(Window *w) { HandlePlacePushButton(w, RTW_BUILD_EW, GetRailTypeInfo(_cur_railtype)->cursor.rail_ew, VHM_RECT, PlaceRail_E); } +/** + * The "rail NW"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_NW(Window *w) { HandlePlacePushButton(w, RTW_BUILD_Y, GetRailTypeInfo(_cur_railtype)->cursor.rail_nwse, VHM_RECT, PlaceRail_NW); } +/** + * The "auto-rail"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_AutoRail(Window *w) { HandlePlacePushButton(w, RTW_AUTORAIL, GetRailTypeInfo(_cur_railtype)->cursor.autorail, VHM_RAIL, PlaceRail_AutoRail); } +/** + * The "demolish"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Demolish(Window *w) { HandlePlacePushButton(w, RTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea); } +/** + * The "build depot"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Depot(Window *w) { if (HandlePlacePushButton(w, RTW_BUILD_DEPOT, GetRailTypeInfo(_cur_railtype)->cursor.depot, VHM_RECT, PlaceRail_Depot)) { - ShowBuildTrainDepotPicker(); + ShowBuildTrainDepotPicker(w); } } +/** + * The "build waypoint"-button click proc of the build-rail toolbar. + * If there are newGRF waypoints, also open a window to pick the waypoint type. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Waypoint(Window *w) { _waypoint_count = GetNumCustomStations(STAT_CLASS_WAYP); if (HandlePlacePushButton(w, RTW_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, VHM_RECT, PlaceRail_Waypoint) && _waypoint_count > 1) { - ShowBuildWaypointPicker(); + ShowBuildWaypointPicker(w); } } +/** + * The "build station"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Station(Window *w) { - if (HandlePlacePushButton(w, RTW_BUILD_STATION, SPR_CURSOR_RAIL_STATION, VHM_RECT, PlaceRail_Station)) ShowStationBuilder(); + if (HandlePlacePushButton(w, RTW_BUILD_STATION, SPR_CURSOR_RAIL_STATION, VHM_RECT, PlaceRail_Station)) ShowStationBuilder(w); } -/** The "build signal"-button proc from BuildRailToolbWndProc() (start ShowSignalBuilder() and/or HandleAutoSignalPlacement()) */ +/** + * The "build signal"-button click proc of the build-rail toolbar. + * Start ShowSignalBuilder() and/or HandleAutoSignalPlacement(). + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_AutoSignals(Window *w) { - if (_patches.enable_signal_gui != _ctrl_pressed) { - if (HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals)) ShowSignalBuilder(); + if (_settings.gui.enable_signal_gui != _ctrl_pressed) { + if (HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals)) ShowSignalBuilder(w); } else { HandlePlacePushButton(w, RTW_BUILD_SIGNALS, ANIMCURSOR_BUILDSIGNALS, VHM_RECT, PlaceRail_AutoSignals); } } +/** + * The "build bridge"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Bridge(Window *w) { HandlePlacePushButton(w, RTW_BUILD_BRIDGE, SPR_CURSOR_BRIDGE, VHM_RECT, PlaceRail_Bridge); } +/** + * The "build tunnel"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Tunnel(Window *w) { HandlePlacePushButton(w, RTW_BUILD_TUNNEL, GetRailTypeInfo(_cur_railtype)->cursor.tunnel, VHM_SPECIAL, PlaceRail_Tunnel); } +/** + * The "remove"-button click proc of the build-rail toolbar. + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Remove(Window *w) { if (w->IsWidgetDisabled(RTW_REMOVE)) return; @@ -410,12 +484,18 @@ if (_railstation.orientation == 0) Swap(x, y); SetTileSelectSize(x, y); } else { - VpSetPlaceSizingLimit(_patches.station_spread); + VpSetPlaceSizingLimit(_settings.station.station_spread); } } } } +/** + * The "convert-rail"-button click proc of the build-rail toolbar. + * Switches to 'convert-rail' mode + * @param w Build-rail toolbar window + * @see BuildRailToolbWndProc() + */ static void BuildRailClick_Convert(Window *w) { HandlePlacePushButton(w, RTW_CONVERT_RAIL, GetRailTypeInfo(_cur_railtype)->cursor.convert, VHM_RECT, PlaceRail_ConvertRail); @@ -467,15 +547,15 @@ SB(p2, 3, 1, 0); SB(p2, 4, 1, _cur_signal_variant); SB(p2, 6, 1, _ctrl_pressed); - SB(p2, 24, 8, _patches.drag_signals_density); + SB(p2, 24, 8, _settings.gui.drag_signals_density); } else { SB(p2, 3, 1, 0); - SB(p2, 4, 1, (_cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC)); + SB(p2, 4, 1, (_cur_year < _settings.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC)); SB(p2, 6, 1, _ctrl_pressed); - SB(p2, 24, 8, _patches.drag_signals_density); + SB(p2, 24, 8, _settings.gui.drag_signals_density); } - /* _patches.drag_signals_density is given as a parameter such that each user + /* _settings.gui.drag_signals_density is given as a parameter such that each user * in a network game can specify his/her own signal density */ DoCommandP( TileVirtXY(thd->selstart.x, thd->selstart.y), @@ -526,90 +606,105 @@ }; -static void UpdateRemoveWidgetStatus(Window *w, int clicked_widget) -{ - switch (clicked_widget) { - case RTW_REMOVE: - /* If it is the removal button that has been clicked, do nothing, - * as it is up to the other buttons to drive removal status */ - return; - break; - case RTW_BUILD_NS: - case RTW_BUILD_X: - case RTW_BUILD_EW: - case RTW_BUILD_Y: - case RTW_AUTORAIL: - case RTW_BUILD_WAYPOINT: - case RTW_BUILD_STATION: - case RTW_BUILD_SIGNALS: - /* Removal button is enabled only if the rail/signal/waypoint/station - * button is still lowered. Once raised, it has to be disabled */ - w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget)); - break; - - default: - /* When any other buttons than rail/signal/waypoint/station, raise and - * disable the removal button */ - w->DisableWidget(RTW_REMOVE); - w->RaiseWidget(RTW_REMOVE); - break; - } -} +/** + * Based on the widget clicked, update the status of the 'remove' button. + * @param w Rail toolbar window + * @param clicked_widget Widget clicked in the toolbar + */ +struct BuildRailToolbarWindow : Window { + BuildRailToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->DisableWidget(RTW_REMOVE); -/** - * Railway toolbar window event definition - * - * @param w window pointer - * @param e event been triggered - */ -static void BuildRailToolbWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: w->DisableWidget(RTW_REMOVE); break; - - case WE_PAINT: w->DrawWidgets(); break; + this->FindWindowPlacementAndResize(desc); + if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this); + } - case WE_CLICK: - if (e->we.click.widget >= RTW_BUILD_NS) { - _remove_button_clicked = false; - _build_railroad_button_proc[e->we.click.widget - RTW_BUILD_NS](w); + ~BuildRailToolbarWindow() + { + if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); + } + + void UpdateRemoveWidgetStatus(int clicked_widget) + { + switch (clicked_widget) { + case RTW_REMOVE: + /* If it is the removal button that has been clicked, do nothing, + * as it is up to the other buttons to drive removal status */ + return; + break; + case RTW_BUILD_NS: + case RTW_BUILD_X: + case RTW_BUILD_EW: + case RTW_BUILD_Y: + case RTW_AUTORAIL: + case RTW_BUILD_WAYPOINT: + case RTW_BUILD_STATION: + case RTW_BUILD_SIGNALS: + /* Removal button is enabled only if the rail/signal/waypoint/station + * button is still lowered. Once raised, it has to be disabled */ + this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget)); + break; + + default: + /* When any other buttons than rail/signal/waypoint/station, raise and + * disable the removal button */ + this->DisableWidget(RTW_REMOVE); + this->RaiseWidget(RTW_REMOVE); + break; } - UpdateRemoveWidgetStatus(w, e->we.click.widget); - if (_ctrl_pressed) RailToolbar_CtrlChanged(w); - break; + } - case WE_KEYPRESS: + virtual void OnPaint() + { + this->DrawWidgets(); + } + + virtual void OnClick(Point pt, int widget) + { + if (widget >= RTW_BUILD_NS) { + _remove_button_clicked = false; + _build_railroad_button_proc[widget - RTW_BUILD_NS](this); + } + this->UpdateRemoveWidgetStatus(widget); + if (_ctrl_pressed) RailToolbar_CtrlChanged(this); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + EventState state = ES_NOT_HANDLED; for (uint8 i = 0; i != lengthof(_rail_keycodes); i++) { - if (e->we.keypress.keycode == _rail_keycodes[i]) { - e->we.keypress.cont = false; + if (keycode == _rail_keycodes[i]) { _remove_button_clicked = false; - _build_railroad_button_proc[i](w); - UpdateRemoveWidgetStatus(w, i + RTW_BUILD_NS); - if (_ctrl_pressed) RailToolbar_CtrlChanged(w); + _build_railroad_button_proc[i](this); + this->UpdateRemoveWidgetStatus(i + RTW_BUILD_NS); + if (_ctrl_pressed) RailToolbar_CtrlChanged(this); + state = ES_HANDLED; break; } } MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection - break; - - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - return; - - case WE_PLACE_DRAG: { - /* no dragging if you have pressed the convert button */ - if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && w->IsWidgetLowered(RTW_BUILD_SIGNALS)) return; - - VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); - return; + return state; } - case WE_PLACE_MOUSEUP: - if (e->we.place.pt.x != -1) { - TileIndex start_tile = e->we.place.starttile; - TileIndex end_tile = e->we.place.tile; + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } - switch (e->we.place.select_proc) { + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) + { + /* no dragging if you have pressed the convert button */ + if (FindWindowById(WC_BUILD_SIGNAL, 0) != NULL && _convert_signal_button && this->IsWidgetLowered(RTW_BUILD_SIGNALS)) return; + + VpSelectTilesWithMethod(pt.x, pt.y, select_method); + } + + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + { + if (pt.x != -1) { + switch (select_proc) { + default: NOT_REACHED(); case DDSP_BUILD_BRIDGE: ResetObjectToPlace(); ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype); @@ -624,7 +719,7 @@ break; case DDSP_DEMOLISH_AREA: - GUIPlaceProcDragXY(e); + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; case DDSP_CONVERT_RAIL: @@ -642,39 +737,36 @@ case DDSP_PLACE_RAIL_NE: case DDSP_PLACE_RAIL_NW: - DoRailroadTrack(e->we.place.select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y); + DoRailroadTrack(select_proc == DDSP_PLACE_RAIL_NE ? TRACK_X : TRACK_Y); break; } } - break; + } - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); - w->DisableWidget(RTW_REMOVE); - w->InvalidateWidget(RTW_REMOVE); + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + this->DisableWidget(RTW_REMOVE); + this->InvalidateWidget(RTW_REMOVE); delete FindWindowById(WC_BUILD_SIGNAL, 0); delete FindWindowById(WC_BUILD_STATION, 0); delete FindWindowById(WC_BUILD_DEPOT, 0); - break; + } - case WE_PLACE_PRESIZE: { - TileIndex tile = e->we.place.tile; - + virtual void OnPlacePresize(Point pt, TileIndex tile) + { DoCommand(tile, 0, 0, DC_AUTO, CMD_BUILD_TUNNEL); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); - } break; - - case WE_DESTROY: - if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); - break; + } - case WE_CTRL_CHANGED: + virtual EventState OnCTRLStateChange() + { /* do not toggle Remove button by Ctrl when placing station */ - if (!w->IsWidgetLowered(RTW_BUILD_STATION) && RailToolbar_CtrlChanged(w)) e->we.ctrl.cont = false; - break; + if (!this->IsWidgetLowered(RTW_BUILD_STATION) && RailToolbar_CtrlChanged(this)) return ES_HANDLED; + return ES_NOT_HANDLED; } -} +}; /** Widget definition for the rail toolbar */ static const Widget _build_rail_widgets[] = { @@ -709,7 +801,6 @@ WC_BUILD_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _build_rail_widgets, - BuildRailToolbWndProc }; @@ -733,27 +824,37 @@ w->widget[RTW_BUILD_TUNNEL].data = rti->gui_sprites.build_tunnel; } +/** + * Open the build rail toolbar window for a specific rail type. + * The window may be opened in the 'normal' way by clicking at the rail icon in + * the main toolbar, or by means of selecting one of the functions of the + * toolbar. In the latter case, the corresponding widget is also selected. + * + * If the terraform toolbar is linked to the toolbar, that window is also opened. + * + * @param railtype Rail type to open the window for + * @param button Widget clicked (\c -1 means no button clicked) + */ void ShowBuildRailToolbar(RailType railtype, int button) { - Window *w; + BuildRailToolbarWindow *w; if (!IsValidPlayer(_current_player)) return; if (!ValParamRailtype(railtype)) return; // don't recreate the window if we're clicking on a button and the window exists. - if (button < 0 || !(w = FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL))) { + if (button < 0 || !(w = dynamic_cast(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_RAIL)))) { DeleteWindowByClass(WC_BUILD_TOOLBAR); _cur_railtype = railtype; - w = AllocateWindowDescFront(&_build_rail_desc, TRANSPORT_RAIL); + w = AllocateWindowDescFront(&_build_rail_desc, TRANSPORT_RAIL); SetupRailToolbar(railtype, w); } _remove_button_clicked = false; if (w != NULL && button >= RTW_CLOSEBOX) { _build_railroad_button_proc[button](w); - UpdateRemoveWidgetStatus(w, button + RTW_BUILD_NS); + w->UpdateRemoveWidgetStatus(button + RTW_BUILD_NS); } - if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w); } /* TODO: For custom stations, respect their allowed platforms/lengths bitmasks! @@ -818,11 +919,16 @@ BRSW_NEWST_SCROLL }; - /* Check if the currently selected station size is allowed */ + /** + * Verify whether the currently selected station size is allowed after selecting a new station class/type. + * If not, change the station size variables ( _railstation.numtracks and _railstation.platlength ). + * @param statspec Specification of the new station class/type + */ void CheckSelectedSize(const StationSpec *statspec) { if (statspec == NULL || _railstation.dragdrop) return; + /* If current number of tracks is not allowed, make it as big as possible (which is always less than currently selected) */ if (HasBit(statspec->disallowed_platforms, _railstation.numtracks - 1)) { this->RaiseWidget(_railstation.numtracks + BRSW_PLATFORM_NUM_BEGIN); _railstation.numtracks = 1; @@ -842,6 +948,7 @@ } } + /** Build a dropdown list of available station classes */ static DropDownList *BuildStationClassDropDown() { DropDownList *list = new DropDownList(); @@ -853,9 +960,14 @@ return list; } +/** + * Window event handler of station build window. + * @param w Staion build window + * @param e Window event to handle + */ public: - BuildRailStationWindow(const WindowDesc *desc, bool newstation) : PickerWindowBase(desc) + BuildRailStationWindow(const WindowDesc *desc, Window *parent, bool newstation) : PickerWindowBase(desc, parent) { this->LowerWidget(_railstation.orientation + BRSW_PLATFORM_DIR_X); if (_railstation.dragdrop) { @@ -899,13 +1011,13 @@ SetTileSelectSize(x, y); } - int rad = (_patches.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED; + int rad = (_settings.station.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED; if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); for (uint bits = 0; bits < 7; bits++) { - bool disable = bits >= _patches.station_spread; + bool disable = bits >= _settings.station.station_spread; if (statspec == NULL) { this->SetWidgetDisabledState(bits + BRSW_PLATFORM_NUM_1, disable); this->SetWidgetDisabledState(bits + BRSW_PLATFORM_LEN_1, disable); @@ -1207,28 +1319,29 @@ { WIDGETS_END}, }; +/** High level window description of the default station-build window */ static const WindowDesc _station_builder_desc = { WDP_AUTO, WDP_AUTO, 148, 200, 148, 200, WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _station_builder_widgets, - NULL }; +/** High level window description of the newGRF station-build window */ static const WindowDesc _newstation_builder_desc = { WDP_AUTO, WDP_AUTO, 148, 290, 148, 290, WC_BUILD_STATION, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _newstation_builder_widgets, - NULL }; -static void ShowStationBuilder() +/** Open station build window */ +static void ShowStationBuilder(Window *parent) { if (GetNumStationClasses() <= 2 && GetNumCustomStations(STAT_CLASS_DFLT) == 1) { - new BuildRailStationWindow(&_station_builder_desc, false); + new BuildRailStationWindow(&_station_builder_desc, parent, false); } else { - new BuildRailStationWindow(&_newstation_builder_desc, true); + new BuildRailStationWindow(&_newstation_builder_desc, parent, true); } } @@ -1269,7 +1382,7 @@ } public: - BuildSignalWindow(const WindowDesc *desc) : PickerWindowBase(desc) + BuildSignalWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { this->FindWindowPlacementAndResize(desc); }; @@ -1280,8 +1393,8 @@ this->SetWidgetLoweredState(BSW_CONVERT, _convert_signal_button); - this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_DECREASE, _patches.drag_signals_density == 1); - this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_INCREASE, _patches.drag_signals_density == 20); + this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_DECREASE, _settings.gui.drag_signals_density == 1); + this->SetWidgetDisabledState(BSW_DRAG_SIGNALS_DENSITY_INCREASE, _settings.gui.drag_signals_density == 20); this->DrawWidgets(); @@ -1296,7 +1409,7 @@ this->DrawSignalSprite(BSW_ELECTRIC_COMBO, SPR_IMG_SIGNAL_ELECTRIC_COMBO, -2, 6); /* Draw dragging signal density value in the BSW_DRAG_SIGNALS_DENSITY widget */ - SetDParam(0, _patches.drag_signals_density); + SetDParam(0, _settings.gui.drag_signals_density); DrawStringCentered(this->widget[BSW_DRAG_SIGNALS_DENSITY].left + (this->widget[BSW_DRAG_SIGNALS_DENSITY].right - this->widget[BSW_DRAG_SIGNALS_DENSITY].left) / 2 + 1, this->widget[BSW_DRAG_SIGNALS_DENSITY].top + 2, STR_JUST_INT, TC_ORANGE); @@ -1324,15 +1437,15 @@ break; case BSW_DRAG_SIGNALS_DENSITY_DECREASE: - if (_patches.drag_signals_density > 1) { - _patches.drag_signals_density--; + if (_settings.gui.drag_signals_density > 1) { + _settings.gui.drag_signals_density--; SetWindowDirty(FindWindowById(WC_GAME_OPTIONS, 0)); } break; case BSW_DRAG_SIGNALS_DENSITY_INCREASE: - if (_patches.drag_signals_density < 20) { - _patches.drag_signals_density++; + if (_settings.gui.drag_signals_density < 20) { + _settings.gui.drag_signals_density++; SetWindowDirty(FindWindowById(WC_GAME_OPTIONS, 0)); } break; @@ -1373,15 +1486,14 @@ WC_BUILD_SIGNAL, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _signal_builder_widgets, - NULL }; /** * Open the signal selection window */ -static void ShowSignalBuilder() +static void ShowSignalBuilder(Window *parent) { - new BuildSignalWindow(&_signal_builder_desc); + new BuildSignalWindow(&_signal_builder_desc, parent); } struct BuildRailDepotWindow : public PickerWindowBase { @@ -1398,7 +1510,7 @@ }; public: - BuildRailDepotWindow(const WindowDesc *desc) : PickerWindowBase(desc) + BuildRailDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { this->LowerWidget(_build_depot_direction + BRDW_DEPOT_NE); this->FindWindowPlacementAndResize(desc); @@ -1448,12 +1560,11 @@ WC_BUILD_DEPOT, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_depot_widgets, - NULL }; -static void ShowBuildTrainDepotPicker() +static void ShowBuildTrainDepotPicker(Window *parent) { - new BuildRailDepotWindow(&_build_depot_desc); + new BuildRailDepotWindow(&_build_depot_desc, parent); } struct BuildRailWaypointWindow : PickerWindowBase { @@ -1472,7 +1583,7 @@ }; public: - BuildRailWaypointWindow(const WindowDesc *desc) : PickerWindowBase(desc) + BuildRailWaypointWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { this->hscroll.cap = 5; this->hscroll.count = _waypoint_count; @@ -1550,15 +1661,16 @@ WC_BUILD_DEPOT, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_waypoint_widgets, - NULL }; -static void ShowBuildWaypointPicker() +static void ShowBuildWaypointPicker(Window *parent) { - new BuildRailWaypointWindow(&_build_waypoint_desc); + new BuildRailWaypointWindow(&_build_waypoint_desc, parent); } - +/** + * Initialize rail building GUI settings + */ void InitializeRailGui() { _build_depot_direction = DIAGDIR_NW; @@ -1567,6 +1679,10 @@ _railstation.dragdrop = true; } +/** + * Re-initialize rail-build toolbar after toggling support for electric trains + * @param disable Boolean whether electric trains are disabled (removed from the game) + */ void ReinitGuiAfterToggleElrail(bool disable) { extern RailType _last_built_railtype; @@ -1582,12 +1698,13 @@ MarkWholeScreenDirty(); } +/** Set the initial (default) railtype to use */ static void SetDefaultRailGui() { if (_local_player == PLAYER_SPECTATOR || !IsValidPlayer(_local_player)) return; extern RailType _last_built_railtype; - RailType rt = (RailType)_patches.default_rail_type; + RailType rt = (RailType)_settings.gui.default_rail_type; if (rt >= RAILTYPE_END) { if (rt == RAILTYPE_END + 2) { /* Find the most used rail type */ @@ -1639,7 +1756,7 @@ */ int32 ResetSignalVariant(int32 = 0) { - SignalVariant new_variant = (_cur_year < _patches.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); + SignalVariant new_variant = (_cur_year < _settings.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); if (new_variant != _cur_signal_variant) { Window *w = FindWindowById(WC_BUILD_SIGNAL, 0); diff -r 68a692eacf22 -r 67db0d431d5e src/road.cpp --- a/src/road.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/road.cpp Tue May 27 00:50:55 2008 +0000 @@ -103,7 +103,7 @@ FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) { const EngineInfo *ei = &e->info; - if (HasBit(ei->climates, _opt.landscape) && + if (HasBit(ei->climates, _settings.game_creation.landscape) && (HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) { SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD); } diff -r 68a692eacf22 -r 67db0d431d5e src/road_cmd.cpp --- a/src/road_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/road_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -43,6 +43,41 @@ #include "table/sprites.h" #include "table/strings.h" + +bool RoadVehiclesAreBuilt() +{ + const Vehicle* v; + + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_ROAD) return true; + } + return false; +} + +/** + * Change the side of the road vehicles drive on (server only). + * @param tile unused + * @param flags operation to perform + * @param p1 the side of the road; 0 = left side and 1 = right side + * @param p2 unused + */ +CommandCost CmdSetRoadDriveSide(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) +{ + /* Check boundaries and you can only change this if NO vehicles have been built yet, + * except in the intro-menu where of course it's always possible to do so. */ + if (p1 > 1 || (_game_mode != GM_MENU && RoadVehiclesAreBuilt())) return CMD_ERROR; + + if (flags & DC_EXEC) { + if (_game_mode == GM_MENU) { + _settings.vehicle.road_side = p1; + } else { + _settings.vehicle.road_side = p1; + } + InvalidateWindow(WC_GAME_OPTIONS, 0); + } + return CommandCost(); +} + #define M(x) (1 << (x)) /* Level crossings may only be built on these slopes */ static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT)); @@ -99,10 +134,18 @@ Foundation GetRoadFoundation(Slope tileh, RoadBits bits); -bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt) +/** + * Is it allowed to remove the given road bits from the given tile? + * @param tile the tile to remove the road from + * @param remove the roadbits that are going to be removed + * @param owner the actual owner of the roadbits of the tile + * @param rt the road type to remove the bits from + * @param flags command flags + * @param town_check Shall the town rating checked/affected + * @return true when it is allowed to remove the road bits + */ +bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, uint32 flags, bool town_check) { - *edge_road = true; - if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true; /* Water can always flood and towns can always remove "normal" road pieces. @@ -115,8 +158,17 @@ * by a town */ if (owner != OWNER_TOWN) return (owner == OWNER_NONE) || CheckOwnership(owner); + if (!town_check) return true; + if (_cheats.magic_bulldozer.value) return true; + Town *t = ClosestTownFromTile(tile, UINT_MAX); + if (t == NULL) return true; + + /* check if you're allowed to remove the street owned by a town + * removal allowance depends on difficulty setting */ + if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return false; + /* Get a bitmask of which neighbouring roads has a tile */ RoadBits n = ROAD_NONE; RoadBits present = GetAnyRoadBits(tile, rt); @@ -125,28 +177,23 @@ if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0), rt) & ROAD_NE) n |= ROAD_SW; if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1), rt) & ROAD_SE) n |= ROAD_NW; + int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE; /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove, * then allow it */ if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) { - *edge_road = false; /* you can remove all kind of roads with extra dynamite */ - if (_patches.extra_dynamite) return true; - - const Town *t = ClosestTownFromTile(tile, (uint)-1); - - SetDParam(0, t->index); - _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; - return false; + if (!_settings.construction.extra_dynamite) { + SetDParam(0, t->index); + _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; + return false; + } + rating_decrease = RATING_ROAD_DOWN_STEP_INNER; } + ChangeTownRating(t, rating_decrease, RATING_ROAD_MINIMUM); return true; } -static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt) -{ - return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt); -} - /** Delete a piece of road. * @param tile tile where to remove road from @@ -157,22 +204,20 @@ */ static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true) { - /* cost for removing inner/edge -roads */ - static const uint16 road_remove_cost[2] = {50, 18}; + RoadTypes rts = GetRoadTypes(tile); + /* The tile doesn't have the given road type */ + if (!HasBit(rts, rt)) return CMD_ERROR; - /* true if the roadpiece was always removeable, - * false if it was a center piece. Affects town ratings drop */ - bool edge_road; + bool town_road_under_stop = false; - Town *t = NULL; switch (GetTileType(tile)) { case MP_ROAD: - if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile); if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; break; case MP_STATION: if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; + if (rt == ROADTYPE_ROAD) town_road_under_stop = GetStopBuiltOnTownRoad(tile); if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; break; @@ -185,15 +230,7 @@ return CMD_ERROR; } - RoadTypes rts = GetRoadTypes(tile); - /* The tile doesn't have the given road type */ - if (!HasBit(rts, rt)) return CMD_ERROR; - - if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; - - /* check if you're allowed to remove the street owned by a town - * removal allowance depends on difficulty setting */ - if (town_check && !CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR; + if (!CheckAllowRemoveRoad(tile, pieces, town_road_under_stop ? OWNER_TOWN : GetRoadOwner(tile, rt), rt, flags, town_check)) return CMD_ERROR; if (!IsTileType(tile, MP_ROAD)) { /* If it's the last roadtype, just clear the whole tile */ @@ -242,7 +279,7 @@ * @li if build on slopes is disabled */ if (IsSteepSlope(tileh) || (IsStraightRoad(other) && (other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) || - (tileh != SLOPE_FLAT && !_patches.build_on_slopes)) { + (tileh != SLOPE_FLAT && !_settings.construction.build_on_slopes)) { pieces |= MirrorRoadBits(pieces); } @@ -259,7 +296,6 @@ return CMD_ERROR; } - if (town_check) ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); if (flags & DC_EXEC) { if (HasRoadWorks(tile)) { /* flooding tile with road works, don't forget to remove the effect vehicle too */ @@ -305,10 +341,6 @@ * we can't draw the crossing without trambits ;) */ if (rt == ROADTYPE_ROAD && HasTileRoadType(tile, ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR; - if (rt == ROADTYPE_ROAD) { - if (town_check) ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); - } - if (flags & DC_EXEC) { RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); if (rts == ROADTYPES_NONE) { @@ -387,7 +419,7 @@ RoadBits type_bits = existing | *pieces; /* Roads on slopes */ - if (_patches.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) { + if (_settings.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) { /* If we add leveling we've got to pay for it */ if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); @@ -407,7 +439,7 @@ if (IsSlopeWithOneCornerRaised(tileh)) { /* Prevent build on slopes if it isn't allowed */ - if (_patches.build_on_slopes) { + if (_settings.construction.build_on_slopes) { /* If we add foundation we've got to pay for it */ if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); @@ -470,7 +502,7 @@ } if ((existing & pieces) == pieces) { /* We only want to set the (dis)allowed road directions */ - if (toggle_drd != DRD_NONE && rt != ROADTYPE_TRAM && GetRoadOwner(tile, ROADTYPE_ROAD) == _current_player) { + if (toggle_drd != DRD_NONE && rt != ROADTYPE_TRAM && IsRoadOwner(tile, ROADTYPE_ROAD, _current_player)) { if (crossing) return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION); if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; @@ -562,7 +594,7 @@ CommandCost ret = CheckRoadSlope(tileh, &pieces, existing, other_bits); /* Return an error if we need to build a foundation (ret != 0) but the * current patch-setting is turned off (or stupid AI@work) */ - if (CmdFailed(ret) || (ret.GetCost() != 0 && !_patches.build_on_slopes)) { + if (CmdFailed(ret) || (ret.GetCost() != 0 && !_settings.construction.build_on_slopes)) { return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); } cost.AddCost(ret); @@ -628,6 +660,7 @@ case MP_STATION: SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); + if (IsDriveThroughStopTile(tile) && rt == ROADTYPE_ROAD) SetStopBuiltOnTownRoad(tile, false); break; default: @@ -816,7 +849,7 @@ Slope tileh = GetTileSlope(tile, NULL); if (tileh != SLOPE_FLAT && ( - !_patches.build_on_slopes || + !_settings.construction.build_on_slopes || IsSteepSlope(tileh) || !CanBuildDepotByTileh(dir, tileh) )) { @@ -863,7 +896,7 @@ /* Clear the road if only one piece is on the tile OR the AI tries * to clear town road OR we are not using the DC_AUTO flag */ if ((CountBits(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || - ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) || + ((flags & DC_AI_BUILDING) && GetOtherRoadBits(tile, ROADTYPE_ROAD) == ROAD_NONE && IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)) || !(flags & DC_AUTO) ) { RoadTypes rts = GetRoadTypes(tile); @@ -967,7 +1000,7 @@ static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside) { return (IsOnSnow(tile) && - !(_opt.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) && + !(_settings.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) && roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS)); } @@ -1258,7 +1291,7 @@ static void TileLoop_Road(TileIndex tile) { - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_ARCTIC: if (IsOnSnow(tile) != (GetTileZ(tile) > GetSnowLine())) { ToggleSnow(tile); @@ -1304,7 +1337,7 @@ { /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */ - const Roadside* new_rs = (_opt.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp]; + const Roadside* new_rs = (_settings.game_creation.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp]; Roadside cur_rs = GetRoadside(tile); /* We have our desired type, do nothing */ @@ -1326,7 +1359,7 @@ } else if (IncreaseRoadWorksCounter(tile)) { TerminateRoadWorks(tile); - if (_patches.mod_road_rebuild) { + if (_settings.economy.mod_road_rebuild) { /* Generate a nicer town surface */ const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD); const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); @@ -1415,11 +1448,53 @@ static void GetTileDesc_Road(TileIndex tile, TileDesc *td) { - td->owner = GetTileOwner(tile); + Owner rail_owner = INVALID_OWNER; + Owner road_owner = INVALID_OWNER; + Owner tram_owner = INVALID_OWNER; + switch (GetRoadTileType(tile)) { - case ROAD_TILE_CROSSING: td->str = STR_1818_ROAD_RAIL_LEVEL_CROSSING; break; - case ROAD_TILE_DEPOT: td->str = STR_1817_ROAD_VEHICLE_DEPOT; break; - default: td->str = _road_tile_strings[GetRoadside(tile)]; break; + case ROAD_TILE_CROSSING: { + td->str = STR_1818_ROAD_RAIL_LEVEL_CROSSING; + RoadTypes rts = GetRoadTypes(tile); + rail_owner = GetTileOwner(tile); + if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD); + if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM); + break; + } + + case ROAD_TILE_DEPOT: + td->str = STR_1817_ROAD_VEHICLE_DEPOT; + road_owner = GetTileOwner(tile); // Tile has only one owner, roadtype does not matter + break; + + default: { + RoadTypes rts = GetRoadTypes(tile); + td->str = (HasBit(rts, ROADTYPE_ROAD) ? _road_tile_strings[GetRoadside(tile)] : STR_TRAMWAY); + if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD); + if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM); + break; + } + } + + /* Now we have to discover, if the tile has only one owner or many: + * - Find a first_owner of the tile. (Currently road or tram must be present, but this will break when the third type becomes available) + * - Compare the found owner with the other owners, and test if they differ. + * Note: If road exists it will be the first_owner. + */ + Owner first_owner = (road_owner == INVALID_OWNER ? tram_owner : road_owner); + bool mixed_owners = (tram_owner != INVALID_OWNER && tram_owner != first_owner) || (rail_owner != INVALID_OWNER && rail_owner != first_owner); + + if (mixed_owners) { + /* Multiple owners */ + td->owner_type[0] = (rail_owner == INVALID_OWNER ? STR_NULL : STR_RAIL_OWNER); + td->owner[0] = rail_owner; + td->owner_type[1] = (road_owner == INVALID_OWNER ? STR_NULL : STR_ROAD_OWNER); + td->owner[1] = road_owner; + td->owner_type[2] = (tram_owner == INVALID_OWNER ? STR_NULL : STR_TRAM_OWNER); + td->owner[2] = tram_owner; + } else { + /* One to rule them all */ + td->owner[0] = first_owner; } } @@ -1476,9 +1551,7 @@ } for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { - /* ROADTYPE_ROAD denotes the tile owner, so update it too */ - if (rt != ROADTYPE_ROAD && !HasTileRoadType(tile, rt)) continue; - + /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rt) == old_player) { SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player); } @@ -1497,7 +1570,7 @@ static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) { - if (_patches.build_on_slopes && AutoslopeEnabled()) { + if (_settings.construction.build_on_slopes && AutoslopeEnabled()) { switch (GetRoadTileType(tile)) { case ROAD_TILE_CROSSING: if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); diff -r 68a692eacf22 -r 67db0d431d5e src/road_gui.cpp --- a/src/road_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/road_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -28,8 +28,8 @@ #include "table/sprites.h" #include "table/strings.h" -static void ShowRVStationPicker(RoadStopType rs); -static void ShowRoadDepotPicker(); +static void ShowRVStationPicker(Window *parent, RoadStopType rs); +static void ShowRoadDepotPicker(Window *parent); static bool _remove_button_clicked; static bool _one_way_button_clicked; @@ -324,19 +324,19 @@ static void BuildRoadClick_Depot(Window *w) { if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return; - if (HandlePlacePushButton(w, RTW_DEPOT, SPR_CURSOR_ROAD_DEPOT, VHM_RECT, PlaceRoad_Depot)) ShowRoadDepotPicker(); + if (HandlePlacePushButton(w, RTW_DEPOT, SPR_CURSOR_ROAD_DEPOT, VHM_RECT, PlaceRoad_Depot)) ShowRoadDepotPicker(w); } static void BuildRoadClick_BusStation(Window *w) { if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return; - if (HandlePlacePushButton(w, RTW_BUS_STATION, SPR_CURSOR_BUS_STATION, VHM_RECT, PlaceRoad_BusStation)) ShowRVStationPicker(ROADSTOP_BUS); + if (HandlePlacePushButton(w, RTW_BUS_STATION, SPR_CURSOR_BUS_STATION, VHM_RECT, PlaceRoad_BusStation)) ShowRVStationPicker(w, ROADSTOP_BUS); } static void BuildRoadClick_TruckStation(Window *w) { if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return; - if (HandlePlacePushButton(w, RTW_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, VHM_RECT, PlaceRoad_TruckStation)) ShowRVStationPicker(ROADSTOP_TRUCK); + if (HandlePlacePushButton(w, RTW_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, VHM_RECT, PlaceRoad_TruckStation)) ShowRVStationPicker(w, ROADSTOP_TRUCK); } /** @@ -400,217 +400,222 @@ 'R', }; -/** - * Update the remove button lowered state of the road toolbar - * - * @param w The toolbar window - * @param clicked_widget The widget which the player clicked just now - */ -static void UpdateOptionWidgetStatus(Window *w, RoadToolbarWidgets clicked_widget) -{ - /* The remove and the one way button state is driven - * by the other buttons so they don't act on themselfs. - * Both are only valid if they are able to apply as options. */ - switch (clicked_widget) { - case RTW_REMOVE: - w->RaiseWidget(RTW_ONE_WAY); - w->InvalidateWidget(RTW_ONE_WAY); - break; - - case RTW_ONE_WAY: - w->RaiseWidget(RTW_REMOVE); - w->InvalidateWidget(RTW_REMOVE); - break; - - case RTW_BUS_STATION: - case RTW_TRUCK_STATION: - w->DisableWidget(RTW_ONE_WAY); - w->SetWidgetDisabledState(RTW_REMOVE, !w->IsWidgetLowered(clicked_widget)); - break; +struct BuildRoadToolbarWindow : Window { + BuildRoadToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->SetWidgetsDisabledState(true, + RTW_REMOVE, + RTW_ONE_WAY, + WIDGET_LIST_END); - case RTW_ROAD_X: - case RTW_ROAD_Y: - case RTW_AUTOROAD: - w->SetWidgetsDisabledState(!w->IsWidgetLowered(clicked_widget), - RTW_REMOVE, - RTW_ONE_WAY, - WIDGET_LIST_END); - break; - - default: - /* When any other buttons than road/station, raise and - * disable the removal button */ - w->SetWidgetsDisabledState(true, - RTW_REMOVE, - RTW_ONE_WAY, - WIDGET_LIST_END); - w->SetWidgetsLoweredState (false, - RTW_REMOVE, - RTW_ONE_WAY, - WIDGET_LIST_END); - break; + this->FindWindowPlacementAndResize(desc); + if (_settings.gui.link_terraform_toolbar) ShowTerraformToolbar(this); } -} -static void BuildRoadToolbWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: - w->SetWidgetsDisabledState(true, - RTW_REMOVE, - RTW_ONE_WAY, - WIDGET_LIST_END); - break; + ~BuildRoadToolbarWindow() + { + if (_settings.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); + } - case WE_PAINT: - w->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD), - RTW_DEPOT, - RTW_BUS_STATION, - RTW_TRUCK_STATION, - WIDGET_LIST_END); - w->DrawWidgets(); - break; + /** + * Update the remove button lowered state of the road toolbar + * + * @param clicked_widget The widget which the player clicked just now + */ + void UpdateOptionWidgetStatus(RoadToolbarWidgets clicked_widget) + { + /* The remove and the one way button state is driven + * by the other buttons so they don't act on themselfs. + * Both are only valid if they are able to apply as options. */ + switch (clicked_widget) { + case RTW_REMOVE: + this->RaiseWidget(RTW_ONE_WAY); + this->InvalidateWidget(RTW_ONE_WAY); + break; - case WE_CLICK: - if (e->we.click.widget >= RTW_ROAD_X) { + case RTW_ONE_WAY: + this->RaiseWidget(RTW_REMOVE); + this->InvalidateWidget(RTW_REMOVE); + break; + + case RTW_BUS_STATION: + case RTW_TRUCK_STATION: + this->DisableWidget(RTW_ONE_WAY); + this->SetWidgetDisabledState(RTW_REMOVE, !this->IsWidgetLowered(clicked_widget)); + break; + + case RTW_ROAD_X: + case RTW_ROAD_Y: + case RTW_AUTOROAD: + this->SetWidgetsDisabledState(!this->IsWidgetLowered(clicked_widget), + RTW_REMOVE, + RTW_ONE_WAY, + WIDGET_LIST_END); + break; + + default: + /* When any other buttons than road/station, raise and + * disable the removal button */ + this->SetWidgetsDisabledState(true, + RTW_REMOVE, + RTW_ONE_WAY, + WIDGET_LIST_END); + this->SetWidgetsLoweredState (false, + RTW_REMOVE, + RTW_ONE_WAY, + WIDGET_LIST_END); + break; + } + } + + virtual void OnPaint() + { + this->SetWidgetsDisabledState(!CanBuildVehicleInfrastructure(VEH_ROAD), + RTW_DEPOT, + RTW_BUS_STATION, + RTW_TRUCK_STATION, + WIDGET_LIST_END); + this->DrawWidgets(); + } + + virtual void OnClick(Point pt, int widget) + { + if (widget >= RTW_ROAD_X) { + _remove_button_clicked = false; + _one_way_button_clicked = false; + _build_road_button_proc[widget - RTW_ROAD_X](this); + } + this->UpdateOptionWidgetStatus((RoadToolbarWidgets)widget); + if (_ctrl_pressed) RoadToolbar_CtrlChanged(this); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + EventState state = ES_NOT_HANDLED; + for (uint i = 0; i != lengthof(_road_keycodes); i++) { + if (keycode == _road_keycodes[i]) { _remove_button_clicked = false; _one_way_button_clicked = false; - _build_road_button_proc[e->we.click.widget - RTW_ROAD_X](w); + _build_road_button_proc[i](this); + this->UpdateOptionWidgetStatus((RoadToolbarWidgets)(i + RTW_ROAD_X)); + if (_ctrl_pressed) RoadToolbar_CtrlChanged(this); + state = ES_HANDLED; + break; } - UpdateOptionWidgetStatus(w, (RoadToolbarWidgets)e->we.click.widget); - if (_ctrl_pressed) RoadToolbar_CtrlChanged(w); - break; - - case WE_KEYPRESS: - for (uint i = 0; i != lengthof(_road_keycodes); i++) { - if (e->we.keypress.keycode == _road_keycodes[i]) { - e->we.keypress.cont = false; - _remove_button_clicked = false; - _one_way_button_clicked = false; - _build_road_button_proc[i](w); - UpdateOptionWidgetStatus(w, (RoadToolbarWidgets)(i + RTW_ROAD_X)); - if (_ctrl_pressed) RoadToolbar_CtrlChanged(w); - break; - } - } - MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection - break; - - case WE_PLACE_OBJ: - _remove_button_clicked = w->IsWidgetLowered(RTW_REMOVE); - _one_way_button_clicked = w->IsWidgetLowered(RTW_ONE_WAY); - _place_proc(e->we.place.tile); - break; + } + MarkTileDirty(_thd.pos.x, _thd.pos.y); // redraw tile selection + return state; + } - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); - w->SetWidgetsDisabledState(true, - RTW_REMOVE, - RTW_ONE_WAY, - WIDGET_LIST_END); - w->InvalidateWidget(RTW_REMOVE); - w->InvalidateWidget(RTW_ONE_WAY); - - delete FindWindowById(WC_BUS_STATION, 0); - delete FindWindowById(WC_TRUCK_STATION, 0); - delete FindWindowById(WC_BUILD_DEPOT, 0); - break; + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _remove_button_clicked = this->IsWidgetLowered(RTW_REMOVE); + _one_way_button_clicked = this->IsWidgetLowered(RTW_ONE_WAY); + _place_proc(tile); + } - case WE_PLACE_DRAG: - /* Here we update the end tile flags - * of the road placement actions. - * At first we reset the end halfroad - * bits and if needed we set them again. */ - switch (e->we.place.select_proc) { - case DDSP_PLACE_ROAD_X_DIR: - _place_road_flag &= ~RF_END_HALFROAD_X; - if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; - break; + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + this->SetWidgetsDisabledState(true, + RTW_REMOVE, + RTW_ONE_WAY, + WIDGET_LIST_END); + this->InvalidateWidget(RTW_REMOVE); + this->InvalidateWidget(RTW_ONE_WAY); - case DDSP_PLACE_ROAD_Y_DIR: - _place_road_flag &= ~RF_END_HALFROAD_Y; - if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; + delete FindWindowById(WC_BUS_STATION, 0); + delete FindWindowById(WC_TRUCK_STATION, 0); + delete FindWindowById(WC_BUILD_DEPOT, 0); + } + + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) + { + /* Here we update the end tile flags + * of the road placement actions. + * At first we reset the end halfroad + * bits and if needed we set them again. */ + switch (select_proc) { + case DDSP_PLACE_ROAD_X_DIR: + _place_road_flag &= ~RF_END_HALFROAD_X; + if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; + break; + + case DDSP_PLACE_ROAD_Y_DIR: + _place_road_flag &= ~RF_END_HALFROAD_Y; + if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; + break; + + case DDSP_PLACE_AUTOROAD: + _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X); + if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; + if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; + + /* For autoroad we need to update the + * direction of the road */ + if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y && + ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) || + (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) { + /* Set dir = X */ + _place_road_flag &= ~RF_DIR_Y; + } else { + /* Set dir = Y */ + _place_road_flag |= RF_DIR_Y; + } + + break; + + default: + break; + } + + VpSelectTilesWithMethod(pt.x, pt.y, select_method); + } + + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + { + if (pt.x != -1) { + switch (select_proc) { + default: NOT_REACHED(); + case DDSP_BUILD_BRIDGE: + ResetObjectToPlace(); + ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype)); break; - case DDSP_PLACE_AUTOROAD: - _place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X); - if (e->we.place.pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y; - if (e->we.place.pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X; - - /* For autoroad we need to update the - * direction of the road */ - if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y && - ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) || - (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) { - /* Set dir = X */ - _place_road_flag &= ~RF_DIR_Y; - } else { - /* Set dir = Y */ - _place_road_flag |= RF_DIR_Y; - } - + case DDSP_DEMOLISH_AREA: + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; - default: + case DDSP_PLACE_ROAD_X_DIR: + case DDSP_PLACE_ROAD_Y_DIR: + case DDSP_PLACE_AUTOROAD: + /* Flag description: + * Use the first three bits (0x07) if dir == Y + * else use the last 2 bits (X dir has + * not the 3rd bit set) */ + _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3)); + + DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D, + (_ctrl_pressed || _remove_button_clicked) ? + CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) : + CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road)); break; } - - VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); - return; - - case WE_PLACE_MOUSEUP: - if (e->we.place.pt.x != -1) { - TileIndex start_tile = e->we.place.starttile; - TileIndex end_tile = e->we.place.tile; - - switch (e->we.place.select_proc) { - default: NOT_REACHED(); - case DDSP_BUILD_BRIDGE: - ResetObjectToPlace(); - ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype)); - break; - - case DDSP_DEMOLISH_AREA: - GUIPlaceProcDragXY(e); - break; + } + } - case DDSP_PLACE_ROAD_X_DIR: - case DDSP_PLACE_ROAD_Y_DIR: - case DDSP_PLACE_AUTOROAD: - /* Flag description: - * Use the first three bits (0x07) if dir == Y - * else use the last 2 bits (X dir has - * not the 3rd bit set) */ - _place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3)); - - DoCommandP(end_tile, start_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5), CcPlaySound1D, - (_ctrl_pressed || _remove_button_clicked) ? - CMD_REMOVE_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) : - CMD_BUILD_LONG_ROAD | CMD_NO_WATER | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road)); - break; - } - } - break; + virtual void OnPlacePresize(Point pt, TileIndex tile) + { + DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL); + VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); + } - case WE_PLACE_PRESIZE: { - TileIndex tile = e->we.place.tile; - - DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL); - VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); - } break; - - case WE_DESTROY: - if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0); - break; - - case WE_CTRL_CHANGED: - if (RoadToolbar_CtrlChanged(w)) e->we.ctrl.cont = false; - break; - - default: - break; + virtual EventState OnCTRLStateChange() + { + if (RoadToolbar_CtrlChanged(this)) return ES_HANDLED; + return ES_NOT_HANDLED; } -} +}; /** Widget definition of the build road toolbar */ static const Widget _build_road_widgets[] = { @@ -638,7 +643,6 @@ WC_BUILD_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _build_road_widgets, - BuildRoadToolbWndProc }; /** Widget definition of the build tram toolbar */ @@ -667,7 +671,6 @@ WC_BUILD_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _build_tramway_widgets, - BuildRoadToolbWndProc }; void ShowBuildRoadToolbar(RoadType roadtype) @@ -676,8 +679,7 @@ _cur_roadtype = roadtype; DeleteWindowByClass(WC_BUILD_TOOLBAR); - Window *w = AllocateWindowDescFront(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD); - if (_patches.link_terraform_toolbar) ShowTerraformToolbar(w); + AllocateWindowDescFront(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD); } /** Widget definition of the build road toolbar in the scenario editor */ @@ -705,13 +707,12 @@ WC_SCEN_BUILD_ROAD, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _build_road_scen_widgets, - BuildRoadToolbWndProc }; void ShowBuildRoadScenToolbar() { _cur_roadtype = ROADTYPE_ROAD; - AllocateWindowDescFront(&_build_road_scen_desc, 0); + AllocateWindowDescFront(&_build_road_scen_desc, 0); } struct BuildRoadDepotWindow : public PickerWindowBase { @@ -728,7 +729,7 @@ }; public: - BuildRoadDepotWindow(const WindowDesc *desc) : PickerWindowBase(desc) + BuildRoadDepotWindow(const WindowDesc *desc, Window *parent) : PickerWindowBase(desc, parent) { this->LowerWidget(_road_depot_orientation + BRDW_DEPOT_NE); if ( _cur_roadtype == ROADTYPE_TRAM) { @@ -785,12 +786,11 @@ WC_BUILD_DEPOT, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_road_depot_widgets, - NULL }; -static void ShowRoadDepotPicker() +static void ShowRoadDepotPicker(Window *parent) { - new BuildRoadDepotWindow(&_build_road_depot_desc); + new BuildRoadDepotWindow(&_build_road_depot_desc, parent); } struct BuildRoadStationWindow : public PickerWindowBase { @@ -812,7 +812,7 @@ }; public: - BuildRoadStationWindow(const WindowDesc *desc, RoadStopType rs) : PickerWindowBase(desc) + BuildRoadStationWindow(const WindowDesc *desc, Window *parent, RoadStopType rs) : PickerWindowBase(desc, parent) { /* Trams don't have non-drivethrough stations */ if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) { @@ -842,7 +842,7 @@ _thd.FSMportMask = NULL; if (_station_show_coverage) { - int rad = _patches.modified_catchment ? CA_TRUCK /* = CA_BUS */ : CA_UNMODIFIED; + int rad = _settings.station.modified_catchment ? CA_TRUCK /* = CA_BUS */ : CA_UNMODIFIED; SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); } else { SetTileSelectSize(1, 1); @@ -931,12 +931,11 @@ WC_BUS_STATION, WC_BUILD_TOOLBAR, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _rv_station_picker_widgets, - NULL }; -static void ShowRVStationPicker(RoadStopType rs) +static void ShowRVStationPicker(Window *parent, RoadStopType rs) { - new BuildRoadStationWindow(&_rv_station_picker_desc, rs); + new BuildRoadStationWindow(&_rv_station_picker_desc, parent, rs); } void InitializeRoadGui() diff -r 68a692eacf22 -r 67db0d431d5e src/road_internal.h --- a/src/road_internal.h Mon May 26 20:45:25 2008 +0000 +++ b/src/road_internal.h Tue May 27 00:50:55 2008 +0000 @@ -20,11 +20,12 @@ * @param tile the tile to remove the road from * @param remove the roadbits that are going to be removed * @param owner the actual owner of the roadbits of the tile - * @param edge_road are the removed bits from a town? * @param rt the road type to remove the bits from + * @param flags command flags + * @param town_check Shall the town rating checked/affected * @return true when it is allowed to remove the road bits */ -bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt); +bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, uint32 flags, bool town_check = true); /** * Draw the catenary for tram road bits diff -r 68a692eacf22 -r 67db0d431d5e src/road_map.h --- a/src/road_map.h Mon May 26 20:45:25 2008 +0000 +++ b/src/road_map.h Tue May 27 00:50:55 2008 +0000 @@ -187,6 +187,12 @@ } } +static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o) +{ + assert(HasTileRoadType(t, rt)); + return (GetRoadOwner(t, rt) == o); +} + /** Which directions are disallowed ? */ enum DisallowedRoadDirections { DRD_NONE, ///< None of the directions are disallowed diff -r 68a692eacf22 -r 67db0d431d5e src/roadveh_cmd.cpp --- a/src/roadveh_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/roadveh_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -205,7 +205,7 @@ /* find the first free roadveh id */ unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_ROAD); - if (unit_num > _patches.max_roadveh) + if (unit_num > _settings.vehicle.max_roadveh) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); if (flags & DC_EXEC) { @@ -257,7 +257,7 @@ v->name = NULL; - v->service_interval = _patches.servint_roadveh; + v->service_interval = _settings.vehicle.servint_roadveh; v->date_of_last_service = _date; v->build_year = _cur_year; @@ -280,7 +280,7 @@ VehiclePositionChanged(v); InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); if (IsLocalPlayer()) InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window @@ -381,7 +381,7 @@ if (flags & DC_EXEC) { // Invalidate depot InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); DeleteWindowById(WC_VEHICLE_VIEW, v->index); DeleteDepotHighlightOfVehicle(v); @@ -419,7 +419,7 @@ static const Depot* FindClosestRoadDepot(const Vehicle* v) { - switch (_patches.pathfinder_for_roadvehs) { + switch (_settings.pf.pathfinder_for_roadvehs) { case VPF_YAPF: /* YAPF */ return YapfFindNearestRoadDepot(v); @@ -574,7 +574,7 @@ DeleteWindowById(WC_VEHICLE_VIEW, v->index); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v); @@ -702,7 +702,7 @@ InvalidateWindow(WC_VEHICLE_DETAILS, v->index); if (!PlayVehicleSound(v, VSE_BREAKDOWN)) { - SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ? + SndPlayVehicleFx((_settings.game_creation.landscape != LT_TOYLAND) ? SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v); } @@ -863,7 +863,7 @@ /* updates statusbar only if speed have changed to save CPU time */ if (spd != v->cur_speed) { v->cur_speed = spd; - if (_patches.vehicle_speed) { + if (_settings.gui.vehicle_speed) { InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } } @@ -1085,7 +1085,7 @@ trackdirs = TRACKDIR_BIT_NONE; } else { /* Proper station type, check if there is free loading bay */ - if (!_patches.roadveh_queue && IsStandardRoadStopTile(tile) && + if (!_settings.pf.roadveh_queue && IsStandardRoadStopTile(tile) && !GetRoadStopByTile(tile, rstype)->HasFreeBay()) { /* Station is full and RV queuing is off */ trackdirs = TRACKDIR_BIT_NONE; @@ -1124,7 +1124,7 @@ return_track(FindFirstBit2x64(trackdirs)); } - switch (_patches.pathfinder_for_roadvehs) { + switch (_settings.pf.pathfinder_for_roadvehs) { case VPF_YAPF: { /* YAPF */ Trackdir trackdir = YapfChooseRoadTrack(v, tile, enterdir); if (trackdir != INVALID_TRACKDIR) return_track(trackdir); @@ -1211,7 +1211,7 @@ static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile) { - if (_patches.pathfinder_for_roadvehs == VPF_YAPF) { + if (_settings.pf.pathfinder_for_roadvehs == VPF_YAPF) { /* use YAPF */ return YapfRoadVehDistanceToTile(v, tile); } @@ -1273,7 +1273,7 @@ v->direction = DiagDirToDir(dir); Trackdir tdir = _roadveh_depot_exit_trackdir[dir]; - const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + tdir]; + const RoadDriveEntry *rdp = _road_drive_data[v->u.road.roadtype][(_settings.vehicle.road_side << RVS_DRIVE_SIDE) + tdir]; int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF); int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); @@ -1451,7 +1451,7 @@ * In this case v->u.road.state is masked to give the road stop entry direction. */ rd = _road_drive_data[v->u.road.roadtype][( (HasBit(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) + - (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; + (_settings.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; if (rd.x & RDE_NEXT_TILE) { TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3)); @@ -1529,7 +1529,7 @@ } /* Get position data for first frame on the new tile */ - rdp = _road_drive_data[v->u.road.roadtype][(dir + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; + rdp = _road_drive_data[v->u.road.roadtype][(dir + (_settings.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking]; x = TileX(tile) * TILE_SIZE + rdp[start_frame].x; y = TileY(tile) * TILE_SIZE + rdp[start_frame].y; @@ -1632,7 +1632,7 @@ return false; } - rdp = _road_drive_data[v->u.road.roadtype][(_opt.road_side << RVS_DRIVE_SIDE) + dir]; + rdp = _road_drive_data[v->u.road.roadtype][(_settings.vehicle.road_side << RVS_DRIVE_SIDE) + dir]; x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x; y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y; @@ -1711,7 +1711,7 @@ * (the station test and stop type test ensure that other vehicles, using the road stop as * a through route, do not stop) */ if (IsRoadVehFront(v) && ((IsInsideMM(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && - _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) || + _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_settings.vehicle.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) || (IsInsideMM(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) && GetRoadStopType(v->tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? ROADSTOP_BUS : ROADSTOP_TRUCK) && @@ -1887,7 +1887,7 @@ static void CheckIfRoadVehNeedsService(Vehicle *v) { /* If we already got a slot at a stop, use that FIRST, and go to a depot later */ - if (v->u.road.slot != NULL || _patches.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return; + if (v->u.road.slot != NULL || _settings.vehicle.servint_roadveh == 0 || !v->NeedsAutomaticServicing()) return; if (v->IsInDepot()) { VehicleServiceInDepot(v); return; @@ -2116,7 +2116,7 @@ v->cargo_subtype = new_subtype; InvalidateWindow(WC_VEHICLE_DETAILS, v->index); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); } if (only_this) break; diff -r 68a692eacf22 -r 67db0d431d5e src/saveload.cpp --- a/src/saveload.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/saveload.cpp Tue May 27 00:50:55 2008 +0000 @@ -1534,7 +1534,7 @@ SaveFileDone(); } -static ThreadObject *save_thread; +static ThreadObject *_save_thread; /** We have written the whole game into memory, _Savegame_pool, now find * and appropiate compressor and start writing to file. @@ -1604,10 +1604,10 @@ void WaitTillSaved() { - if (save_thread == NULL) return; + if (_save_thread == NULL) return; - save_thread->Join(); - save_thread = NULL; + _save_thread->Join(); + _save_thread = NULL; } /** @@ -1679,7 +1679,7 @@ SaveFileStart(); if (_network_server || - (save_thread = ThreadObject::New(&SaveFileToDiskThread, NULL)) == NULL) { + (_save_thread = ThreadObject::New(&SaveFileToDiskThread, NULL)) == NULL) { if (!_network_server) DEBUG(sl, 1, "Cannot create savegame thread, reverting to single-threaded mode..."); SaveOrLoadResult result = SaveFileToDisk(false); @@ -1776,7 +1776,7 @@ } } -/** Do a save when exiting the game (patch option) _patches.autosave_on_exit */ +/** Do a save when exiting the game (patch option) _settings.gui.autosave_on_exit */ void DoExitSave() { SaveOrLoad("exit.sav", SL_SAVE, AUTOSAVE_DIR); diff -r 68a692eacf22 -r 67db0d431d5e src/saveload.h --- a/src/saveload.h Mon May 26 20:45:25 2008 +0000 +++ b/src/saveload.h Tue May 27 00:50:55 2008 +0000 @@ -13,7 +13,7 @@ #define SIZE_MAX ((size_t)-1) -static const uint NEWGRF_AIRPORTS_SAVEGAME = 96; +static const uint NEWGRF_AIRPORTS_SAVEGAME = 98; enum SaveOrLoadResult { SL_OK = 0, ///< completed successfully diff -r 68a692eacf22 -r 67db0d431d5e src/settings.cpp --- a/src/settings.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/settings.cpp Tue May 27 00:50:55 2008 +0000 @@ -28,7 +28,7 @@ #include "network/network_internal.h" #include "settings_internal.h" #include "command_func.h" -#include "console.h" +#include "console_func.h" #include "saveload.h" #include "npf.h" #include "yapf/yapf.h" @@ -60,14 +60,12 @@ #include "sound/sound_driver.hpp" #include "music/music_driver.hpp" #include "blitter/factory.hpp" +#include "station_func.h" #include "table/strings.h" -GameOptions _opt; -GameOptions _opt_newgame; -GameOptions *_opt_ptr; -Patches _patches; -Patches _patches_newgame; +Settings _settings; +Settings _settings_newgame; struct IniFile; struct IniItem; @@ -332,9 +330,11 @@ if (len == 0) len = strlen(name); /* does it exist already? */ - for (group = ini->group; group; group = group->next) - if (!memcmp(group->name, name, len) && group->name[len] == 0) + for (group = ini->group; group != NULL; group = group->next) { + if (!memcmp(group->name, name, len) && group->name[len] == 0) { return group; + } + } /* otherwise make a new one */ group = ini_group_alloc(ini, name, len); @@ -342,14 +342,37 @@ return group; } +static void ini_removegroup(IniFile *ini, const char *name) +{ + size_t len = strlen(name); + IniGroup *prev = NULL; + IniGroup *group; + + /* does it exist already? */ + for (group = ini->group; group != NULL; prev = group, group = group->next) { + if (memcmp(group->name, name, len) == 0) { + break; + } + } + + if (group == NULL) return; + + if (prev != NULL) { + prev->next = prev->next->next; + } else { + ini->group = ini->group->next; + } +} + /** lookup an item or make a new one */ static IniItem *ini_getitem(IniGroup *group, const char *name, bool create) { IniItem *item; size_t len = strlen(name); - for (item = group->item; item; item = item->next) + for (item = group->item; item != NULL; item = item->next) { if (strcmp(item->name, name) == 0) return item; + } if (!create) return NULL; @@ -718,7 +741,7 @@ if (!SlIsObjectCurrentlyValid(sld->version_from, sld->version_to)) continue; - /* XXX - wtf is this?? (group override?) */ + /* For patches.xx.yy load the settings from [xx] yy = ? */ s = strchr(sdb->name, '.'); if (s != NULL) { group = ini_getgroup(ini, sdb->name, s - sdb->name); @@ -729,8 +752,20 @@ } item = ini_getitem(group, s, false); + if (item == NULL && group != group_def) { + /* For patches.xx.yy load the settings from [patches] yy = ? in case the previous + * did not exist (e.g. loading old config files with a [patches] section */ + item = ini_getitem(group_def, s, false); + } + if (item == NULL) { + /* For patches.xx.zz.yy load the settings from [zz] yy = ? in case the previous + * did not exist (e.g. loading old config files with a [yapf] section */ + const char *sc = strchr(s, '.'); + if (sc != NULL) item = ini_getitem(ini_getgroup(ini, s, sc - s), sc + 1, false); + } + p = (item == NULL) ? sdb->def : string_to_val(sdb, item->value); - ptr = GetVariableAddress(object, sld); + ptr = GetVariableAddress(sld->global ? NULL : object, sld); switch (sdb->cmd) { case SDT_BOOLX: /* All four are various types of (integer) numbers */ @@ -758,8 +793,11 @@ break; case SDT_INTLIST: { - if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) + if (!load_intlist((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) { ShowInfoF("ini: error in array '%s'", sdb->name); + } else if (sd->desc.proc_cnvt != NULL) { + sd->desc.proc_cnvt((const char*)p); + } break; } default: NOT_REACHED(); break; @@ -1054,8 +1092,8 @@ SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to) #define SDT_LIST(base, var, type, flags, guiflags, def, str, proc)\ SDT_CONDLIST(base, var, type, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc) -#define SDT_CONDLISTO(base, var, length, type, from, to, flags, guiflags, def, str, proc)\ - SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, length, def, 0, 0, 0, NULL, str, proc, NULL, from, to) +#define SDT_CONDLISTO(base, var, length, type, from, to, flags, guiflags, def, str, proc, load)\ + SDT_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, base, var, length, def, 0, 0, 0, NULL, str, proc, load, from, to) #define SDT_CONDSTR(base, var, type, from, to, flags, guiflags, def, str, proc)\ SDT_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, base, var, lengthof(((base*)8)->var), def, 0, 0, 0, NULL, str, proc, NULL, from, to) @@ -1096,6 +1134,7 @@ #define NO SGF_NETWORK_ONLY #define CR SGF_CURRENCY #define NN SGF_NO_NETWORK +#define NG SGF_NEWGAME_ONLY /* Begin - Callback Functions for the various settings */ /* virtual PositionMainToolbar function, calls the right one.*/ @@ -1115,7 +1154,7 @@ { if (p1 == 1) { ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_MULTIPLAYER, 0, 0); - _patches.ainew_active = true; + _settings.ai.ainew_active = true; } return 0; } @@ -1161,6 +1200,12 @@ return 0; } +static int32 InvalidateTownViewWindow(int32 p1) +{ + InvalidateWindowClassesData(WC_TOWN_VIEW, p1); + return 0; +} + static int32 UpdateConsists(int32 p1) { Vehicle *v; @@ -1175,7 +1220,7 @@ static int32 CheckInterval(int32 p1) { bool warning; - const Patches *ptc = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches; + const VehicleSettings *ptc = (_game_mode == GM_MENU) ? &_settings_newgame.vehicle : &_settings.vehicle; if (p1) { warning = ( (IsInsideMM(ptc->servint_trains, 5, 90 + 1) || ptc->servint_trains == 0) && @@ -1197,19 +1242,19 @@ static int32 EngineRenewUpdate(int32 p1) { - DoCommandP(0, 0, _patches.autorenew, NULL, CMD_SET_AUTOREPLACE); + DoCommandP(0, 0, _settings.gui.autorenew, NULL, CMD_SET_AUTOREPLACE); return 0; } static int32 EngineRenewMonthsUpdate(int32 p1) { - DoCommandP(0, 1, _patches.autorenew_months, NULL, CMD_SET_AUTOREPLACE); + DoCommandP(0, 1, _settings.gui.autorenew_months, NULL, CMD_SET_AUTOREPLACE); return 0; } static int32 EngineRenewMoneyUpdate(int32 p1) { - DoCommandP(0, 2, _patches.autorenew_money, NULL, CMD_SET_AUTOREPLACE); + DoCommandP(0, 2, _settings.gui.autorenew_money, NULL, CMD_SET_AUTOREPLACE); return 0; } @@ -1231,6 +1276,92 @@ return 0; } +/* + * A: competitors + * B: start time in months / 3 + * C: town count (3 = high, 0 = very low) + * D: industry count (4 = high, 0 = none) + * E: inital loan (in GBP) + * F: interest rate + * G: running costs (0 = low, 2 = high) + * H: construction speed of competitors (0 = very slow, 4 = very fast) + * I: intelligence (0-2) + * J: breakdowns (0 = off, 2 = normal) + * K: subsidy multiplier (0 = 1.5, 3 = 4.0) + * L: construction cost (0-2) + * M: terrain type (0 = very flat, 3 = mountainous) + * N: amount of water (0 = very low, 3 = high) + * O: economy (0 = steady, 1 = fluctuating) + * P: Train reversing (0 = end of line + stations, 1 = end of line) + * Q: disasters + * R: area restructuring (0 = permissive, 2 = hostile) + * S: the difficulty level + */ +static const DifficultySettings _default_game_diff[3] = { /* + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S*/ + {2, 2, 2, 4, 300000, 2, 0, 2, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0}, ///< easy + {4, 1, 2, 3, 150000, 3, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1}, ///< medium + {7, 0, 3, 3, 100000, 4, 1, 3, 2, 2, 0, 2, 3, 2, 1, 1, 1, 2, 2}, ///< hard +}; + +void SetDifficultyLevel(int mode, DifficultySettings *gm_opt) +{ + assert(mode <= 3); + + if (mode != 3) { + *gm_opt = _default_game_diff[mode]; + } else { + gm_opt->diff_level = 3; + } +} + +/** + * Checks the difficulty levels read from the configuration and + * forces them to be correct when invalid. + */ +void CheckDifficultyLevels() +{ + if (_settings_newgame.difficulty.diff_level != 3) { + SetDifficultyLevel(_settings_newgame.difficulty.diff_level, &_settings_newgame.difficulty); + } +} + +static int32 DifficultyReset(int32 level) +{ + SetDifficultyLevel(level, (_game_mode == GM_MENU) ? &_settings_newgame.difficulty : &_settings.difficulty); + return 0; +} + +static int32 DifficultyChange(int32) +{ + if (_game_mode == GM_MENU) { + _settings_newgame.difficulty.diff_level = 3; + } else { + _settings.difficulty.diff_level = 3; + } + + /* If we are a network-client, update the difficult setting (if it is open). + * Use this instead of just dirtying the window because we need to load in + * the new difficulty settings */ + if (_networking && FindWindowById(WC_GAME_OPTIONS, 0) != NULL) { + ShowGameDifficulty(); + } + + return 0; +} + +static int32 DifficultyNoiseChange(int32 i) +{ + if (_game_mode == GM_NORMAL) { + UpdateAirportsNoise(); + if (_settings.economy.station_noise_level) { + InvalidateWindowClassesData(WC_TOWN_VIEW, 0); + } + } + + return DifficultyChange(i); +} + /** * Check for right TownLayout usage in editor mode. * The No Road mode is not desirable since towns have to be @@ -1241,9 +1372,9 @@ */ static int32 CheckTownLayout(int32 p1) { - if (_patches.town_layout == TL_NO_ROADS && _game_mode == GM_EDITOR) { + if (_settings.economy.town_layout == TL_NO_ROADS && _game_mode == GM_EDITOR) { ShowErrorMessage(INVALID_STRING_ID, STR_CONFIG_PATCHES_TOWN_LAYOUT_INVALID, 0, 0); - _patches.town_layout = TL_ORIGINAL; + _settings.economy.town_layout = TL_ORIGINAL; } return 0; } @@ -1260,6 +1391,21 @@ return lookup_oneofmany("normal|hilly|desert|candy", value); } +/** + * Check for decent values been supplied by the user for the noise tolerance setting. + * The primary idea is to avoid division by zero in game mode. + * The secondary idea is to make it so the values will be somewhat sane and that towns will + * not be overcrowed with airports. It would be easy to abuse such a feature + * So basically, 200, 400, 800 are the lowest allowed values */ +static int32 CheckNoiseToleranceLevel(const char *value) +{ + Settings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings; + for (uint16 i = 0; i < lengthof(s->economy.town_noise_population); i++) { + s->economy.town_noise_population[i] = max(uint16(200 * (i + 1)), s->economy.town_noise_population[i]); + } + return 0; +} + /* End - Callback Functions */ #ifndef EXTERNAL_PLAYER @@ -1359,6 +1505,9 @@ }; #endif /* ENABLE_NETWORK */ +static const uint GAME_DIFFICULTY_NUM = 18; +uint16 _old_diff_custom[GAME_DIFFICULTY_NUM]; + static const SettingDesc _gameopt_settings[] = { /* In version 4 a new difficulty setting has been added to the difficulty settings, * town attitude towards demolishing. Needs special handling because some dimwit thought @@ -1369,18 +1518,19 @@ * and why not byte for example? * 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlArray() hack * for savegames version 0 - though it is an array, it has to go through the byteswap process */ - SDT_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_FILE_I16 | SLE_VAR_U16, 0, 0, GameOptions, diff, 17, 0, 0, 0, 0, NULL, STR_NULL, NULL, NULL, 0, 3), - SDT_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_UINT16, 0, 0, GameOptions, diff, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, NULL, 4, SL_MAX_VERSION), - SDT_VAR(GameOptions, diff_level, SLE_UINT8, 0, 0, 0, 0, 3, 0, STR_NULL, NULL), - SDT_OMANY(GameOptions, currency, SLE_UINT8, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL), - SDT_OMANY(GameOptions, units, SLE_UINT8, N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL), + SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_FILE_I16 | SLE_VAR_U16, C, 0, _old_diff_custom, 17, 0, 0, 0, 0, NULL, STR_NULL, NULL, 0, 3), + SDTG_GENERAL("diff_custom", SDT_INTLIST, SL_ARR, SLE_UINT16, C, 0, _old_diff_custom, 18, 0, 0, 0, 0, NULL, STR_NULL, NULL, 4, 96), + + SDT_VAR(Settings, difficulty.diff_level, SLE_UINT8, 0, 0, 0, 0, 3, 0, STR_NULL, NULL), + SDT_OMANY(Settings, gui.currency, SLE_UINT8, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL), + SDT_OMANY(Settings, gui.units, SLE_UINT8, N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL), /* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */ - SDT_OMANY(GameOptions, town_name, SLE_UINT8, 0, 0, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL), - SDT_OMANY(GameOptions, landscape, SLE_UINT8, 0, 0, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape), - SDT_VAR(GameOptions, snow_line, SLE_UINT8, 0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL), - SDT_CONDOMANY(GameOptions,autosave, SLE_UINT8, 0, 22, N, 0, 0, 0, "", STR_NULL, NULL, NULL), - SDT_CONDOMANY(GameOptions,autosave, SLE_UINT8,23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL, NULL), - SDT_OMANY(GameOptions, road_side, SLE_UINT8, 0, 0, 1, 1, "left|right", STR_NULL, NULL, NULL), + SDT_OMANY(Settings, game_creation.town_name, SLE_UINT8, 0, 0, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL), + SDT_OMANY(Settings, game_creation.landscape, SLE_UINT8, 0, 0, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape), + SDT_VAR(Settings, game_creation.snow_line, SLE_UINT8, 0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL), + SDT_CONDOMANY(Settings, gui.autosave, SLE_UINT8, 0, 22, N, 0, 0, 0, "", STR_NULL, NULL, NULL), + SDT_CONDOMANY(Settings, gui.autosave, SLE_UINT8, 23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL, NULL), + SDT_OMANY(Settings, vehicle.road_side, SLE_UINT8, 0, 0, 1, 1, "left|right", STR_NULL, NULL, NULL), SDT_END() }; @@ -1395,244 +1545,218 @@ * service depot, causing desyncs on a massive scale. */ const SettingDesc _patch_settings[] = { /***************************************************************************/ - /* User-interface section of the GUI-configure patches window */ - SDT_BOOL(Patches, vehicle_speed, S, 0, true, STR_CONFIG_PATCHES_VEHICLESPEED, NULL), - SDT_BOOL(Patches, status_long_date, S, 0, true, STR_CONFIG_PATCHES_LONGDATE, NULL), - SDT_BOOL(Patches, show_finances, S, 0, true, STR_CONFIG_PATCHES_SHOWFINANCES, NULL), - SDT_BOOL(Patches, autoscroll, S, 0, false, STR_CONFIG_PATCHES_AUTOSCROLL, NULL), - SDT_BOOL(Patches, reverse_scroll, S, 0, false, STR_CONFIG_PATCHES_REVERSE_SCROLLING, NULL), - SDT_BOOL(Patches, smooth_scroll, S, 0, false, STR_CONFIG_PATCHES_SMOOTH_SCROLLING, NULL), - SDT_BOOL(Patches, measure_tooltip, S, 0, false, STR_CONFIG_PATCHES_MEASURE_TOOLTIP, NULL), - SDT_VAR(Patches, errmsg_duration, SLE_UINT8, S, 0, 5, 0, 20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION, NULL), - SDT_VAR(Patches, toolbar_pos, SLE_UINT8, S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS, v_PositionMainToolbar), - SDT_VAR(Patches, window_snap_radius, SLE_UINT8, S,D0, 10, 1, 32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS, NULL), - SDT_BOOL(Patches, population_in_label, S, 0, true, STR_CONFIG_PATCHES_POPULATION_IN_LABEL, PopulationInLabelActive), - SDT_VAR(Patches, map_x, SLE_UINT8, S, 0, 8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_X, NULL), - SDT_VAR(Patches, map_y, SLE_UINT8, S, 0, 8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_Y, NULL), - SDT_BOOL(Patches, link_terraform_toolbar, S, 0, false, STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,NULL), - SDT_VAR(Patches, liveries, SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_LIVERIES, RedrawScreen), - SDT_BOOL(Patches, prefer_teamchat, S, 0, false, STR_CONFIG_PATCHES_PREFER_TEAMCHAT, NULL), - SDT_VAR(Patches, scrollwheel_scrolling,SLE_UINT8,S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL), - SDT_VAR(Patches,scrollwheel_multiplier,SLE_UINT8,S, 0, 5, 1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,NULL), - SDT_BOOL(Patches, pause_on_newgame, S, 0, false, STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME, NULL), - SDT_VAR(Patches,advanced_vehicle_list,SLE_UINT8,S,MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,NULL), - SDT_BOOL(Patches, timetable_in_ticks, S, 0, false, STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS, NULL), - SDT_VAR(Patches, loading_indicators, SLE_UINT8, S,MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS, RedrawScreen), - SDT_VAR(Patches, default_rail_type, SLE_UINT8, S,MS, 4, 0, 6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE, NULL), - - /***************************************************************************/ - /* Construction section of the GUI-configure patches window */ - SDT_BOOL(Patches, build_on_slopes, 0,NN, true, STR_CONFIG_PATCHES_BUILDONSLOPES, NULL), - SDT_CONDBOOL(Patches, autoslope, 75, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_AUTOSLOPE, NULL), - SDT_BOOL(Patches, extra_dynamite, 0, 0, false, STR_CONFIG_PATCHES_EXTRADYNAMITE, NULL), - SDT_BOOL(Patches, longbridges, 0,NN, true, STR_CONFIG_PATCHES_LONGBRIDGES, NULL), - SDT_BOOL(Patches, signal_side, N,NN, true, STR_CONFIG_PATCHES_SIGNALSIDE, RedrawScreen), - SDT_BOOL(Patches, always_small_airport, 0,NN, false, STR_CONFIG_PATCHES_SMALL_AIRPORTS, NULL), - SDT_BOOL(Patches, enable_signal_gui, S, 0, false, STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI, CloseSignalGUI), - SDT_VAR(Patches, drag_signals_density,SLE_UINT8,S, 0, 4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,DragSignalsDensityChanged), - SDT_VAR(Patches, semaphore_build_before,SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant), - SDT_CONDVAR(Patches, town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0, MS, TL_ORIGINAL, TL_NO_ROADS, NUM_TLS - 1, 1, STR_CONFIG_PATCHES_TOWN_LAYOUT, CheckTownLayout), - - /***************************************************************************/ - /* Vehicle section of the GUI-configure patches window */ - SDT_BOOL(Patches, realistic_acceleration, 0, 0, false, STR_CONFIG_PATCHES_REALISTICACCEL, RealisticAccelerationChanged), - SDT_BOOL(Patches, forbid_90_deg, 0, 0, false, STR_CONFIG_PATCHES_FORBID_90_DEG, NULL), - SDT_BOOL(Patches, mammoth_trains, 0,NN, true, STR_CONFIG_PATCHES_MAMMOTHTRAINS, NULL), - SDT_BOOL(Patches, gotodepot, 0, 0, true, STR_CONFIG_PATCHES_GOTODEPOT, NULL), - SDT_BOOL(Patches, roadveh_queue, 0, 0, true, STR_CONFIG_PATCHES_ROADVEH_QUEUE, NULL), - - SDT_CONDBOOL(Patches, new_pathfinding_all, 0,86, 0, 0, false, STR_NULL, NULL), - SDT_CONDBOOL(Patches, yapf.ship_use_yapf, 28,86, 0, 0, false, STR_NULL, NULL), - SDT_CONDBOOL(Patches, yapf.road_use_yapf, 28,86, 0, 0, true, STR_NULL, NULL), - SDT_CONDBOOL(Patches, yapf.rail_use_yapf, 28,86, 0, 0, true, STR_NULL, NULL), - - SDT_CONDVAR(Patches, pathfinder_for_trains, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 2, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_TRAINS, NULL), - SDT_CONDVAR(Patches, pathfinder_for_roadvehs, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 2, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_ROADVEH, NULL), - SDT_CONDVAR(Patches, pathfinder_for_ships, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 0, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_SHIPS, NULL), + /* Saved patch variables. */ + /* Do not ADD or REMOVE something in this "difficulty.XXX" table or before it. It breaks savegame compatability. */ + SDT_CONDVAR(Settings, difficulty.max_no_competitors, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 2, 0, 7, 1, STR_NULL, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.competitor_start_time, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 2, 0, 3, 1, STR_6830_IMMEDIATE, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.number_towns, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 2, 0, 3, 1, STR_NUM_VERY_LOW, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.number_industries, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 4, 0, 4, 1, STR_NONE, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.max_loan, SLE_UINT32, 97, SL_MAX_VERSION, 0,NG|CR,300000,100000,500000,50000,STR_NULL, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.initial_interest, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 2, 2, 4, 1, STR_NULL, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.vehicle_costs, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 0, 0, 2, 1, STR_6820_LOW, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.competitor_speed, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 2, 0, 4, 1, STR_681B_VERY_SLOW, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.competitor_intelligence, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 0, 0, 2, 1, STR_6820_LOW, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.vehicle_breakdowns, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 1, 0, 2, 1, STR_6823_NONE, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.subsidy_multiplier, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 2, 0, 3, 1, STR_6826_X1_5, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.construction_cost, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 0, 0, 2, 1, STR_6820_LOW, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.terrain_type, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 1, 0, 3, 1, STR_682A_VERY_FLAT, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.quantity_sea_lakes, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 0, 0, 3, 1, STR_VERY_LOW, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.economy, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 0, 0, 1, 1, STR_682E_STEADY, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.line_reverse_mode, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 0, 0, 1, 1, STR_6834_AT_END_OF_LINE_AND_AT_STATIONS, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.disasters, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 0, 0, 1, 1, STR_6836_OFF, DifficultyChange), + SDT_CONDVAR(Settings, difficulty.town_council_tolerance, SLE_UINT8, 97, SL_MAX_VERSION, 0, 0, 0, 0, 2, 1, STR_PERMISSIVE, DifficultyNoiseChange), + SDT_CONDVAR(Settings, difficulty.diff_level, SLE_UINT8, 97, SL_MAX_VERSION, 0,NG, 0, 0, 3, 0, STR_NULL, DifficultyReset), - SDT_BOOL(Patches, train_income_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_INCOME_LESS, NULL), - SDT_VAR(Patches, order_review_system,SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW, NULL), - SDT_BOOL(Patches, never_expire_vehicles, 0,NN, false, STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES,NULL), - SDT_BOOL(Patches, lost_train_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_LOST_TRAIN, NULL), - SDT_BOOL(Patches, autorenew, S, 0, false, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE, EngineRenewUpdate), - SDT_VAR(Patches, autorenew_months, SLE_INT16, S, 0, 6, -12, 12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, EngineRenewMonthsUpdate), - SDT_VAR(Patches, autorenew_money, SLE_UINT, S,CR,100000, 0, 2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY, EngineRenewMoneyUpdate), - SDT_BOOL(Patches, always_build_infrastructure, S, 0, false, STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen), - SDT_VAR(Patches, max_trains, SLE_UINT16, 0, 0, 500, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_TRAINS, RedrawScreen), - SDT_VAR(Patches, max_roadveh, SLE_UINT16, 0, 0, 500, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_ROADVEH, RedrawScreen), - SDT_VAR(Patches, max_aircraft, SLE_UINT16, 0, 0, 200, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_AIRCRAFT, RedrawScreen), - SDT_VAR(Patches, max_ships, SLE_UINT16, 0, 0, 300, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_SHIPS, RedrawScreen), - SDT_BOOL(Patches, servint_ispercent, 0, 0, false, STR_CONFIG_PATCHES_SERVINT_ISPERCENT, CheckInterval), - SDT_VAR(Patches, servint_trains, SLE_UINT16, 0,D0, 150, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_TRAINS, InValidateDetailsWindow), - SDT_VAR(Patches, servint_roadveh, SLE_UINT16, 0,D0, 150, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_ROADVEH, InValidateDetailsWindow), - SDT_VAR(Patches, servint_ships, SLE_UINT16, 0,D0, 360, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_SHIPS, InValidateDetailsWindow), - SDT_VAR(Patches, servint_aircraft, SLE_UINT16, 0,D0, 100, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_AIRCRAFT, InValidateDetailsWindow), - SDT_BOOL(Patches, no_servicing_if_no_breakdowns, 0, 0, false, STR_CONFIG_PATCHES_NOSERVICE, NULL), - SDT_BOOL(Patches, wagon_speed_limits, 0,NN, true, STR_CONFIG_PATCHES_WAGONSPEEDLIMITS, UpdateConsists), - SDT_CONDBOOL(Patches, disable_elrails, 38, SL_MAX_VERSION, 0, NN, false, STR_CONFIG_PATCHES_DISABLE_ELRAILS, SettingsDisableElrail), - SDT_CONDVAR(Patches, freight_trains, SLE_UINT8, 39, SL_MAX_VERSION, 0,NN, 1, 1, 255, 1, STR_CONFIG_PATCHES_FREIGHT_TRAINS, NULL), - SDT_CONDBOOL(Patches, timetabling, 67, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_TIMETABLE_ALLOW, NULL), - SDT_CONDVAR(Patches, plane_speed, SLE_UINT8, 90, SL_MAX_VERSION, 0, 0, 4, 1, 4, 0, STR_CONFIG_PATCHES_PLANE_SPEED, NULL), - SDT_CONDBOOL(Patches, dynamic_engines, 95, SL_MAX_VERSION, 0,NN, false, STR_CONFIG_PATCHES_DYNAMIC_ENGINES, NULL), + /* There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI. */ + SDT_CONDOMANY(Settings, game_creation.town_name, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL), + SDT_CONDOMANY(Settings, game_creation.landscape, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape), + SDT_CONDVAR(Settings, game_creation.snow_line, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL), + SDT_CONDOMANY(Settings, vehicle.road_side, SLE_UINT8, 97, SL_MAX_VERSION, 0,NN, 1, 1, "left|right", STR_NULL, NULL, NULL), - /***************************************************************************/ - /* Station section of the GUI-configure patches window */ - SDT_BOOL(Patches, join_stations, 0, 0, true, STR_CONFIG_PATCHES_JOINSTATIONS, NULL), - SDT_CONDBOOL(Patches, sg_full_load_any, 0, 92, 0, 0, true, STR_NULL, NULL), - SDT_BOOL(Patches, improved_load, 0,NN, false, STR_CONFIG_PATCHES_IMPROVEDLOAD, NULL), - SDT_BOOL(Patches, selectgoods, 0, 0, true, STR_CONFIG_PATCHES_SELECTGOODS, NULL), - SDT_BOOL(Patches, new_nonstop, S, 0, false, STR_CONFIG_PATCHES_NEW_NONSTOP, NULL), - SDT_CONDBOOL(Patches, sg_new_nonstop, 0, 92, 0, 0, false, STR_NULL, NULL), - SDT_BOOL(Patches, nonuniform_stations, 0,NN, true, STR_CONFIG_PATCHES_NONUNIFORM_STATIONS,NULL), - SDT_VAR(Patches, station_spread,SLE_UINT8,0, 0, 12, 4, 64, 0, STR_CONFIG_PATCHES_STATION_SPREAD, InvalidateStationBuildWindow), - SDT_BOOL(Patches, serviceathelipad, 0, 0, true, STR_CONFIG_PATCHES_SERVICEATHELIPAD, NULL), - SDT_BOOL(Patches, modified_catchment, 0, 0, true, STR_CONFIG_PATCHES_CATCHMENT, NULL), - SDT_CONDBOOL(Patches, gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_GRADUAL_LOADING, NULL), - SDT_CONDBOOL(Patches, road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL), - SDT_CONDBOOL(Patches, adjacent_stations, 62, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ADJACENT_STATIONS, NULL), + SDT_BOOL(Settings, construction.build_on_slopes, 0,NN, true, STR_CONFIG_PATCHES_BUILDONSLOPES, NULL), + SDT_CONDBOOL(Settings, construction.autoslope, 75, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_AUTOSLOPE, NULL), + SDT_BOOL(Settings, construction.extra_dynamite, 0, 0, false, STR_CONFIG_PATCHES_EXTRADYNAMITE, NULL), + SDT_BOOL(Settings, construction.longbridges, 0,NN, true, STR_CONFIG_PATCHES_LONGBRIDGES, NULL), + SDT_BOOL(Settings, construction.signal_side, N,NN, true, STR_CONFIG_PATCHES_SIGNALSIDE, RedrawScreen), + SDT_BOOL(Settings, station.always_small_airport, 0,NN, false, STR_CONFIG_PATCHES_SMALL_AIRPORTS, NULL), + SDT_CONDVAR(Settings, economy.town_layout, SLE_UINT8, 59, SL_MAX_VERSION, 0,MS,TL_ORIGINAL,TL_NO_ROADS,NUM_TLS-1,1, STR_CONFIG_PATCHES_TOWN_LAYOUT, CheckTownLayout), - /***************************************************************************/ - /* Economy section of the GUI-configure patches window */ - SDT_BOOL(Patches, inflation, 0, 0, true, STR_CONFIG_PATCHES_INFLATION, NULL), - SDT_VAR(Patches, raw_industry_construction,SLE_UINT8,0,MS,0,0, 2, 0, STR_CONFIG_PATCHES_RAW_INDUSTRY_CONSTRUCTION_METHOD, InvalidateBuildIndustryWindow), - SDT_BOOL(Patches, multiple_industry_per_town, 0, 0, false, STR_CONFIG_PATCHES_MULTIPINDTOWN, NULL), - SDT_BOOL(Patches, same_industry_close, 0, 0, false, STR_CONFIG_PATCHES_SAMEINDCLOSE, NULL), - SDT_BOOL(Patches, bribe, 0, 0, true, STR_CONFIG_PATCHES_BRIBE, NULL), - SDT_CONDBOOL(Patches, exclusive_rights, 79, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_EXCLUSIVE, NULL), - SDT_CONDBOOL(Patches, give_money, 79, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_GIVE_MONEY, NULL), - SDT_VAR(Patches, snow_line_height,SLE_UINT8, 0, 0, 7, 2, 13, 0, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT, NULL), - SDT_VAR(Patches, colored_news_year,SLE_INT32, 0,NC, 2000, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_COLORED_NEWS_YEAR,NULL), - SDT_VAR(Patches, starting_year, SLE_INT32, 0,NC, 1950, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_STARTING_YEAR,NULL), - SDT_VAR(Patches, ending_year, SLE_INT32,0,NC|NO,2051, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_ENDING_YEAR, NULL), - SDT_BOOL(Patches, smooth_economy, 0, 0, true, STR_CONFIG_PATCHES_SMOOTH_ECONOMY, NULL), - SDT_BOOL(Patches, allow_shares, 0, 0, false, STR_CONFIG_PATCHES_ALLOW_SHARES, NULL), - SDT_CONDVAR(Patches, town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0, 4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH, NULL), - SDT_CONDVAR(Patches, larger_towns, SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL), - SDT_CONDVAR(Patches, initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0, 2, 1, 10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL), - SDT_CONDBOOL(Patches, mod_road_rebuild, 77, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_MODIFIED_ROAD_REBUILD, NULL), + SDT_BOOL(Settings, vehicle.realistic_acceleration, 0, 0, false, STR_CONFIG_PATCHES_REALISTICACCEL, RealisticAccelerationChanged), + SDT_BOOL(Settings, pf.forbid_90_deg, 0, 0, false, STR_CONFIG_PATCHES_FORBID_90_DEG, NULL), + SDT_BOOL(Settings, vehicle.mammoth_trains, 0,NN, true, STR_CONFIG_PATCHES_MAMMOTHTRAINS, NULL), + SDT_BOOL(Settings, order.gotodepot, 0, 0, true, STR_CONFIG_PATCHES_GOTODEPOT, NULL), + SDT_BOOL(Settings, pf.roadveh_queue, 0, 0, true, STR_CONFIG_PATCHES_ROADVEH_QUEUE, NULL), + + SDT_CONDBOOL(Settings, pf.new_pathfinding_all, 0, 86, 0, 0, false, STR_NULL, NULL), + SDT_CONDBOOL(Settings, pf.yapf.ship_use_yapf, 28, 86, 0, 0, false, STR_NULL, NULL), + SDT_CONDBOOL(Settings, pf.yapf.road_use_yapf, 28, 86, 0, 0, true, STR_NULL, NULL), + SDT_CONDBOOL(Settings, pf.yapf.rail_use_yapf, 28, 86, 0, 0, true, STR_NULL, NULL), + + SDT_CONDVAR(Settings, pf.pathfinder_for_trains, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 2, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_TRAINS, NULL), + SDT_CONDVAR(Settings, pf.pathfinder_for_roadvehs, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 2, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_ROADVEH, NULL), + SDT_CONDVAR(Settings, pf.pathfinder_for_ships, SLE_UINT8, 87, SL_MAX_VERSION, 0, MS, 0, 0, 2, 1, STR_CONFIG_PATCHES_PATHFINDER_FOR_SHIPS, NULL), + + SDT_BOOL(Settings, vehicle.never_expire_vehicles, 0,NN, false, STR_CONFIG_PATCHES_NEVER_EXPIRE_VEHICLES, NULL), + SDT_VAR(Settings, vehicle.max_trains, SLE_UINT16, 0, 0, 500, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_TRAINS, RedrawScreen), + SDT_VAR(Settings, vehicle.max_roadveh, SLE_UINT16, 0, 0, 500, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_ROADVEH, RedrawScreen), + SDT_VAR(Settings, vehicle.max_aircraft, SLE_UINT16, 0, 0, 200, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_AIRCRAFT, RedrawScreen), + SDT_VAR(Settings, vehicle.max_ships, SLE_UINT16, 0, 0, 300, 0, 5000, 0, STR_CONFIG_PATCHES_MAX_SHIPS, RedrawScreen), + SDT_BOOL(Settings, vehicle.servint_ispercent, 0, 0, false, STR_CONFIG_PATCHES_SERVINT_ISPERCENT, CheckInterval), + SDT_VAR(Settings, vehicle.servint_trains, SLE_UINT16, 0,D0, 150, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_TRAINS, InValidateDetailsWindow), + SDT_VAR(Settings, vehicle.servint_roadveh, SLE_UINT16, 0,D0, 150, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_ROADVEH, InValidateDetailsWindow), + SDT_VAR(Settings, vehicle.servint_ships, SLE_UINT16, 0,D0, 360, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_SHIPS, InValidateDetailsWindow), + SDT_VAR(Settings, vehicle.servint_aircraft, SLE_UINT16, 0,D0, 100, 5, 800, 0, STR_CONFIG_PATCHES_SERVINT_AIRCRAFT, InValidateDetailsWindow), + SDT_BOOL(Settings, order.no_servicing_if_no_breakdowns, 0, 0, false, STR_CONFIG_PATCHES_NOSERVICE, NULL), + SDT_BOOL(Settings, vehicle.wagon_speed_limits, 0,NN, true, STR_CONFIG_PATCHES_WAGONSPEEDLIMITS, UpdateConsists), + SDT_CONDBOOL(Settings, vehicle.disable_elrails, 38, SL_MAX_VERSION, 0,NN, false, STR_CONFIG_PATCHES_DISABLE_ELRAILS, SettingsDisableElrail), + SDT_CONDVAR(Settings, vehicle.freight_trains, SLE_UINT8, 39, SL_MAX_VERSION, 0,NN, 1, 1, 255, 1, STR_CONFIG_PATCHES_FREIGHT_TRAINS, NULL), + SDT_CONDBOOL(Settings, order.timetabling, 67, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_TIMETABLE_ALLOW, NULL), + SDT_CONDVAR(Settings, vehicle.plane_speed, SLE_UINT8, 90, SL_MAX_VERSION, 0, 0, 4, 1, 4, 0, STR_CONFIG_PATCHES_PLANE_SPEED, NULL), + SDT_CONDBOOL(Settings, vehicle.dynamic_engines, 95, SL_MAX_VERSION, 0,NN, false, STR_CONFIG_PATCHES_DYNAMIC_ENGINES, NULL), + + SDT_BOOL(Settings, station.join_stations, 0, 0, true, STR_CONFIG_PATCHES_JOINSTATIONS, NULL), + SDT_CONDBOOL(Settings, gui.sg_full_load_any, 0, 92, 0, 0 , true, STR_NULL, NULL), + SDT_BOOL(Settings, order.improved_load, 0,NN, true, STR_CONFIG_PATCHES_IMPROVEDLOAD, NULL), + SDT_BOOL(Settings, order.selectgoods, 0, 0, true, STR_CONFIG_PATCHES_SELECTGOODS, NULL), + SDT_CONDBOOL(Settings, gui.sg_new_nonstop, 0, 92, 0, 0, false, STR_NULL, NULL), + SDT_BOOL(Settings, station.nonuniform_stations, 0,NN, true, STR_CONFIG_PATCHES_NONUNIFORM_STATIONS, NULL), + SDT_VAR(Settings, station.station_spread, SLE_UINT8, 0, 0, 12, 4, 64, 0, STR_CONFIG_PATCHES_STATION_SPREAD, InvalidateStationBuildWindow), + SDT_BOOL(Settings, order.serviceathelipad, 0, 0, true, STR_CONFIG_PATCHES_SERVICEATHELIPAD, NULL), + SDT_BOOL(Settings, station.modified_catchment, 0, 0, true, STR_CONFIG_PATCHES_CATCHMENT, NULL), + SDT_CONDBOOL(Settings, order.gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_GRADUAL_LOADING, NULL), + SDT_CONDBOOL(Settings, construction.road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL), + SDT_CONDBOOL(Settings, station.adjacent_stations, 62, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ADJACENT_STATIONS, NULL), + SDT_CONDBOOL(Settings, economy.station_noise_level, 96, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_NOISE_LEVEL, InvalidateTownViewWindow), + + SDT_BOOL(Settings, economy.inflation, 0, 0, true, STR_CONFIG_PATCHES_INFLATION, NULL), + SDT_VAR(Settings, construction.raw_industry_construction, SLE_UINT8, 0,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_RAW_INDUSTRY_CONSTRUCTION_METHOD, InvalidateBuildIndustryWindow), + SDT_BOOL(Settings, economy.multiple_industry_per_town, 0, 0, false, STR_CONFIG_PATCHES_MULTIPINDTOWN, NULL), + SDT_BOOL(Settings, economy.same_industry_close, 0, 0, false, STR_CONFIG_PATCHES_SAMEINDCLOSE, NULL), + SDT_BOOL(Settings, economy.bribe, 0, 0, true, STR_CONFIG_PATCHES_BRIBE, NULL), + SDT_CONDBOOL(Settings, economy.exclusive_rights, 79, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_EXCLUSIVE, NULL), + SDT_CONDBOOL(Settings, economy.give_money, 79, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_ALLOW_GIVE_MONEY, NULL), + SDT_VAR(Settings, game_creation.snow_line_height, SLE_UINT8, 0, 0, 7, 2, 13, 0, STR_CONFIG_PATCHES_SNOWLINE_HEIGHT, NULL), + SDT_VAR(Settings, gui.colored_news_year, SLE_INT32, 0,NC, 2000,MIN_YEAR,MAX_YEAR,1,STR_CONFIG_PATCHES_COLORED_NEWS_YEAR, NULL), + SDT_VAR(Settings, game_creation.starting_year, SLE_INT32, 0,NC, 1950,MIN_YEAR,MAX_YEAR,1,STR_CONFIG_PATCHES_STARTING_YEAR, NULL), + SDT_VAR(Settings, gui.ending_year, SLE_INT32, 0,NC|NO,2051,MIN_YEAR,MAX_YEAR,1,STR_CONFIG_PATCHES_ENDING_YEAR, NULL), + SDT_BOOL(Settings, economy.smooth_economy, 0, 0, true, STR_CONFIG_PATCHES_SMOOTH_ECONOMY, NULL), + SDT_BOOL(Settings, economy.allow_shares, 0, 0, false, STR_CONFIG_PATCHES_ALLOW_SHARES, NULL), + SDT_CONDVAR(Settings, economy.town_growth_rate, SLE_UINT8, 54, SL_MAX_VERSION, 0, MS, 2, 0, 4, 0, STR_CONFIG_PATCHES_TOWN_GROWTH, NULL), + SDT_CONDVAR(Settings, economy.larger_towns, SLE_UINT8, 54, SL_MAX_VERSION, 0, D0, 4, 0, 255, 1, STR_CONFIG_PATCHES_LARGER_TOWNS, NULL), + SDT_CONDVAR(Settings, economy.initial_city_size, SLE_UINT8, 56, SL_MAX_VERSION, 0, 0, 2, 1, 10, 1, STR_CONFIG_PATCHES_CITY_SIZE_MULTIPLIER, NULL), + SDT_CONDBOOL(Settings, economy.mod_road_rebuild, 77, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_MODIFIED_ROAD_REBUILD, NULL), + + SDT_BOOL(Settings, ai.ainew_active, 0, 0, false, STR_CONFIG_PATCHES_AINEW_ACTIVE, AiNew_PatchActive_Warning), + SDT_BOOL(Settings, ai.ai_in_multiplayer, 0, 0, false, STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER, Ai_In_Multiplayer_Warning), + SDT_BOOL(Settings, ai.ai_disable_veh_train, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_TRAINS, NULL), + SDT_BOOL(Settings, ai.ai_disable_veh_roadveh, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH, NULL), + SDT_BOOL(Settings, ai.ai_disable_veh_aircraft, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT, NULL), + SDT_BOOL(Settings, ai.ai_disable_veh_ship, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_SHIPS, NULL), + + SDT_VAR(Settings, vehicle.extend_vehicle_life, SLE_UINT8, 0, 0, 0, 0, 100, 0, STR_NULL, NULL), + SDT_VAR(Settings, economy.dist_local_authority, SLE_UINT8, 0, 0, 20, 5, 60, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.wait_oneway_signal, SLE_UINT8, 0, 0, 15, 2, 100, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.wait_twoway_signal, SLE_UINT8, 0, 0, 41, 2, 100, 0, STR_NULL, NULL), + SDT_CONDLISTO(Settings, economy.town_noise_population, 3, SLE_UINT16, 96, SL_MAX_VERSION, 0,D0, "800,2000,4000", STR_NULL, NULL, CheckNoiseToleranceLevel), + + SDT_VAR(Settings, pf.opf.pf_maxlength, SLE_UINT16, 0, 0, 4096, 64, 65535, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.opf.pf_maxdepth, SLE_UINT8, 0, 0, 48, 4, 255, 0, STR_NULL, NULL), + + SDT_VAR(Settings, pf.npf.npf_max_search_nodes, SLE_UINT, 0, 0, 10000, 500, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_firstred_penalty, SLE_UINT, 0, 0, ( 10 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_firstred_exit_penalty, SLE_UINT, 0, 0, (100 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_lastred_penalty, SLE_UINT, 0, 0, ( 10 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_station_penalty, SLE_UINT, 0, 0, ( 1 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_slope_penalty, SLE_UINT, 0, 0, ( 1 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_rail_depot_reverse_penalty, SLE_UINT, 0, 0, ( 50 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_buoy_penalty, SLE_UINT, 0, 0, ( 2 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_water_curve_penalty, SLE_UINT, 0, 0, (NPF_TILE_LENGTH / 4), 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_road_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL), + SDT_VAR(Settings, pf.npf.npf_crossing_penalty, SLE_UINT, 0, 0, ( 3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.npf.npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, ( 8 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), + + + SDT_CONDBOOL(Settings, pf.yapf.disable_node_optimization, 28, SL_MAX_VERSION, 0, 0, false, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.max_search_nodes, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000, 500, 1000000, 0, STR_NULL, NULL), + SDT_CONDBOOL(Settings, pf.yapf.rail_firstred_twoway_eol, 28, SL_MAX_VERSION, 0, 0, true, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_firstred_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_firstred_exit_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_lastred_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_lastred_exit_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_station_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 30 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_slope_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_curve45_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_curve90_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 6 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_depot_reverse_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 50 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_crossing_penalty, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_max_signals, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10, 1, 100, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_signal_p0, SLE_INT, 28, SL_MAX_VERSION, 0, 0, 500, -1000000, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_signal_p1, SLE_INT, 28, SL_MAX_VERSION, 0, 0, -100, -1000000, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_look_ahead_signal_p2, SLE_INT, 28, SL_MAX_VERSION, 0, 0, 5, -1000000, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_longer_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_longer_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_shorter_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.road_slope_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.road_curve_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.road_crossing_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, pf.yapf.road_stop_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), + + SDT_CONDVAR(Settings, game_creation.land_generator, SLE_UINT8, 30, SL_MAX_VERSION, 0,MS, 1, 0, 1, 0, STR_CONFIG_PATCHES_LAND_GENERATOR, NULL), + SDT_CONDVAR(Settings, game_creation.oil_refinery_limit, SLE_UINT8, 30, SL_MAX_VERSION, 0, 0, 32, 12, 48, 0, STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE, NULL), + SDT_CONDVAR(Settings, game_creation.tgen_smoothness, SLE_UINT8, 30, SL_MAX_VERSION, 0,MS, 1, 0, 3, 0, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN, NULL), + SDT_CONDVAR(Settings, game_creation.generation_seed, SLE_UINT32, 30, SL_MAX_VERSION, 0, 0, GENERATE_NEW_SEED, 0, UINT32_MAX, 0, STR_NULL, NULL), + SDT_CONDVAR(Settings, game_creation.tree_placer, SLE_UINT8, 30, SL_MAX_VERSION, 0,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_TREE_PLACER, NULL), + SDT_VAR(Settings, game_creation.heightmap_rotation, SLE_UINT8, S,MS, 0, 0, 1, 0, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION, NULL), + SDT_VAR(Settings, game_creation.se_flat_world_height, SLE_UINT8, S, 0, 0, 0, 15, 0, STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT, NULL), + + SDT_CONDOMANY(Settings, gui.currency, SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 0, CUSTOM_CURRENCY_ID, "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|ROL|RUR|SIT|SEK|YTL|SKK|BRR|custom", STR_NULL, NULL, NULL), + SDT_CONDOMANY(Settings, gui.units, SLE_UINT8, 97, SL_MAX_VERSION, N, 0, 1, 2, "imperial|metric|si", STR_NULL, NULL, NULL), /***************************************************************************/ - /* AI section of the GUI-configure patches window */ - SDT_BOOL(Patches, ainew_active, 0, 0, false, STR_CONFIG_PATCHES_AINEW_ACTIVE, AiNew_PatchActive_Warning), - SDT_BOOL(Patches, ai_in_multiplayer, 0, 0, false, STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER, Ai_In_Multiplayer_Warning), - SDT_BOOL(Patches, ai_disable_veh_train, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_TRAINS, NULL), - SDT_BOOL(Patches, ai_disable_veh_roadveh, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH, NULL), - SDT_BOOL(Patches, ai_disable_veh_aircraft,0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_AIRCRAFT,NULL), - SDT_BOOL(Patches, ai_disable_veh_ship, 0, 0, false, STR_CONFIG_PATCHES_AI_BUILDS_SHIPS, NULL), - - /***************************************************************************/ - /* Patches without any GUI representation */ - SDT_BOOL(Patches, keep_all_autosave, S, 0, false, STR_NULL, NULL), - SDT_BOOL(Patches, autosave_on_exit, S, 0, false, STR_NULL, NULL), - SDT_VAR(Patches, max_num_autosaves, SLE_UINT8, S, 0, 16, 0, 255, 0, STR_NULL, NULL), - SDT_BOOL(Patches, bridge_pillars, S, 0, true, STR_NULL, NULL), - SDT_VAR(Patches, extend_vehicle_life, SLE_UINT8, 0, 0, 0, 0, 100, 0, STR_NULL, NULL), - SDT_BOOL(Patches, auto_euro, S, 0, true, STR_NULL, NULL), - SDT_VAR(Patches, dist_local_authority,SLE_UINT8, 0, 0, 20, 5, 60, 0, STR_NULL, NULL), - SDT_VAR(Patches, wait_oneway_signal, SLE_UINT8, 0, 0, 15, 2, 100, 0, STR_NULL, NULL), - SDT_VAR(Patches, wait_twoway_signal, SLE_UINT8, 0, 0, 41, 2, 100, 0, STR_NULL, NULL), - - /***************************************************************************/ - /* New Pathfinding patch settings */ - SDT_VAR(Patches, pf_maxlength, SLE_UINT16, 0, 0, 4096, 64, 65535, 0, STR_NULL, NULL), - SDT_VAR(Patches, pf_maxdepth, SLE_UINT8, 0, 0, 48, 4, 255, 0, STR_NULL, NULL), - /* The maximum number of nodes to search */ - SDT_VAR(Patches, npf_max_search_nodes,SLE_UINT, 0, 0, 10000, 500, 100000, 0, STR_NULL, NULL), + /* Unsaved patch variables. */ + SDT_OMANY(Settings, gui.autosave, SLE_UINT8, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL, NULL), + SDT_BOOL(Settings, gui.vehicle_speed, S, 0, true, STR_CONFIG_PATCHES_VEHICLESPEED, NULL), + SDT_BOOL(Settings, gui.status_long_date, S, 0, true, STR_CONFIG_PATCHES_LONGDATE, NULL), + SDT_BOOL(Settings, gui.show_finances, S, 0, true, STR_CONFIG_PATCHES_SHOWFINANCES, NULL), + SDT_BOOL(Settings, gui.autoscroll, S, 0, false, STR_CONFIG_PATCHES_AUTOSCROLL, NULL), + SDT_BOOL(Settings, gui.reverse_scroll, S, 0, false, STR_CONFIG_PATCHES_REVERSE_SCROLLING, NULL), + SDT_BOOL(Settings, gui.smooth_scroll, S, 0, false, STR_CONFIG_PATCHES_SMOOTH_SCROLLING, NULL), + SDT_BOOL(Settings, gui.measure_tooltip, S, 0, false, STR_CONFIG_PATCHES_MEASURE_TOOLTIP, NULL), + SDT_VAR(Settings, gui.errmsg_duration, SLE_UINT8, S, 0, 5, 0, 20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION, NULL), + SDT_VAR(Settings, gui.toolbar_pos, SLE_UINT8, S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS, v_PositionMainToolbar), + SDT_VAR(Settings, gui.window_snap_radius, SLE_UINT8, S,D0, 10, 1, 32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS, NULL), + SDT_BOOL(Settings, gui.population_in_label, S, 0, true, STR_CONFIG_PATCHES_POPULATION_IN_LABEL, PopulationInLabelActive), + SDT_BOOL(Settings, gui.link_terraform_toolbar, S, 0, false, STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR, NULL), + SDT_VAR(Settings, gui.liveries, SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_LIVERIES, RedrawScreen), + SDT_BOOL(Settings, gui.prefer_teamchat, S, 0, false, STR_CONFIG_PATCHES_PREFER_TEAMCHAT, NULL), + SDT_VAR(Settings, gui.scrollwheel_scrolling, SLE_UINT8, S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL), + SDT_VAR(Settings, gui.scrollwheel_multiplier, SLE_UINT8, S, 0, 5, 1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER, NULL), + SDT_BOOL(Settings, gui.pause_on_newgame, S, 0, false, STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME, NULL), + SDT_VAR(Settings, gui.advanced_vehicle_list, SLE_UINT8, S,MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS, NULL), + SDT_BOOL(Settings, gui.timetable_in_ticks, S, 0, false, STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS, NULL), + SDT_VAR(Settings, gui.loading_indicators, SLE_UINT8, S,MS, 1, 0, 2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS, RedrawScreen), + SDT_VAR(Settings, gui.default_rail_type, SLE_UINT8, S,MS, 4, 0, 6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE, NULL), + SDT_BOOL(Settings, gui.enable_signal_gui, S, 0, false, STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI, CloseSignalGUI), + SDT_VAR(Settings, gui.drag_signals_density, SLE_UINT8, S, 0, 4, 1, 20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY, DragSignalsDensityChanged), + SDT_VAR(Settings, gui.semaphore_build_before, SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant), + SDT_BOOL(Settings, gui.train_income_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_INCOME_LESS, NULL), + SDT_VAR(Settings, gui.order_review_system, SLE_UINT8, S,MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW, NULL), + SDT_BOOL(Settings, gui.lost_train_warn, S, 0, true, STR_CONFIG_PATCHES_WARN_LOST_TRAIN, NULL), + SDT_BOOL(Settings, gui.autorenew, S, 0, false, STR_CONFIG_PATCHES_AUTORENEW_VEHICLE, EngineRenewUpdate), + SDT_VAR(Settings, gui.autorenew_months, SLE_INT16, S, 0, 6, -12, 12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS, EngineRenewMonthsUpdate), + SDT_VAR(Settings, gui.autorenew_money, SLE_UINT, S,CR,100000, 0, 2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY, EngineRenewMoneyUpdate), + SDT_BOOL(Settings, gui.always_build_infrastructure, S, 0, false, STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen), + SDT_BOOL(Settings, gui.new_nonstop, S, 0, false, STR_CONFIG_PATCHES_NEW_NONSTOP, NULL), + SDT_BOOL(Settings, gui.keep_all_autosave, S, 0, false, STR_NULL, NULL), + SDT_BOOL(Settings, gui.autosave_on_exit, S, 0, false, STR_NULL, NULL), + SDT_VAR(Settings, gui.max_num_autosaves, SLE_UINT8, S, 0, 16, 0, 255, 0, STR_NULL, NULL), + SDT_BOOL(Settings, gui.bridge_pillars, S, 0, true, STR_NULL, NULL), + SDT_BOOL(Settings, gui.auto_euro, S, 0, true, STR_NULL, NULL), - /* When a red signal is encountered, a small detour can be made around - * it. This specifically occurs when a track is doubled, in which case - * the detour is typically 2 tiles. It is also often used at station - * entrances, when there is a choice of multiple platforms. If we take - * a typical 4 platform station, the detour is 4 tiles. To properly - * support larger stations we increase this value. - * We want to prevent that trains that want to leave at one side of a - * station, leave through the other side, turn around, enter the - * station on another platform and exit the station on the right side - * again, just because the sign at the right side was red. If we take - * a typical 5 length station, this detour is 10 or 11 tiles (not - * sure), so we set the default penalty at 10 (the station tile - * penalty will further prevent this. - * We give presignal exits (and combo's) a different (larger) penalty, because - * we really don't want trains waiting in front of a presignal exit. */ - SDT_VAR(Patches, npf_rail_firstred_penalty, SLE_UINT, 0, 0, (10 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), - SDT_VAR(Patches, npf_rail_firstred_exit_penalty,SLE_UINT, 0, 0, (100 * NPF_TILE_LENGTH),0, 100000, 0, STR_NULL, NULL), - /* This penalty is for when the last signal before the target is red. - * This is useful for train stations, where there are multiple - * platforms to choose from, which lie in different signal blocks. - * Every target in a occupied signal block (ie an occupied platform) - * will get this penalty. */ - SDT_VAR(Patches, npf_rail_lastred_penalty, SLE_UINT, 0, 0, (10 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), - /* When a train plans a route over a station tile, this penalty is - * applied. We want that trains plan a route around a typical, 4x5 - * station, which means two tiles to the right, and two tiles back to - * the left around it, or 5 tiles of station through it. If we assign - * a penalty of 1 tile for every station tile passed, the route will - * be around it. */ - SDT_VAR(Patches, npf_rail_station_penalty, SLE_UINT, 0, 0, (1 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), - SDT_VAR(Patches, npf_rail_slope_penalty, SLE_UINT, 0, 0, (1 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), - /* This penalty is applied when a train makes a turn. Its value of 1 makes - * sure that it has a minimal impact on the pathfinding, only when two - * paths have equal length it will make a difference */ - SDT_VAR(Patches, npf_rail_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL), - /* Ths penalty is applied when a vehicle reverses inside a depot (doesn't - * apply to ships, as they can just come out the other end). XXX: Is this a - * good value? */ - SDT_VAR(Patches, npf_rail_depot_reverse_penalty,SLE_UINT, 0, 0, (NPF_TILE_LENGTH * 50), 0, 100000, 0, STR_NULL, NULL), - SDT_VAR(Patches, npf_buoy_penalty, SLE_UINT, 0, 0, (2 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), - /* This penalty is applied when a ship makes a turn. It is bigger than the - * rail curve penalty, since ships (realisticly) have more trouble with - * making turns */ - SDT_VAR(Patches, npf_water_curve_penalty, SLE_UINT, 0, 0, (NPF_TILE_LENGTH / 4), 0, 100000, 0, STR_NULL, NULL), - /* This is the penalty for road, same as for rail. */ - SDT_VAR(Patches, npf_road_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL), - /* This is the penalty for level crossings, for both road and rail vehicles */ - SDT_VAR(Patches, npf_crossing_penalty, SLE_UINT, 0, 0, (3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL), - /* This is the penalty for drive-through road, stops. */ - SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - - - /* The maximum number of nodes to search */ - SDT_CONDBOOL(Patches, yapf.disable_node_optimization , 28, SL_MAX_VERSION, 0, 0, false , STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.max_search_nodes , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10000 , 500, 1000000, 0, STR_NULL, NULL), - SDT_CONDBOOL(Patches, yapf.rail_firstred_twoway_eol , 28, SL_MAX_VERSION, 0, 0, true , STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_firstred_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_firstred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_lastred_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_lastred_exit_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 100 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_station_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 30 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_slope_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_curve45_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_curve90_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 6 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - /* This penalty is applied when a train reverses inside a depot */ - SDT_CONDVAR (Patches, yapf.rail_depot_reverse_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 50 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - /* This is the penalty for level crossings (for trains only) */ - SDT_CONDVAR (Patches, yapf.rail_crossing_penalty , SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - /* look-ahead how many signals are checked */ - SDT_CONDVAR (Patches, yapf.rail_look_ahead_max_signals, SLE_UINT, 28, SL_MAX_VERSION, 0, 0, 10 , 1, 100, 0, STR_NULL, NULL), - /* look-ahead n-th red signal penalty polynomial: penalty = p2 * n^2 + p1 * n + p0 */ - SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p0 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 500 , -1000000, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p1 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, -100 , -1000000, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_look_ahead_signal_p2 , SLE_INT , 28, SL_MAX_VERSION, 0, 0, 5 , -1000000, 1000000, 0, STR_NULL, NULL), - /* penalties for too long or too short station platforms */ - SDT_CONDVAR (Patches, yapf.rail_longer_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_longer_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_shorter_platform_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 40 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.rail_shorter_platform_per_tile_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 0 * YAPF_TILE_LENGTH, 0, 20000, 0, STR_NULL, NULL), - /* road vehicles - penalties */ - SDT_CONDVAR (Patches, yapf.road_slope_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.road_curve_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.road_crossing_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - SDT_CONDVAR (Patches, yapf.road_stop_penalty , SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL), - - /***************************************************************************/ - /* Terrain genation related patch options */ - SDT_CONDVAR(Patches, land_generator, SLE_UINT8, 30, SL_MAX_VERSION, 0, MS, 1, 0, 1, 0, STR_CONFIG_PATCHES_LAND_GENERATOR, NULL), - SDT_CONDVAR(Patches, oil_refinery_limit, SLE_UINT8, 30, SL_MAX_VERSION, 0, 0, 32, 12, 48, 0, STR_CONFIG_PATCHES_OIL_REF_EDGE_DISTANCE, NULL), - SDT_CONDVAR(Patches, tgen_smoothness, SLE_UINT8, 30, SL_MAX_VERSION, 0, MS, 1, 0, 3, 0, STR_CONFIG_PATCHES_ROUGHNESS_OF_TERRAIN, NULL), - SDT_CONDVAR(Patches, generation_seed, SLE_UINT32, 30, SL_MAX_VERSION, 0, 0, GENERATE_NEW_SEED, 0, MAX_UVALUE(uint32), 0, STR_NULL, NULL), - SDT_CONDVAR(Patches, tree_placer, SLE_UINT8, 30, SL_MAX_VERSION, 0, MS, 2, 0, 2, 0, STR_CONFIG_PATCHES_TREE_PLACER, NULL), - SDT_VAR (Patches, heightmap_rotation, SLE_UINT8, S, MS, 0, 0, 1, 0, STR_CONFIG_PATCHES_HEIGHTMAP_ROTATION, NULL), - SDT_VAR (Patches, se_flat_world_height, SLE_UINT8, S, 0, 0, 0, 15, 0, STR_CONFIG_PATCHES_SE_FLAT_WORLD_HEIGHT, NULL), + SDT_VAR(Settings, game_creation.map_x, SLE_UINT8, S, 0, 8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_X, NULL), + SDT_VAR(Settings, game_creation.map_y, SLE_UINT8, S, 0, 8, 6, 11, 0, STR_CONFIG_PATCHES_MAP_Y, NULL), /* * Since the network code (CmdChangePatchSetting and friends) use the index in this array to decide @@ -1643,7 +1767,7 @@ #ifdef __APPLE__ /* We might need to emulate a right mouse button on mac */ - SDT_VAR(Patches,right_mouse_btn_emulation,SLE_UINT8,S,MS,0, 0, 2, 0, STR_CONFIG_PATCHES_RIGHT_MOUSE_BTN_EMU, NULL), + SDT_VAR(Settings, gui.right_mouse_btn_emulation, SLE_UINT8, S, MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_RIGHT_MOUSE_BTN_EMU, NULL), #endif SDT_END() @@ -1669,6 +1793,31 @@ #undef NO #undef CR +static void PrepareOldDiffCustom() +{ + memset(_old_diff_custom, 0, sizeof(_old_diff_custom)); +} + +static void HandleOldDiffCustom() +{ + uint options_to_load = GAME_DIFFICULTY_NUM - (CheckSavegameVersion(4) ? 1 : 0); + + /* If we did read to old_diff_custom, then at least one value must be non 0. */ + bool old_diff_custom_used = false; + for (uint i = 0; i < options_to_load && !old_diff_custom_used; i++) { + old_diff_custom_used = (_old_diff_custom[i] != 0); + } + + if (!old_diff_custom_used) return; + + for (uint i = 0; i < options_to_load; i++) { + const SettingDesc *sd = &_patch_settings[i]; + void *var = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings, &sd->save); + Write_ValidateSetting(var, sd, (int32)((i == 4 ? 1000 : 1) * _old_diff_custom[i])); + } +} + + static void NewsDisplayLoadConfig(IniFile *ini, const char *grpname) { IniGroup *group = ini_getgroup(ini, grpname); @@ -1834,8 +1983,11 @@ proc(ini, (const SettingDesc*)_win32_settings, "win32", NULL); #endif /* WIN32 */ - proc(ini, _gameopt_settings, "gameopt", &_opt_newgame); - proc(ini, _patch_settings, "patches", &_patches_newgame); + PrepareOldDiffCustom(); + proc(ini, _gameopt_settings, "gameopt", &_settings_newgame); + HandleOldDiffCustom(); + + proc(ini, _patch_settings, "patches", &_settings_newgame); proc(ini, _currency_settings,"currency", &_custom_currency); #ifdef ENABLE_NETWORK @@ -1845,8 +1997,6 @@ #endif /* ENABLE_NETWORK */ } -extern void CheckDifficultyLevels(); - /** Load the values from the configuration files */ void LoadFromConfig() { @@ -1864,6 +2014,12 @@ void SaveToConfig() { IniFile *ini = ini_load(_config_file); + + /* Remove some obsolete groups. These have all been loaded into other groups. */ + ini_removegroup(ini, "patches"); + ini_removegroup(ini, "yapf"); + ini_removegroup(ini, "gameopt"); + HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list); GRFSaveConfig(ini, "newgrf", _grfconfig_newgame); GRFSaveConfig(ini, "newgrf-static", _grfconfig_static); @@ -1896,10 +2052,11 @@ if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking) return CMD_ERROR; if ((sd->desc.flags & SGF_NO_NETWORK) && _networking) return CMD_ERROR; + if ((sd->desc.flags & SGF_NEWGAME_ONLY) && _game_mode != GM_MENU) return CMD_ERROR; if (flags & DC_EXEC) { - Patches *patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches; - void *var = GetVariableAddress(patches_ptr, &sd->save); + Settings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings; + void *var = GetVariableAddress(s, &sd->save); Write_ValidateSetting(var, sd, (int32)p2); if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); @@ -1916,7 +2073,7 @@ * This only affects patch-members that are not needed to be the same on all * clients in a network game. * @param value new value of the patch */ -bool SetPatchValue(uint index, const Patches *object, int32 value) +bool SetPatchValue(uint index, const Settings *object, int32 value) { const SettingDesc *sd = &_patch_settings[index]; /* If an item is player-based, we do not send it over the network @@ -1928,7 +2085,7 @@ Write_ValidateSetting(var, sd, value); if (_game_mode != GM_MENU) { - void *var2 = GetVariableAddress(&_patches_newgame, &sd->save); + void *var2 = GetVariableAddress(&_settings_newgame, &sd->save); Write_ValidateSetting(var2, sd, value); } if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv)); @@ -1947,11 +2104,22 @@ { const SettingDesc *sd; + /* First check all full names */ for (*i = 0, sd = _patch_settings; sd->save.cmd != SL_END; sd++, (*i)++) { if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; if (strcmp(sd->desc.name, name) == 0) return sd; } + /* Then check the shortcut variant of the name. */ + for (*i = 0, sd = _patch_settings; sd->save.cmd != SL_END; sd++, (*i)++) { + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + const char *short_name = strchr(sd->desc.name, '.'); + if (short_name != NULL) { + short_name++; + if (strcmp(short_name, name) == 0) return sd; + } + } + return NULL; } @@ -1962,18 +2130,17 @@ bool success; uint index; const SettingDesc *sd = GetPatchFromName(name, &index); - const Patches *patches_ptr; void *ptr; if (sd == NULL) { - IConsolePrintF(_icolour_warn, "'%s' is an unknown patch setting.", name); + IConsolePrintF(CC_WARNING, "'%s' is an unknown patch setting.", name); return true; } - patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches; - ptr = GetVariableAddress(patches_ptr, &sd->save); + Settings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings; + ptr = GetVariableAddress(s, &sd->save); - success = SetPatchValue(index, patches_ptr, value); + success = SetPatchValue(index, s, value); return success; } @@ -1985,11 +2152,11 @@ const void *ptr; if (sd == NULL) { - IConsolePrintF(_icolour_warn, "'%s' is an unknown patch setting.", name); + IConsolePrintF(CC_WARNING, "'%s' is an unknown patch setting.", name); return; } - ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_patches_newgame : &_patches, &sd->save); + ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings, &sd->save); if (sd->desc.cmd == SDT_BOOLX) { snprintf(value, sizeof(value), (*(bool*)ptr == 1) ? "on" : "off"); @@ -1997,27 +2164,27 @@ snprintf(value, sizeof(value), "%d", (int32)ReadValue(ptr, sd->save.conv)); } - IConsolePrintF(_icolour_warn, "Current value for '%s' is: '%s' (min: %s%d, max: %d)", + IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %d)", name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max); } void IConsoleListPatches() { - IConsolePrintF(_icolour_warn, "All patches with their current value:"); + IConsolePrintF(CC_WARNING, "All patches with their current value:"); for (const SettingDesc *sd = _patch_settings; sd->save.cmd != SL_END; sd++) { char value[80]; - const void *ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_patches_newgame : &_patches, &sd->save); + const void *ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings, &sd->save); if (sd->desc.cmd == SDT_BOOLX) { snprintf(value, lengthof(value), (*(bool*)ptr == 1) ? "on" : "off"); } else { snprintf(value, lengthof(value), "%d", (uint32)ReadValue(ptr, sd->save.conv)); } - IConsolePrintF(_icolour_def, "%s = %s", sd->desc.name, value); + IConsolePrintF(CC_DEFAULT, "%s = %s", sd->desc.name, value); } - IConsolePrintF(_icolour_warn, "Use 'patch' command to change a value"); + IConsolePrintF(CC_WARNING, "Use 'patch' command to change a value"); } /** Save and load handler for patches/settings @@ -2028,7 +2195,7 @@ { for (; osd->save.cmd != SL_END; osd++) { const SaveLoad *sld = &osd->save; - void *ptr = GetVariableAddress(object, sld); + void *ptr = GetVariableAddress(sld->global ? NULL : object, sld); if (!SlObjectMember(ptr, sld)) continue; } @@ -2078,13 +2245,9 @@ /* Copy over default setting since some might not get loaded in * a networking environment. This ensures for example that the local * autosave-frequency stays when joining a network-server */ - _opt = _opt_newgame; - LoadSettings(_gameopt_settings, &_opt); -} - -static void Save_OPTS() -{ - SaveSettings(_gameopt_settings, &_opt); + PrepareOldDiffCustom(); + LoadSettings(_gameopt_settings, &_settings); + HandleOldDiffCustom(); } static void Load_PATS() @@ -2092,35 +2255,28 @@ /* Copy over default setting since some might not get loaded in * a networking environment. This ensures for example that the local * signal_side stays when joining a network-server */ - _patches = _patches_newgame; - LoadSettings(_patch_settings, &_patches); + LoadSettings(_patch_settings, &_settings); } static void Save_PATS() { - SaveSettings(_patch_settings, &_patches); + SaveSettings(_patch_settings, &_settings); } void CheckConfig() { - // Increase old default values for pf_maxdepth and pf_maxlength - // to support big networks. - if (_patches_newgame.pf_maxdepth == 16 && _patches_newgame.pf_maxlength == 512) { - _patches_newgame.pf_maxdepth = 48; - _patches_newgame.pf_maxlength = 4096; + /* + * Increase old default values for pf_maxdepth and pf_maxlength + * to support big networks. + */ + if (_settings_newgame.pf.opf.pf_maxdepth == 16 && _settings_newgame.pf.opf.pf_maxlength == 512) { + _settings_newgame.pf.opf.pf_maxdepth = 48; + _settings_newgame.pf.opf.pf_maxlength = 4096; } } -void UpdatePatches() -{ - /* Since old(er) savegames don't have any patches saved, we initialise - * them with the default values just as it was in the old days. - * Also new games need this copying-over */ - _patches = _patches_newgame; /* backwards compatibility */ -} - extern const ChunkHandler _setting_chunk_handlers[] = { - { 'OPTS', Save_OPTS, Load_OPTS, CH_RIFF}, + { 'OPTS', NULL, Load_OPTS, CH_RIFF}, { 'PATS', Save_PATS, Load_PATS, CH_RIFF | CH_LAST}, }; diff -r 68a692eacf22 -r 67db0d431d5e src/settings_func.h --- a/src/settings_func.h Mon May 26 20:45:25 2008 +0000 +++ b/src/settings_func.h Tue May 27 00:50:55 2008 +0000 @@ -12,6 +12,5 @@ void LoadFromConfig(); void SaveToConfig(); void CheckConfig(); -void UpdatePatches(); #endif /* SETTINGS_FUNC_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/settings_gui.cpp --- a/src/settings_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/settings_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -20,7 +20,6 @@ #include "strings_func.h" #include "functions.h" #include "window_func.h" -#include "vehicle_base.h" #include "core/alloc_func.hpp" #include "string_func.h" #include "gfx_func.h" @@ -102,17 +101,6 @@ return i; } -static inline bool RoadVehiclesAreBuilt() -{ - const Vehicle* v; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_ROAD) return true; - } - return false; -} - - enum GameOptionsWidgets { GAMEOPT_CURRENCY_BTN = 4, GAMEOPT_DISTANCE_BTN = 6, @@ -151,199 +139,181 @@ ShowDropDownList(w, list, sel, GAMEOPT_TOWNNAME_BTN); } -/** - * Update/redraw the languages dropdown - * @param w the window the dropdown belongs to - */ -static void ShowLangDropdown(Window *w) -{ - typedef std::map LangList; - - /* Sort language names */ - LangList langs; - for (int i = 0; i < _dynlang.num; i++) langs[SPECSTR_LANGUAGE_START + i] = i; - - DropDownList *list = new DropDownList(); - for (LangList::iterator it = langs.begin(); it != langs.end(); it++) { - list->push_back(new DropDownListStringItem((*it).first, (*it).second, false)); - } - - ShowDropDownList(w, list, _dynlang.curr, GAMEOPT_LANG_BTN); -} - static void ShowCustCurrency(); -static void GameOptionsWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - int i; - StringID str = STR_02BE_DEFAULT; - - w->SetWidgetDisabledState(GAMEOPT_VEHICLENAME_SAVE, !(_vehicle_design_names & 1)); - if (!w->IsWidgetDisabled(GAMEOPT_VEHICLENAME_SAVE)) str = STR_02BF_CUSTOM; - SetDParam(0, str); - SetDParam(1, _currency_specs[_opt_ptr->currency].name); - SetDParam(2, STR_UNITS_IMPERIAL + _opt_ptr->units); - SetDParam(3, STR_02E9_DRIVE_ON_LEFT + _opt_ptr->road_side); - SetDParam(4, TownName(_opt_ptr->town_name)); - SetDParam(5, _autosave_dropdown[_opt_ptr->autosave]); - SetDParam(6, SPECSTR_LANGUAGE_START + _dynlang.curr); - i = GetCurRes(); - SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i); - SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format); - w->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen); - - w->DrawWidgets(); - DrawString(20, 175, STR_OPTIONS_FULLSCREEN, TC_FROMSTRING); // fullscreen - } break; - - case WE_CLICK: - switch (e->we.click.widget) { - case GAMEOPT_CURRENCY_BTN: /* Setup currencies dropdown */ - ShowDropDownMenu(w, BuildCurrencyDropdown(), _opt_ptr->currency, GAMEOPT_CURRENCY_BTN, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0); - break; - - case GAMEOPT_DISTANCE_BTN: /* Setup distance unit dropdown */ - ShowDropDownMenu(w, _units_dropdown, _opt_ptr->units, GAMEOPT_DISTANCE_BTN, 0, 0); - break; - - case GAMEOPT_ROADSIDE_BTN: { /* Setup road-side dropdown */ - int i = 0; - - /* You can only change the drive side if you are in the menu or ingame with - * no vehicles present. In a networking game only the server can change it */ - if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) - i = (-1) ^ (1 << _opt_ptr->road_side); // disable the other value - - ShowDropDownMenu(w, _driveside_dropdown, _opt_ptr->road_side, GAMEOPT_ROADSIDE_BTN, i, 0); - } break; - - case GAMEOPT_TOWNNAME_BTN: /* Setup townname dropdown */ - ShowTownnameDropdown(w, _opt_ptr->town_name); - break; - - case GAMEOPT_AUTOSAVE_BTN: /* Setup autosave dropdown */ - ShowDropDownMenu(w, _autosave_dropdown, _opt_ptr->autosave, GAMEOPT_AUTOSAVE_BTN, 0, 0); - break; - - case GAMEOPT_VEHICLENAME_BTN: /* Setup customized vehicle-names dropdown */ - ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names & 1) ? 1 : 0, GAMEOPT_VEHICLENAME_BTN, (_vehicle_design_names & 2) ? 0 : 2, 0); - break; - - case GAMEOPT_VEHICLENAME_SAVE: /* Save customized vehicle-names to disk */ - break; // not implemented - - case GAMEOPT_LANG_BTN: /* Setup interface language dropdown */ - ShowLangDropdown(w); - break; - - case GAMEOPT_RESOLUTION_BTN: /* Setup resolution dropdown */ - ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), GAMEOPT_RESOLUTION_BTN, 0, 0); - break; +struct GameOptionsWindow : Window { + Settings *opt; - case GAMEOPT_FULLSCREEN: /* Click fullscreen on/off */ - /* try to toggle full-screen on/off */ - if (!ToggleFullScreen(!_fullscreen)) { - ShowErrorMessage(INVALID_STRING_ID, STR_FULLSCREEN_FAILED, 0, 0); - } - w->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen); - w->SetDirty(); - break; - - case GAMEOPT_SCREENSHOT_BTN: /* Setup screenshot format dropdown */ - ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, GAMEOPT_SCREENSHOT_BTN, 0, 0); - break; - } - break; - - case WE_DROPDOWN_SELECT: - switch (e->we.dropdown.button) { - case GAMEOPT_VEHICLENAME_BTN: /* Vehicle design names */ - if (e->we.dropdown.index == 0) { - DeleteCustomEngineNames(); - MarkWholeScreenDirty(); - } else if (!(_vehicle_design_names & 1)) { - LoadCustomEngineNames(); - MarkWholeScreenDirty(); - } - break; - - case GAMEOPT_CURRENCY_BTN: /* Currency */ - if (e->we.dropdown.index == CUSTOM_CURRENCY_ID) ShowCustCurrency(); - _opt_ptr->currency = e->we.dropdown.index; - MarkWholeScreenDirty(); - break; - - case GAMEOPT_DISTANCE_BTN: /* Measuring units */ - _opt_ptr->units = e->we.dropdown.index; - MarkWholeScreenDirty(); - break; - - case GAMEOPT_ROADSIDE_BTN: /* Road side */ - if (_opt_ptr->road_side != e->we.dropdown.index) { // only change if setting changed - DoCommandP(0, e->we.dropdown.index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_00B4_CAN_T_DO_THIS)); - MarkWholeScreenDirty(); - } - break; - - case GAMEOPT_TOWNNAME_BTN: /* Town names */ - if (_game_mode == GM_MENU) { - _opt_ptr->town_name = e->we.dropdown.index; - InvalidateWindow(WC_GAME_OPTIONS, 0); - } - break; - - case GAMEOPT_AUTOSAVE_BTN: /* Autosave options */ - _opt.autosave = _opt_newgame.autosave = e->we.dropdown.index; - w->SetDirty(); - break; - - case GAMEOPT_LANG_BTN: /* Change interface language */ - ReadLanguagePack(e->we.dropdown.index); - CheckForMissingGlyphsInLoadedLanguagePack(); - UpdateAllStationVirtCoord(); - UpdateAllWaypointSigns(); - MarkWholeScreenDirty(); - break; - - case GAMEOPT_RESOLUTION_BTN: /* Change resolution */ - if (e->we.dropdown.index < _num_resolutions && ChangeResInGame(_resolutions[e->we.dropdown.index][0], _resolutions[e->we.dropdown.index][1])) - w->SetDirty(); - break; - - case GAMEOPT_SCREENSHOT_BTN: /* Change screenshot format */ - SetScreenshotFormat(e->we.dropdown.index); - w->SetDirty(); - break; - } - break; - - case WE_DESTROY: - DeleteWindowById(WC_CUSTOM_CURRENCY, 0); - break; + GameOptionsWindow(const WindowDesc *desc) : Window(desc) + { + this->opt = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings; + this->FindWindowPlacementAndResize(desc); } -} + ~GameOptionsWindow() + { + DeleteWindowById(WC_CUSTOM_CURRENCY, 0); + } -/** Change the side of the road vehicles drive on (server only). - * @param tile unused - * @param flags operation to perform - * @param p1 the side of the road; 0 = left side and 1 = right side - * @param p2 unused - */ -CommandCost CmdSetRoadDriveSide(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) -{ - /* Check boundaries and you can only change this if NO vehicles have been built yet, - * except in the intro-menu where of course it's always possible to do so. */ - if (p1 > 1 || (_game_mode != GM_MENU && RoadVehiclesAreBuilt())) return CMD_ERROR; + virtual void OnPaint() + { + StringID str = STR_02BE_DEFAULT; - if (flags & DC_EXEC) { - _opt_ptr->road_side = p1; - InvalidateWindow(WC_GAME_OPTIONS, 0); + this->SetWidgetDisabledState(GAMEOPT_VEHICLENAME_SAVE, !(_vehicle_design_names & 1)); + if (!this->IsWidgetDisabled(GAMEOPT_VEHICLENAME_SAVE)) str = STR_02BF_CUSTOM; + SetDParam(0, str); + SetDParam(1, _currency_specs[this->opt->gui.currency].name); + SetDParam(2, STR_UNITS_IMPERIAL + this->opt->gui.units); + SetDParam(3, STR_02E9_DRIVE_ON_LEFT + this->opt->vehicle.road_side); + SetDParam(4, TownName(this->opt->game_creation.town_name)); + SetDParam(5, _autosave_dropdown[this->opt->gui.autosave]); + SetDParam(6, SPECSTR_LANGUAGE_START + _dynlang.curr); + int i = GetCurRes(); + SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i); + SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format); + this->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen); + + this->DrawWidgets(); + DrawString(20, 175, STR_OPTIONS_FULLSCREEN, TC_FROMSTRING); // fullscreen } - return CommandCost(); -} + + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case GAMEOPT_CURRENCY_BTN: // Setup currencies dropdown + ShowDropDownMenu(this, BuildCurrencyDropdown(), this->opt->gui.currency, GAMEOPT_CURRENCY_BTN, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0); + break; + + case GAMEOPT_DISTANCE_BTN: // Setup distance unit dropdown + ShowDropDownMenu(this, _units_dropdown, this->opt->gui.units, GAMEOPT_DISTANCE_BTN, 0, 0); + break; + + case GAMEOPT_ROADSIDE_BTN: { // Setup road-side dropdown + int i = 0; + extern bool RoadVehiclesAreBuilt(); + + /* You can only change the drive side if you are in the menu or ingame with + * no vehicles present. In a networking game only the server can change it */ + if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) { + i = (-1) ^ (1 << this->opt->vehicle.road_side); // disable the other value + } + + ShowDropDownMenu(this, _driveside_dropdown, this->opt->vehicle.road_side, GAMEOPT_ROADSIDE_BTN, i, 0); + } break; + + case GAMEOPT_TOWNNAME_BTN: // Setup townname dropdown + ShowTownnameDropdown(this, this->opt->game_creation.town_name); + break; + + case GAMEOPT_AUTOSAVE_BTN: // Setup autosave dropdown + ShowDropDownMenu(this, _autosave_dropdown, this->opt->gui.autosave, GAMEOPT_AUTOSAVE_BTN, 0, 0); + break; + + case GAMEOPT_VEHICLENAME_BTN: // Setup customized vehicle-names dropdown + ShowDropDownMenu(this, _designnames_dropdown, (_vehicle_design_names & 1) ? 1 : 0, GAMEOPT_VEHICLENAME_BTN, (_vehicle_design_names & 2) ? 0 : 2, 0); + break; + + case GAMEOPT_VEHICLENAME_SAVE: // Save customized vehicle-names to disk + break; // not implemented + + case GAMEOPT_LANG_BTN: { // Setup interface language dropdown + typedef std::map LangList; + + /* Sort language names */ + LangList langs; + for (int i = 0; i < _dynlang.num; i++) langs[SPECSTR_LANGUAGE_START + i] = i; + + DropDownList *list = new DropDownList(); + for (LangList::iterator it = langs.begin(); it != langs.end(); it++) { + list->push_back(new DropDownListStringItem((*it).first, (*it).second, false)); + } + + ShowDropDownList(this, list, _dynlang.curr, GAMEOPT_LANG_BTN); + } break; + + case GAMEOPT_RESOLUTION_BTN: // Setup resolution dropdown + ShowDropDownMenu(this, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), GAMEOPT_RESOLUTION_BTN, 0, 0); + break; + + case GAMEOPT_FULLSCREEN: // Click fullscreen on/off + /* try to toggle full-screen on/off */ + if (!ToggleFullScreen(!_fullscreen)) { + ShowErrorMessage(INVALID_STRING_ID, STR_FULLSCREEN_FAILED, 0, 0); + } + this->SetWidgetLoweredState(GAMEOPT_FULLSCREEN, _fullscreen); + this->SetDirty(); + break; + + case GAMEOPT_SCREENSHOT_BTN: // Setup screenshot format dropdown + ShowDropDownMenu(this, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, GAMEOPT_SCREENSHOT_BTN, 0, 0); + break; + } + } + + virtual void OnDropdownSelect(int widget, int index) + { + switch (widget) { + case GAMEOPT_VEHICLENAME_BTN: // Vehicle design names + if (index == 0) { + DeleteCustomEngineNames(); + MarkWholeScreenDirty(); + } else if (!(_vehicle_design_names & 1)) { + LoadCustomEngineNames(); + MarkWholeScreenDirty(); + } + break; + + case GAMEOPT_CURRENCY_BTN: /* Currency */ + if (index == CUSTOM_CURRENCY_ID) ShowCustCurrency(); + this->opt->gui.currency = index; + MarkWholeScreenDirty(); + break; + + case GAMEOPT_DISTANCE_BTN: // Measuring units + this->opt->gui.units = index; + MarkWholeScreenDirty(); + break; + + case GAMEOPT_ROADSIDE_BTN: // Road side + if (this->opt->vehicle.road_side != index) { // only change if setting changed + DoCommandP(0, index, 0, NULL, CMD_SET_ROAD_DRIVE_SIDE | CMD_MSG(STR_00B4_CAN_T_DO_THIS)); + MarkWholeScreenDirty(); + } + break; + + case GAMEOPT_TOWNNAME_BTN: // Town names + if (_game_mode == GM_MENU) { + this->opt->game_creation.town_name = index; + InvalidateWindow(WC_GAME_OPTIONS, 0); + } + break; + + case GAMEOPT_AUTOSAVE_BTN: // Autosave options + _settings.gui.autosave = _settings_newgame.gui.autosave = index; + this->SetDirty(); + break; + + case GAMEOPT_LANG_BTN: // Change interface language + ReadLanguagePack(index); + CheckForMissingGlyphsInLoadedLanguagePack(); + UpdateAllStationVirtCoord(); + UpdateAllWaypointSigns(); + MarkWholeScreenDirty(); + break; + + case GAMEOPT_RESOLUTION_BTN: // Change resolution + if (index < _num_resolutions && ChangeResInGame(_resolutions[index][0], _resolutions[index][1])) { + this->SetDirty(); + } + break; + + case GAMEOPT_SCREENSHOT_BTN: // Change screenshot format + SetScreenshotFormat(index); + this->SetDirty(); + break; + } + } +}; static const Widget _game_options_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -382,98 +352,13 @@ WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _game_options_widgets, - GameOptionsWndProc }; void ShowGameOptions() { DeleteWindowById(WC_GAME_OPTIONS, 0); - new Window(&_game_options_desc); -} - -struct GameSettingData { - int16 min; - int16 max; - int16 step; - StringID str; -}; - -static const GameSettingData _game_setting_info[] = { - { 0, 7, 1, STR_NULL}, - { 0, 3, 1, STR_6830_IMMEDIATE}, - { 0, 3, 1, STR_NUM_VERY_LOW}, - { 0, 4, 1, STR_NONE}, - {100, 500, 50, STR_NULL}, - { 2, 4, 1, STR_NULL}, - { 0, 2, 1, STR_6820_LOW}, - { 0, 4, 1, STR_681B_VERY_SLOW}, - { 0, 2, 1, STR_6820_LOW}, - { 0, 2, 1, STR_6823_NONE}, - { 0, 3, 1, STR_6826_X1_5}, - { 0, 2, 1, STR_6820_LOW}, - { 0, 3, 1, STR_682A_VERY_FLAT}, - { 0, 3, 1, STR_VERY_LOW}, - { 0, 1, 1, STR_682E_STEADY}, - { 0, 1, 1, STR_6834_AT_END_OF_LINE_AND_AT_STATIONS}, - { 0, 1, 1, STR_6836_OFF}, - { 0, 2, 1, STR_PERMISSIVE}, -}; - -/* - * A: competitors - * B: start time in months / 3 - * C: town count (3 = high, 0 = very low) - * D: industry count (4 = high, 0 = none) - * E: inital loan / 1000 (in GBP) - * F: interest rate - * G: running costs (0 = low, 2 = high) - * H: construction speed of competitors (0 = very slow, 4 = very fast) - * I: intelligence (0-2) - * J: breakdowns (0 = off, 2 = normal) - * K: subsidy multiplier (0 = 1.5, 3 = 4.0) - * L: construction cost (0-2) - * M: terrain type (0 = very flat, 3 = mountainous) - * N: amount of water (0 = very low, 3 = high) - * O: economy (0 = steady, 1 = fluctuating) - * P: Train reversing (0 = end of line + stations, 1 = end of line) - * Q: disasters - * R: area restructuring (0 = permissive, 2 = hostile) - */ -static const GDType _default_game_diff[3][GAME_DIFFICULTY_NUM] = { /* - A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R*/ - {2, 2, 2, 4, 300, 2, 0, 2, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0}, ///< easy - {4, 1, 2, 3, 150, 3, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1}, ///< medium - {7, 0, 3, 3, 100, 4, 1, 3, 2, 2, 0, 2, 3, 2, 1, 1, 1, 2}, ///< hard -}; - -void SetDifficultyLevel(int mode, GameOptions *gm_opt) -{ - int i; - assert(mode <= 3); - - gm_opt->diff_level = mode; - if (mode != 3) { // not custom - for (i = 0; i != GAME_DIFFICULTY_NUM; i++) - ((GDType*)&gm_opt->diff)[i] = _default_game_diff[mode][i]; - } -} - -/** - * Checks the difficulty levels read from the configuration and - * forces them to be correct when invalid. - */ -void CheckDifficultyLevels() -{ - if (_opt_newgame.diff_level != 3) { - SetDifficultyLevel(_opt_newgame.diff_level, &_opt_newgame); - } else { - for (uint i = 0; i < GAME_DIFFICULTY_NUM; i++) { - GDType *diff = ((GDType*)&_opt_newgame.diff) + i; - *diff = Clamp(*diff, _game_setting_info[i].min, _game_setting_info[i].max); - *diff -= *diff % _game_setting_info[i].step; - } - } + new GameOptionsWindow(&_game_options_desc); } extern void StartupEconomy(); @@ -501,23 +386,23 @@ WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _game_difficulty_widgets, - NULL }; +void SetDifficultyLevel(int mode, DifficultySettings *gm_opt); + struct GameDifficultyWindow : public Window { private: + static const uint GAME_DIFFICULTY_NUM = 18; bool clicked_increase; uint8 clicked_button; uint8 timeout; /* Temporary holding place of values in the difficulty window until 'Save' is clicked */ - GameOptions opt_mod_temp; + Settings opt_mod_temp; enum { GAMEDIFF_WND_TOP_OFFSET = 45, GAMEDIFF_WND_ROWSIZE = 9, - // 0x383E = (1 << 13) | (1 << 12) | (1 << 11) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) - DIFF_INGAME_DISABLED_BUTTONS = 0x383E, NO_SETTINGS_BUTTON = 0xFF, }; @@ -542,7 +427,7 @@ { /* Copy current settings (ingame or in intro) to temporary holding place * change that when setting stuff, copy back on clicking 'OK' */ - this->opt_mod_temp = *_opt_ptr; + this->opt_mod_temp = (_game_mode == GM_MENU) ? _settings_newgame : _settings; this->clicked_increase = false; this->clicked_button = NO_SETTINGS_BUTTON; this->timeout = 0; @@ -559,7 +444,7 @@ WIDGET_LIST_END); this->SetWidgetDisabledState(GDW_HIGHSCORE, _game_mode == GM_EDITOR || _networking); // highscore chart in multiplayer this->SetWidgetDisabledState(GDW_ACCEPT, _networking && !_network_server); // Save-button in multiplayer (and if client) - this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level); + this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); this->FindWindowPlacementAndResize(&_game_difficulty_desc); } @@ -567,29 +452,20 @@ { this->DrawWidgets(); - /* XXX - Disabled buttons in normal gameplay or during muliplayer as non server. - * Bitshifted for each button to see if that bit is set. If it is set, the - * button is disabled */ - uint32 disabled = 0; - if (_networking && !_network_server) { - disabled = MAX_UVALUE(uint32); // Disable all - } else if (_game_mode == GM_NORMAL) { - disabled = DIFF_INGAME_DISABLED_BUTTONS; - } - - int value; + uint i; + const SettingDesc *sd = GetPatchFromName("difficulty.max_no_competitors", &i); int y = GAMEDIFF_WND_TOP_OFFSET; - for (uint i = 0; i != GAME_DIFFICULTY_NUM; i++) { - const GameSettingData *gsd = &_game_setting_info[i]; - value = ((GDType*)&this->opt_mod_temp.diff)[i]; + for (i = 0; i < GAME_DIFFICULTY_NUM; i++, sd++) { + const SettingDescBase *sdb = &sd->desc; + int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); + bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0); DrawArrowButtons(5, y, 3, (this->clicked_button == i) ? 1 + !!this->clicked_increase : 0, - !(HasBit(disabled, i) || gsd->min == value), - !(HasBit(disabled, i) || gsd->max == value)); + editable && sdb->min != value, + editable && sdb->max != value); - value += _game_setting_info[i].str; - if (i == 4) value *= 1000; // XXX - handle currency option + value += sdb->str; SetDParam(0, value); DrawString(30, y, STR_6805_MAXIMUM_NO_COMPETITORS + i, TC_FROMSTRING); @@ -614,30 +490,33 @@ const uint8 btn = y / (GAMEDIFF_WND_ROWSIZE + 2); if (btn >= GAME_DIFFICULTY_NUM || y % (GAMEDIFF_WND_ROWSIZE + 2) >= 9) return; + uint i; + const SettingDesc *sd = GetPatchFromName("difficulty.max_no_competitors", &i) + btn; + const SettingDescBase *sdb = &sd->desc; + /* Clicked disabled button? */ - if (_game_mode == GM_NORMAL && HasBit((int)DIFF_INGAME_DISABLED_BUTTONS, btn)) return; + bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0); + if (!editable) return; this->timeout = 5; + int32 val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); - int16 val = ((GDType*)&this->opt_mod_temp.diff)[btn]; - - const GameSettingData *info = &_game_setting_info[btn]; // get information about the difficulty setting if (x >= 10) { /* Increase button clicked */ - val = min(val + info->step, info->max); + val = min(val + sdb->interval, sdb->max); this->clicked_increase = true; } else { /* Decrease button clicked */ - val -= info->step; - val = max(val, info->min); + val -= sdb->interval; + val = max(val, sdb->min); this->clicked_increase = false; } this->clicked_button = btn; /* save value in temporary variable */ - ((GDType*)&this->opt_mod_temp.diff)[btn] = val; - this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level); - SetDifficultyLevel(3, &this->opt_mod_temp); // set difficulty level to custom + WriteValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv, val); + this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); + SetDifficultyLevel(3, &this->opt_mod_temp.difficulty); // set difficulty level to custom this->LowerWidget(GDW_LVL_CUSTOM); this->SetDirty(); } break; @@ -647,25 +526,32 @@ case GDW_LVL_HARD: case GDW_LVL_CUSTOM: /* temporarily change difficulty level */ - this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level); - SetDifficultyLevel(widget - GDW_LVL_EASY, &this->opt_mod_temp); - this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.diff_level); + this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); + SetDifficultyLevel(widget - GDW_LVL_EASY, &this->opt_mod_temp.difficulty); + this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); this->SetDirty(); break; case GDW_HIGHSCORE: // Highscore Table - ShowHighscoreTable(this->opt_mod_temp.diff_level, -1); + ShowHighscoreTable(this->opt_mod_temp.difficulty.diff_level, -1); break; case GDW_ACCEPT: { // Save button - save changes - GDType btn, val; - for (btn = 0; btn != GAME_DIFFICULTY_NUM; btn++) { - val = ((GDType*)&this->opt_mod_temp.diff)[btn]; + Settings *opt_ptr = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings; + + uint i; + const SettingDesc *sd = GetPatchFromName("difficulty.max_no_competitors", &i); + for (uint btn = 0; btn != GAME_DIFFICULTY_NUM; btn++, sd++) { + int32 new_val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); + int32 cur_val = (int32)ReadValue(GetVariableAddress(opt_ptr, &sd->save), sd->save.conv); /* if setting has changed, change it */ - if (val != ((GDType*)&_opt_ptr->diff)[btn]) - DoCommandP(0, btn, val, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + if (new_val != cur_val) { + DoCommandP(0, i + btn, new_val, NULL, CMD_CHANGE_PATCH_SETTING); + } } - DoCommandP(0, UINT_MAX, this->opt_mod_temp.diff_level, NULL, CMD_CHANGE_DIFFICULTY_LEVEL); + + GetPatchFromName("difficulty.diff_level", &i); + DoCommandP(0, i, this->opt_mod_temp.difficulty.diff_level, NULL, CMD_CHANGE_PATCH_SETTING); delete this; /* If we are in the editor, we should reload the economy. * This way when you load a game, the max loan and interest rate @@ -697,124 +583,125 @@ } static const char *_patches_ui[] = { - "vehicle_speed", - "status_long_date", - "show_finances", - "autoscroll", - "reverse_scroll", - "smooth_scroll", - "errmsg_duration", - "toolbar_pos", - "measure_tooltip", - "window_snap_radius", - "population_in_label", - "link_terraform_toolbar", - "liveries", - "prefer_teamchat", + "gui.vehicle_speed", + "gui.status_long_date", + "gui.show_finances", + "gui.autoscroll", + "gui.reverse_scroll", + "gui.smooth_scroll", + "gui.errmsg_duration", + "gui.toolbar_pos", + "gui.measure_tooltip", + "gui.window_snap_radius", + "gui.population_in_label", + "gui.link_terraform_toolbar", + "gui.liveries", + "gui.prefer_teamchat", /* While the horizontal scrollwheel scrolling is written as general code, only * the cocoa (OSX) driver generates input for it. * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */ - "scrollwheel_scrolling", - "scrollwheel_multiplier", + "gui.scrollwheel_scrolling", + "gui.scrollwheel_multiplier", #ifdef __APPLE__ /* We might need to emulate a right mouse button on mac */ - "right_mouse_btn_emulation", + "gui.right_mouse_btn_emulation", #endif - "pause_on_newgame", - "advanced_vehicle_list", - "loading_indicators", - "timetable_in_ticks", - "default_rail_type", - "always_build_infrastructure", + "gui.pause_on_newgame", + "gui.advanced_vehicle_list", + "gui.loading_indicators", + "gui.timetable_in_ticks", + "gui.default_rail_type", + "gui.always_build_infrastructure", }; static const char *_patches_construction[] = { - "build_on_slopes", - "autoslope", - "extra_dynamite", - "longbridges", - "signal_side", - "always_small_airport", - "enable_signal_gui", - "drag_signals_density", - "oil_refinery_limit", - "semaphore_build_before", + "construction.build_on_slopes", + "construction.autoslope", + "construction.extra_dynamite", + "construction.longbridges", + "construction.signal_side", + "station.always_small_airport", + "gui.enable_signal_gui", + "gui.drag_signals_density", + "game_creation.oil_refinery_limit", + "gui.semaphore_build_before", }; static const char *_patches_stations[] = { - "join_stations", - "improved_load", - "selectgoods", - "new_nonstop", - "nonuniform_stations", - "station_spread", - "serviceathelipad", - "modified_catchment", - "gradual_loading", - "road_stop_on_town_road", - "adjacent_stations", + "station.join_stations", + "order.improved_load", + "order.selectgoods", + "gui.new_nonstop", + "station.nonuniform_stations", + "station.station_spread", + "order.serviceathelipad", + "station.modified_catchment", + "order.gradual_loading", + "construction.road_stop_on_town_road", + "station.adjacent_stations", + "economy.station_noise_level", }; static const char *_patches_economy[] = { - "inflation", - "raw_industry_construction", - "multiple_industry_per_town", - "same_industry_close", - "bribe", - "exclusive_rights", - "give_money", - "colored_news_year", - "ending_year", - "smooth_economy", - "allow_shares", - "town_layout", - "mod_road_rebuild", - "town_growth_rate", - "larger_towns", - "initial_city_size", + "economy.inflation", + "construction.raw_industry_construction", + "economy.multiple_industry_per_town", + "economy.same_industry_close", + "economy.bribe", + "economy.exclusive_rights", + "economy.give_money", + "gui.colored_news_year", + "gui.ending_year", + "economy.smooth_economy", + "economy.allow_shares", + "economy.town_layout", + "economy.mod_road_rebuild", + "economy.town_growth_rate", + "economy.larger_towns", + "economy.initial_city_size", }; static const char *_patches_ai[] = { - "ainew_active", - "ai_in_multiplayer", - "ai_disable_veh_train", - "ai_disable_veh_roadveh", - "ai_disable_veh_aircraft", - "ai_disable_veh_ship", + "ai.ainew_active", + "ai.ai_in_multiplayer", + "ai.ai_disable_veh_train", + "ai.ai_disable_veh_roadveh", + "ai.ai_disable_veh_aircraft", + "ai.ai_disable_veh_ship", }; static const char *_patches_vehicles[] = { - "realistic_acceleration", - "forbid_90_deg", - "mammoth_trains", - "gotodepot", - "roadveh_queue", - "pathfinder_for_trains", - "pathfinder_for_roadvehs", - "pathfinder_for_ships", - "train_income_warn", - "order_review_system", - "never_expire_vehicles", - "lost_train_warn", - "autorenew", - "autorenew_months", - "autorenew_money", - "max_trains", - "max_roadveh", - "max_aircraft", - "max_ships", - "servint_ispercent", - "servint_trains", - "servint_roadveh", - "servint_ships", - "servint_aircraft", - "no_servicing_if_no_breakdowns", - "wagon_speed_limits", - "disable_elrails", - "freight_trains", - "plane_speed", - "timetabling", - "dynamic_engines", + "vehicle.realistic_acceleration", + "pf.forbid_90_deg", + "vehicle.mammoth_trains", + "order.gotodepot", + "pf.roadveh_queue", + "pf.pathfinder_for_trains", + "pf.pathfinder_for_roadvehs", + "pf.pathfinder_for_ships", + "gui.train_income_warn", + "gui.order_review_system", + "vehicle.never_expire_vehicles", + "gui.lost_train_warn", + "gui.autorenew", + "gui.autorenew_months", + "gui.autorenew_money", + "vehicle.max_trains", + "vehicle.max_roadveh", + "vehicle.max_aircraft", + "vehicle.max_ships", + "vehicle.servint_ispercent", + "vehicle.servint_trains", + "vehicle.servint_roadveh", + "vehicle.servint_ships", + "vehicle.servint_aircraft", + "order.no_servicing_if_no_breakdowns", + "vehicle.wagon_speed_limits", + "vehicle.disable_elrails", + "vehicle.freight_trains", + "vehicle.plane_speed", + "order.timetabling", + "vehicle.dynamic_engines", }; struct PatchEntry { @@ -851,7 +738,7 @@ }; struct PatchesSelectionWindow : Window { - static Patches *patches_ptr; + static Settings *patches_ptr; static int patches_max; int page; @@ -862,7 +749,7 @@ { static bool first_time = true; - patches_ptr = (_game_mode == GM_MENU) ? &_patches_newgame : &_patches; + patches_ptr = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings; /* Build up the dynamic settings-array only once per OpenTTD session */ if (first_time) { @@ -1074,7 +961,7 @@ } }; -Patches *PatchesSelectionWindow::patches_ptr = NULL; +Settings *PatchesSelectionWindow::patches_ptr = NULL; int PatchesSelectionWindow::patches_max = 0; static const Widget _patches_selection_widgets[] = { @@ -1097,7 +984,6 @@ WC_GAME_OPTIONS, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _patches_selection_widgets, - NULL, }; void ShowPatchesSelection() @@ -1328,7 +1214,6 @@ WC_CUSTOM_CURRENCY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _cust_currency_widgets, - NULL, }; static void ShowCustCurrency() diff -r 68a692eacf22 -r 67db0d431d5e src/settings_internal.h --- a/src/settings_internal.h Mon May 26 20:45:25 2008 +0000 +++ b/src/settings_internal.h Tue May 27 00:50:55 2008 +0000 @@ -39,8 +39,8 @@ SGF_NETWORK_ONLY = 1 << 3, ///< this setting only applies to network games SGF_CURRENCY = 1 << 4, ///< the number represents money, so when reading value multiply by exchange rate SGF_NO_NETWORK = 1 << 5, ///< this setting does not apply to network games; it may not be changed during the game - SGF_END = 1 << 6, - /* 3 more possible flags */ + SGF_NEWGAME_ONLY = 1 << 6, ///< this setting cannot be changed in inside a game + SGF_END = 1 << 7, }; DECLARE_ENUM_AS_BIT_SET(SettingGuiFlagLong); @@ -84,6 +84,6 @@ }; const SettingDesc *GetPatchFromName(const char *name, uint *i); -bool SetPatchValue(uint index, const Patches *object, int32 value); +bool SetPatchValue(uint index, const Settings *object, int32 value); #endif /* SETTINGS_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/settings_type.h --- a/src/settings_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/settings_type.h Tue May 27 00:50:55 2008 +0000 @@ -5,241 +5,283 @@ #ifndef SETTINGS_TYPE_H #define SETTINGS_TYPE_H -#include "yapf/yapf_settings.h" #include "date_type.h" #include "town_type.h" #include "transport_type.h" -#define GAME_DIFFICULTY_NUM 18 - -/** Specific type for Game Difficulty to ease changing the type */ -typedef uint16 GDType; -struct GameDifficulty { - GDType max_no_competitors; - GDType competitor_start_time; - GDType number_towns; - GDType number_industries; - GDType max_loan; - GDType initial_interest; - GDType vehicle_costs; - GDType competitor_speed; - GDType competitor_intelligence; ///< no longer in use - GDType vehicle_breakdowns; - GDType subsidy_multiplier; - GDType construction_cost; - GDType terrain_type; - GDType quantity_sea_lakes; - GDType economy; - GDType line_reverse_mode; - GDType disasters; - GDType town_council_tolerance; ///< minimum required town ratings to be allowed to demolish stuff -}; - -struct GameOptions { - GameDifficulty diff; - byte diff_level; - byte currency; - byte units; - byte town_name; - byte landscape; - byte snow_line; - byte autosave; - byte road_side; +/** Settings related to the difficulty of the game */ +struct DifficultySettings { + byte max_no_competitors; ///< the number of competitors (AIs) + byte competitor_start_time; ///< how long to wait for the first competitors (AIs) + byte number_towns; ///< the amount of towns + byte number_industries; ///< the amount of industries + uint32 max_loan; ///< the maximum initial loan + byte initial_interest; ///< amount of interest (to pay over the loan) + byte vehicle_costs; ///< amount of money spent on vehicle running cost + byte competitor_speed; ///< the speed at which the AI builds + byte competitor_intelligence; ///< the competior's (AI) intelligence + byte vehicle_breakdowns; ///< likelihood of vehicles breaking down + byte subsidy_multiplier; ///< amount of subsidy + byte construction_cost; ///< how expensive is building + byte terrain_type; ///< the mountainousness of the landscape + byte quantity_sea_lakes; ///< the amount of seas/lakes + byte economy; ///< how volatile is the economy + byte line_reverse_mode; ///< reversing at stations or not + byte disasters; ///< are disasters enabled + byte town_council_tolerance; ///< minimum required town ratings to be allowed to demolish stuff + byte diff_level; ///< the difficulty level }; -/* These are the options for the current game - * either ingame, or loaded. Also used for networking games */ -extern GameOptions _opt; - -/* These are the default options for a new game */ -extern GameOptions _opt_newgame; - -/* Pointer to one of the two _opt OR _opt_newgame structs */ -extern GameOptions *_opt_ptr; - -struct Patches { - bool modified_catchment; ///< different-size catchment areas - bool vehicle_speed; ///< show vehicle speed - bool build_on_slopes; ///< allow building on slopes - bool mammoth_trains; ///< allow very long trains - bool join_stations; ///< allow joining of train stations - bool sg_full_load_any; ///< new full load calculation, any cargo must be full read from pre v93 savegames - bool improved_load; ///< improved loading algorithm - bool gradual_loading; ///< load vehicles gradually - byte station_spread; ///< amount a station may spread - bool inflation; ///< disable inflation - bool selectgoods; ///< only send the goods to station if a train has been there - bool longbridges; ///< allow 100 tile long bridges - bool gotodepot; ///< allow goto depot in orders - uint8 raw_industry_construction; ///< Type of (raw) industry construction (none, "normal", prospecting) - bool multiple_industry_per_town; ///< allow many industries of the same type per town - bool same_industry_close; ///< allow same type industries to be built close to each other - bool lost_train_warn; ///< if a train can't find its destination, show a warning - uint8 order_review_system; - bool train_income_warn; ///< if train is generating little income, show a warning - bool status_long_date; ///< always show long date in status bar - bool signal_side; ///< show signals on right side - bool show_finances; ///< show finances at end of year - bool sg_new_nonstop; ///< ttdpatch compatible nonstop handling read from pre v93 savegames - bool new_nonstop; ///< ttdpatch compatible nonstop handling - bool roadveh_queue; ///< buggy road vehicle queueing - bool autoscroll; ///< scroll when moving mouse to the edge. - byte errmsg_duration; ///< duration of error message - byte land_generator; ///< the landscape generator - byte oil_refinery_limit; ///< distance oil refineries allowed from map edge - byte snow_line_height; ///< a number 0-15 that configured snow line height - byte tgen_smoothness; ///< how rough is the terrain from 0-3 - uint32 generation_seed; ///< noise seed for world generation - byte tree_placer; ///< the tree placer algorithm - byte heightmap_rotation; ///< rotation director for the heightmap - byte se_flat_world_height; ///< land height a flat world gets in SE - bool bribe; ///< enable bribing the local authority - bool nonuniform_stations; ///< allow nonuniform train stations - bool adjacent_stations; ///< allow stations to be built directly adjacent to other stations - bool always_small_airport; ///< always allow small airports - bool realistic_acceleration; ///< realistic acceleration for trains - bool wagon_speed_limits; ///< enable wagon speed limits - bool forbid_90_deg; ///< forbid trains to make 90 deg turns - bool no_servicing_if_no_breakdowns; ///< dont send vehicles to depot when breakdowns are disabled - bool link_terraform_toolbar; ///< display terraform toolbar when displaying rail, road, water and airport toolbars - bool reverse_scroll; ///< Right-Click-Scrolling scrolls in the opposite direction - bool smooth_scroll; ///< Smooth scroll viewports - bool disable_elrails; ///< when true, the elrails are disabled - bool measure_tooltip; ///< Show a permanent tooltip when dragging tools - byte liveries; ///< Options for displaying company liveries, 0=none, 1=self, 2=all - bool prefer_teamchat; ///< Choose the chat message target with , true=all players, false=your team - uint8 advanced_vehicle_list; ///< Use the "advanced" vehicle list - uint8 loading_indicators; ///< Show loading indicators - uint8 default_rail_type; ///< The default rail type for the rail GUI +/** Settings related to the GUI and other stuff that is not saved in the savegame. */ +struct GUISettings { + bool vehicle_speed; ///< show vehicle speed + bool sg_full_load_any; ///< new full load calculation, any cargo must be full read from pre v93 savegames + bool lost_train_warn; ///< if a train can't find its destination, show a warning + uint8 order_review_system; ///< perform order reviews on vehicles + bool train_income_warn; ///< if train is generating little income, show a warning + bool status_long_date; ///< always show long date in status bar + bool show_finances; ///< show finances at end of year + bool sg_new_nonstop; ///< ttdpatch compatible nonstop handling read from pre v93 savegames + bool new_nonstop; ///< ttdpatch compatible nonstop handling + bool autoscroll; ///< scroll when moving mouse to the edge + byte errmsg_duration; ///< duration of error message + bool link_terraform_toolbar; ///< display terraform toolbar when displaying rail, road, water and airport toolbars + bool reverse_scroll; ///< right-Click-Scrolling scrolls in the opposite direction + bool smooth_scroll; ///< smooth scroll viewports + bool measure_tooltip; ///< show a permanent tooltip when dragging tools + byte liveries; ///< options for displaying company liveries, 0=none, 1=self, 2=all + bool prefer_teamchat; ///< choose the chat message target with , true=all players, false=your team + uint8 advanced_vehicle_list; ///< use the "advanced" vehicle list + uint8 loading_indicators; ///< show loading indicators + uint8 default_rail_type; ///< the default rail type for the rail GUI + uint8 toolbar_pos; ///< position of toolbars, 0=left, 1=center, 2=right + uint8 window_snap_radius; ///< windows snap at each other if closer than this + bool always_build_infrastructure; ///< always allow building of infrastructure, even when you do not have the vehicles for it + byte autosave; ///< how often should we do autosaves? + bool keep_all_autosave; ///< name the autosave in a different way + bool autosave_on_exit; ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?" + byte max_num_autosaves; ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1) + bool population_in_label; ///< show the population of a town in his label? + uint8 right_mouse_btn_emulation; ///< should we emulate right mouse clicking? + uint8 scrollwheel_scrolling; ///< scrolling using the scroll wheel? + uint8 scrollwheel_multiplier; ///< how much 'wheel' per incoming event from the OS? + bool pause_on_newgame; ///< whether to start new games paused or not + bool enable_signal_gui; ///< show the signal GUI when the signal button is pressed + Year ending_year; ///< end of the game (just show highscore) + Year colored_news_year; ///< when does newspaper become colored? + bool timetable_in_ticks; ///< whether to show the timetable in ticks rather than days + bool bridge_pillars; ///< show bridge pillars for high bridges + bool auto_euro; ///< automatically switch to euro in 2002 + byte drag_signals_density; ///< many signals density + Year semaphore_build_before; ///< build semaphore signals automatically before this year + bool autorenew; ///< should autorenew be enabled for new companies? + int16 autorenew_months; ///< how many months from EOL of vehicles should autorenew trigger for new companies? + int32 autorenew_money; ///< how much money before autorenewing for new companies? + byte currency; ///< currency we currently use + byte units; ///< unit system we show everything +}; - uint8 toolbar_pos; ///< position of toolbars, 0=left, 1=center, 2=right - uint8 window_snap_radius; ///< Windows snap at each other if closer than this - - bool always_build_infrastructure; ///< Always allow building of infrastructure, even when you do not have the vehicles for it - UnitID max_trains; ///< max trains in game per player (these are 16bit because the unitnumber field can't hold more) - UnitID max_roadveh; ///< max trucks in game per player - UnitID max_aircraft; ///< max planes in game per player - UnitID max_ships; ///< max ships in game per player - - bool servint_ispercent; ///< service intervals are in percents - uint16 servint_trains; ///< service interval for trains - uint16 servint_roadveh; ///< service interval for road vehicles - uint16 servint_aircraft; ///< service interval for aircraft - uint16 servint_ships; ///< service interval for ships - - uint8 pathfinder_for_trains; ///< the pathfinder to use for trains - uint8 pathfinder_for_roadvehs; ///< the pathfinder to use for roadvehicles - uint8 pathfinder_for_ships; ///< the pathfinder to use for ships - - uint8 plane_speed; ///< divisor for speed of aircraft - - bool autorenew; - int16 autorenew_months; - int32 autorenew_money; - - byte pf_maxdepth; ///< maximum recursion depth when searching for a train route for new pathfinder - uint16 pf_maxlength; ///< maximum length when searching for a train route for new pathfinder - - bool bridge_pillars; ///< show bridge pillars for high bridges +/** Settings related to the creation of games. */ +struct GameCreationSettings { + uint32 generation_seed; ///< noise seed for world generation + Year starting_year; ///< starting date + uint8 map_x; ///< X size of map + uint8 map_y; ///< Y size of map + byte land_generator; ///< the landscape generator + byte oil_refinery_limit; ///< distance oil refineries allowed from map edge + byte snow_line_height; ///< a number 0-15 that configured snow line height + byte tgen_smoothness; ///< how rough is the terrain from 0-3 + byte tree_placer; ///< the tree placer algorithm + byte heightmap_rotation; ///< rotation director for the heightmap + byte se_flat_world_height; ///< land height a flat world gets in SE + byte town_name; ///< the town name generator used for town names + byte landscape; ///< the landscape we're currently in + byte snow_line; ///< the snowline level in this game +}; - bool ai_disable_veh_train; ///< disable types for AI - bool ai_disable_veh_roadveh; ///< disable types for AI - bool ai_disable_veh_aircraft; ///< disable types for AI - bool ai_disable_veh_ship; ///< disable types for AI - Year starting_year; ///< starting date - Year ending_year; ///< end of the game (just show highscore) - Year colored_news_year; ///< when does newspaper become colored? - - bool keep_all_autosave; ///< name the autosave in a different way. - bool autosave_on_exit; ///< save an autosave when you quit the game, but do not ask "Do you really want to quit?" - byte max_num_autosaves; ///< controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1) - bool extra_dynamite; ///< extra dynamite - bool road_stop_on_town_road; ///< allow building of drive-through road stops on town owned roads - - bool never_expire_vehicles; ///< never expire vehicles - byte extend_vehicle_life; ///< extend vehicle life by this many years +/** Settings related to construction in-game */ +struct ConstructionSettings { + bool build_on_slopes; ///< allow building on slopes + bool autoslope; ///< allow terraforming under things + bool longbridges; ///< allow 100 tile long bridges + bool signal_side; ///< show signals on right side + bool extra_dynamite; ///< extra dynamite + bool road_stop_on_town_road; ///< allow building of drive-through road stops on town owned roads + uint8 raw_industry_construction; ///< type of (raw) industry construction (none, "normal", prospecting) +}; - bool auto_euro; ///< automatically switch to euro in 2002 - bool serviceathelipad; ///< service helicopters at helipads automatically (no need to send to depot) - bool smooth_economy; ///< smooth economy - bool allow_shares; ///< allow the buying/selling of shares - byte dist_local_authority; ///< distance for town local authority, default 20 - - byte wait_oneway_signal; ///< waitingtime in days before a oneway signal - byte wait_twoway_signal; ///< waitingtime in days before a twoway signal +/** Settings related to the AI. */ +struct AISettings { + bool ainew_active; ///< is the new AI active? + bool ai_in_multiplayer; ///< so we allow AIs in multiplayer + bool ai_disable_veh_train; ///< disable types for AI + bool ai_disable_veh_roadveh; ///< disable types for AI + bool ai_disable_veh_aircraft; ///< disable types for AI + bool ai_disable_veh_ship; ///< disable types for AI +}; - uint8 map_x; ///< Size of map - uint8 map_y; +/** Settings related to the old pathfinder. */ +struct OPFSettings { + uint16 pf_maxlength; ///< maximum length when searching for a train route for new pathfinder + byte pf_maxdepth; ///< maximum recursion depth when searching for a train route for new pathfinder +}; - byte drag_signals_density; ///< many signals density - Year semaphore_build_before; ///< Build semaphore signals automatically before this year - bool ainew_active; ///< Is the new AI active? - bool ai_in_multiplayer; ///< Do we allow AIs in multiplayer - - /* - * New Path Finding - */ - bool new_pathfinding_all; ///< Use the newest pathfinding algorithm for all - +/** Settings related to the new pathfinder. */ +struct NPFSettings { /** * The maximum amount of search nodes a single NPF run should take. This * limit should make sure performance stays at acceptable levels at the cost - * of not being perfect anymore. This will probably be fixed in a more - * sophisticated way sometime soon + * of not being perfect anymore. */ uint32 npf_max_search_nodes; - uint32 npf_rail_firstred_penalty; ///< The penalty for when the first signal is red (and it is not an exit or combo signal) - uint32 npf_rail_firstred_exit_penalty; ///< The penalty for when the first signal is red (and it is an exit or combo signal) - uint32 npf_rail_lastred_penalty; ///< The penalty for when the last signal is red - uint32 npf_rail_station_penalty; ///< The penalty for station tiles - uint32 npf_rail_slope_penalty; ///< The penalty for sloping upwards - uint32 npf_rail_curve_penalty; ///< The penalty for curves - uint32 npf_rail_depot_reverse_penalty; ///< The penalty for reversing in depots - uint32 npf_buoy_penalty; ///< The penalty for going over (through) a buoy - uint32 npf_water_curve_penalty; ///< The penalty for curves - uint32 npf_road_curve_penalty; ///< The penalty for curves - uint32 npf_crossing_penalty; ///< The penalty for level crossings - uint32 npf_road_drive_through_penalty; ///< The penalty for going through a drive-through road stop - - bool population_in_label; ///< Show the population of a town in his label? - - uint8 freight_trains; ///< Value to multiply the weight of cargo by - - /** YAPF settings */ - YapfSettings yapf; - - uint8 right_mouse_btn_emulation; - - uint8 scrollwheel_scrolling; - uint8 scrollwheel_multiplier; - - uint8 town_growth_rate; ///< Town growth rate - uint8 larger_towns; ///< The number of cities to build. These start off larger and grow twice as fast - uint8 initial_city_size; ///< Multiplier for the initial size of the cities compared to towns - - bool pause_on_newgame; ///< Whether to start new games paused or not. - - TownLayoutByte town_layout; ///< Select town layout - - bool timetabling; ///< Whether to allow timetabling. - bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days. - - bool autoslope; ///< Allow terraforming under things. - - bool mod_road_rebuild; ///< Roadworks remove unneccesary RoadBits - - bool exclusive_rights; ///< allow buying exclusive rights - bool give_money; ///< allow giving other players money - - bool enable_signal_gui; ///< Show the signal GUI when the signal button is pressed - - bool dynamic_engines; ///< Enable dynamic allocation of engine data + uint32 npf_rail_firstred_penalty; ///< the penalty for when the first signal is red (and it is not an exit or combo signal) + uint32 npf_rail_firstred_exit_penalty; ///< the penalty for when the first signal is red (and it is an exit or combo signal) + uint32 npf_rail_lastred_penalty; ///< the penalty for when the last signal is red + uint32 npf_rail_station_penalty; ///< the penalty for station tiles + uint32 npf_rail_slope_penalty; ///< the penalty for sloping upwards + uint32 npf_rail_curve_penalty; ///< the penalty for curves + uint32 npf_rail_depot_reverse_penalty; ///< the penalty for reversing in depots + uint32 npf_buoy_penalty; ///< the penalty for going over (through) a buoy + uint32 npf_water_curve_penalty; ///< the penalty for curves + uint32 npf_road_curve_penalty; ///< the penalty for curves + uint32 npf_crossing_penalty; ///< the penalty for level crossings + uint32 npf_road_drive_through_penalty; ///< the penalty for going through a drive-through road stop }; -extern Patches _patches; +/** Settings related to the yet another pathfinder. */ +struct YAPFSettings { + bool disable_node_optimization; ///< whether to use exit-dir instead of trackdir in node key + uint32 max_search_nodes; ///< stop path-finding when this number of nodes visited + bool ship_use_yapf; ///< use YAPF for ships + bool road_use_yapf; ///< use YAPF for road + bool rail_use_yapf; ///< use YAPF for rail + uint32 road_slope_penalty; ///< penalty for up-hill slope + uint32 road_curve_penalty; ///< penalty for curves + uint32 road_crossing_penalty; ///< penalty for level crossing + uint32 road_stop_penalty; ///< penalty for going through a drive-through road stop + bool rail_firstred_twoway_eol; ///< treat first red two-way signal as dead end + uint32 rail_firstred_penalty; ///< penalty for first red signal + uint32 rail_firstred_exit_penalty; ///< penalty for first red exit signal + uint32 rail_lastred_penalty; ///< penalty for last red signal + uint32 rail_lastred_exit_penalty; ///< penalty for last red exit signal + uint32 rail_station_penalty; ///< penalty for non-target station tile + uint32 rail_slope_penalty; ///< penalty for up-hill slope + uint32 rail_curve45_penalty; ///< penalty for curve + uint32 rail_curve90_penalty; ///< penalty for 90-deg curve + uint32 rail_depot_reverse_penalty; ///< penalty for reversing in the depot + uint32 rail_crossing_penalty; ///< penalty for level crossing + uint32 rail_look_ahead_max_signals; ///< max. number of signals taken into consideration in look-ahead load balancer + int32 rail_look_ahead_signal_p0; ///< constant in polynomial penalty function + int32 rail_look_ahead_signal_p1; ///< constant in polynomial penalty function + int32 rail_look_ahead_signal_p2; ///< constant in polynomial penalty function -/** The patch values that are used for new games and/or modified in config file */ -extern Patches _patches_newgame; + uint32 rail_longer_platform_penalty; ///< penalty for longer station platform than train + uint32 rail_longer_platform_per_tile_penalty; ///< penalty for longer station platform than train (per tile) + uint32 rail_shorter_platform_penalty; ///< penalty for shorter station platform than train + uint32 rail_shorter_platform_per_tile_penalty; ///< penalty for shorter station platform than train (per tile) +}; + +/** Settings related to all pathfinders. */ +struct PathfinderSettings { + uint8 pathfinder_for_trains; ///< the pathfinder to use for trains + uint8 pathfinder_for_roadvehs; ///< the pathfinder to use for roadvehicles + uint8 pathfinder_for_ships; ///< the pathfinder to use for ships + bool new_pathfinding_all; ///< use the newest pathfinding algorithm for all + + bool roadveh_queue; ///< buggy road vehicle queueing + bool forbid_90_deg; ///< forbid trains to make 90 deg turns + + byte wait_oneway_signal; ///< waitingtime in days before a oneway signal + byte wait_twoway_signal; ///< waitingtime in days before a twoway signal + + OPFSettings opf; ///< pathfinder settings for the old pathfinder + NPFSettings npf; ///< pathfinder settings for the new pathfinder + YAPFSettings yapf; ///< pathfinder settings for the yet another pathfinder +}; + +/** Settings related to orders. */ +struct OrderSettings { + bool improved_load; ///< improved loading algorithm + bool gradual_loading; ///< load vehicles gradually + bool selectgoods; ///< only send the goods to station if a train has been there + bool gotodepot; ///< allow goto depot in orders + bool no_servicing_if_no_breakdowns; ///< dont send vehicles to depot when breakdowns are disabled + bool timetabling; ///< whether to allow timetabling + bool serviceathelipad; ///< service helicopters at helipads automatically (no need to send to depot) +}; + +/** Settings related to vehicles. */ +struct VehicleSettings { + bool mammoth_trains; ///< allow very long trains + bool realistic_acceleration; ///< realistic acceleration for trains + bool wagon_speed_limits; ///< enable wagon speed limits + bool disable_elrails; ///< when true, the elrails are disabled + UnitID max_trains; ///< max trains in game per player + UnitID max_roadveh; ///< max trucks in game per player + UnitID max_aircraft; ///< max planes in game per player + UnitID max_ships; ///< max ships in game per player + bool servint_ispercent; ///< service intervals are in percents + uint16 servint_trains; ///< service interval for trains + uint16 servint_roadveh; ///< service interval for road vehicles + uint16 servint_aircraft; ///< service interval for aircraft + uint16 servint_ships; ///< service interval for ships + uint8 plane_speed; ///< divisor for speed of aircraft + uint8 freight_trains; ///< value to multiply the weight of cargo by + bool dynamic_engines; ///< enable dynamic allocation of engine data + bool never_expire_vehicles; ///< never expire vehicles + byte extend_vehicle_life; ///< extend vehicle life by this many years + byte road_side; ///< the side of the road vehicles drive on +}; + +/** Settings related to the economy. */ +struct EconomySettings { + bool inflation; ///< disable inflation + bool bribe; ///< enable bribing the local authority + bool smooth_economy; ///< smooth economy + bool allow_shares; ///< allow the buying/selling of shares + byte dist_local_authority; ///< distance for town local authority, default 20 + bool exclusive_rights; ///< allow buying exclusive rights + bool give_money; ///< allow giving other players money + bool mod_road_rebuild; ///< roadworks remove unneccesary RoadBits + bool multiple_industry_per_town; ///< allow many industries of the same type per town + bool same_industry_close; ///< allow same type industries to be built close to each other + uint8 town_growth_rate; ///< town growth rate + uint8 larger_towns; ///< the number of cities to build. These start off larger and grow twice as fast + uint8 initial_city_size; ///< multiplier for the initial size of the cities compared to towns + TownLayoutByte town_layout; ///< select town layout + bool station_noise_level; ///< build new airports when the town noise level is still within accepted limits + uint16 town_noise_population[3]; ///< population to base decision on noise evaluation (@see town_council_tolerance) +}; + +/** Settings related to stations. */ +struct StationSettings { + bool modified_catchment; ///< different-size catchment areas + bool join_stations; ///< allow joining of train stations + bool nonuniform_stations; ///< allow nonuniform train stations + bool adjacent_stations; ///< allow stations to be built directly adjacent to other stations + bool always_small_airport; ///< always allow small airports + byte station_spread; ///< amount a station may spread +}; + +/** All settings together. */ +struct Settings { + DifficultySettings difficulty; ///< settings related to the difficulty + GUISettings gui; ///< settings related to the GUI + GameCreationSettings game_creation; ///< settings used during the creation of a game (map) + ConstructionSettings construction; ///< construction of things in-game + AISettings ai; ///< what may the AI do? + PathfinderSettings pf; ///< settings for all pathfinders + OrderSettings order; ///< settings related to orders + VehicleSettings vehicle; ///< options for vehicles + EconomySettings economy; ///< settings to change the economy + StationSettings station; ///< settings related to station management +}; + +/** The current settings. */ +extern Settings _settings; + +/** The settings values that are used for new games and/or modified in config file */ +extern Settings _settings_newgame; #endif /* SETTINGS_TYPE_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/ship_cmd.cpp --- a/src/ship_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/ship_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -106,7 +106,7 @@ static const Depot* FindClosestShipDepot(const Vehicle* v) { - if (_patches.pathfinder_for_ships == VPF_NPF) { /* NPF is used */ + if (_settings.pf.pathfinder_for_ships == VPF_NPF) { /* NPF is used */ Trackdir trackdir = GetVehicleTrackdir(v); NPFFoundTargetData ftd = NPFRouteToDepotTrialError(v->tile, trackdir, false, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES); @@ -137,7 +137,7 @@ static void CheckIfShipNeedsService(Vehicle *v) { - if (_patches.servint_ships == 0 || !v->NeedsAutomaticServicing()) return; + if (_settings.vehicle.servint_ships == 0 || !v->NeedsAutomaticServicing()) return; if (v->IsInDepot()) { VehicleServiceInDepot(v); return; @@ -196,7 +196,7 @@ InvalidateWindow(WC_VEHICLE_DETAILS, v->index); if (!PlayVehicleSound(v, VSE_BREAKDOWN)) { - SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ? + SndPlayVehicleFx((_settings.game_creation.landscape != LT_TOYLAND) ? SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); } @@ -320,7 +320,7 @@ /*updates statusbar only if speed have changed to save CPU time */ if (spd != v->cur_speed) { v->cur_speed = spd; - if (_patches.vehicle_speed) + if (_settings.gui.vehicle_speed) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } @@ -459,7 +459,7 @@ { assert(IsValidDiagDirection(enterdir)); - switch (_patches.pathfinder_for_ships) { + switch (_settings.pf.pathfinder_for_ships) { case VPF_YAPF: { /* YAPF */ Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks); if (trackdir != INVALID_TRACKDIR) return TrackdirToTrack(trackdir); @@ -756,7 +756,7 @@ unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_SHIP); - if (!Vehicle::AllocateList(NULL, 1) || unit_num > _patches.max_ships) + if (!Vehicle::AllocateList(NULL, 1) || unit_num > _settings.vehicle.max_ships) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); if (flags & DC_EXEC) { @@ -800,7 +800,7 @@ v->name = NULL; v->u.ship.state = TRACK_BIT_DEPOT; - v->service_interval = _patches.servint_ships; + v->service_interval = _settings.vehicle.servint_ships; v->date_of_last_service = _date; v->build_year = _cur_year; v->cur_image = 0x0E5E; @@ -814,7 +814,7 @@ VehiclePositionChanged(v); InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_SHIPS_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); if (IsLocalPlayer()) InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Ship window @@ -851,7 +851,7 @@ if (flags & DC_EXEC) { InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_SHIPS_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); DeleteWindowById(WC_VEHICLE_VIEW, v->index); DeleteDepotHighlightOfVehicle(v); @@ -997,7 +997,7 @@ v->cargo_subtype = new_subtype; InvalidateWindow(WC_VEHICLE_DETAILS, v->index); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_SHIPS_LIST, 0); } return cost; diff -r 68a692eacf22 -r 67db0d431d5e src/signal.cpp --- a/src/signal.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/signal.cpp Tue May 27 00:50:55 2008 +0000 @@ -465,7 +465,7 @@ * Updates blocks in _globset buffer * * @param owner player whose signals we are updating - * @return false iff presignal entry would be green (needed for trains leaving depot) + * @return state of the first block from _globset * @pre IsValidPlayer(owner) */ static SigSegState UpdateSignalsInBuffer(Owner owner) @@ -630,7 +630,7 @@ * @param tile tile where we start * @param side side of tile * @param owner owner whose signals we will update - * @return false iff train can leave depot + * @return the state of the signal segment */ SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner) { diff -r 68a692eacf22 -r 67db0d431d5e src/signs_gui.cpp --- a/src/signs_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/signs_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -66,54 +66,63 @@ DEBUG(misc, 3, "Resorting global signs list"); } -static void SignListWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - if (_sign_sort_dirty) GlobalSortSignList(); - - SetVScrollCount(w, _num_sign_sort); - - SetDParam(0, w->vscroll.count); - w->DrawWidgets(); - - /* No signs? */ - int y = 16; // offset from top of widget - if (w->vscroll.count == 0) { - DrawString(2, y, STR_304A_NONE, TC_FROMSTRING); - return; - } - - /* Start drawing the signs */ - for (uint16 i = w->vscroll.pos; i < w->vscroll.cap + w->vscroll.pos && i < w->vscroll.count; i++) { - const Sign *si = _sign_sort[i]; - - if (si->owner != OWNER_NONE) DrawPlayerIcon(si->owner, 4, y + 1); +struct SignListWindow : Window { + SignListWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->vscroll.cap = 12; + this->resize.step_height = 10; + this->resize.height = this->height - 10 * 7; // minimum if 5 in the list - SetDParam(0, si->index); - DrawString(22, y, STR_SIGN_NAME, TC_YELLOW); - y += 10; - } - } break; - - case WE_CLICK: - if (e->we.click.widget == 3) { - uint32 id_v = (e->we.click.pt.y - 15) / 10; + this->FindWindowPlacementAndResize(desc); + } - if (id_v >= w->vscroll.cap) return; - id_v += w->vscroll.pos; - if (id_v >= w->vscroll.count) return; + virtual void OnPaint() + { + if (_sign_sort_dirty) GlobalSortSignList(); - const Sign *si = _sign_sort[id_v]; - ScrollMainWindowToTile(TileVirtXY(si->x, si->y)); - } - break; + SetVScrollCount(this, _num_sign_sort); - case WE_RESIZE: - w->vscroll.cap += e->we.sizing.diff.y / 10; - break; + SetDParam(0, this->vscroll.count); + this->DrawWidgets(); + + /* No signs? */ + int y = 16; // offset from top of widget + if (this->vscroll.count == 0) { + DrawString(2, y, STR_304A_NONE, TC_FROMSTRING); + return; + } + + /* Start drawing the signs */ + for (uint16 i = this->vscroll.pos; i < this->vscroll.cap + this->vscroll.pos && i < this->vscroll.count; i++) { + const Sign *si = _sign_sort[i]; + + if (si->owner != OWNER_NONE) DrawPlayerIcon(si->owner, 4, y + 1); + + SetDParam(0, si->index); + DrawString(22, y, STR_SIGN_NAME, TC_YELLOW); + y += 10; + } } -} + + virtual void OnClick(Point pt, int widget) + { + if (widget == 3) { + uint32 id_v = (pt.y - 15) / 10; + + if (id_v >= this->vscroll.cap) return; + id_v += this->vscroll.pos; + if (id_v >= this->vscroll.count) return; + + const Sign *si = _sign_sort[id_v]; + ScrollMainWindowToTile(TileVirtXY(si->x, si->y)); + } + } + + virtual void OnResize(Point new_size, Point delta) + { + this->vscroll.cap += delta.y / 10; + } +}; static const Widget _sign_list_widget[] = { { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -130,18 +139,12 @@ WC_SIGN_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE, _sign_list_widget, - SignListWndProc }; void ShowSignList() { - Window *w = AllocateWindowDescFront(&_sign_list_desc, 0); - if (w != NULL) { - w->vscroll.cap = 12; - w->resize.step_height = 10; - w->resize.height = w->height - 10 * 7; // minimum if 5 in the list - } + AllocateWindowDescFront(&_sign_list_desc, 0); } static void RenameSign(SignID index, const char *text) @@ -170,6 +173,7 @@ this->LowerWidget(QUERY_EDIT_SIGN_WIDGET_TEXT); UpdateSignEditWindow(si); + this->FindWindowPlacementAndResize(desc); } ~SignWindow() @@ -255,10 +259,10 @@ } } - virtual bool OnKeyPress(uint16 key, uint16 keycode) + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { - bool cont = true; - switch (this->HandleEditBoxKey(QUERY_EDIT_SIGN_WIDGET_TEXT, key, keycode, cont)) { + EventState state = ES_NOT_HANDLED; + switch (this->HandleEditBoxKey(QUERY_EDIT_SIGN_WIDGET_TEXT, key, keycode, state)) { case 1: // Enter pressed, confirms change RenameSign(this->cur_sign, this->text.buf); /* FALL THROUGH */ @@ -267,7 +271,7 @@ delete this; break; } - return cont; + return state; } virtual void OnMouseLoop() @@ -295,7 +299,6 @@ WC_QUERY_STRING, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _query_sign_edit_widgets, - NULL }; void ShowRenameSignWindow(const Sign *si) diff -r 68a692eacf22 -r 67db0d431d5e src/smallmap_gui.cpp --- a/src/smallmap_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/smallmap_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -459,7 +459,7 @@ case MP_TREES: if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT) { - bits = (_opt.landscape == LT_ARCTIC) ? MKCOLOR(0x98575798) : MKCOLOR(0xC25757C2); + bits = (_settings.game_creation.landscape == LT_ARCTIC) ? MKCOLOR(0x98575798) : MKCOLOR(0xC25757C2); } else { bits = MKCOLOR(0x54575754); } @@ -490,6 +490,10 @@ case MP_INDUSTRY: o = OWNER_END; break; case MP_HOUSE: o = OWNER_TOWN; break; default: o = GetTileOwner(tile); break; + /* FIXME: For MP_ROAD there are multiple owners. + * GetTileOwner returns the rail owner (level crossing) resp. the owner of ROADTYPE_ROAD (normal road), + * even if there are no ROADTYPE_ROAD bits on the tile. + */ } return _owner_colors[o]; @@ -1078,7 +1082,6 @@ WC_SMALLMAP, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE, _smallmap_widgets, - NULL }; void ShowSmallMap() @@ -1224,7 +1227,6 @@ WC_EXTRA_VIEW_PORT, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _extra_view_port_widgets, - NULL }; void ShowExtraViewPortWindow(TileIndex tile) diff -r 68a692eacf22 -r 67db0d431d5e src/sortlist_type.h --- a/src/sortlist_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/sortlist_type.h Tue May 27 00:50:55 2008 +0000 @@ -5,12 +5,16 @@ #ifndef SORTLIST_TYPE_H #define SORTLIST_TYPE_H +#include "misc/smallvec.h" +#include "date_type.h" + enum SortListFlags { - VL_NONE = 0, ///< no sort - VL_DESC = 1 << 0, ///< sort descending or ascending - VL_RESORT = 1 << 1, ///< instruct the code to resort the list in the next loop - VL_REBUILD = 1 << 2, ///< create sort-listing to use for qsort and friends - VL_END = 1 << 3, + VL_NONE = 0, ///< no sort + VL_DESC = 1 << 0, ///< sort descending or ascending + VL_RESORT = 1 << 1, ///< instruct the code to resort the list in the next loop + VL_REBUILD = 1 << 2, ///< rebuild the sort list + VL_FIRST_SORT = 1 << 3, ///< sort with qsort first + VL_END = 1 << 4, }; DECLARE_ENUM_AS_BIT_SET(SortListFlags); @@ -20,12 +24,269 @@ }; template -struct GUIList { - T* sort_list; ///< The items to sort. - SortListFlags flags; ///< used to control sorting/resorting/etc. - uint16 list_length; ///< length of the list being sorted - uint16 resort_timer; ///< resort list after a given amount of ticks if set - byte sort_type; ///< what criteria to sort on +class GUIList : public SmallVector { +public: + typedef int CDECL SortFunction(const T*, const T*); + +public: // Temporary: public for conversion only + SortFunction* const *func_list; ///< The sort criteria functions + SortListFlags flags; ///< used to control sorting/resorting/etc. + uint8 sort_type; ///< what criteria to sort on + uint16 resort_timer; ///< resort list after a given amount of ticks if set + + /** + * Check if the list is sortable + * + * @return true if we can sort the list + */ + bool IsSortable() const + { + return (this->data != NULL && this->items >= 2); + } + + /** + * Reset the resort timer + */ + void ResetResortTimer() + { + /* Resort every 10 days */ + this->resort_timer = DAY_TICKS * 10; + } + + /** + * Reverse the list + */ + void Reverse() + { + assert(this->IsSortable()); + + T *a = this->data; + T *b = a + (this->items - 1); + + do { + Swap(*a, *b); + } while (++a < --b); + } + +public: + GUIList() : + func_list(NULL), + flags(VL_FIRST_SORT), + sort_type(0), + resort_timer(1) + {}; + + /** + * Get the sorttype of the list + * + * @return The current sorttype + */ + uint8 SortType() const + { + return this->sort_type; + } + + /** + * Set the sorttype of the list + * + * @param n_type the new sort type + */ + void SetSortType(uint8 n_type) + { + if (this->sort_type != n_type) { + SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT); + this->sort_type = n_type; + } + } + + /** + * Export current sort conditions + * + * @return the current sort conditions + */ + Listing GetListing() const + { + Listing l; + l.order = HASBITS(this->flags, VL_DESC); + l.criteria = this->sort_type; + + return l; + } + + /** + * Import sort conditions + * + * @param l The sport conditions we want to use + */ + void SetListing(Listing l) + { + if (l.order) { + SETBITS(this->flags, VL_DESC); + } else { + CLRBITS(this->flags, VL_DESC); + } + this->sort_type = l.criteria; + + SETBITS(this->flags, VL_FIRST_SORT); + } + + /** + * Check if a resort is needed next loop + * If used the resort timer will decrease every call + * till 0. If 0 reached the resort bit will be set and + * the timer will be reset. + * + * @return true if resort bit is set for next loop + */ + bool NeedResort() + { + if (--this->resort_timer == 0) { + SETBITS(this->flags, VL_RESORT); + this->ResetResortTimer(); + return true; + } + return false; + } + + /** + * Force a resort next Sort call + * Reset the resort timer if used too. + */ + void ForceResort() + { + SETBITS(this->flags, VL_RESORT); + } + + /** + * Check if the sort order is descending + * + * @return true if the sort order is descending + */ + bool IsDescSortOrder() const + { + return HASBITS(this->flags, VL_DESC); + } + + /** + * Toogle the sort order + * Since that is the worst condition for the sort function + * reverse the list here. + */ + FORCEINLINE void ToggleSortOrder() + { + this->flags ^= VL_DESC; + + if (this->IsSortable()) this->Reverse(); + } + + /** + * GnomeSort algorithm + * This sorting uses a slightly modifyied Gnome search. + * The basic Gnome search trys to sort already sorted + * list parts. The modification skips these. For the first + * sorting we use qsort since it is faster for irregular + * sorted data. + * + * @param compare The function to compare two list items + * */ + FORCEINLINE void Sort(SortFunction *compare) + { + /* Do not sort if the resort bit is not set */ + if (!HASBITS(this->flags, VL_RESORT)) return; + + CLRBITS(this->flags, VL_RESORT); + + this->ResetResortTimer(); + + /* Do not sort when the list is not sortable */ + if (!this->IsSortable()) return; + + const bool desc = HASBITS(this->flags, VL_DESC); + + if (HASBITS(this->flags, VL_FIRST_SORT)) { + qsort(this->data, this->items, sizeof(T), (int (CDECL *)(const void *, const void *))compare); + + if (desc) this->Reverse(); + return; + } + + T *a = this->data; + T *b = a + 1; + + uint length = this->items; + uint offset = 0; // Jump variable + + while (length > 1) { + const int diff = compare(a, b); + if ((!desc && diff <= 0) || (desc && diff >= 0)) { + if (offset != 0) { + /* Jump back to the last direction switch point */ + a += offset; + b += offset; + offset = 0; + continue; + } + a++; + b++; + length--; + } else { + Swap(*a, *b); + if (a != this->data) { + offset++; + a--; + b--; + } + } + } + } + + /** + * Hand the array of sort function pointers to the sort list + * + * @param n_funcs The pointer to the first sort func + */ + void SetSortFuncs(SortFunction* const* n_funcs) + { + this->func_list = n_funcs; + } + + /** + * Overload of Sort() + * Overloaded to reduce external code + */ + void Sort() + { + assert(this->func_list != NULL); + this->Sort(this->func_list[this->sort_type]); + } + + /** + * Check if a rebuild is needed + * @return true if a rebuild is needed + */ + bool NeedRebuild() const + { + return HASBITS(this->flags, VL_REBUILD); + } + + /** + * Force that a rebuild is needed + */ + void ForceRebuild() + { + SETBITS(this->flags, VL_REBUILD); + } + + /** + * Notify the sortlist that the rebuild is done + * + * @note This forces a resort + */ + void RebuildDone() + { + CLRBITS(this->flags, VL_REBUILD); + SETBITS(this->flags, VL_RESORT); + } }; #endif /* SORTLIST_TYPE_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/station.cpp --- a/src/station.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/station.cpp Tue May 27 00:50:55 2008 +0000 @@ -74,8 +74,7 @@ } MarkDirty(); - RebuildStationLists(); - InvalidateWindowClasses(WC_STATION_LIST); + InvalidateWindowData(WC_STATION_LIST, this->owner, 0); DeleteWindowById(WC_STATION_VIEW, index); @@ -286,7 +285,7 @@ /* check new rect dimensions against preset max */ int w = new_rect.right - new_rect.left + 1; int h = new_rect.bottom - new_rect.top + 1; - if (mode != ADD_FORCE && (w > _patches.station_spread || h > _patches.station_spread)) { + if (mode != ADD_FORCE && (w > _settings.station.station_spread || h > _settings.station.station_spread)) { assert(mode != ADD_TRY); _error_message = STR_306C_STATION_TOO_SPREAD_OUT; return false; diff -r 68a692eacf22 -r 67db0d431d5e src/station_cmd.cpp --- a/src/station_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/station_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -358,7 +358,7 @@ CountMapSquareAround(tile, CMSATree) >= 8 || CountMapSquareAround(tile, CMSAForest) >= 2) ) { - return _opt.landscape == LT_TROPIC ? STR_SV_STNAME_FOREST : STR_SV_STNAME_WOODS; + return _settings.game_creation.landscape == LT_TROPIC ? STR_SV_STNAME_FOREST : STR_SV_STNAME_WOODS; } /* check elevation compared to town */ @@ -625,7 +625,7 @@ TileXY(rect.left, rect.bottom), rect.right - rect.left + 1, rect.top - rect.bottom + 1, - _patches.modified_catchment ? FindCatchmentRadius(st) : (uint)CA_UNMODIFIED + _settings.station.modified_catchment ? FindCatchmentRadius(st) : (uint)CA_UNMODIFIED ); } else { memset(accepts, 0, sizeof(accepts)); @@ -712,8 +712,7 @@ { if (st->facilities == 0) { st->delete_ctr = 0; - RebuildStationLists(); - InvalidateWindow(WC_STATION_LIST, st->owner); + InvalidateWindowData(WC_STATION_LIST, st->owner, 0); } /* station remains but it probably lost some parts - station sign should stay in the station boundaries */ UpdateStationSignCoord(st); @@ -763,7 +762,7 @@ * b) the build_on_slopes switch is disabled */ if (IsSteepSlope(tileh) || - ((_is_old_ai_player || !_patches.build_on_slopes) && tileh != SLOPE_FLAT)) { + ((_is_old_ai_player || !_settings.construction.build_on_slopes) && tileh != SLOPE_FLAT)) { return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); } @@ -840,7 +839,7 @@ uint w = fin[1]; uint h = fin[2]; - if (_patches.nonuniform_stations) { + if (_settings.station.nonuniform_stations) { /* determine new size of train station region.. */ int x = min(TileX(st->train_tile), TileX(tile)); int y = min(TileY(st->train_tile), TileY(tile)); @@ -884,7 +883,7 @@ } } /* make sure the final size is not too big. */ - if (curw > _patches.station_spread || curh > _patches.station_spread) { + if (curw > _settings.station.station_spread || curh > _settings.station.station_spread) { _error_message = STR_306C_STATION_TOO_SPREAD_OUT; return false; } @@ -973,7 +972,7 @@ w_org = numtracks; } - if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR; + if (h_org > _settings.station.station_spread || w_org > _settings.station.station_spread) return CMD_ERROR; /* these values are those that will be stored in train_tile and station_platforms */ uint finalvalues[3]; @@ -986,14 +985,14 @@ /* If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug * for detail info, see: * https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365 */ - CommandCost ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL); + CommandCost ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _settings.station.nonuniform_stations ? &est : NULL); if (CmdFailed(ret)) return ret; CommandCost cost(EXPENSES_CONSTRUCTION, ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len); Station *st = NULL; bool check_surrounding = true; - if (_patches.adjacent_stations) { + if (_settings.station.adjacent_stations) { if (est != INVALID_STATION) { if (HasBit(p1, 24)) { /* You can't build an adjacent station over the top of one that @@ -1028,7 +1027,7 @@ if (st->train_tile != 0) { /* check if we want to expanding an already existing station? */ - if (_is_old_ai_player || !_patches.join_stations) + if (_is_old_ai_player || !_settings.station.join_stations) return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD); if (!CanExpandRailroadStation(st, finalvalues, axis)) return CMD_ERROR; @@ -1083,7 +1082,7 @@ /* Now really clear the land below the station * It should never return CMD_ERROR.. but you never know ;) * (a bit strange function name for it, but it really does clear the land, when DC_EXEC is in flags) */ - ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _patches.nonuniform_stations ? &est : NULL); + ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _settings.station.nonuniform_stations ? &est : NULL); if (CmdFailed(ret)) return ret; st->train_tile = finalvalues[0]; @@ -1140,8 +1139,7 @@ st->MarkTilesDirty(false); UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); - RebuildStationLists(); - InvalidateWindow(WC_STATION_LIST, st->owner); + InvalidateWindowData(WC_STATION_LIST, st->owner, 0); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS); } @@ -1253,7 +1251,7 @@ /* Do not allow removing from stations if non-uniform stations are not enabled * The check must be here to give correct error message */ - if (!_patches.nonuniform_stations) return_cmd_error(STR_NONUNIFORM_STATIONS_DISALLOWED); + if (!_settings.station.nonuniform_stations) return_cmd_error(STR_NONUNIFORM_STATIONS_DISALLOWED); /* If we reached here, the tile is valid so increase the quantity of tiles we will remove */ quantity++; @@ -1298,7 +1296,7 @@ static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags) { /* if there is flooding and non-uniform stations are enabled, remove platforms tile by tile */ - if (_current_player == OWNER_WATER && _patches.nonuniform_stations) { + if (_current_player == OWNER_WATER && _settings.station.nonuniform_stations) { return DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_FROM_RAILROAD_STATION); } @@ -1391,7 +1389,7 @@ bool type = HasBit(p2, 0); bool is_drive_through = HasBit(p2, 1); bool build_over_road = is_drive_through && IsNormalRoadTile(tile); - bool town_owned_road = build_over_road && IsTileOwner(tile, OWNER_TOWN); + bool town_owned_road = false; RoadTypes rts = (RoadTypes)GB(p2, 2, 3); if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR; @@ -1410,14 +1408,17 @@ /* Not allowed to build over this road */ if (build_over_road) { - if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD); - RoadTypes cur_rts = GetRoadTypes(tile); /* there is a road, check if we can build road+tram stop over it */ if (HasBit(cur_rts, ROADTYPE_ROAD)) { Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD); - if (road_owner != OWNER_TOWN && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR; + if (road_owner == OWNER_TOWN) { + town_owned_road = true; + if (!_settings.construction.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD); + } else { + if (road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR; + } } /* there is a tram, check if we can build road+tram stop over it */ @@ -1437,7 +1438,7 @@ Station *st = NULL; - if (!_patches.adjacent_stations || !HasBit(p2, 5)) { + if (!_settings.station.adjacent_stations || !HasBit(p2, 5)) { st = GetStationAround(tile, 1, 1, INVALID_STATION); if (st == CHECK_STATIONS_ERR) return CMD_ERROR; } @@ -1498,8 +1499,7 @@ UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); - RebuildStationLists(); - InvalidateWindow(WC_STATION_LIST, st->owner); + InvalidateWindowData(WC_STATION_LIST, st->owner, 0); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS); } return cost; @@ -1608,6 +1608,88 @@ return ret; } +/** Recalculate the noise generated by the airports of each town */ +void UpdateAirportsNoise() +{ + Town *t; + const Station *st; + + FOR_ALL_TOWNS(t) t->noise_reached = 0; + + FOR_ALL_STATIONS(st) { + if (IsAirport(st->xy)) { + st->town->noise_reached += GetAirportNoiseLevelForTown(st->Airport(), st->town->xy, st->xy); + } + } +} + +/** Get a possible noise reduction factor based on distance from town center. + * The further you get, the less noise you generate. + * So all those folks at city council can now happily slee... work in their offices + * @param afc AirportFTAClass pointer of the class being proposed + * @param town_tile TileIndex of town's center, the one who will receive the airport's candidature + * @param tile TileIndex where the new airport might be built + * @return the noise that will be generated, according to distance + */ +uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile) +{ + struct TileIndexDistance { + TileIndex index; + uint distance; + }; + + uint distance; + + /* 0 cannot be accounted, and 1 is the lowest that can be reduced from town. + * So no need to go any further*/ + if (afc->noise_level < 2) return afc->noise_level; + + /* Find the airport-to-be's closest corner to the town */ + if (afc->size_x == 1 && afc->size_y == 1) { + distance = DistanceManhattan(town_tile, tile); // ont tile, one corner, it's THE corner + } else { + /* calculate manhattan distance to town of each side of the airport */ + TileIndexDistance dist[4]; ///< Array that will contain all 4 corners in TileIndex and distance + uint min_tile = UINT_MAX; ///< Sentinel value + uint min_indice = 4; + + /* Based on the size of the airport, establish location of each corner*/ + dist[0].index = tile; // north tile + dist[1].index = TileAddWrap(tile, afc->size_x - 1, afc->size_y - 1); // south tile + dist[2].index = TileAddWrap(tile, afc->size_x - 1, 0); // west tile + dist[3].index = TileAddWrap(tile, 0, afc->size_y - 1); //east tile + + /* now, go and find the smallest one, thus the closest to town */ + for (uint i = 0; i < 4; i++) { + dist[i].distance = DistanceManhattan(town_tile, dist[i].index); + + if (dist[i].distance < min_tile) { + min_tile = dist[i].distance; // here's a new candidate + min_indice = i; + } + } + + distance = dist[min_indice].distance; + } + + /* The steps for measuring noise reduction are based on the "magical" (and arbitrary) 8 base distance + * adding the town_council_tolerance 4 times, as a way to graduate, depending of the tolerance. + * Basically, it says that the less tolerant a town is, the bigger the distance before + * an actual decrease can be granted */ + uint8 town_tolerance_distance = 8 + (_settings.difficulty.town_council_tolerance * 4); + + /* The airport is in the "inner" distance where there is no noise reduction */ + if (distance < town_tolerance_distance) return afc->noise_level; + + /* now, we want to have the distance segmented using the distance judged bareable by town + * This will give us the coefficient of reduction the distance provides. */ + uint noise_reduction = min(afc->noise_level, distance / town_tolerance_distance); + + /* If the noise reduction equals the airport noise itself, don't give it for free. Use it all minus 1. + * Otherwise, simply reduce the airport's level. */ + return max(1U, noise_reduction == afc->noise_level ? afc->noise_level - 1 : afc->noise_level - noise_reduction); +} + /** Place an Airport. * @param tile tile where airport will be built * @param flags operation to perform @@ -1639,24 +1721,38 @@ /* Check if the given station class is valid */ if (GB(p2, 8, 8) >= FSMPORTS_CLASS_MAX) return CMD_ERROR; - /* Check if local auth refuses a new airport */ - uint num = 0; - FOR_ALL_STATIONS(st) { - if (st->town == t && st->facilities & FACIL_AIRPORT && st->Airport() != AirportFTAClass::oil_rig) num++; + /* Check if we can allocate a custom stationspec to this station */ + const FSMportsSpec *fsmportsspec = GetCustomFSMportsSpec((FSMportsClassID)GB(p2, 8, 8), GB(p2, 16, 8)); + if (fsmportsspec == NULL) return CMD_ERROR; + + /* Go get the final noise level, that is base noise minus factor from distance to town center */ + uint newnoise_level = GetAirportNoiseLevelForTown(fsmportsspec->portFSM, t->xy, tile); + + /* Check if local auth would allow a new airport */ + bool authority_refused; + + if (_settings.economy.station_noise_level) { + /* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */ + authority_refused = (t->noise_reached + newnoise_level) > t->MaxTownNoise(); + } else { + uint num = 0; + const Station *st; + FOR_ALL_STATIONS(st) { + if (st->town == t && st->facilities & FACIL_AIRPORT && st->Airport() != AirportFTAClass::oil_rig) num++; + } + authority_refused = (num >= 2); } - if (num >= 2) { + + if (authority_refused) { SetDParam(0, t->index); return_cmd_error(STR_2035_LOCAL_AUTHORITY_REFUSES); } - /* Check if we can allocate a custom stationspec to this station */ - const FSMportsSpec *fsmportsspec = GetCustomFSMportsSpec((FSMportsClassID)GB(p2, 8, 8), GB(p2, 16, 8)); - if (fsmportsspec == NULL) return CMD_ERROR; /* Perform NewStation checks */ byte w = fsmportsspec->size_x[layout_set]; byte h = fsmportsspec->size_y[layout_set]; - if (w > _patches.station_spread || h > _patches.station_spread) { + if (w > _settings.station.station_spread || h > _settings.station.station_spread) { _error_message = STR_306C_STATION_TOO_SPREAD_OUT; return CMD_ERROR; } @@ -1666,7 +1762,7 @@ return CMD_ERROR; } - if (!_patches.adjacent_stations || !HasBit(p1, 24)) { + if (!_settings.station.adjacent_stations || !HasBit(p1, 24)) { st = GetStationAround(tile, w, h, INVALID_STATION); if (st == CHECK_STATIONS_ERR) return CMD_ERROR; } else { @@ -1742,6 +1838,9 @@ cost.AddCost(_price.build_airport * w * h); if (flags & DC_EXEC) { + /* Always add the noise, so there will be no need to recalculate when option toggles */ + st->town->noise_reached += newnoise_level; + st->airport_tile = tile; st->AddFacility(FACIL_AIRPORT, tile); st->airport_flags.ResetAll(); @@ -1773,7 +1872,7 @@ BEGIN_TILE_LOOP(tile_cur, w, h, tile) { partial_snow_desert = 0x00; byte layout = *layout_ptr++; - if ((GetTropicZone(tile_cur) == TROPICZONE_DESERT) || ((GetTileZ(tile_cur) >= GetSnowLine() && _opt.landscape == LT_ARCTIC))) + if ((GetTropicZone(tile_cur) == TROPICZONE_DESERT) || ((GetTileZ(tile_cur) >= GetSnowLine() && _settings.game_creation.landscape == LT_ARCTIC))) partial_snow_desert = 1; MakeAirport(tile_cur, st->owner, st->index, layout); if (layout != 255) @@ -1786,9 +1885,12 @@ UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); - RebuildStationLists(); - InvalidateWindow(WC_STATION_LIST, st->owner); + InvalidateWindowData(WC_STATION_LIST, st->owner, 0); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES); + + if (_settings.economy.station_noise_level) { + InvalidateWindow(WC_TOWN_VIEW, st->town->index); + } } return cost; @@ -1849,12 +1951,22 @@ ); } + /* Go get the final noise level, that is base noise minus factor from distance to town center. + * And as for construction, always remove it, even if the patch is not set, in order to avoid the + * need of recalculation */ + st->town->noise_reached -= GetAirportNoiseLevelForTown(st->Airport(), st->town->xy, tile); + st->rect.AfterRemoveRect(st, tile, w, h); st->airport_tile = 0; st->facilities &= ~FACIL_AIRPORT; InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES); + + if (_settings.economy.station_noise_level) { + InvalidateWindow(WC_TOWN_VIEW, st->town->index); + } + UpdateStationVirtCoordDirty(st); DeleteStationIfEmpty(st); } @@ -1901,8 +2013,7 @@ UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); - RebuildStationLists(); - InvalidateWindow(WC_STATION_LIST, st->owner); + InvalidateWindowData(WC_STATION_LIST, st->owner, 0); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS); } @@ -2015,7 +2126,7 @@ /* middle */ Station *st = NULL; - if (!_patches.adjacent_stations || !HasBit(p1, 0)) { + if (!_settings.station.adjacent_stations || !HasBit(p1, 0)) { st = GetStationAround( tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), _dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION); @@ -2060,8 +2171,7 @@ UpdateStationVirtCoordDirty(st); UpdateStationAcceptance(st, false); - RebuildStationLists(); - InvalidateWindow(WC_STATION_LIST, st->owner); + InvalidateWindowData(WC_STATION_LIST, st->owner, 0); InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS); } @@ -2311,7 +2421,12 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc *td) { - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); + if (IsDriveThroughStopTile(tile) && HasTileRoadType(tile, ROADTYPE_ROAD) && GetStopBuiltOnTownRoad(tile)) { + /* Display a second owner */ + td->owner_type[1] = STR_ROAD_OWNER; + td->owner[1] = OWNER_TOWN; + } td->build_date = GetStationByTile(tile)->build_date; StringID str; @@ -2756,7 +2871,7 @@ st->name = strdup(_cmd_text); UpdateStationVirtCoord(st); - ResortStationLists(); + InvalidateWindowData(WC_STATION_LIST, st->owner, 1); MarkWholeScreenDirty(); } @@ -2779,7 +2894,7 @@ int w_prod; // width and height of the "producer" of the cargo int h_prod; int max_rad; - if (_patches.modified_catchment) { + if (_settings.station.modified_catchment) { w_prod = w; h_prod = h; w += 2 * MAX_CATCHMENT; @@ -2802,7 +2917,7 @@ if (st->IsBuoy()) continue; // bouys don't accept cargo - if (_patches.modified_catchment) { + if (_settings.station.modified_catchment) { /* min and max coordinates of the producer relative */ const int x_min_prod = max_rad + 1; const int x_max_prod = max_rad + w_prod; @@ -2856,7 +2971,7 @@ if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore - if (_patches.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one + if (_settings.order.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one if (IsCargoInClass(type, CC_PASSENGERS)) { if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop @@ -2981,8 +3096,7 @@ SetTileOwner(tile, new_player); if (!IsBuoy(tile)) st->owner = new_player; // do not set st->owner for buoys - RebuildStationLists(); - InvalidateWindowClasses(WC_STATION_LIST); + InvalidateWindowClassesData(WC_STATION_LIST, 0); } else { if (IsDriveThroughStopTile(tile)) { /* Remove the drive-through road stop */ @@ -3005,16 +3119,15 @@ * Road stops built on town-owned roads check the conditions * that would allow clearing of the original road. * @param tile road stop tile to check + * @param flags command flags * @return true if the road can be cleared */ -static bool CanRemoveRoadWithStop(TileIndex tile) +static bool CanRemoveRoadWithStop(TileIndex tile, uint32 flags) { /* The road can always be cleared if it was not a town-owned road */ if (!GetStopBuiltOnTownRoad(tile)) return true; - bool edge_road; - return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, &edge_road, ROADTYPE_ROAD) && - CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_TRAM), OWNER_TOWN, &edge_road, ROADTYPE_TRAM); + return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags); } static CommandCost ClearTile_Station(TileIndex tile, byte flags) @@ -3039,11 +3152,11 @@ case STATION_RAIL: return RemoveRailroadStation(st, tile, flags); case STATION_AIRPORT: return RemoveAirport(st, flags); case STATION_TRUCK: - if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile)) + if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) return_cmd_error(STR_3047_MUST_DEMOLISH_TRUCK_STATION); return RemoveRoadStop(st, flags, tile); case STATION_BUS: - if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile)) + if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) return_cmd_error(STR_3046_MUST_DEMOLISH_BUS_STATION); return RemoveRoadStop(st, flags, tile); case STATION_BUOY: return RemoveBuoy(st, flags); @@ -3095,7 +3208,7 @@ static CommandCost TerraformTile_Station(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) { - if (_patches.build_on_slopes && AutoslopeEnabled()) { + if (_settings.construction.build_on_slopes && AutoslopeEnabled()) { /* TODO: If you implement newgrf callback 149 'land slope check', you have to decide what to do with it here. * TTDP does not call it. */ diff -r 68a692eacf22 -r 67db0d431d5e src/station_func.h --- a/src/station_func.h Mon May 26 20:45:25 2008 +0000 +++ b/src/station_func.h Tue May 27 00:50:55 2008 +0000 @@ -47,5 +47,6 @@ /* Check if a rail station tile is electrifiable. */ bool IsStationTileElectrifiable(TileIndex tile); +void UpdateAirportsNoise(); #endif /* STATION_FUNC_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/station_gui.cpp --- a/src/station_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/station_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -168,39 +168,6 @@ typedef GUIList GUIStationList; /** - * Set the station sort flag for all station-list windows. - * @param sl_flag Sort list flag to set for all station-list windows - */ -static void SetStationListsFlag(SortListFlags sl_flag) -{ - Window *const *wz; - - FOR_ALL_WINDOWS(wz) { - Window *w = *wz; - if (w->window_class == WC_STATION_LIST) { - dynamic_cast(w)->flags |= sl_flag; - w->SetDirty(); - } - } -} - -/** - * Set the 'VL_REBUILD' flag for all station lists - */ -void RebuildStationLists() -{ - SetStationListsFlag(VL_REBUILD); -} - -/** - * Set the 'VL_RESORT' flag for all station lists - */ -void ResortStationLists() -{ - SetStationListsFlag(VL_RESORT); -} - -/** * Rebuild station list if the VL_REBUILD flag is set * * @param sl pointer to plstations_d (station list and flags) @@ -211,16 +178,13 @@ */ static void BuildStationsList(GUIStationList *sl, PlayerID owner, byte facilities, uint32 cargo_filter, bool include_empty) { - uint n = 0; - const Station *st; - if (!(sl->flags & VL_REBUILD)) return; - /* Create array for sorting */ - const Station **station_sort = MallocT(GetMaxStationIndex() + 1); + sl->Clear(); DEBUG(misc, 3, "Building station list for player %d", owner); + const Station *st; FOR_ALL_STATIONS(st) { if (st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy() && HasStationInUse(st->index, owner))) { if (facilities & st->facilities) { //only stations with selected facilities @@ -229,28 +193,23 @@ if (!st->goods[j].cargo.Empty()) { num_waiting_cargo++; //count number of waiting cargo if (HasBit(cargo_filter, j)) { - station_sort[n++] = st; + *sl->Append() = st; break; } } } /* stations without waiting cargo */ if (num_waiting_cargo == 0 && include_empty) { - station_sort[n++] = st; + *sl->Append() = st; } } } } - free((void*)sl->sort_list); - sl->sort_list = MallocT(n); - sl->list_length = n; - - for (uint i = 0; i < n; ++i) sl->sort_list[i] = station_sort[i]; + sl->Compact(); sl->flags &= ~VL_REBUILD; sl->flags |= VL_RESORT; - free((void*)station_sort); } @@ -272,7 +231,7 @@ _internal_sort_order = sl->flags & VL_DESC; _last_station = NULL; // used for "cache" in namesorting - qsort((void*)sl->sort_list, sl->list_length, sizeof(sl->sort_list[0]), _station_sorter[sl->sort_type]); + qsort((void*)sl->Begin(), sl->Length(), sizeof(sl->Begin()), _station_sorter[sl->sort_type]); sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; sl->flags &= ~VL_RESORT; @@ -344,13 +303,14 @@ this->SetWidgetLoweredState(SLW_CARGOALL, _cargo_filter == _cargo_mask && include_empty); this->SetWidgetLoweredState(SLW_NOCARGOWAITING, include_empty); - this->sort_list = NULL; this->flags = VL_REBUILD; this->sort_type = station_sort.criteria; if (station_sort.order) this->flags |= VL_DESC; /* set up resort timer */ this->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; + + this->FindWindowPlacementAndResize(desc); } virtual void OnPaint() @@ -360,7 +320,7 @@ BuildStationsList(this, owner, facilities, _cargo_filter, include_empty); SortStationsList(this); - SetVScrollCount(this, this->list_length); + SetVScrollCount(this, this->Length()); /* draw widgets, with player's name in the caption */ SetDParam(0, owner); @@ -406,11 +366,11 @@ return; } - int max = min(this->vscroll.pos + this->vscroll.cap, this->list_length); + int max = min(this->vscroll.pos + this->vscroll.cap, this->Length()); y = 40; // start of the list-widget for (int i = this->vscroll.pos; i < max; ++i) { // do until max number of stations of owner - const Station *st = this->sort_list[i]; + const Station *st = *this->Get(i); int x; assert(st->xy != 0); @@ -444,9 +404,9 @@ id_v += this->vscroll.pos; - if (id_v >= this->list_length) return; // click out of list bound + if (id_v >= this->Length()) return; // click out of list bound - const Station *st = this->sort_list[id_v]; + const Station *st = *this->Get(id_v); /* do not check HasStationInUse - it is slow and may be invalid */ assert(st->owner == (PlayerID)this->window_number || (st->owner == OWNER_NONE && !st->IsBuoy())); @@ -605,6 +565,11 @@ { this->vscroll.cap += delta.y / 10; } + + virtual void OnInvalidateData(int data) + { + this->flags |= (data == 0 ? VL_REBUILD : VL_RESORT); + } }; Listing PlayerStationsWindow::station_sort = {0, 0}; @@ -643,7 +608,6 @@ WC_STATION_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE, _player_stations_widgets, - NULL }; /** @@ -1015,7 +979,6 @@ WC_STATION_VIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _station_view_widgets, - NULL }; /** diff -r 68a692eacf22 -r 67db0d431d5e src/station_gui.h --- a/src/station_gui.h Mon May 26 20:45:25 2008 +0000 +++ b/src/station_gui.h Tue May 27 00:50:55 2008 +0000 @@ -48,10 +48,6 @@ SVW_RESIZE, ///< Resize button }; -/* sorter stuff */ -void RebuildStationLists(); -void ResortStationLists(); - enum StationCoverageType { SCT_PASSENGERS_ONLY, SCT_NON_PASSENGERS_ONLY, diff -r 68a692eacf22 -r 67db0d431d5e src/station_map.h --- a/src/station_map.h Mon May 26 20:45:25 2008 +0000 +++ b/src/station_map.h Tue May 27 00:50:55 2008 +0000 @@ -134,6 +134,12 @@ return HasBit(_m[t].m6, 2); } +static inline void SetStopBuiltOnTownRoad(TileIndex t, bool on_town_road) +{ + assert(IsDriveThroughStopTile(t)); + SB(_m[t].m6, 2, 1, on_town_road); +} + /** * Gets the direction the road stop entrance points towards. diff -r 68a692eacf22 -r 67db0d431d5e src/station_type.h --- a/src/station_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/station_type.h Tue May 27 00:50:55 2008 +0000 @@ -57,7 +57,7 @@ CA_TRAIN = 4, CA_DOCK = 5, - CA_UNMODIFIED = 4, ///< Used when _patches.modified_catchment is false + CA_UNMODIFIED = 4, ///< Used when _settings.station.modified_catchment is false MAX_CATCHMENT = 10, ///< Airports have a catchment up to this number. }; diff -r 68a692eacf22 -r 67db0d431d5e src/statusbar_gui.cpp --- a/src/statusbar_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/statusbar_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -82,7 +82,7 @@ this->DrawWidgets(); SetDParam(0, _date); - DrawStringCentered(70, 1, (_pause_game || _patches.status_long_date) ? STR_00AF : STR_00AE, TC_FROMSTRING); + DrawStringCentered(70, 1, (_pause_game || _settings.gui.status_long_date) ? STR_00AF : STR_00AE, TC_FROMSTRING); if (p != NULL) { /* Draw player money */ @@ -168,7 +168,6 @@ WC_STATUS_BAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _main_status_widgets, - NULL }; /** diff -r 68a692eacf22 -r 67db0d431d5e src/strings.cpp --- a/src/strings.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/strings.cpp Tue May 27 00:50:55 2008 +0000 @@ -546,7 +546,7 @@ */ uint ConvertSpeedToDisplaySpeed(uint speed) { - return (speed * units[_opt_ptr->units].s_m) >> units[_opt_ptr->units].s_s; + return (speed * units[_settings.gui.units].s_m) >> units[_settings.gui.units].s_s; } /** @@ -556,7 +556,7 @@ */ uint ConvertDisplaySpeedToSpeed(uint speed) { - return ((speed << units[_opt_ptr->units].s_s) + units[_opt_ptr->units].s_m / 2) / units[_opt_ptr->units].s_m; + return ((speed << units[_settings.gui.units].s_s) + units[_settings.gui.units].s_m / 2) / units[_settings.gui.units].s_m; } static char* FormatString(char* buff, const char* str, const int64* argv, uint casei, const char* last) @@ -602,9 +602,9 @@ case SCC_VELOCITY: {// {VELOCITY} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); + assert(_settings.gui.units < lengthof(units)); args[0] = ConvertSpeedToDisplaySpeed(GetInt32(&argv)); - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].velocity), args, modifier >> 24, last); + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].velocity), args, modifier >> 24, last); modifier = 0; break; } @@ -625,18 +625,18 @@ switch (cargo_str) { case STR_TONS: { int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].w_m >> units[_settings.gui.units].w_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_weight), args, modifier >> 24, last); modifier = 0; break; } case STR_LITERS: { int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].v_m >> units[_settings.gui.units].v_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_volume), args, modifier >> 24, last); modifier = 0; break; } @@ -718,9 +718,9 @@ case SCC_VOLUME: { // {VOLUME} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_volume), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].v_m >> units[_settings.gui.units].v_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_volume), args, modifier >> 24, last); modifier = 0; break; } @@ -763,45 +763,45 @@ case SCC_POWER: { // {POWER} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].p_m >> units[_opt_ptr->units].p_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].power), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].p_m >> units[_settings.gui.units].p_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].power), args, modifier >> 24, last); modifier = 0; break; } case SCC_VOLUME_SHORT: { // {VOLUME_S} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].v_m >> units[_opt_ptr->units].v_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_volume), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].v_m >> units[_settings.gui.units].v_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].s_volume), args, modifier >> 24, last); modifier = 0; break; } case SCC_WEIGHT: { // {WEIGHT} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].l_weight), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].w_m >> units[_settings.gui.units].w_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].l_weight), args, modifier >> 24, last); modifier = 0; break; } case SCC_WEIGHT_SHORT: { // {WEIGHT_S} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].w_m >> units[_opt_ptr->units].w_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].s_weight), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].w_m >> units[_settings.gui.units].w_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].s_weight), args, modifier >> 24, last); modifier = 0; break; } case SCC_FORCE: { // {FORCE} int64 args[1]; - assert(_opt_ptr->units < lengthof(units)); - args[0] = GetInt32(&argv) * units[_opt_ptr->units].f_m >> units[_opt_ptr->units].f_s; - buff = FormatString(buff, GetStringPtr(units[_opt_ptr->units].force), args, modifier >> 24, last); + assert(_settings.gui.units < lengthof(units)); + args[0] = GetInt32(&argv) * units[_settings.gui.units].f_m >> units[_settings.gui.units].f_s; + buff = FormatString(buff, GetStringPtr(units[_settings.gui.units].force), args, modifier >> 24, last); modifier = 0; break; } @@ -1137,7 +1137,7 @@ const char* const* base; uint num; - if (_opt_ptr->landscape == LT_TOYLAND) { + if (_settings.game_creation.landscape == LT_TOYLAND) { base = _silly_surname_list; num = lengthof(_silly_surname_list); } else { @@ -1167,7 +1167,7 @@ buff = strecpy(buff, initial, last); } - if (_opt_ptr->landscape == LT_TOYLAND) { + if (_settings.game_creation.landscape == LT_TOYLAND) { base = _silly_surname_list; num = lengthof(_silly_surname_list); } else { diff -r 68a692eacf22 -r 67db0d431d5e src/subsidy_gui.cpp --- a/src/subsidy_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/subsidy_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -19,161 +19,153 @@ #include "table/strings.h" -static void HandleSubsidyClick(int y) -{ - const Subsidy *s; - uint num; - int offs; - TileIndex xy; +struct SubsidyListWindow : Window { + SubsidyListWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + } - if (y < 0) return; + virtual void OnClick(Point pt, int widget) + { + if (widget != 3) return; - num = 0; - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age < 12) { + int y = pt.y - 25; + + if (y < 0) return; + + uint num = 0; + for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age < 12) { + y -= 10; + if (y < 0) this->HandleClick(s); + num++; + } + } + + if (num == 0) { y -= 10; - if (y < 0) goto handle_click; - num++; + if (y < 0) return; + } + + y -= 11; + if (y < 0) return; + + for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age >= 12) { + y -= 10; + if (y < 0) this->HandleClick(s); + } } } - if (num == 0) { - y -= 10; - if (y < 0) return; - } - - y -= 11; - if (y < 0) return; - - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age >= 12) { - y -= 10; - if (y < 0) goto handle_click; - } - } - return; + void HandleClick(const Subsidy *s) + { + TownEffect te = GetCargo(s->cargo_type)->town_effect; + TileIndex xy; -handle_click: - - TownEffect te = GetCargo(s->cargo_type)->town_effect; - - /* determine from coordinate for subsidy and try to scroll to it */ - offs = s->from; - if (s->age >= 12) { - xy = GetStation(offs)->xy; - } else if (te == TE_PASSENGERS || te == TE_MAIL) { - xy = GetTown(offs)->xy; - } else { - xy = GetIndustry(offs)->xy; - } - - if (_ctrl_pressed || !ScrollMainWindowToTile(xy)) { - if (_ctrl_pressed) ShowExtraViewPortWindow(xy); - - /* otherwise determine to coordinate for subsidy and scroll to it */ - offs = s->to; + /* determine from coordinate for subsidy and try to scroll to it */ + uint offs = s->from; if (s->age >= 12) { xy = GetStation(offs)->xy; - } else if (te == TE_PASSENGERS || te == TE_MAIL || te == TE_GOODS || te == TE_FOOD) { + } else if (te == TE_PASSENGERS || te == TE_MAIL) { xy = GetTown(offs)->xy; } else { xy = GetIndustry(offs)->xy; } - if (_ctrl_pressed) { - ShowExtraViewPortWindow(xy); - } else { - ScrollMainWindowToTile(xy); - } - } -} - -static void DrawSubsidiesWindow(const Window *w) -{ - YearMonthDay ymd; - const Subsidy *s; - uint num; - int x; - int y; - - w->DrawWidgets(); - - ConvertDateToYMD(_date, &ymd); + if (_ctrl_pressed || !ScrollMainWindowToTile(xy)) { + if (_ctrl_pressed) ShowExtraViewPortWindow(xy); - int width = w->width - 13; // scroll bar = 11 + pixel each side - y = 15; - x = 1; - - /* Section for drawing the offered subisidies */ - DrawStringTruncated(x, y, STR_2026_SUBSIDIES_ON_OFFER_FOR, TC_FROMSTRING, width); - y += 10; - num = 0; + /* otherwise determine to coordinate for subsidy and scroll to it */ + offs = s->to; + if (s->age >= 12) { + xy = GetStation(offs)->xy; + } else if (te == TE_PASSENGERS || te == TE_MAIL || te == TE_GOODS || te == TE_FOOD) { + xy = GetTown(offs)->xy; + } else { + xy = GetIndustry(offs)->xy; + } - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age < 12) { - int x2; - - /* Displays the two offered towns */ - SetupSubsidyDecodeParam(s, 1); - x2 = DrawStringTruncated(x + 2, y, STR_2027_FROM_TO, TC_FROMSTRING, width); - - /* Displays the deadline before voiding the proposal */ - SetDParam(0, _date - ymd.day + 384 - s->age * 32); - DrawStringTruncated(x2, y, STR_2028_BY, TC_FROMSTRING, width - x2); - y += 10; - num++; + if (_ctrl_pressed) { + ShowExtraViewPortWindow(xy); + } else { + ScrollMainWindowToTile(xy); + } } } - if (num == 0) { - DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2); - y += 10; - } - - /* Section for drawing the already granted subisidies */ - DrawStringTruncated(x, y + 1, STR_202B_SERVICES_ALREADY_SUBSIDISED, TC_FROMSTRING, width); - y += 10; - num = 0; - - for (s = _subsidies; s != endof(_subsidies); s++) { - if (s->cargo_type != CT_INVALID && s->age >= 12) { - int xt; - - SetupSubsidyDecodeParam(s, 1); - - PlayerID player = GetStation(s->to)->owner; - SetDParam(3, player); - - /* Displays the two connected stations */ - xt = DrawStringTruncated(x + 2, y, STR_202C_FROM_TO, TC_FROMSTRING, width - 2); + virtual void OnPaint() + { + YearMonthDay ymd; + const Subsidy *s; - /* Displays the date where the granted subsidy will end */ - if ((xt > 3) && (width - xt) > 9 ) { // do not draw if previous drawing failed or if it will overlap on scrollbar - SetDParam(0, _date - ymd.day + 768 - s->age * 32); - DrawStringTruncated(xt, y, STR_202D_UNTIL, TC_FROMSTRING, width - xt); - } - y += 10; - num++; - } - } - - if (num == 0) DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2); -} + this->DrawWidgets(); -static void SubsidiesListWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: DrawSubsidiesWindow(w); break; + ConvertDateToYMD(_date, &ymd); - case WE_CLICK: - switch (e->we.click.widget) { - case 3: - HandleSubsidyClick(e->we.click.pt.y - 25); - break; + int width = this->width - 13; // scroll bar = 11 + pixel each side + int y = 15; + int x = 1; + + /* Section for drawing the offered subisidies */ + DrawStringTruncated(x, y, STR_2026_SUBSIDIES_ON_OFFER_FOR, TC_FROMSTRING, width); + y += 10; + uint num = 0; + + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age < 12) { + int x2; + + /* Displays the two offered towns */ + SetupSubsidyDecodeParam(s, 1); + x2 = DrawStringTruncated(x + 2, y, STR_2027_FROM_TO, TC_FROMSTRING, width - 2); + + if (width - x2 > 10) { + /* Displays the deadline before voiding the proposal */ + SetDParam(0, _date - ymd.day + 384 - s->age * 32); + DrawStringTruncated(x2, y, STR_2028_BY, TC_FROMSTRING, width - x2); + } + + y += 10; + num++; } - break; + } + + if (num == 0) { + DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2); + y += 10; + } + + /* Section for drawing the already granted subisidies */ + DrawStringTruncated(x, y + 1, STR_202B_SERVICES_ALREADY_SUBSIDISED, TC_FROMSTRING, width); + y += 10; + num = 0; + + for (s = _subsidies; s != endof(_subsidies); s++) { + if (s->cargo_type != CT_INVALID && s->age >= 12) { + int xt; + + SetupSubsidyDecodeParam(s, 1); + + PlayerID player = GetStation(s->to)->owner; + SetDParam(3, player); + + /* Displays the two connected stations */ + xt = DrawStringTruncated(x + 2, y, STR_202C_FROM_TO, TC_FROMSTRING, width - 2); + + /* Displays the date where the granted subsidy will end */ + if ((xt > 3) && (width - xt) > 9 ) { // do not draw if previous drawing failed or if it will overlap on scrollbar + SetDParam(0, _date - ymd.day + 768 - s->age * 32); + DrawStringTruncated(xt, y, STR_202D_UNTIL, TC_FROMSTRING, width - xt); + } + y += 10; + num++; + } + } + + if (num == 0) DrawStringTruncated(x + 2, y, STR_202A_NONE, TC_FROMSTRING, width - 2); } -} +}; static const Widget _subsidies_list_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, @@ -191,11 +183,10 @@ WC_SUBSIDIES_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE, _subsidies_list_widgets, - SubsidiesListWndProc }; void ShowSubsidiesList() { - AllocateWindowDescFront(&_subsidies_list_desc, 0); + AllocateWindowDescFront(&_subsidies_list_desc, 0); } diff -r 68a692eacf22 -r 67db0d431d5e src/terraform_cmd.cpp --- a/src/terraform_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/terraform_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -301,7 +301,10 @@ return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE); } /* Check tiletype-specific things, and add extra-cost */ + const bool curr_gen = _generating_world; + if (_game_mode == GM_EDITOR) _generating_world = true; // used to create green terraformed land CommandCost cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, flags | DC_AUTO, z_min * TILE_HEIGHT, tileh); + _generating_world = curr_gen; if (CmdFailed(cost)) { _terraform_err_tile = tile; return cost; diff -r 68a692eacf22 -r 67db0d431d5e src/terraform_gui.cpp --- a/src/terraform_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/terraform_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -110,12 +110,9 @@ * allows for additional implements that are more local. For example X_Y drag * of convertrail which belongs in rail_gui.cpp and not terraform_gui.cpp **/ -bool GUIPlaceProcDragXY(const WindowEvent *e) +bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile) { - TileIndex start_tile = e->we.place.starttile; - TileIndex end_tile = e->we.place.tile; - - switch (e->we.place.select_proc) { + switch (proc) { case DDSP_DEMOLISH_AREA: DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA)); break; @@ -186,29 +183,45 @@ VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_LEVEL_AREA); } +/** Enum referring to the widgets of the terraform toolbar */ +enum TerraformToolbarWidgets { + TTW_CLOSEBOX = 0, ///< Close window button + TTW_CAPTION, ///< Window caption + TTW_STICKY, ///< Sticky window button + TTW_SEPERATOR, ///< Thin seperator line between level land button and demolish button + TTW_BUTTONS_START, ///< Start of pushable buttons + TTW_LOWER_LAND = TTW_BUTTONS_START, ///< Lower land button + TTW_RAISE_LAND, ///< Raise land button + TTW_LEVEL_LAND, ///< Level land button + TTW_DEMOLISH, ///< Demolish aka dynamite button + TTW_BUY_LAND, ///< Buy land button + TTW_PLANT_TREES, ///< Plant trees button (note: opens seperate window, no place-push-button) + TTW_PLACE_SIGN, ///< Place sign button +}; + static void TerraformClick_Lower(Window *w) { - HandlePlacePushButton(w, 4, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerLand); + HandlePlacePushButton(w, TTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerLand); } static void TerraformClick_Raise(Window *w) { - HandlePlacePushButton(w, 5, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseLand); + HandlePlacePushButton(w, TTW_RAISE_LAND, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseLand); } static void TerraformClick_Level(Window *w) { - HandlePlacePushButton(w, 6, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand); + HandlePlacePushButton(w, TTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand); } static void TerraformClick_Dynamite(Window *w) { - HandlePlacePushButton(w, 7, ANIMCURSOR_DEMOLISH , VHM_RECT, PlaceProc_DemolishArea); + HandlePlacePushButton(w, TTW_DEMOLISH, ANIMCURSOR_DEMOLISH , VHM_RECT, PlaceProc_DemolishArea); } static void TerraformClick_BuyLand(Window *w) { - HandlePlacePushButton(w, 8, SPR_CURSOR_BUY_LAND, VHM_RECT, PlaceProc_BuyLand); + HandlePlacePushButton(w, TTW_BUY_LAND, SPR_CURSOR_BUY_LAND, VHM_RECT, PlaceProc_BuyLand); } static void TerraformClick_Trees(Window *w) @@ -219,7 +232,7 @@ static void TerraformClick_PlaceSign(Window *w) { - HandlePlacePushButton(w, 10, SPR_CURSOR_SIGN, VHM_RECT, PlaceProc_Sign); + HandlePlacePushButton(w, TTW_PLACE_SIGN, SPR_CURSOR_SIGN, VHM_RECT, PlaceProc_Sign); } static OnButtonClick * const _terraform_button_proc[] = { @@ -232,70 +245,81 @@ TerraformClick_PlaceSign, }; -static void TerraformToolbWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: - w->DrawWidgets(); - break; +struct TerraformToolbarWindow : Window { + TerraformToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->FindWindowPlacementAndResize(desc); + } - case WE_CLICK: - if (e->we.click.widget >= 4) _terraform_button_proc[e->we.click.widget - 4](w); - break; + ~TerraformToolbarWindow() + { + } - case WE_KEYPRESS: { - uint i; + virtual void OnPaint() + { + this->DrawWidgets(); + } - for (i = 0; i != lengthof(_terraform_keycodes); i++) { - if (e->we.keypress.keycode == _terraform_keycodes[i]) { - e->we.keypress.cont = false; - _terraform_button_proc[i](w); - break; + virtual void OnClick(Point pt, int widget) + { + if (widget >= TTW_BUTTONS_START) _terraform_button_proc[widget - TTW_BUTTONS_START](this); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + for (uint i = 0; i != lengthof(_terraform_keycodes); i++) { + if (keycode == _terraform_keycodes[i]) { + _terraform_button_proc[i](this); + return ES_HANDLED; } } - break; + return ES_NOT_HANDLED; } - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - return; + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } - case WE_PLACE_DRAG: - VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); - break; + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) + { + VpSelectTilesWithMethod(pt.x, pt.y, select_method); + } - case WE_PLACE_MOUSEUP: - if (e->we.place.pt.x != -1) { - switch (e->we.place.select_proc) { + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + { + if (pt.x != -1) { + switch (select_proc) { + default: NOT_REACHED(); case DDSP_DEMOLISH_AREA: case DDSP_RAISE_AND_LEVEL_AREA: case DDSP_LOWER_AND_LEVEL_AREA: case DDSP_LEVEL_AREA: - GUIPlaceProcDragXY(e); + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; } } - break; + } - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); - break; + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); } -} +}; static const Widget _terraform_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_LANDSCAPING_TOOLBAR, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, STR_NULL, STR_STICKY_BUTTON}, +{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // TTW_CLOSEBOX +{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_LANDSCAPING_TOOLBAR, STR_018C_WINDOW_TITLE_DRAG_THIS}, // TTW_CAPTION +{WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, STR_NULL, STR_STICKY_BUTTON}, // TTW_STICKY -{ WWT_PANEL, RESIZE_NONE, 7, 66, 69, 14, 35, 0x0, STR_NULL}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_TERRAFORM_DOWN, STR_018E_LOWER_A_CORNER_OF_LAND}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_TERRAFORM_UP, STR_018F_RAISE_A_CORNER_OF_LAND}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 44, 65, 14, 35, SPR_IMG_LEVEL_LAND, STR_LEVEL_LAND_TOOLTIP}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_BUY_LAND, STR_0329_PURCHASE_LAND_FOR_FUTURE}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_PLANTTREES, STR_0185_PLANT_TREES_PLACE_SIGNS}, -{ WWT_IMGBTN, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_SIGN, STR_0289_PLACE_SIGN}, +{ WWT_PANEL, RESIZE_NONE, 7, 66, 69, 14, 35, 0x0, STR_NULL}, // TTW_SEPERATOR +{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_TERRAFORM_DOWN, STR_018E_LOWER_A_CORNER_OF_LAND}, // TTW_LOWER_LAND +{ WWT_IMGBTN, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_TERRAFORM_UP, STR_018F_RAISE_A_CORNER_OF_LAND}, // TTW_RAISE_LAND +{ WWT_IMGBTN, RESIZE_NONE, 7, 44, 65, 14, 35, SPR_IMG_LEVEL_LAND, STR_LEVEL_LAND_TOOLTIP}, // TTW_LEVEL_LAND +{ WWT_IMGBTN, RESIZE_NONE, 7, 70, 91, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, // TTW_DEMOLISH +{ WWT_IMGBTN, RESIZE_NONE, 7, 92, 113, 14, 35, SPR_IMG_BUY_LAND, STR_0329_PURCHASE_LAND_FOR_FUTURE}, // TTW_BUY_LAND +{ WWT_IMGBTN, RESIZE_NONE, 7, 114, 135, 14, 35, SPR_IMG_PLANTTREES, STR_0185_PLANT_TREES_PLACE_SIGNS}, // TTW_PLANT_TREES +{ WWT_IMGBTN, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_SIGN, STR_0289_PLACE_SIGN}, // TTW_PLACE_SIGN { WIDGETS_END}, }; @@ -305,20 +329,19 @@ WC_SCEN_LAND_GEN, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _terraform_widgets, - TerraformToolbWndProc }; void ShowTerraformToolbar(Window *link) { if (!IsValidPlayer(_current_player)) return; - Window *w = AllocateWindowDescFront(&_terraform_desc, 0); + Window *w = AllocateWindowDescFront(&_terraform_desc, 0); if (w != NULL && link != NULL) { /* Align the terraform toolbar under the main toolbar and put the linked * toolbar to left of it */ w->top = 22; + w->SetDirty(); link->left = w->left - link->width; - link->SetDirty(); } } @@ -339,8 +362,6 @@ int sizex, sizey; uint h; - _generating_world = true; // used to create green terraformed land - if (_terraform_size == 1) { StringID msg = mode ? STR_0808_CAN_T_RAISE_LAND_HERE : STR_0809_CAN_T_LOWER_LAND_HERE; @@ -376,8 +397,6 @@ } } END_TILE_LOOP(tile2, sizex, sizey, tile) } - - _generating_world = false; } static void PlaceProc_RaiseBigLand(TileIndex tile) @@ -435,23 +454,23 @@ } static const Widget _scen_edit_land_gen_widgets[] = { -{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, RESIZE_NONE, 7, 11, 191, 0, 13, STR_0223_LAND_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_STICKYBOX, RESIZE_NONE, 7, 192, 203, 0, 13, STR_NULL, STR_STICKY_BUTTON}, -{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 102, 0x0, STR_NULL}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 2, 23, 16, 37, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 24, 45, 16, 37, SPR_IMG_TERRAFORM_DOWN, STR_018E_LOWER_A_CORNER_OF_LAND}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 46, 67, 16, 37, SPR_IMG_TERRAFORM_UP, STR_018F_RAISE_A_CORNER_OF_LAND}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 68, 89, 16, 37, SPR_IMG_LEVEL_LAND, STR_LEVEL_LAND_TOOLTIP}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 90, 111, 16, 37, SPR_IMG_BUILD_CANAL, STR_CREATE_LAKE}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 112, 133, 16, 37, SPR_IMG_BUILD_RIVER, STR_CREATE_RIVER}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 134, 156, 16, 37, SPR_IMG_ROCKS, STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 157, 179, 16, 37, SPR_IMG_LIGHTHOUSE_DESERT, STR_NULL}, // XXX - dynamic -{ WWT_IMGBTN, RESIZE_NONE, 14, 180, 201, 16, 37, SPR_IMG_TRANSMITTER, STR_028E_PLACE_TRANSMITTER}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 150, 161, 45, 56, SPR_ARROW_UP, STR_0228_INCREASE_SIZE_OF_LAND_AREA}, -{ WWT_IMGBTN, RESIZE_NONE, 14, 150, 161, 58, 69, SPR_ARROW_DOWN, STR_0229_DECREASE_SIZE_OF_LAND_AREA}, -{ WWT_TEXTBTN, RESIZE_NONE, 14, 24, 179, 76, 87, STR_SE_NEW_WORLD, STR_022A_GENERATE_RANDOM_LAND}, -{ WWT_TEXTBTN, RESIZE_NONE, 14, 24, 179, 89, 100, STR_022B_RESET_LANDSCAPE, STR_RESET_LANDSCAPE_TOOLTIP}, +{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // ETTW_CLOSEBOX +{ WWT_CAPTION, RESIZE_NONE, 7, 11, 191, 0, 13, STR_0223_LAND_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, // ETTW_CAPTION +{ WWT_STICKYBOX, RESIZE_NONE, 7, 192, 203, 0, 13, STR_NULL, STR_STICKY_BUTTON}, // ETTW_STICKY +{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 102, 0x0, STR_NULL}, // ETTW_BACKGROUND +{ WWT_IMGBTN, RESIZE_NONE, 14, 2, 23, 16, 37, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC}, // ETTW_DEMOLISH +{ WWT_IMGBTN, RESIZE_NONE, 14, 24, 45, 16, 37, SPR_IMG_TERRAFORM_DOWN, STR_018E_LOWER_A_CORNER_OF_LAND}, // ETTW_LOWER_LAND +{ WWT_IMGBTN, RESIZE_NONE, 14, 46, 67, 16, 37, SPR_IMG_TERRAFORM_UP, STR_018F_RAISE_A_CORNER_OF_LAND}, // ETTW_RAISE_LAND +{ WWT_IMGBTN, RESIZE_NONE, 14, 68, 89, 16, 37, SPR_IMG_LEVEL_LAND, STR_LEVEL_LAND_TOOLTIP}, // ETTW_LEVEL_LAND +{ WWT_IMGBTN, RESIZE_NONE, 14, 90, 111, 16, 37, SPR_IMG_BUILD_CANAL, STR_CREATE_LAKE}, // ETTW_BUILD_CANAL +{ WWT_IMGBTN, RESIZE_NONE, 14, 112, 133, 16, 37, SPR_IMG_BUILD_RIVER, STR_CREATE_RIVER}, // ETTW_BUILD_RIVER +{ WWT_IMGBTN, RESIZE_NONE, 14, 134, 156, 16, 37, SPR_IMG_ROCKS, STR_028C_PLACE_ROCKY_AREAS_ON_LANDSCAPE}, // ETTW_PLACE_ROCKS +{ WWT_IMGBTN, RESIZE_NONE, 14, 157, 179, 16, 37, SPR_IMG_LIGHTHOUSE_DESERT, STR_NULL}, // ETTW_PLACE_DESERT_LIGHTHOUSE XXX - dynamic +{ WWT_IMGBTN, RESIZE_NONE, 14, 180, 201, 16, 37, SPR_IMG_TRANSMITTER, STR_028E_PLACE_TRANSMITTER}, // ETTW_PLACE_TRANSMITTER +{ WWT_IMGBTN, RESIZE_NONE, 14, 150, 161, 45, 56, SPR_ARROW_UP, STR_0228_INCREASE_SIZE_OF_LAND_AREA}, // ETTW_INCREASE_SIZE +{ WWT_IMGBTN, RESIZE_NONE, 14, 150, 161, 58, 69, SPR_ARROW_DOWN, STR_0229_DECREASE_SIZE_OF_LAND_AREA}, // ETTW_DECREASE_SIZE +{ WWT_TEXTBTN, RESIZE_NONE, 14, 24, 179, 76, 87, STR_SE_NEW_WORLD, STR_022A_GENERATE_RANDOM_LAND}, // ETTW_NEW_SCENARIO +{ WWT_TEXTBTN, RESIZE_NONE, 14, 24, 179, 89, 100, STR_022B_RESET_LANDSCAPE, STR_RESET_LANDSCAPE_TOOLTIP}, // ETTW_RESET_LANDSCAPE { WIDGETS_END}, }; @@ -466,53 +485,77 @@ {-28, 0}, {-24, -2}, {-20, -4}, {-16, -6}, {-12, -8}, { -8,-10}, { -4,-12}, { 0,-14}, { 4,-12}, { 8,-10}, { 12, -8}, { 16, -6}, { 20, -4}, { 24, -2}, { 28, 0}, }; +/** Enum referring to the widgets of the editor terraform toolbar */ +enum EditorTerraformToolbarWidgets { + ETTW_START = 0, ///< Used for iterations + ETTW_CLOSEBOX = ETTW_START, ///< Close window button + ETTW_CAPTION, ///< Window caption + ETTW_STICKY, ///< Sticky window button + ETTW_BACKGROUND, ///< Background of the lower part of the window + ETTW_BUTTONS_START, ///< Start of pushable buttons + ETTW_DEMOLISH = ETTW_BUTTONS_START, ///< Demolish aka dynamite button + ETTW_LOWER_LAND, ///< Lower land button + ETTW_RAISE_LAND, ///< Raise land button + ETTW_LEVEL_LAND, ///< Level land button + ETTW_BUILD_CANAL, ///< Build canal button + ETTW_BUILD_RIVER, ///< Build river button + ETTW_PLACE_ROCKS, ///< Place rocks button + ETTW_PLACE_DESERT_LIGHTHOUSE, ///< Place desert button (in tropical climate) / place lighthouse button (else) + ETTW_PLACE_TRANSMITTER, ///< Place transmitter button + ETTW_BUTTONS_END, ///< End of pushable buttons + ETTW_INCREASE_SIZE = ETTW_BUTTONS_END, ///< Upwards arrow button to increase terraforming size + ETTW_DECREASE_SIZE, ///< Downwards arrow button to decrease terraforming size + ETTW_NEW_SCENARIO, ///< Button for generating a new scenario + ETTW_RESET_LANDSCAPE, ///< Button for removing all player-owned property +}; + /** * @todo Merge with terraform_gui.cpp (move there) after I have cooled down at its braindeadness * and changed OnButtonClick to include the widget as well in the function declaration. Post 0.4.0 - Darkvater */ static void EditorTerraformClick_Dynamite(Window *w) { - HandlePlacePushButton(w, 4, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea); + HandlePlacePushButton(w, ETTW_DEMOLISH, ANIMCURSOR_DEMOLISH, VHM_RECT, PlaceProc_DemolishArea); } static void EditorTerraformClick_LowerBigLand(Window *w) { - HandlePlacePushButton(w, 5, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerBigLand); + HandlePlacePushButton(w, ETTW_LOWER_LAND, ANIMCURSOR_LOWERLAND, VHM_POINT, PlaceProc_LowerBigLand); } static void EditorTerraformClick_RaiseBigLand(Window *w) { - HandlePlacePushButton(w, 6, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseBigLand); + HandlePlacePushButton(w, ETTW_RAISE_LAND, ANIMCURSOR_RAISELAND, VHM_POINT, PlaceProc_RaiseBigLand); } static void EditorTerraformClick_LevelLand(Window *w) { - HandlePlacePushButton(w, 7, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand); + HandlePlacePushButton(w, ETTW_LEVEL_LAND, SPR_CURSOR_LEVEL_LAND, VHM_POINT, PlaceProc_LevelLand); } static void EditorTerraformClick_WaterArea(Window *w) { - HandlePlacePushButton(w, 8, SPR_CURSOR_CANAL, VHM_RECT, PlaceProc_WaterArea); + HandlePlacePushButton(w, ETTW_BUILD_CANAL, SPR_CURSOR_CANAL, VHM_RECT, PlaceProc_WaterArea); } static void EditorTerraformClick_RiverArea(Window *w) { - HandlePlacePushButton(w, 9, SPR_CURSOR_RIVER, VHM_RECT, PlaceProc_RiverArea); + HandlePlacePushButton(w, ETTW_BUILD_RIVER, SPR_CURSOR_RIVER, VHM_RECT, PlaceProc_RiverArea); } static void EditorTerraformClick_RockyArea(Window *w) { - HandlePlacePushButton(w, 10, SPR_CURSOR_ROCKY_AREA, VHM_RECT, PlaceProc_RockyArea); + HandlePlacePushButton(w, ETTW_PLACE_ROCKS, SPR_CURSOR_ROCKY_AREA, VHM_RECT, PlaceProc_RockyArea); } static void EditorTerraformClick_DesertLightHouse(Window *w) { - HandlePlacePushButton(w, 11, SPR_CURSOR_LIGHTHOUSE, VHM_RECT, (_opt.landscape == LT_TROPIC) ? PlaceProc_DesertArea : PlaceProc_LightHouse); + HandlePlacePushButton(w, ETTW_PLACE_DESERT_LIGHTHOUSE, SPR_CURSOR_LIGHTHOUSE, VHM_RECT, (_settings.game_creation.landscape == LT_TROPIC) ? PlaceProc_DesertArea : PlaceProc_LightHouse); } static void EditorTerraformClick_Transmitter(Window *w) { - HandlePlacePushButton(w, 12, SPR_CURSOR_TRANSMITTER, VHM_RECT, PlaceProc_Transmitter); + HandlePlacePushButton(w, ETTW_PLACE_TRANSMITTER, SPR_CURSOR_TRANSMITTER, VHM_RECT, PlaceProc_Transmitter); } static const uint16 _editor_terraform_keycodes[] = { @@ -569,62 +612,64 @@ } } -static void ScenEditLandGenWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_CREATE: - /* XXX - lighthouse button is widget 11!! Don't forget when changing */ - w->widget[11].tooltips = (_opt.landscape == LT_TROPIC) ? STR_028F_DEFINE_DESERT_AREA : STR_028D_PLACE_LIGHTHOUSE; - break; - - case WE_PAINT: { - w->DrawWidgets(); - - int n = _terraform_size * _terraform_size; - const int8 *coords = &_multi_terraform_coords[0][0]; - - assert(n != 0); - do { - DrawSprite(SPR_WHITE_POINT, PAL_NONE, 88 + coords[0], 55 + coords[1]); - coords += 2; - } while (--n); +struct ScenarioEditorLandscapeGenerationWindow : Window { + ScenarioEditorLandscapeGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->widget[ETTW_PLACE_DESERT_LIGHTHOUSE].tooltips = (_settings.game_creation.landscape == LT_TROPIC) ? STR_028F_DEFINE_DESERT_AREA : STR_028D_PLACE_LIGHTHOUSE; + this->FindWindowPlacementAndResize(desc); + } - if (w->IsWidgetLowered(5) || w->IsWidgetLowered(6)) // change area-size if raise/lower corner is selected - SetTileSelectSize(_terraform_size, _terraform_size); - - } break; + virtual void OnPaint() { + this->DrawWidgets(); - case WE_KEYPRESS: - for (uint i = 0; i != lengthof(_editor_terraform_keycodes); i++) { - if (e->we.keypress.keycode == _editor_terraform_keycodes[i]) { - e->we.keypress.cont = false; - _editor_terraform_button_proc[i](w); - break; - } + int n = _terraform_size * _terraform_size; + const int8 *coords = &_multi_terraform_coords[0][0]; + + assert(n != 0); + do { + DrawSprite(SPR_WHITE_POINT, PAL_NONE, 88 + coords[0], 55 + coords[1]); + coords += 2; + } while (--n); + + if (this->IsWidgetLowered(ETTW_LOWER_LAND) || this->IsWidgetLowered(ETTW_RAISE_LAND)) { // change area-size if raise/lower corner is selected + SetTileSelectSize(_terraform_size, _terraform_size); + } + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + for (uint i = 0; i != lengthof(_editor_terraform_keycodes); i++) { + if (keycode == _editor_terraform_keycodes[i]) { + _editor_terraform_button_proc[i](this); + return ES_HANDLED; } - break; + } + return ES_NOT_HANDLED; + } - case WE_CLICK: - switch (e->we.click.widget) { - case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: - _editor_terraform_button_proc[e->we.click.widget - 4](w); - break; - case 13: case 14: { // Increase/Decrease terraform size - int size = (e->we.click.widget == 13) ? 1 : -1; - w->HandleButtonClick(e->we.click.widget); + virtual void OnClick(Point pt, int widget) + { + if (IsInsideMM(widget, ETTW_BUTTONS_START, ETTW_BUTTONS_END)) { + _editor_terraform_button_proc[widget - ETTW_BUTTONS_START](this); + } else { + switch (widget) { + case ETTW_INCREASE_SIZE: + case ETTW_DECREASE_SIZE: { // Increase/Decrease terraform size + int size = (widget == ETTW_INCREASE_SIZE) ? 1 : -1; + this->HandleButtonClick(widget); size += _terraform_size; if (!IsInsideMM(size, 1, 8 + 1)) return; _terraform_size = size; SndPlayFx(SND_15_BEEP); - w->SetDirty(); + this->SetDirty(); } break; - case 15: // gen random land - w->HandleButtonClick(15); + case ETTW_NEW_SCENARIO: // gen random land + this->HandleButtonClick(widget); ShowCreateScenario(); break; - case 16: // Reset landscape + case ETTW_RESET_LANDSCAPE: // Reset landscape ShowQuery( STR_022C_RESET_LANDSCAPE, STR_RESET_LANDSCAPE_CONFIRMATION_TEXT, @@ -632,59 +677,64 @@ ResetLandscapeConfirmationCallback); break; } - break; - - case WE_TIMEOUT: - for (uint i = 0; i < w->widget_count; i++) { - if (w->IsWidgetLowered(i)) { - w->RaiseWidget(i); - w->InvalidateWidget(i); - } - if (i == 3) i = 12; - } - break; - - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - break; - - case WE_PLACE_DRAG: - VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.select_method); - break; + } + } - case WE_PLACE_MOUSEUP: - if (e->we.place.pt.x != -1) { - switch (e->we.place.select_proc) { - case DDSP_CREATE_ROCKS: - case DDSP_CREATE_DESERT: - case DDSP_CREATE_WATER: - case DDSP_CREATE_RIVER: - case DDSP_RAISE_AND_LEVEL_AREA: - case DDSP_LOWER_AND_LEVEL_AREA: - case DDSP_LEVEL_AREA: - case DDSP_DEMOLISH_AREA: - GUIPlaceProcDragXY(e); - break; - } + virtual void OnTimeout() + { + for (uint i = ETTW_START; i < this->widget_count; i++) { + if (i == ETTW_BUTTONS_START) i = ETTW_BUTTONS_END; // skip the buttons + if (this->IsWidgetLowered(i)) { + this->RaiseWidget(i); + this->InvalidateWidget(i); } - break; + } + } - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); - w->SetDirty(); - break; + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); } -} + + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) + { + VpSelectTilesWithMethod(pt.x, pt.y, select_method); + } + + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + { + if (pt.x != -1) { + switch (select_proc) { + default: NOT_REACHED(); + case DDSP_CREATE_ROCKS: + case DDSP_CREATE_DESERT: + case DDSP_CREATE_WATER: + case DDSP_CREATE_RIVER: + case DDSP_RAISE_AND_LEVEL_AREA: + case DDSP_LOWER_AND_LEVEL_AREA: + case DDSP_LEVEL_AREA: + case DDSP_DEMOLISH_AREA: + GUIPlaceProcDragXY(select_proc, start_tile, end_tile); + break; + } + } + } + + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + this->SetDirty(); + } +}; static const WindowDesc _scen_edit_land_gen_desc = { WDP_AUTO, WDP_AUTO, 204, 103, 204, 103, WC_SCEN_LAND_GEN, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _scen_edit_land_gen_widgets, - ScenEditLandGenWndProc, }; void ShowEditorTerraformToolbar() { - AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0); + AllocateWindowDescFront(&_scen_edit_land_gen_desc, 0); } diff -r 68a692eacf22 -r 67db0d431d5e src/textbuf_gui.h --- a/src/textbuf_gui.h Mon May 26 20:45:25 2008 +0000 +++ b/src/textbuf_gui.h Tue May 27 00:50:55 2008 +0000 @@ -28,8 +28,10 @@ void InitializeTextBuffer(Textbuf *tb, const char *buf, uint16 maxlength, uint16 maxwidth); void UpdateTextBufferSize(Textbuf *tb); +typedef void QueryCallbackProc(Window*, bool); + void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, Window *parent, CharSetFilter afilter); -void ShowQuery(StringID caption, StringID message, Window *w, void (*callback)(Window*, bool)); +void ShowQuery(StringID caption, StringID message, Window *w, QueryCallbackProc *callback); /** The number of 'characters' on the on-screen keyboard. */ static const uint OSK_KEYBOARD_ENTRIES = 50; diff -r 68a692eacf22 -r 67db0d431d5e src/texteff.cpp --- a/src/texteff.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/texteff.cpp Tue May 27 00:50:55 2008 +0000 @@ -6,7 +6,7 @@ #include "openttd.h" #include "landscape.h" #include "gfx_func.h" -#include "console.h" +#include "console_func.h" #include "variables.h" #include "blitter/factory.hpp" #include "texteff.hpp" @@ -392,7 +392,7 @@ dpi->top <= te->bottom && dpi->left + dpi->width > te->x && dpi->top + dpi->height > te->y) { - if (te->mode == TE_RISING || (_patches.loading_indicators && !IsTransparencySet(TO_LOADING))) { + if (te->mode == TE_RISING || (_settings.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) { AddStringToDraw(te->x, te->y, te->string_id, te->params_1, te->params_2); } } @@ -407,7 +407,7 @@ dpi->top <= te->bottom * 2 - te->y && dpi->left + dpi->width > te->x && dpi->top + dpi->height > te->y) { - if (te->mode == TE_RISING || (_patches.loading_indicators && !IsTransparencySet(TO_LOADING))) { + if (te->mode == TE_RISING || (_settings.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) { AddStringToDraw(te->x, te->y, (StringID)(te->string_id - 1), te->params_1, te->params_2); } } diff -r 68a692eacf22 -r 67db0d431d5e src/tgp.cpp --- a/src/tgp.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/tgp.cpp Tue May 27 00:50:55 2008 +0000 @@ -10,7 +10,6 @@ #include "variables.h" #include "void_map.h" #include "tgp.h" -#include "console.h" #include "genworld.h" #include "core/alloc_func.hpp" #include "core/random_func.hpp" @@ -212,10 +211,10 @@ {1500, 1000, 1200, 1000, 500, 32, 20, 0, 0, 0, 0, 0}, }; -/** Desired water percentage (100% == 1024) - indexed by _opt.diff.quantity_sea_lakes */ +/** Desired water percentage (100% == 1024) - indexed by _settings.difficulty.quantity_sea_lakes */ static const amplitude_t _water_percent[4] = {20, 80, 250, 400}; -/** Desired maximum height - indexed by _opt.diff.terrain_type */ +/** Desired maximum height - indexed by _settings.difficulty.terrain_type */ static const int8 _max_height[4] = { 6, ///< Very flat 9, ///< Flat @@ -343,7 +342,7 @@ do { log_frequency = iteration_round - log_frequency_min; if (log_frequency >= 0) { - amplitude = _amplitudes_by_smoothness_and_frequency[_patches.tgen_smoothness][log_frequency]; + amplitude = _amplitudes_by_smoothness_and_frequency[_settings.game_creation.tgen_smoothness][log_frequency]; } else { amplitude = 0; } @@ -403,7 +402,7 @@ /* Transform height into 0..1 space */ fheight = (double)(*h - h_min) / (double)(h_max - h_min); /* Apply sine transform depending on landscape type */ - switch(_opt.landscape) { + switch(_settings.game_creation.landscape) { case LT_TOYLAND: case LT_TEMPERATE: /* Move and scale 0..1 into -1..+1 */ @@ -532,7 +531,7 @@ */ static void HeightMapCoastLines() { - int smallest_size = min(_patches.map_x, _patches.map_y); + int smallest_size = min(_settings.game_creation.map_x, _settings.game_creation.map_y); const int margin = 4; uint y, x; double max_x; @@ -662,9 +661,9 @@ * - height histogram redistribution by sine wave transform */ static void HeightMapNormalize() { - const amplitude_t water_percent = _water_percent[_opt.diff.quantity_sea_lakes]; - const height_t h_max_new = I2H(_max_height[_opt.diff.terrain_type]); - const height_t roughness = 7 + 3 * _patches.tgen_smoothness; + const amplitude_t water_percent = _water_percent[_settings.difficulty.quantity_sea_lakes]; + const height_t h_max_new = I2H(_max_height[_settings.difficulty.terrain_type]); + const height_t roughness = 7 + 3 * _settings.game_creation.tgen_smoothness; HeightMapAdjustWaterLevel(water_percent, h_max_new); @@ -693,7 +692,7 @@ */ static double int_noise(const long x, const long y, const int prime) { - long n = x + y * prime + _patches.generation_seed; + long n = x + y * prime + _settings.game_creation.generation_seed; n = (n << 13) ^ n; diff -r 68a692eacf22 -r 67db0d431d5e src/tile_cmd.h --- a/src/tile_cmd.h Mon May 26 20:45:25 2008 +0000 +++ b/src/tile_cmd.h Tue May 27 00:50:55 2008 +0000 @@ -49,7 +49,8 @@ struct TileDesc { StringID str; - Owner owner; + Owner owner[4]; + StringID owner_type[4]; Date build_date; uint64 dparam[2]; }; diff -r 68a692eacf22 -r 67db0d431d5e src/tilehighlight_func.h --- a/src/tilehighlight_func.h Mon May 26 20:45:25 2008 +0000 +++ b/src/tilehighlight_func.h Tue May 27 00:50:55 2008 +0000 @@ -12,7 +12,7 @@ typedef void PlaceProc(TileIndex tile); void PlaceProc_DemolishArea(TileIndex tile); -bool GUIPlaceProcDragXY(const WindowEvent *e); +bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_tile, TileIndex end_tile); bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, ViewportHighlightMode mode, PlaceProc *placeproc); void SetObjectToPlaceWnd(CursorID icon, SpriteID pal, ViewportHighlightMode mode, Window *w); diff -r 68a692eacf22 -r 67db0d431d5e src/timetable_cmd.cpp --- a/src/timetable_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/timetable_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -54,7 +54,7 @@ */ CommandCost CmdChangeTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - if (!_patches.timetabling) return CMD_ERROR; + if (!_settings.order.timetabling) return CMD_ERROR; VehicleID veh = GB(p1, 0, 16); if (!IsValidVehicleID(veh)) return CMD_ERROR; @@ -90,7 +90,7 @@ */ CommandCost CmdSetVehicleOnTime(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - if (!_patches.timetabling) return CMD_ERROR; + if (!_settings.order.timetabling) return CMD_ERROR; VehicleID veh = GB(p1, 0, 16); if (!IsValidVehicleID(veh)) return CMD_ERROR; @@ -116,7 +116,7 @@ */ CommandCost CmdAutofillTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - if (!_patches.timetabling) return CMD_ERROR; + if (!_settings.order.timetabling) return CMD_ERROR; VehicleID veh = GB(p1, 0, 16); if (!IsValidVehicleID(veh)) return CMD_ERROR; @@ -157,7 +157,7 @@ v->current_order_time = 0; - if (!_patches.timetabling) return; + if (!_settings.order.timetabling) return; /* Make sure the timetable only starts when the vehicle reaches the first * order, not when travelling from the depot to the first station. */ diff -r 68a692eacf22 -r 67db0d431d5e src/timetable_gui.cpp --- a/src/timetable_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/timetable_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -38,7 +38,7 @@ void SetTimetableParams(int param1, int param2, uint32 time) { - if (_patches.timetable_in_ticks) { + if (_settings.gui.timetable_in_ticks) { SetDParam(param1, STR_TIMETABLE_TICKS); SetDParam(param2, time); } else { @@ -56,6 +56,8 @@ this->vscroll.cap = 8; this->resize.step_height = 10; this->sel_index = -1; + + this->FindWindowPlacementAndResize(desc); } int GetOrderFromTimetableWndPt(int y, const Vehicle *v) @@ -170,7 +172,7 @@ } y += 10; - if (v->lateness_counter == 0 || (!_patches.timetable_in_ticks && v->lateness_counter / DAY_TICKS == 0)) { + if (v->lateness_counter == 0 || (!_settings.gui.timetable_in_ticks && v->lateness_counter / DAY_TICKS == 0)) { DrawString(2, y, STR_TIMETABLE_STATUS_ON_TIME, TC_BLACK); } else { SetTimetableParams(0, 1, abs(v->lateness_counter)); @@ -220,7 +222,7 @@ if (order != NULL) { uint time = (selected % 2 == 1) ? order->travel_time : order->wait_time; - if (!_patches.timetable_in_ticks) time /= DAY_TICKS; + if (!_settings.gui.timetable_in_ticks) time /= DAY_TICKS; if (time != 0) { SetDParam(0, time); @@ -257,7 +259,7 @@ uint32 p1 = PackTimetableArgs(v, this->sel_index); uint64 time = StrEmpty(str) ? 0 : strtoul(str, NULL, 10); - if (!_patches.timetable_in_ticks) time *= DAY_TICKS; + if (!_settings.gui.timetable_in_ticks) time *= DAY_TICKS; uint32 p2 = minu(time, MAX_UVALUE(uint16)); @@ -298,7 +300,6 @@ WC_VEHICLE_TIMETABLE, WC_VEHICLE_VIEW, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _timetable_widgets, - NULL }; void ShowTimetableWindow(const Vehicle *v) diff -r 68a692eacf22 -r 67db0d431d5e src/toolbar_gui.cpp --- a/src/toolbar_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/toolbar_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -35,7 +35,7 @@ #include "signs_func.h" #include "fios.h" #include "functions.h" -#include "console.h" +#include "console_gui.h" #include "news_gui.h" #include "tilehighlight_func.h" @@ -542,8 +542,8 @@ w->HandleButtonClick(6); w->SetDirty(); - _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year - 1, MIN_YEAR, MAX_YEAR); - SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); + _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year - 1, MIN_YEAR, MAX_YEAR); + SetDate(ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); } _left_button_clicked = false; } @@ -555,8 +555,8 @@ w->HandleButtonClick(7); w->SetDirty(); - _patches_newgame.starting_year = Clamp(_patches_newgame.starting_year + 1, MIN_YEAR, MAX_YEAR); - SetDate(ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); + _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + 1, MIN_YEAR, MAX_YEAR); + SetDate(ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); } _left_button_clicked = false; } @@ -666,137 +666,155 @@ ToolbarHelpClick, }; -static void MainToolbarWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: - /* Draw brown-red toolbar bg. */ - GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB2); - GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT)); - - /* If spectator, disable all construction buttons - * ie : Build road, rail, ships, airports and landscaping - * Since enabled state is the default, just disable when needed */ - w->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END); - /* disable company list drop downs, if there are no companies */ - w->SetWidgetsDisabledState(ActivePlayerCount() == 0, 7, 8, 13, 14, 15, 16, WIDGET_LIST_END); - - w->SetWidgetDisabledState(19, !CanBuildVehicleInfrastructure(VEH_TRAIN)); - w->SetWidgetDisabledState(22, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT)); - - w->DrawWidgets(); - break; - - case WE_CLICK: - if (_game_mode != GM_MENU && !w->IsWidgetDisabled(e->we.click.widget)) _toolbar_button_procs[e->we.click.widget](w); - break; +struct MainToolbarWindow : Window { + MainToolbarWindow(const WindowDesc *desc) : Window(desc) + { + this->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button + this->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button - case WE_KEYPRESS: - switch (e->we.keypress.keycode) { - case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break; - case WKC_F2: ShowGameOptions(); break; - case WKC_F3: MenuClickSaveLoad(0); break; - case WKC_F4: ShowSmallMap(); break; - case WKC_F5: ShowTownDirectory(); break; - case WKC_F6: ShowSubsidiesList(); break; - case WKC_F7: ShowPlayerStations(_local_player); break; - case WKC_F8: ShowPlayerFinances(_local_player); break; - case WKC_F9: ShowPlayerCompany(_local_player); break; - case WKC_F10: ShowOperatingProfitGraph(); break; - case WKC_F11: ShowCompanyLeagueTable(); break; - case WKC_F12: ShowBuildIndustryWindow(); break; - case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break; - case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break; - case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break; - case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break; - case WKC_NUM_PLUS: // Fall through - case WKC_EQUALS: // Fall through - case WKC_SHIFT | WKC_EQUALS: // Fall through - case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break; - case WKC_NUM_MINUS: // Fall through - case WKC_MINUS: // Fall through - case WKC_SHIFT | WKC_MINUS: // Fall through - case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break; - case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break; - case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break; - case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break; - case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break; - case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break; - case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break; - case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break; - case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break; - case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break; - case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail - case 'L': ShowTerraformToolbar(); break; - case 'M': ShowSmallMap(); break; - case 'V': ShowExtraViewPortWindow(); break; - default: return; - } - e->we.keypress.cont = false; - break; + CLRBITS(this->flags4, WF_WHITE_BORDER_MASK); - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - break; + this->FindWindowPlacementAndResize(desc); + PositionMainToolbar(this); + DoZoomInOutWindow(ZOOM_NONE, this); + } - case WE_ABORT_PLACE_OBJ: - w->RaiseWidget(25); - w->SetDirty(); - break; + virtual void OnPaint() + { + /* Draw brown-red toolbar bg. */ + GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB2); + GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT)); - case WE_TICK: - if (w->IsWidgetLowered(0) != !!_pause_game) { - w->ToggleWidgetLoweredState(0); - w->InvalidateWidget(0); + /* If spectator, disable all construction buttons + * ie : Build road, rail, ships, airports and landscaping + * Since enabled state is the default, just disable when needed */ + this->SetWidgetsDisabledState(_current_player == PLAYER_SPECTATOR, 19, 20, 21, 22, 23, WIDGET_LIST_END); + /* disable company list drop downs, if there are no companies */ + this->SetWidgetsDisabledState(ActivePlayerCount() == 0, 7, 8, 13, 14, 15, 16, WIDGET_LIST_END); + + this->SetWidgetDisabledState(19, !CanBuildVehicleInfrastructure(VEH_TRAIN)); + this->SetWidgetDisabledState(22, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT)); + + this->DrawWidgets(); + } + + virtual void OnClick(Point pt, int widget) + { + if (_game_mode != GM_MENU && !this->IsWidgetDisabled(widget)) _toolbar_button_procs[widget](this); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + switch (keycode) { + case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(this); break; + case WKC_F2: ShowGameOptions(); break; + case WKC_F3: MenuClickSaveLoad(0); break; + case WKC_F4: ShowSmallMap(); break; + case WKC_F5: ShowTownDirectory(); break; + case WKC_F6: ShowSubsidiesList(); break; + case WKC_F7: ShowPlayerStations(_local_player); break; + case WKC_F8: ShowPlayerFinances(_local_player); break; + case WKC_F9: ShowPlayerCompany(_local_player); break; + case WKC_F10: ShowOperatingProfitGraph(); break; + case WKC_F11: ShowCompanyLeagueTable(); break; + case WKC_F12: ShowBuildIndustryWindow(); break; + case WKC_SHIFT | WKC_F1: ShowVehicleListWindow(_local_player, VEH_TRAIN); break; + case WKC_SHIFT | WKC_F2: ShowVehicleListWindow(_local_player, VEH_ROAD); break; + case WKC_SHIFT | WKC_F3: ShowVehicleListWindow(_local_player, VEH_SHIP); break; + case WKC_SHIFT | WKC_F4: ShowVehicleListWindow(_local_player, VEH_AIRCRAFT); break; + case WKC_NUM_PLUS: // Fall through + case WKC_EQUALS: // Fall through + case WKC_SHIFT | WKC_EQUALS: // Fall through + case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(this); break; + case WKC_NUM_MINUS: // Fall through + case WKC_MINUS: // Fall through + case WKC_SHIFT | WKC_MINUS: // Fall through + case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(this); break; + case WKC_SHIFT | WKC_F7: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, -1); break; + case WKC_SHIFT | WKC_F8: ShowBuildRoadToolbar(_last_built_roadtype); break; + case WKC_SHIFT | WKC_F9: ShowBuildDocksToolbar(); break; + case WKC_SHIFT | WKC_F10: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break; + case WKC_SHIFT | WKC_F11: ShowBuildTreesToolbar(); break; + case WKC_SHIFT | WKC_F12: ShowMusicWindow(); break; + case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break; + case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break; + case WKC_CTRL | WKC_ALT | 'C': if (!_networking) ShowCheatWindow(); break; + case 'A': if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype, 4); break; // Invoke Autorail + case 'L': ShowTerraformToolbar(); break; + case 'M': ShowSmallMap(); break; + case 'V': ShowExtraViewPortWindow(); break; + default: return ES_NOT_HANDLED; + } + return ES_HANDLED; + } + + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } + + virtual void OnPlaceObjectAbort() + { + this->RaiseWidget(25); + this->SetDirty(); + } + + virtual void OnTick() + { + if (this->IsWidgetLowered(0) != !!_pause_game) { + this->ToggleWidgetLoweredState(0); + this->InvalidateWidget(0); + } + + if (this->IsWidgetLowered(1) != !!_fast_forward) { + this->ToggleWidgetLoweredState(1); + this->InvalidateWidget(1); + } + } + + virtual void OnResize(Point new_size, Point delta) + { + /* There are 27 buttons plus some spacings if the space allows it */ + uint button_width; + uint spacing; + if (this->width >= 27 * 22) { + button_width = 22; + spacing = this->width - (27 * button_width); + } else { + button_width = this->width / 27; + spacing = 0; + } + uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 }; + + for (uint i = 0, x = 0, j = 0; i < 27; i++) { + if (extra_spacing_at[j] == i) { + j++; + uint add = spacing / (lengthof(extra_spacing_at) - j); + spacing -= add; + x += add; } - if (w->IsWidgetLowered(1) != !!_fast_forward) { - w->ToggleWidgetLoweredState(1); - w->InvalidateWidget(1); - } - break; - - case WE_RESIZE: { - /* There are 27 buttons plus some spacings if the space allows it */ - uint button_width; - uint spacing; - if (w->width >= 27 * 22) { - button_width = 22; - spacing = w->width - (27 * button_width); - } else { - button_width = w->width / 27; - spacing = 0; - } - uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 }; + this->widget[i].left = x; + x += (spacing != 0) ? button_width : (this->width - x) / (27 - i); + this->widget[i].right = x - 1; + } + } - for (uint i = 0, x = 0, j = 0; i < 27; i++) { - if (extra_spacing_at[j] == i) { - j++; - uint add = spacing / (lengthof(extra_spacing_at) - j); - spacing -= add; - x += add; - } - - w->widget[i].left = x; - x += (spacing != 0) ? button_width : (w->width - x) / (27 - i); - w->widget[i].right = x - 1; + virtual void OnTimeout() + { + for (uint i = 2; i < this->widget_count; i++) { + if (this->IsWidgetLowered(i)) { + this->RaiseWidget(i); + this->InvalidateWidget(i); } - } break; + } + } - case WE_TIMEOUT: - for (uint i = 2; i < w->widget_count; i++) { - if (w->IsWidgetLowered(i)) { - w->RaiseWidget(i); - w->InvalidateWidget(i); - } - } - break; - - case WE_INVALIDATE_DATA: - if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18); - break; + virtual void OnInvalidateData(int data) + { + if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18); } -} +}; static const Widget _toolb_normal_widgets[] = { { WWT_IMGBTN, RESIZE_LEFT, 14, 0, 0, 0, 21, SPR_IMG_PAUSE, STR_0171_PAUSE_GAME}, @@ -840,7 +858,6 @@ WC_MAIN_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET, _toolb_normal_widgets, - MainToolbarWndProc }; @@ -876,163 +893,176 @@ ToolbarHelpClick, }; -static void ScenEditToolbarWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: - w->SetWidgetDisabledState(6, _patches_newgame.starting_year <= MIN_YEAR); - w->SetWidgetDisabledState(7, _patches_newgame.starting_year >= MAX_YEAR); +struct ScenarioEditorToolbarWindow : Window { + ScenarioEditorToolbarWindow(const WindowDesc *desc) : Window(desc) + { + CLRBITS(this->flags4, WF_WHITE_BORDER_MASK); - /* Draw brown-red toolbar bg. */ - GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB2); - GfxFillRect(0, 0, w->width - 1, w->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT)); - - w->DrawWidgets(); + this->FindWindowPlacementAndResize(desc); + PositionMainToolbar(this); + DoZoomInOutWindow(ZOOM_NONE, this); + } - SetDParam(0, ConvertYMDToDate(_patches_newgame.starting_year, 0, 1)); - DrawStringCenteredTruncated(w->widget[6].right, w->widget[7].left, 6, STR_00AF, TC_FROMSTRING); + virtual void OnPaint() + { + this->SetWidgetDisabledState(6, _settings_newgame.game_creation.starting_year <= MIN_YEAR); + this->SetWidgetDisabledState(7, _settings_newgame.game_creation.starting_year >= MAX_YEAR); - /* We hide this panel when the toolbar space gets too small */ - if (w->widget[4].left != w->widget[4].right) { - DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1, 1, STR_0221_OPENTTD, TC_FROMSTRING); - DrawStringCenteredTruncated(w->widget[4].left + 1, w->widget[4].right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING); + /* Draw brown-red toolbar bg. */ + GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB2); + GfxFillRect(0, 0, this->width - 1, this->height - 1, 0xB4 | (1 << PALETTE_MODIFIER_GREYOUT)); + + this->DrawWidgets(); + + SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); + DrawStringCenteredTruncated(this->widget[6].right, this->widget[7].left, 6, STR_00AF, TC_FROMSTRING); + + /* We hide this panel when the toolbar space gets too small */ + if (this->widget[4].left != this->widget[4].right) { + DrawStringCenteredTruncated(this->widget[4].left + 1, this->widget[4].right - 1, 1, STR_0221_OPENTTD, TC_FROMSTRING); + DrawStringCenteredTruncated(this->widget[4].left + 1, this->widget[4].right - 1, 11, STR_0222_SCENARIO_EDITOR, TC_FROMSTRING); + } + } + + virtual void OnClick(Point pt, int widget) + { + if (_game_mode == GM_MENU) return; + _scen_toolbar_button_procs[widget](this); + } + + virtual EventState OnKeyPress(uint16 key, uint16 keycode) + { + switch (keycode) { + case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(this); break; + case WKC_F2: ShowGameOptions(); break; + case WKC_F3: MenuClickSaveLoad(0); break; + case WKC_F4: ToolbarScenGenLand(this); break; + case WKC_F5: ToolbarScenGenTown(this); break; + case WKC_F6: ToolbarScenGenIndustry(this); break; + case WKC_F7: ToolbarScenBuildRoad(this); break; + case WKC_F8: ToolbarScenPlantTrees(this); break; + case WKC_F9: ToolbarScenPlaceSign(this); break; + case WKC_F10: ShowMusicWindow(); break; + case WKC_F11: PlaceLandBlockInfo(); break; + case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break; + case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break; + + /* those following are all fall through */ + case WKC_NUM_PLUS: + case WKC_EQUALS: + case WKC_SHIFT | WKC_EQUALS: + case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(this); break; + + /* those following are all fall through */ + case WKC_NUM_MINUS: + case WKC_MINUS: + case WKC_SHIFT | WKC_MINUS: + case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(this); break; + + case 'L': ShowEditorTerraformToolbar(); break; + case 'M': ShowSmallMap(); break; + case 'V': ShowExtraViewPortWindow(); break; + default: return ES_NOT_HANDLED; + } + return ES_HANDLED; + } + + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } + + virtual void OnPlaceObjectAbort() + { + this->RaiseWidget(25); + this->SetDirty(); + } + + virtual void OnResize(Point new_size, Point delta) + { + /* There are 15 buttons plus some spacings if the space allows it. + * Furthermore there are two panels of which one is non - essential + * and that one can be removed is the space is too small. */ + uint buttons_width; + uint spacing; + + static int normal_min_width = (15 * 22) + (2 * 130); + static int one_less_panel_min_width = (15 * 22) + 130; + + if (this->width >= one_less_panel_min_width) { + buttons_width = 15 * 22; + spacing = this->width - ((this->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width); + } else { + buttons_width = this->width - 130; + spacing = 0; + } + uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 16, 0 }; + + /* Yes, it defines about 27 widgets for this toolbar */ + for (uint i = 0, x = 0, j = 0, b = 0; i < 27; i++) { + switch (i) { + case 4: + this->widget[i].left = x; + if (this->width < normal_min_width) { + this->widget[i].right = x; + j++; + continue; + } + + x += 130; + this->widget[i].right = x - 1; + break; + + case 5: { + int offset = x - this->widget[i].left; + this->widget[i + 1].left += offset; + this->widget[i + 1].right += offset; + this->widget[i + 2].left += offset; + this->widget[i + 2].right += offset; + this->widget[i].left = x; + x += 130; + this->widget[i].right = x - 1; + i += 2; + } break; + + default: + if (this->widget[i].bottom == 0) continue; + + this->widget[i].left = x; + x += buttons_width / (15 - b); + this->widget[i].right = x - 1; + buttons_width -= buttons_width / (15 - b); + b++; + break; } - break; - - case WE_CLICK: - if (_game_mode == GM_MENU) return; - _scen_toolbar_button_procs[e->we.click.widget](w); - break; - - case WE_KEYPRESS: - switch (e->we.keypress.keycode) { - case WKC_F1: case WKC_PAUSE: ToolbarPauseClick(w); break; - case WKC_F2: ShowGameOptions(); break; - case WKC_F3: MenuClickSaveLoad(0); break; - case WKC_F4: ToolbarScenGenLand(w); break; - case WKC_F5: ToolbarScenGenTown(w); break; - case WKC_F6: ToolbarScenGenIndustry(w); break; - case WKC_F7: ToolbarScenBuildRoad(w); break; - case WKC_F8: ToolbarScenPlantTrees(w); break; - case WKC_F9: ToolbarScenPlaceSign(w); break; - case WKC_F10: ShowMusicWindow(); break; - case WKC_F11: PlaceLandBlockInfo(); break; - case WKC_CTRL | 'S': MenuClickSmallScreenshot(); break; - case WKC_CTRL | 'G': MenuClickWorldScreenshot(); break; - - /* those following are all fall through */ - case WKC_NUM_PLUS: - case WKC_EQUALS: - case WKC_SHIFT | WKC_EQUALS: - case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break; - - /* those following are all fall through */ - case WKC_NUM_MINUS: - case WKC_MINUS: - case WKC_SHIFT | WKC_MINUS: - case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break; - - case 'L': ShowEditorTerraformToolbar(); break; - case 'M': ShowSmallMap(); break; - case 'V': ShowExtraViewPortWindow(); break; - default: return; + if (extra_spacing_at[j] == i) { + j++; + uint add = spacing / (lengthof(extra_spacing_at) - j); + spacing -= add; + x += add; } - e->we.keypress.cont = false; - break; - - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - break; - - case WE_ABORT_PLACE_OBJ: - w->RaiseWidget(25); - w->SetDirty(); - break; - - case WE_RESIZE: { - /* There are 15 buttons plus some spacings if the space allows it. - * Furthermore there are two panels of which one is non - essential - * and that one can be removed is the space is too small. */ - uint buttons_width; - uint spacing; - - static int normal_min_width = (15 * 22) + (2 * 130); - static int one_less_panel_min_width = (15 * 22) + 130; + } + } - if (w->width >= one_less_panel_min_width) { - buttons_width = 15 * 22; - spacing = w->width - ((w->width >= normal_min_width) ? normal_min_width : one_less_panel_min_width); - } else { - buttons_width = w->width - 130; - spacing = 0; - } - uint extra_spacing_at[] = { 3, 4, 7, 8, 10, 16, 0 }; - - /* Yes, it defines about 27 widgets for this toolbar */ - for (uint i = 0, x = 0, j = 0, b = 0; i < 27; i++) { - switch (i) { - case 4: - w->widget[i].left = x; - if (w->width < normal_min_width) { - w->widget[i].right = x; - j++; - continue; - } - - x += 130; - w->widget[i].right = x - 1; - break; - - case 5: { - int offset = x - w->widget[i].left; - w->widget[i + 1].left += offset; - w->widget[i + 1].right += offset; - w->widget[i + 2].left += offset; - w->widget[i + 2].right += offset; - w->widget[i].left = x; - x += 130; - w->widget[i].right = x - 1; - i += 2; - } break; + virtual void OnTick() + { + if (this->IsWidgetLowered(0) != !!_pause_game) { + this->ToggleWidgetLoweredState(0); + this->SetDirty(); + } - default: - if (w->widget[i].bottom == 0) continue; - - w->widget[i].left = x; - x += buttons_width / (15 - b); - w->widget[i].right = x - 1; - buttons_width -= buttons_width / (15 - b); - b++; - break; - } + if (this->IsWidgetLowered(1) != !!_fast_forward) { + this->ToggleWidgetLoweredState(1); + this->SetDirty(); + } + } - if (extra_spacing_at[j] == i) { - j++; - uint add = spacing / (lengthof(extra_spacing_at) - j); - spacing -= add; - x += add; - } - } - } break; - - case WE_TICK: - if (w->IsWidgetLowered(0) != !!_pause_game) { - w->ToggleWidgetLoweredState(0); - w->SetDirty(); - } - - if (w->IsWidgetLowered(1) != !!_fast_forward) { - w->ToggleWidgetLoweredState(1); - w->SetDirty(); - } - break; - - case WE_INVALIDATE_DATA: - HandleZoomMessage(w, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 9, 10); - break; + virtual void OnInvalidateData(int data) + { + if (FindWindowById(WC_MAIN_WINDOW, 0) != NULL) HandleZoomMessage(this, FindWindowById(WC_MAIN_WINDOW, 0)->viewport, 17, 18); } -} +}; static const Widget _toolb_scen_widgets[] = { { WWT_IMGBTN, RESIZE_LEFT, 14, 0, 0, 0, 21, SPR_IMG_PAUSE, STR_0171_PAUSE_GAME}, @@ -1076,7 +1106,6 @@ WC_MAIN_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _toolb_scen_widgets, - ScenEditToolbarWndProc }; /* --- Rendering/handling the drop down menus --- */ @@ -1124,8 +1153,8 @@ ToolbarMenuWindow(int x, int y, int width, int height, const Widget *widgets, int item_count, int sel_index, int parent_button, StringID base_string, int checked_items, - int disabled_mask) : - Window(x, y, width, height, NULL, WC_TOOLBAR_MENU, widgets), + int disabled_items) : + Window(x, y, width, height, WC_TOOLBAR_MENU, widgets), item_count(item_count), sel_index(sel_index), main_button(GB(parent_button, 0, 8)), action_id((GB(parent_button, 8, 8) != 0) ? GB(parent_button, 8, 8) : parent_button), checked_items(checked_items), disabled_items(disabled_items), base_string(base_string) @@ -1280,7 +1309,7 @@ int gray_items; ToolbarPlayerMenuWindow(int x, int y, int width, int height, const Widget *widgets, int main_button, int gray) : - Window(x, y, width, height, NULL, WC_TOOLBAR_MENU, widgets), + Window(x, y, width, height, WC_TOOLBAR_MENU, widgets), item_count(0), main_button(main_button), action_id(main_button), gray_items(gray) { this->flags4 &= ~WF_WHITE_BORDER_MASK; @@ -1293,6 +1322,8 @@ this->sel_index = 0; } } + + this->FindWindowPlacementAndResize(width, height); } ~ToolbarPlayerMenuWindow() @@ -1432,15 +1463,9 @@ /* Clean old GUI values; railtype is (re)set by rail_gui.cpp */ _last_built_roadtype = ROADTYPE_ROAD; - Window *w = new Window((_game_mode != GM_EDITOR) ? &_toolb_normal_desc : &_toolb_scen_desc); - assert(w != NULL); - - CLRBITS(w->flags4, WF_WHITE_BORDER_MASK); - - w->SetWidgetDisabledState(0, _networking && !_network_server); // if not server, disable pause button - w->SetWidgetDisabledState(1, _networking); // if networking, disable fast-forward button - - /* 'w' is for sure a WC_MAIN_TOOLBAR */ - PositionMainToolbar(w); - DoZoomInOutWindow(ZOOM_NONE, w); + if (_game_mode == GM_EDITOR) { + new ScenarioEditorToolbarWindow(&_toolb_scen_desc);; + } else { + new MainToolbarWindow(&_toolb_normal_desc); + } } diff -r 68a692eacf22 -r 67db0d431d5e src/town.h --- a/src/town.h Mon May 26 20:45:25 2008 +0000 +++ b/src/town.h Tue May 27 00:50:55 2008 +0000 @@ -116,6 +116,9 @@ * bit 2 = STADIUM */ byte flags12; + /* level of noise that all the airports are generating */ + uint16 noise_reached; + /* Which players have a statue? */ byte statues; @@ -184,6 +187,18 @@ void InitializeLayout(); inline TownLayout GetActiveLayout() const; + + /** Calculate the max town noise + * The value is counted using the population divided by the content of the + * entry in town_noise_population corespondig to the town's tolerance. + * To this result, we add 3, which is the noise of the lowest airport. + * So user can at least buld that airport + * @return the maximum noise level the town will tolerate */ + inline uint16 MaxTownNoise() const { + if (this->population == 0) return 0; // no population? no noise + + return ((this->population / _settings.economy.town_noise_population[_settings.difficulty.town_council_tolerance]) + 3); + } }; /** @@ -192,7 +207,7 @@ */ inline TownLayout Town::GetActiveLayout() const { - return (_patches.town_layout == TL_RANDOM) ? this->layout : _patches.town_layout; + return (_settings.economy.town_layout == TL_RANDOM) ? this->layout : _settings.economy.town_layout; } struct HouseSpec { diff -r 68a692eacf22 -r 67db0d431d5e src/town_cmd.cpp --- a/src/town_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/town_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -324,7 +324,7 @@ SetDParam(0, t->index); SetDParam(1, t->population); UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, - _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); + _settings.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); MarkTownSignDirty(t); } @@ -596,7 +596,7 @@ if (callback != CALLBACK_FAILED) { if (accepts[0] != CT_INVALID) ac[accepts[0]] = GB(callback, 0, 4); if (accepts[1] != CT_INVALID) ac[accepts[1]] = GB(callback, 4, 4); - if (_opt.landscape != LT_TEMPERATE && HasBit(callback, 12)) { + if (_settings.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) { /* The 'S' bit indicates food instead of goods */ ac[CT_FOOD] = GB(callback, 8, 4); } else { @@ -620,7 +620,7 @@ td->str = STR_2058_UNDER_CONSTRUCTION; } - td->owner = OWNER_TOWN; + td->owner[0] = OWNER_TOWN; } static TrackStatus GetTileTrackStatus_Town(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side) @@ -1212,14 +1212,14 @@ do target_dir = RandomDiagDir(); while (!(cur_rb & DiagDirToRoadBits(target_dir))); tile = TileAddByDiagDir(tile, target_dir); - if (IsTileType(tile, MP_ROAD)) { + if (IsTileType(tile, MP_ROAD) && !IsRoadDepot(tile) && HasTileRoadType(tile, ROADTYPE_ROAD)) { /* Don't allow building over roads of other cities */ - if (IsTileOwner(tile, OWNER_TOWN) && GetTownByTile(tile) != t) { + if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN) && GetTownByTile(tile) != t) { _grow_town_result = GROWTH_SUCCEED; - } else if (IsTileOwner(tile, OWNER_NONE) && _game_mode == GM_EDITOR) { + } else if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) { /* If we are in the SE, and this road-piece has no town owner yet, it just found an * owner :) (happy happy happy road now) */ - SetTileOwner(tile, OWNER_TOWN); + SetRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN); SetTownIndex(tile, t->index); } } @@ -1255,7 +1255,7 @@ /* Let the town be a ghost town * The player wanted it in such a way. Thus there he has it. ;) * Never reached in editor mode. */ - if (_patches.town_layout == TL_NO_ROADS && _generating_world) { + if (_settings.economy.town_layout == TL_NO_ROADS && _generating_world) { return false; } @@ -1367,9 +1367,9 @@ * the other towns may take considerable amount of time (10000 is * too much). */ int tries = 1000; - bool grf = (_opt.town_name >= _nb_orig_names); - uint32 grfid = grf ? GetGRFTownNameId(_opt.town_name - _nb_orig_names) : 0; - uint16 townnametype = grf ? GetGRFTownNameType(_opt.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _opt.town_name; + bool grf = (_settings.game_creation.town_name >= _nb_orig_names); + uint32 grfid = grf ? GetGRFTownNameId(_settings.game_creation.town_name - _nb_orig_names) : 0; + uint16 townnametype = grf ? GetGRFTownNameType(_settings.game_creation.town_name - _nb_orig_names) : SPECSTR_TOWNNAME_START + _settings.game_creation.town_name; assert(townnameparts != NULL); @@ -1453,14 +1453,14 @@ t->exclusive_counter = 0; t->statues = 0; - if (_opt.town_name < _nb_orig_names) { + if (_settings.game_creation.town_name < _nb_orig_names) { /* Original town name */ t->townnamegrfid = 0; - t->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name; + t->townnametype = SPECSTR_TOWNNAME_START + _settings.game_creation.town_name; } else { /* Newgrf town name */ - t->townnamegrfid = GetGRFTownNameId(_opt.town_name - _nb_orig_names); - t->townnametype = GetGRFTownNameType(_opt.town_name - _nb_orig_names); + t->townnamegrfid = GetGRFTownNameId(_settings.game_creation.town_name - _nb_orig_names); + t->townnametype = GetGRFTownNameType(_settings.game_creation.town_name - _nb_orig_names); } t->townnameparts = townnameparts; @@ -1485,11 +1485,13 @@ break; case TSM_CITY: - x *= _patches.initial_city_size; + x *= _settings.economy.initial_city_size; t->larger_town = true; break; } + t->noise_reached = 0; + t->num_houses += x; UpdateTownRadius(t); @@ -1578,13 +1580,13 @@ return NULL; } -static const byte _num_initial_towns[4] = {5, 11, 23, 46}; +static const byte _num_initial_towns[4] = {5, 11, 23, 46}; // very low, low, normal, high bool GenerateTowns() { uint num = 0; - uint n = ScaleByMapSize(_num_initial_towns[_opt.diff.number_towns] + (Random() & 7)); - uint num_cities = _patches.larger_towns == 0 ? 0 : n / _patches.larger_towns; + uint n = ScaleByMapSize(_num_initial_towns[_settings.difficulty.number_towns] + (Random() & 7)); + uint num_cities = _settings.economy.larger_towns == 0 ? 0 : n / _settings.economy.larger_towns; SetGeneratingWorldProgress(GWP_TOWN, n); @@ -1592,7 +1594,7 @@ IncreaseGeneratingWorldProgress(GWP_TOWN); /* try 20 times to create a random-sized town for the first loop. */ TownSizeMode mode = num_cities > 0 ? TSM_CITY : TSM_RANDOM; - if (CreateRandomTown(20, mode, _patches.initial_city_size) != NULL) num++; + if (CreateRandomTown(20, mode, _settings.economy.initial_city_size) != NULL) num++; if (num_cities > 0) num_cities--; } while (--n); @@ -1877,8 +1879,8 @@ HouseZonesBits rad = GetTownRadiusGroup(t, tile); /* Above snow? */ - int land = _opt.landscape; - if (land == LT_ARCTIC && z >= _opt.snow_line) land = -1; + int land = _settings.game_creation.landscape; + if (land == LT_ARCTIC && z >= _settings.game_creation.snow_line) land = -1; uint bitmask = (1 << rad) + (1 << (land + 12)); @@ -2217,7 +2219,7 @@ static void TownActionBuyRights(Town *t) { /* Check if it's allowed to by the rights */ - if (!_patches.exclusive_rights) return; + if (!_settings.economy.exclusive_rights) return; t->exclusive_counter = 12; t->exclusivity = _current_player; @@ -2331,7 +2333,7 @@ } ClrBit(t->flags12, TOWN_IS_FUNDED); - if (_patches.town_growth_rate == 0 && t->fund_buildings_months == 0) return; + if (_settings.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return; /** Towns are processed every TOWN_GROWTH_FREQUENCY ticks, and this is the * number of times towns are processed before a new building is built. */ @@ -2350,17 +2352,17 @@ if (n == 0 && !Chance16(1, 12)) return; } - if (_opt.landscape == LT_ARCTIC) { + if (_settings.game_creation.landscape == LT_ARCTIC) { if (TilePixelHeight(t->xy) >= GetSnowLine() && t->act_food == 0 && t->population > 90) return; - } else if (_opt.landscape == LT_TROPIC) { + } else if (_settings.game_creation.landscape == LT_TROPIC) { if (GetTropicZone(t->xy) == TROPICZONE_DESERT && (t->act_food == 0 || t->act_water == 0) && t->population > 60) return; } /* Use the normal growth rate values if new buildings have been funded in * this town and the growth rate is set to none. */ - uint growth_multiplier = _patches.town_growth_rate != 0 ? _patches.town_growth_rate - 1 : 1; + uint growth_multiplier = _settings.economy.town_growth_rate != 0 ? _settings.economy.town_growth_rate - 1 : 1; m >>= growth_multiplier; if (t->larger_town) m /= 2; @@ -2403,7 +2405,7 @@ { if (!IsValidPlayer(_current_player)) return true; - Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); + Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority); if (t == NULL) return true; if (t->ratings[_current_player] > RATING_VERYPOOR) return true; @@ -2436,8 +2438,8 @@ Town *ClosestTownFromTile(TileIndex tile, uint threshold) { if (IsTileType(tile, MP_HOUSE) || ( - IsTileType(tile, MP_ROAD) && - GetRoadOwner(tile, ROADTYPE_ROAD) == OWNER_TOWN + IsTileType(tile, MP_ROAD) && HasTileRoadType(tile, ROADTYPE_ROAD) && + IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN) )) { return GetTownByTile(tile); } else { @@ -2522,7 +2524,7 @@ * owned by a town no removal if rating is lower than ... depends now on * difficulty setting. Minimum town rating selected by difficulty level */ - int modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type]; + int modemod = _default_rating_settings[_settings.difficulty.town_council_tolerance][type]; if (GetRating(t) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { SetDParam(0, t->index); diff -r 68a692eacf22 -r 67db0d431d5e src/town_gui.cpp --- a/src/town_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/town_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -31,16 +31,6 @@ extern bool GenerateTowns(); static int _scengen_town_size = 1; // depress medium-sized towns per default -enum TownAuthorityWidget { - TWA_CLOSEBOX = 0, - TWA_CAPTION, - TWA_RATING_INFO, - TWA_COMMAND_LIST, - TWA_SCROLLBAR, - TWA_ACTION_INFO, - TWA_EXECUTE, -}; - static const Widget _town_authority_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // TWA_CLOSEBOX { WWT_CAPTION, RESIZE_NONE, 13, 11, 316, 0, 13, STR_2022_LOCAL_AUTHORITY, STR_018C_WINDOW_TITLE_DRAG_THIS}, // TWA_CAPTION @@ -86,7 +76,7 @@ TownActions buttons = TACT_NONE; /* Spectators and unwanted have no options */ - if (pid != PLAYER_SPECTATOR && !(_patches.bribe && t->unwanted[pid])) { + if (pid != PLAYER_SPECTATOR && !(_settings.economy.bribe && t->unwanted[pid])) { /* Things worth more than this are not shown */ Money avail = GetPlayer(pid)->player_money + _price.station_value * 200; @@ -98,11 +88,11 @@ const TownActions cur = (TownActions)(1 << i); /* Is the player not able to bribe ? */ - if (cur == TACT_BRIBE && (!_patches.bribe || t->ratings[pid] >= RATING_BRIBE_MAXIMUM)) + if (cur == TACT_BRIBE && (!_settings.economy.bribe || t->ratings[pid] >= RATING_BRIBE_MAXIMUM)) continue; /* Is the player not able to buy exclusive rights ? */ - if (cur == TACT_BUY_RIGHTS && !_patches.exclusive_rights) + if (cur == TACT_BUY_RIGHTS && !_settings.economy.exclusive_rights) continue; /* Is the player not able to build a statue ? */ @@ -142,11 +132,25 @@ } struct TownAuthorityWindow : Window { +private: + Town *town; int sel_index; + enum TownAuthorityWidget { + TWA_CLOSEBOX = 0, + TWA_CAPTION, + TWA_RATING_INFO, + TWA_COMMAND_LIST, + TWA_SCROLLBAR, + TWA_ACTION_INFO, + TWA_EXECUTE, + }; + +public: TownAuthorityWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number), sel_index(-1) { + this->town = GetTown(this->window_number); this->vscroll.cap = 5; this->FindWindowPlacementAndResize(desc); @@ -154,9 +158,8 @@ virtual void OnPaint() { - const Town *t = GetTown(this->window_number); int numact; - uint buttons = GetMaskOfTownActions(&numact, _local_player, t); + uint buttons = GetMaskOfTownActions(&numact, _local_player, this->town); SetVScrollCount(this, numact + 1); @@ -176,13 +179,13 @@ const Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active && (HasBit(t->have_ratings, p->index) || t->exclusivity == p->index)) { + if (p->is_active && (HasBit(this->town->have_ratings, p->index) || this->town->exclusivity == p->index)) { DrawPlayerIcon(p->index, 2, y); SetDParam(0, p->index); SetDParam(1, p->index); - int r = t->ratings[p->index]; + int r = this->town->ratings[p->index]; StringID str; (str = STR_3035_APPALLING, r <= RATING_APPALLING) || // Apalling (str++, r <= RATING_VERYPOOR) || // Very Poor @@ -194,7 +197,7 @@ (str++, true); // Outstanding SetDParam(2, str); - if (t->exclusivity == p->index) { // red icon for player with exclusive rights + if (this->town->exclusivity == p->index) { // red icon for player with exclusive rights DrawSprite(SPR_BLOT, PALETTE_TO_RED, 18, y); } @@ -233,12 +236,11 @@ { switch (widget) { case TWA_COMMAND_LIST: { - const Town *t = GetTown(this->window_number); int y = (pt.y - 0x6B) / 10; if (!IsInsideMM(y, 0, 5)) return; - y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_player, t), y + this->vscroll.pos - 1); + y = GetNthSetBit(GetMaskOfTownActions(NULL, _local_player, this->town), y + this->vscroll.pos - 1); if (y >= 0) { this->sel_index = y; this->SetDirty(); @@ -248,7 +250,7 @@ } case TWA_EXECUTE: - DoCommandP(GetTown(this->window_number)->xy, this->window_number, this->sel_index, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS)); + DoCommandP(this->town->xy, this->window_number, this->sel_index, NULL, CMD_DO_TOWN_ACTION | CMD_MSG(STR_00B4_CAN_T_DO_THIS)); break; } } @@ -264,7 +266,6 @@ WC_TOWN_AUTHORITY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, _town_authority_widgets, - NULL }; static void ShowTownAuthorityWindow(uint town) @@ -272,98 +273,138 @@ AllocateWindowDescFront(&_town_authority_desc, town); } - -enum TownViewWidget { - TVW_CAPTION = 1, - TVW_STICKY, - TVW_CENTERVIEW = 6, - TVW_SHOWAUTORITY, - TVW_CHANGENAME, - TVW_EXPAND, - TVW_DELETE, -}; - -static void TownViewWndProc(Window *w, WindowEvent *e) -{ - Town *t = GetTown(w->window_number); - - switch (e->event) { - case WE_CREATE: { - bool ingame = _game_mode != GM_EDITOR; - if (t->larger_town) w->widget[TVW_CAPTION].data = STR_CITY; - w->SetWidgetHiddenState(TVW_DELETE, ingame); // hide delete button on game mode - w->SetWidgetHiddenState(TVW_EXPAND, ingame); // hide expand button on game mode - w->SetWidgetHiddenState(TVW_SHOWAUTORITY, !ingame); // hide autority button on editor mode - - if (ingame) { - /* resize caption bar */ - w->widget[TVW_CAPTION].right = w->widget[TVW_STICKY].left -1; - /* move the rename from top on scenario to bottom in game */ - w->widget[TVW_CHANGENAME].top = w->widget[TVW_EXPAND].top; - w->widget[TVW_CHANGENAME].bottom = w->widget[TVW_EXPAND].bottom; - w->widget[TVW_CHANGENAME].right = w->widget[TVW_STICKY].right; - } - } break; - - case WE_PAINT: - /* disable renaming town in network games if you are not the server */ - w->SetWidgetDisabledState(TVW_CHANGENAME, _networking && !_network_server); - - SetDParam(0, t->index); - w->DrawWidgets(); - - SetDParam(0, t->population); - SetDParam(1, t->num_houses); - DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING); +struct TownViewWindow : Window { +private: + Town *town; - SetDParam(0, t->act_pass); - SetDParam(1, t->max_pass); - DrawString(2, 117, STR_200D_PASSENGERS_LAST_MONTH_MAX, TC_FROMSTRING); - - SetDParam(0, t->act_mail); - SetDParam(1, t->max_mail); - DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING); - - w->DrawViewport(); - break; - - case WE_CLICK: - switch (e->we.click.widget) { - case TVW_CENTERVIEW: /* scroll to location */ - if (_ctrl_pressed) { - ShowExtraViewPortWindow(t->xy); - } else { - ScrollMainWindowToTile(t->xy); - } - break; + enum TownViewWidget { + TVW_CAPTION = 1, + TVW_STICKY, + TVW_VIEWPORTPANEL, + TVW_INFOPANEL = 5, + TVW_CENTERVIEW, + TVW_SHOWAUTORITY, + TVW_CHANGENAME, + TVW_EXPAND, + TVW_DELETE, + }; - case TVW_SHOWAUTORITY: /* town authority */ - ShowTownAuthorityWindow(w->window_number); - break; - - case TVW_CHANGENAME: /* rename */ - SetDParam(0, w->window_number); - ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, w, CS_ALPHANUMERAL); - break; - - case TVW_EXPAND: /* expand town - only available on Scenario editor */ - ExpandTown(t); - break; +public: + TownViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->town = GetTown(this->window_number); + bool ingame = _game_mode != GM_EDITOR; - case TVW_DELETE: /* delete town - only available on Scenario editor */ - delete t; - break; - } break; + this->flags4 |= WF_DISABLE_VP_SCROLL; + InitializeWindowViewport(this, 3, 17, 254, 86, this->town->xy, ZOOM_LVL_TOWN); - case WE_ON_EDIT_TEXT: - if (!StrEmpty(e->we.edittext.str)) { - _cmd_text = e->we.edittext.str; - DoCommandP(0, w->window_number, 0, NULL, - CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN)); + if (this->town->larger_town) this->widget[TVW_CAPTION].data = STR_CITY; + this->SetWidgetHiddenState(TVW_DELETE, ingame); // hide delete button on game mode + this->SetWidgetHiddenState(TVW_EXPAND, ingame); // hide expand button on game mode + this->SetWidgetHiddenState(TVW_SHOWAUTORITY, !ingame); // hide autority button on editor mode + + if (ingame) { + /* resize caption bar */ + this->widget[TVW_CAPTION].right = this->widget[TVW_STICKY].left -1; + /* move the rename from top on scenario to bottom in game */ + this->widget[TVW_CHANGENAME].top = this->widget[TVW_EXPAND].top; + this->widget[TVW_CHANGENAME].bottom = this->widget[TVW_EXPAND].bottom; + this->widget[TVW_CHANGENAME].right = this->widget[TVW_STICKY].right; + } + + /* Space required for showing noise level information */ + if (_settings.economy.station_noise_level) { + ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10); + } + + this->FindWindowPlacementAndResize(desc); + } + + virtual void OnPaint() + { + /* disable renaming town in network games if you are not the server */ + this->SetWidgetDisabledState(TVW_CHANGENAME, _networking && !_network_server); + + SetDParam(0, this->town->index); + this->DrawWidgets(); + + SetDParam(0, this->town->population); + SetDParam(1, this->town->num_houses); + DrawString(2, 107, STR_2006_POPULATION, TC_FROMSTRING); + + SetDParam(0, this->town->act_pass); + SetDParam(1, this->town->max_pass); + DrawString(2, 117, STR_200D_PASSENGERS_LAST_MONTH_MAX, TC_FROMSTRING); + + SetDParam(0, this->town->act_mail); + SetDParam(1, this->town->max_mail); + DrawString(2, 127, STR_200E_MAIL_LAST_MONTH_MAX, TC_FROMSTRING); + + this->DrawViewport(); + + /* only show the town noise, if the noise option is activated. */ + if (_settings.economy.station_noise_level) { + SetDParam(0, this->town->noise_reached); + SetDParam(1, this->town->MaxTownNoise()); + DrawString(2, 137, STR_NOISE_IN_TOWN, 0); + } + } + + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case TVW_CENTERVIEW: /* scroll to location */ + if (_ctrl_pressed) { + ShowExtraViewPortWindow(this->town->xy); + } else { + ScrollMainWindowToTile(this->town->xy); + } + break; + + case TVW_SHOWAUTORITY: /* town authority */ + ShowTownAuthorityWindow(this->window_number); + break; + + case TVW_CHANGENAME: /* rename */ + SetDParam(0, this->window_number); + ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, this, CS_ALPHANUMERAL); + break; + + case TVW_EXPAND: /* expand town - only available on Scenario editor */ + ExpandTown(this->town); + break; + + case TVW_DELETE: /* delete town - only available on Scenario editor */ + delete this->town; + break; + } + } + + virtual void OnInvalidateData(int data = 0) + { + /* Called when setting station noise have changed, in order to resize the window */ + this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading + + if (_settings.economy.station_noise_level) { // adjust depending + if (this->height == 150) { // window is smaller, needs to be bigger + ResizeWindowForWidget(this, TVW_INFOPANEL, 0, 10); } - break; + } else { + if (this->height != 150) { // window is bigger, needs to be smaller + ResizeWindowForWidget(this, TVW_INFOPANEL, 0, -10); + } + } } -} + + virtual void OnQueryTextFinished(char *str) + { + if (!StrEmpty(str)) { + _cmd_text = str; + DoCommandP(0, this->window_number, 0, NULL, + CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN)); + } + } +}; static const Widget _town_view_widgets[] = { @@ -386,26 +427,13 @@ WC_TOWN_VIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON, _town_view_widgets, - TownViewWndProc }; void ShowTownViewWindow(TownID town) { - Window *w; - - w = AllocateWindowDescFront(&_town_view_desc, town); - - if (w != NULL) { - w->flags4 |= WF_DISABLE_VP_SCROLL; - InitializeWindowViewport(w, 3, 17, 254, 86, GetTown(town)->xy, ZOOM_LVL_TOWN); - } + AllocateWindowDescFront(&_town_view_desc, town); } -enum TownDirectoryWidget { - TDW_SORTNAME = 3, - TDW_SORTPOPULATION, - TDW_CENTERTOWN, -}; static const Widget _town_directory_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 13, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, RESIZE_NONE, 13, 11, 195, 0, 13, STR_2000_TOWNS, STR_018C_WINDOW_TITLE_DRAG_THIS}, @@ -478,107 +506,120 @@ } -static void TownDirectoryWndProc(Window *w, WindowEvent *e) -{ - switch (e->event) { - case WE_PAINT: { - if (_town_sort_dirty) { - _town_sort_dirty = false; - MakeSortedTownList(); +struct TownDirectoryWindow : public Window { +private: + enum TownDirectoryWidget { + TDW_SORTNAME = 3, + TDW_SORTPOPULATION, + TDW_CENTERTOWN, + }; + +public: + TownDirectoryWindow(const WindowDesc *desc) : Window(desc, 0) + { + this->vscroll.cap = 16; + this->resize.step_height = 10; + this->resize.height = this->height - 10 * 6; // minimum of 10 items in the list, each item 10 high + + this->FindWindowPlacementAndResize(desc); + } + + virtual void OnPaint() + { + if (_town_sort_dirty) { + _town_sort_dirty = false; + MakeSortedTownList(); + } + + SetVScrollCount(this, _num_town_sort); + + this->DrawWidgets(); + this->DrawSortButtonState((_town_sort_order <= 1) ? TDW_SORTNAME : TDW_SORTPOPULATION, _town_sort_order & 1 ? SBS_DOWN : SBS_UP); + + { + int n = 0; + uint16 i = this->vscroll.pos; + int y = 28; + + while (i < _num_town_sort) { + const Town* t = _town_sort[i]; + + assert(t->xy); + + SetDParam(0, t->index); + SetDParam(1, t->population); + DrawString(2, y, STR_2057, TC_FROMSTRING); + + y += 10; + i++; + if (++n == this->vscroll.cap) break; // max number of towns in 1 window } - SetVScrollCount(w, _num_town_sort); - - w->DrawWidgets(); - w->DrawSortButtonState((_town_sort_order <= 1) ? TDW_SORTNAME : TDW_SORTPOPULATION, _town_sort_order & 1 ? SBS_DOWN : SBS_UP); - - { - int n = 0; - uint16 i = w->vscroll.pos; - int y = 28; - - while (i < _num_town_sort) { - const Town* t = _town_sort[i]; - - assert(t->xy); - - SetDParam(0, t->index); - SetDParam(1, t->population); - DrawString(2, y, STR_2057, TC_FROMSTRING); - - y += 10; - i++; - if (++n == w->vscroll.cap) break; // max number of towns in 1 window - } - SetDParam(0, GetWorldPopulation()); - DrawString(3, w->height - 12 + 2, STR_TOWN_POPULATION, TC_FROMSTRING); - } - } break; - - case WE_CLICK: - switch (e->we.click.widget) { - case TDW_SORTNAME: /* Sort by Name ascending/descending */ - _town_sort_order = (_town_sort_order == 0) ? 1 : 0; - _town_sort_dirty = true; - w->SetDirty(); - break; + SetDParam(0, GetWorldPopulation()); + DrawString(3, this->height - 12 + 2, STR_TOWN_POPULATION, TC_FROMSTRING); + } + } - case TDW_SORTPOPULATION: /* Sort by Population ascending/descending */ - _town_sort_order = (_town_sort_order == 2) ? 3 : 2; - _town_sort_dirty = true; - w->SetDirty(); - break; - - case TDW_CENTERTOWN: { /* Click on Town Matrix */ - const Town* t; - - uint16 id_v = (e->we.click.pt.y - 28) / 10; - - if (id_v >= w->vscroll.cap) return; // click out of bounds - - id_v += w->vscroll.pos; - - if (id_v >= _num_town_sort) return; // click out of town bounds + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case TDW_SORTNAME: /* Sort by Name ascending/descending */ + _town_sort_order = (_town_sort_order == 0) ? 1 : 0; + _town_sort_dirty = true; + this->SetDirty(); + break; - t = _town_sort[id_v]; - assert(t->xy); - if (_ctrl_pressed) { - ShowExtraViewPortWindow(t->xy); - } else { - ScrollMainWindowToTile(t->xy); - } - } break; + case TDW_SORTPOPULATION: /* Sort by Population ascending/descending */ + _town_sort_order = (_town_sort_order == 2) ? 3 : 2; + _town_sort_dirty = true; + this->SetDirty(); + break; + + case TDW_CENTERTOWN: { /* Click on Town Matrix */ + const Town* t; + + uint16 id_v = (pt.y - 28) / 10; + + if (id_v >= this->vscroll.cap) return; // click out of bounds + + id_v += this->vscroll.pos; + + if (id_v >= _num_town_sort) return; // click out of town bounds + + t = _town_sort[id_v]; + assert(t->xy); + if (_ctrl_pressed) { + ShowExtraViewPortWindow(t->xy); + } else { + ScrollMainWindowToTile(t->xy); + } + break; } - break; + } + } - case WE_100_TICKS: - w->SetDirty(); - break; + virtual void OnHundredthTick() + { + this->SetDirty(); + } - case WE_RESIZE: - w->vscroll.cap += e->we.sizing.diff.y / 10; - break; + virtual void OnResize(Point new_size, Point delta) + { + this->vscroll.cap += delta.y / 10; } -} +}; static const WindowDesc _town_directory_desc = { WDP_AUTO, WDP_AUTO, 208, 202, 208, 202, WC_TOWN_DIRECTORY, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _town_directory_widgets, - TownDirectoryWndProc }; - void ShowTownDirectory() { - Window *w = AllocateWindowDescFront(&_town_directory_desc, 0); - - if (w != NULL) { - w->vscroll.cap = 16; - w->resize.step_height = 10; - w->resize.height = w->height - 10 * 6; // minimum of 10 items in the list, each item 10 high - } + if (BringWindowToFrontById(WC_TOWN_DIRECTORY, 0)) return; + new TownDirectoryWindow(&_town_directory_desc); } void CcBuildTown(bool success, TileIndex tile, uint32 p1, uint32 p2) @@ -596,16 +637,6 @@ DoCommandP(tile, size, mode, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE)); } -enum TownScenarioEditorWidget { - TSEW_NEWTOWN = 4, - TSEW_RANDOMTOWN, - TSEW_MANYRANDOMTOWNS, - TSEW_SMALLTOWN, - TSEW_MEDIUMTOWN, - TSEW_LARGETOWN, - TSEW_CITY, -}; - static const Widget _scen_edit_town_gen_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, { WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_0233_TOWN_GENERATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, @@ -622,85 +653,102 @@ { WIDGETS_END}, }; -static void ScenEditTownGenWndProc(Window *w, WindowEvent *e) +struct ScenarioEditorTownGenerationWindow : Window { - switch (e->event) { - case WE_PAINT: - w->DrawWidgets(); - break; - - case WE_CREATE: - w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN); - break; - - case WE_CLICK: - switch (e->we.click.widget) { - case TSEW_NEWTOWN: - HandlePlacePushButton(w, TSEW_NEWTOWN, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town); - break; - - case TSEW_RANDOMTOWN: { - Town *t; - uint size = min(_scengen_town_size, (int)TSM_CITY); - TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED; +private: + enum TownScenarioEditorWidget { + TSEW_NEWTOWN = 4, + TSEW_RANDOMTOWN, + TSEW_MANYRANDOMTOWNS, + TSEW_SMALLTOWN, + TSEW_MEDIUMTOWN, + TSEW_LARGETOWN, + TSEW_CITY, + }; - w->HandleButtonClick(TSEW_RANDOMTOWN); - _generating_world = true; - t = CreateRandomTown(20, mode, size); - _generating_world = false; - - if (t == NULL) { - ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0); - } else { - ScrollMainWindowToTile(t->xy); - } - } break; +public: + ScenarioEditorTownGenerationWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN); + this->FindWindowPlacementAndResize(desc); + } - case TSEW_MANYRANDOMTOWNS: - w->HandleButtonClick(TSEW_MANYRANDOMTOWNS); + virtual void OnPaint() + { + this->DrawWidgets(); + } - _generating_world = true; - if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0); - _generating_world = false; - break; + virtual void OnClick(Point pt, int widget) + { + switch (widget) { + case TSEW_NEWTOWN: + HandlePlacePushButton(this, TSEW_NEWTOWN, SPR_CURSOR_TOWN, VHM_RECT, PlaceProc_Town); + break; - case TSEW_SMALLTOWN: case TSEW_MEDIUMTOWN: case TSEW_LARGETOWN: case TSEW_CITY: - w->RaiseWidget(_scengen_town_size + TSEW_SMALLTOWN); - _scengen_town_size = e->we.click.widget - TSEW_SMALLTOWN; - w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN); - w->SetDirty(); - break; + case TSEW_RANDOMTOWN: { + Town *t; + uint size = min(_scengen_town_size, (int)TSM_CITY); + TownSizeMode mode = _scengen_town_size > TSM_CITY ? TSM_CITY : TSM_FIXED; + + this->HandleButtonClick(TSEW_RANDOMTOWN); + _generating_world = true; + t = CreateRandomTown(20, mode, size); + _generating_world = false; + + if (t == NULL) { + ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0); + } else { + ScrollMainWindowToTile(t->xy); + } } break; - case WE_TIMEOUT: - w->RaiseWidget(TSEW_RANDOMTOWN); - w->RaiseWidget(TSEW_MANYRANDOMTOWNS); - w->SetDirty(); - break; + case TSEW_MANYRANDOMTOWNS: + this->HandleButtonClick(TSEW_MANYRANDOMTOWNS); - case WE_PLACE_OBJ: - _place_proc(e->we.place.tile); - break; + _generating_world = true; + if (!GenerateTowns()) ShowErrorMessage(STR_NO_SPACE_FOR_TOWN, STR_CANNOT_GENERATE_TOWN, 0, 0); + _generating_world = false; + break; - case WE_ABORT_PLACE_OBJ: - w->RaiseButtons(); - w->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN); - w->SetDirty(); - break; + case TSEW_SMALLTOWN: case TSEW_MEDIUMTOWN: case TSEW_LARGETOWN: case TSEW_CITY: + this->RaiseWidget(_scengen_town_size + TSEW_SMALLTOWN); + _scengen_town_size = widget - TSEW_SMALLTOWN; + this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN); + this->SetDirty(); + break; + } } -} + + virtual void OnTimeout() + { + this->RaiseWidget(TSEW_RANDOMTOWN); + this->RaiseWidget(TSEW_MANYRANDOMTOWNS); + this->SetDirty(); + } + + virtual void OnPlaceObject(Point pt, TileIndex tile) + { + _place_proc(tile); + } + + virtual void OnPlaceObjectAbort() + { + this->RaiseButtons(); + this->LowerWidget(_scengen_town_size + TSEW_SMALLTOWN); + this->SetDirty(); + } +}; static const WindowDesc _scen_edit_town_gen_desc = { WDP_AUTO, WDP_AUTO, 160, 95, 160, 95, WC_SCEN_TOWN_GEN, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _scen_edit_town_gen_widgets, - ScenEditTownGenWndProc, }; void ShowBuildTownWindow() { if (_game_mode != GM_EDITOR && !IsValidPlayer(_current_player)) return; - AllocateWindowDescFront(&_scen_edit_town_gen_desc, 0); + AllocateWindowDescFront(&_scen_edit_town_gen_desc, 0); } diff -r 68a692eacf22 -r 67db0d431d5e src/town_type.h --- a/src/town_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/town_type.h Tue May 27 00:50:55 2008 +0000 @@ -54,7 +54,8 @@ RATING_INDUSTRY_DOWN_STEP = -1500, RATING_INDUSTRY_MINIMUM = RATING_MINIMUM, - RATING_ROAD_DOWN_STEP = -50, + RATING_ROAD_DOWN_STEP_INNER = -50, ///< removing a roadpiece in the middle + RATING_ROAD_DOWN_STEP_EDGE = -18, ///< removing a roadpiece at the edge RATING_ROAD_MINIMUM = -100, RATING_HOUSE_MINIMUM = RATING_MINIMUM, diff -r 68a692eacf22 -r 67db0d431d5e src/train_cmd.cpp --- a/src/train_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/train_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -92,7 +92,7 @@ byte FreightWagonMult(CargoID cargo) { if (!GetCargo(cargo)->is_freight) return 1; - return _patches.freight_trains; + return _settings.vehicle.freight_trains; } @@ -278,7 +278,7 @@ } /* max speed is the minimum of the speed limits of all vehicles in the consist */ - if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) { + if ((rvi_u->railveh_type != RAILVEH_WAGON || _settings.vehicle.wagon_speed_limits) && !UsesWagonOverride(u)) { uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed); if (speed != 0) max_speed = min(speed, max_speed); } @@ -726,7 +726,7 @@ Vehicle *v = vl[0]; UnitID unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_TRAIN); - if (unit_num > _patches.max_trains) + if (unit_num > _settings.vehicle.max_trains) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); if (flags & DC_EXEC) { @@ -765,7 +765,7 @@ v->u.rail.railtype = rvi->railtype; _new_vehicle_id = v->index; - v->service_interval = _patches.servint_trains; + v->service_interval = _settings.vehicle.servint_trains; v->date_of_last_service = _date; v->build_year = _cur_year; v->cur_image = 0xAC2; @@ -803,7 +803,7 @@ } InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); InvalidateWindow(WC_COMPANY, v->owner); if (IsLocalPlayer()) { InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window @@ -1001,7 +1001,7 @@ if (HasBit(p2, 0) && src_head == dst_head) return CommandCost(); { - int max_len = _patches.mammoth_trains ? 100 : 10; + int max_len = _settings.vehicle.mammoth_trains ? 100 : 10; /* check if all vehicles in the source train are stopped inside a depot. */ int src_len = CheckTrainStoppedInDepot(src_head); @@ -1044,7 +1044,7 @@ /* moving a loco to a new line?, then we need to assign a unitnumber. */ if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) { UnitID unit_num = GetFreeUnitNumber(VEH_TRAIN); - if (unit_num > _patches.max_trains) + if (unit_num > _settings.vehicle.max_trains) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); if (flags & DC_EXEC) src->unitnumber = unit_num; @@ -1272,7 +1272,7 @@ InvalidateWindow(WC_VEHICLE_DEPOT, dst_head->tile); } - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); } return CommandCost(); @@ -1353,7 +1353,7 @@ DeleteWindowById(WC_VEHICLE_VIEW, first->index); } InvalidateWindow(WC_VEHICLE_DEPOT, first->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); } CommandCost cost(EXPENSES_NEW_VEHICLES); @@ -1544,7 +1544,7 @@ int old = v->u.rail.last_speed; if (spd != old) { v->u.rail.last_speed = spd; - if (_patches.vehicle_speed || (old == 0) != (spd == 0)) { + if (_settings.gui.vehicle_speed || (old == 0) != (spd == 0)) { InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); } } @@ -1883,7 +1883,7 @@ if (v->vehstatus & VS_CRASHED || v->breakdown_ctr != 0) return CMD_ERROR; if (flags & DC_EXEC) { - if (_patches.realistic_acceleration && v->cur_speed != 0) { + if (_settings.vehicle.realistic_acceleration && v->cur_speed != 0) { ToggleBit(v->u.rail.flags, VRF_REVERSING); } else { v->cur_speed = 0; @@ -2001,7 +2001,7 @@ v->cargo_subtype = new_subtype; InvalidateWindow(WC_VEHICLE_DETAILS, v->index); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); } } } @@ -2058,7 +2058,7 @@ return tfdd; } - switch (_patches.pathfinder_for_trains) { + switch (_settings.pf.pathfinder_for_trains) { case VPF_YAPF: { /* YAPF */ bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse); tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND @@ -2369,7 +2369,7 @@ /* quick return in case only one possible track is available */ if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks); - switch (_patches.pathfinder_for_trains) { + switch (_settings.pf.pathfinder_for_trains) { case VPF_YAPF: { /* YAPF */ Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found); if (trackdir != INVALID_TRACKDIR) { @@ -2446,7 +2446,7 @@ /* it is first time the problem occurred, set the "path not found" flag */ SetBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION); /* and notify user about the event */ - if (_patches.lost_train_warn && v->owner == _local_player) { + if (_settings.gui.lost_train_warn && v->owner == _local_player) { SetDParam(0, v->unitnumber); AddNewsItem( STR_TRAIN_IS_LOST, @@ -2474,7 +2474,7 @@ static bool CheckReverseTrain(Vehicle *v) { - if (_opt.diff.line_reverse_mode != 0 || + if (_settings.difficulty.line_reverse_mode != 0 || v->u.rail.track == TRACK_BIT_DEPOT || v->u.rail.track == TRACK_BIT_WORMHOLE || !(v->direction & 1)) { return false; @@ -2487,7 +2487,7 @@ assert(v->u.rail.track); - switch (_patches.pathfinder_for_trains) { + switch (_settings.pf.pathfinder_for_trains) { case VPF_YAPF: /* YAPF */ reverse_best = YapfCheckReverseTrain(v); break; @@ -2607,13 +2607,13 @@ uint accel; if (v->vehstatus & VS_STOPPED || HasBit(v->u.rail.flags, VRF_REVERSING)) { - if (_patches.realistic_acceleration) { + if (_settings.vehicle.realistic_acceleration) { accel = GetTrainAcceleration(v, AM_BRAKE) * 2; } else { accel = v->acceleration * -2; } } else { - if (_patches.realistic_acceleration) { + if (_settings.vehicle.realistic_acceleration) { accel = GetTrainAcceleration(v, AM_ACCEL); } else { accel = v->acceleration; @@ -2754,7 +2754,7 @@ /** Modify the speed of the vehicle due to a turn */ static inline void AffectSpeedByDirChange(Vehicle *v, Direction new_dir) { - if (_patches.realistic_acceleration) return; + if (_settings.vehicle.realistic_acceleration) return; DirDiff diff = DirDifference(v->direction, new_dir); if (diff == DIRDIFF_SAME) return; @@ -2766,7 +2766,7 @@ /** Modify the speed of the vehicle due to a change in altitude */ static inline void AffectSpeedByZChange(Vehicle *v, byte old_z) { - if (old_z == v->z_pos || _patches.realistic_acceleration) return; + if (old_z == v->z_pos || _settings.vehicle.realistic_acceleration) return; const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype]; @@ -2805,12 +2805,12 @@ InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); } - RebuildVehicleLists(); - - BEGIN_ENUM_WAGONS(v) + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); + + for (; v != NULL; v = v->Next()) { v->vehstatus |= VS_CRASHED; MarkSingleVehicleDirty(v); - END_ENUM_WAGONS(v) + } /* must be updated after the train has been marked crashed */ if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing); @@ -2819,9 +2819,11 @@ static uint CountPassengersInTrain(const Vehicle *v) { uint num = 0; - BEGIN_ENUM_WAGONS(v) + + for (; v != NULL; v = v->Next()) { if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo.Count(); - END_ENUM_WAGONS(v) + } + return num; } @@ -2969,7 +2971,7 @@ TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts) & reachable_trackdirs); TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); - if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) { + if (_settings.pf.pathfinder_for_trains != VPF_NTP && _settings.pf.forbid_90_deg && prev == NULL) { /* We allow wagons to make 90 deg turns, because forbid_90_deg * can be switched on halfway a turn */ bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); @@ -2997,12 +2999,12 @@ v->cur_speed = 0; v->subspeed = 0; v->progress = 255 - 100; - if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20) return; + if (++v->load_unload_time_rem < _settings.pf.wait_oneway_signal * 20) return; } else if (HasSignalOnTrackdir(gp.new_tile, i)) { v->cur_speed = 0; v->subspeed = 0; v->progress = 255 - 10; - if (++v->load_unload_time_rem < _patches.wait_twoway_signal * 73) { + if (++v->load_unload_time_rem < _settings.pf.wait_twoway_signal * 73) { TileIndex o_tile = gp.new_tile + TileOffsByDiagDir(enterdir); Direction rdir = ReverseDir(dir); @@ -3152,7 +3154,7 @@ } } - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); MarkSingleVehicleDirty(v); @@ -3244,7 +3246,7 @@ InvalidateWindow(WC_VEHICLE_DETAILS, v->index); if (!PlayVehicleSound(v, VSE_BREAKDOWN)) { - SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ? + SndPlayVehicleFx((_settings.game_creation.landscape != LT_TOYLAND) ? SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); } @@ -3404,7 +3406,7 @@ /* mask unreachable track bits if we are forbidden to do 90deg turns */ TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); - if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) { + if (_settings.pf.pathfinder_for_trains != VPF_NTP && _settings.pf.forbid_90_deg) { bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track)); } @@ -3537,7 +3539,7 @@ { static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16; - if (_patches.servint_trains == 0 || !v->NeedsAutomaticServicing()) return; + if (_settings.vehicle.servint_trains == 0 || !v->NeedsAutomaticServicing()) return; if (v->IsInDepot()) { VehicleServiceInDepot(v); return; @@ -3612,7 +3614,7 @@ FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN && IsFrontEngine(v)) { /* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */ - if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) { + if (_settings.gui.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) { SetDParam(1, v->GetDisplayProfitThisYear()); SetDParam(0, v->unitnumber); AddNewsItem( @@ -3651,9 +3653,7 @@ FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN && IsFrontEngine(v)) { - Vehicle *u = v; - - BEGIN_ENUM_WAGONS(u) { + for (Vehicle *u = v; u != NULL; u = u->Next()) { if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one if (IsMultiheaded(u)) { @@ -3678,7 +3678,7 @@ ClearMultiheaded(u); } } - } END_ENUM_WAGONS(u) + } } } } @@ -3699,9 +3699,7 @@ FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN) { if (HasBit(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) { - Vehicle *u = v; - - BEGIN_ENUM_WAGONS(u) { + for (Vehicle *u = v; u != NULL; u = u->Next()) { const RailVehicleInfo *rvi = RailVehInfo(u->engine_type); ClrBit(u->subtype, 7); @@ -3740,7 +3738,7 @@ break; default: NOT_REACHED(); break; } - } END_ENUM_WAGONS(u) + } } } } diff -r 68a692eacf22 -r 67db0d431d5e src/train_gui.cpp --- a/src/train_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/train_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -18,6 +18,7 @@ #include "order_func.h" #include "engine_func.h" #include "engine_base.h" +#include "window_func.h" #include "table/sprites.h" #include "table/strings.h" @@ -27,8 +28,8 @@ if (!success) return; /* find a locomotive in the depot. */ - Vehicle *found = NULL; - Vehicle *v; + const Vehicle *found = NULL; + const Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == tile && @@ -43,7 +44,7 @@ found = GetLastVehicleInChain(found); /* put the new wagon at the end of the loco. */ DoCommandP(0, _new_vehicle_id | (found->index << 16), 0, NULL, CMD_MOVE_RAIL_VEHICLE); - RebuildVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); } } @@ -123,7 +124,7 @@ SetDParam(0, v->cargo_type); SetDParam(1, v->cargo.Count()); SetDParam(2, v->cargo.Source()); - SetDParam(3, _patches.freight_trains); + SetDParam(3, _settings.vehicle.freight_trains); str = FreightWagonMult(v->cargo_type) > 1 ? STR_FROM_MULT : STR_8813_FROM; } DrawString(x, y, str, TC_FROMSTRING); @@ -149,7 +150,7 @@ if (v->cargo_cap != 0) { SetDParam(0, v->cargo_type); SetDParam(1, v->cargo_cap); - SetDParam(2, _patches.freight_trains); + SetDParam(2, _settings.vehicle.freight_trains); DrawString(x, y, FreightWagonMult(v->cargo_type) > 1 ? STR_CAPACITY_MULT : STR_013F_CAPACITY, TC_FROMSTRING); } } @@ -248,7 +249,7 @@ SetDParam(1, act_cargo[i]); // {CARGO} #2 SetDParam(2, i); // {SHORTCARGO} #1 SetDParam(3, max_cargo[i]); // {SHORTCARGO} #2 - SetDParam(4, _patches.freight_trains); + SetDParam(4, _settings.vehicle.freight_trains); DrawString(x, y + 2, FreightWagonMult(i) > 1 ? STR_TOTAL_CAPACITY_MULT : STR_TOTAL_CAPACITY, TC_FROMSTRING); } } diff -r 68a692eacf22 -r 67db0d431d5e src/transparency_gui.cpp --- a/src/transparency_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/transparency_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -125,7 +125,6 @@ WC_TRANSPARENCY_TOOLBAR, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON, _transparency_widgets, - NULL }; void ShowTransparencyToolbar(void) diff -r 68a692eacf22 -r 67db0d431d5e src/tree_cmd.cpp --- a/src/tree_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/tree_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -112,7 +112,7 @@ */ static TreeType GetRandomTreeType(TileIndex tile, uint seed) { - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_TEMPERATE: return (TreeType)(seed * TREE_COUNT_TEMPERATE / 256 + TREE_TEMPERATE); @@ -249,7 +249,7 @@ if (CanPlantTreesOnTile(tile, true)) { PlaceTree(tile, r); - if (_patches.tree_placer != TP_IMPROVED) continue; + if (_settings.game_creation.tree_placer != TP_IMPROVED) continue; /* Place a number of trees based on the tile height. * This gives a cool effect of multiple trees close together. @@ -259,7 +259,7 @@ j = GetTileZ(tile) / TILE_HEIGHT * 2; while (j--) { /* Above snowline more trees! */ - if (_opt.landscape == LT_ARCTIC && ht > GetSnowLine()) { + if (_settings.game_creation.landscape == LT_ARCTIC && ht > GetSnowLine()) { PlaceTreeAtSameHeight(tile, ht); PlaceTreeAtSameHeight(tile, ht); }; @@ -270,7 +270,7 @@ } while (--i); /* place extra trees at rainforest area */ - if (_opt.landscape == LT_TROPIC) { + if (_settings.game_creation.landscape == LT_TROPIC) { i = ScaleByMapSize(15000); do { @@ -296,18 +296,18 @@ { uint i, total; - if (_patches.tree_placer == TP_NONE) return; + if (_settings.game_creation.tree_placer == TP_NONE) return; - if (_opt.landscape != LT_TOYLAND) PlaceMoreTrees(); + if (_settings.game_creation.landscape != LT_TOYLAND) PlaceMoreTrees(); - switch (_patches.tree_placer) { - case TP_ORIGINAL: i = _opt.landscape == LT_ARCTIC ? 15 : 6; break; - case TP_IMPROVED: i = _opt.landscape == LT_ARCTIC ? 4 : 2; break; + switch (_settings.game_creation.tree_placer) { + case TP_ORIGINAL: i = _settings.game_creation.landscape == LT_ARCTIC ? 15 : 6; break; + case TP_IMPROVED: i = _settings.game_creation.landscape == LT_ARCTIC ? 4 : 2; break; default: NOT_REACHED(); return; } total = ScaleByMapSize(1000); - if (_opt.landscape == LT_TROPIC) total += ScaleByMapSize(15000); + if (_settings.game_creation.landscape == LT_TROPIC) total += ScaleByMapSize(15000); total *= i; SetGeneratingWorldProgress(GWP_TREE, total); @@ -332,7 +332,7 @@ if (p2 >= MapSize()) return CMD_ERROR; /* Check the tree type. It can be random or some valid value within the current climate */ - if (p1 != (uint)-1 && p1 - _tree_base_by_landscape[_opt.landscape] >= _tree_count_by_landscape[_opt.landscape]) return CMD_ERROR; + if (p1 != (uint)-1 && p1 - _tree_base_by_landscape[_settings.game_creation.landscape] >= _tree_count_by_landscape[_settings.game_creation.landscape]) return CMD_ERROR; // make sure sx,sy are smaller than ex,ey ex = TileX(tile); @@ -390,7 +390,7 @@ } if (_game_mode != GM_EDITOR && IsValidPlayer(_current_player)) { - Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); + Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority); if (t != NULL) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM); } @@ -533,7 +533,7 @@ uint num; if (IsValidPlayer(_current_player)) { - Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority); + Town *t = ClosestTownFromTile(tile, _settings.economy.dist_local_authority); if (t != NULL) ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM); } @@ -560,7 +560,7 @@ td->str = tt == TREE_CACTUS ? STR_2810_CACTUS_PLANTS : STR_280E_TREES; } - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); } static void AnimateTile_Trees(TileIndex tile) @@ -626,7 +626,7 @@ if (GetTreeGround(tile) == TREE_GROUND_SHORE) { TileLoop_Water(tile); } else { - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_TROPIC: TileLoopTreesDesert(tile); break; case LT_ARCTIC: TileLoopTreesAlps(tile); break; } @@ -652,7 +652,7 @@ switch (GetTreeGrowth(tile)) { case 3: /* regular sized tree */ - if (_opt.landscape == LT_TROPIC && + if (_settings.game_creation.landscape == LT_TROPIC && GetTreeType(tile) != TREE_CACTUS && GetTropicZone(tile) == TROPICZONE_DESERT) { AddTreeGrowth(tile, 1); @@ -704,7 +704,7 @@ case TREE_GROUND_GRASS: MakeClear(tile, CLEAR_GRASS, GetTreeDensity(tile)); break; case TREE_GROUND_ROUGH: MakeClear(tile, CLEAR_ROUGH, 3); break; default: // snow or desert - MakeClear(tile, _opt.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW, GetTreeDensity(tile)); + MakeClear(tile, _settings.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW, GetTreeDensity(tile)); break; } } @@ -725,7 +725,7 @@ TreeType tree; /* place a tree at a random rainforest spot */ - if (_opt.landscape == LT_TROPIC && + if (_settings.game_creation.landscape == LT_TROPIC && (r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) && CanPlantTreesOnTile(tile, false) && (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) { diff -r 68a692eacf22 -r 67db0d431d5e src/tree_gui.cpp --- a/src/tree_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/tree_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -74,8 +74,8 @@ this->DrawWidgets(); - int i = this->base = _tree_base_by_landscape[_opt.landscape]; - int count = this->count = _tree_count_by_landscape[_opt.landscape]; + int i = this->base = _tree_base_by_landscape[_settings.game_creation.landscape]; + int count = this->count = _tree_count_by_landscape[_settings.game_creation.landscape]; int x = 18; int y = 54; @@ -92,10 +92,6 @@ virtual void OnClick(Point pt, int widget) { switch (widget) { - case BTW_CLOSE: - ResetObjectToPlace(); - break; - case BTW_TYPE_11: case BTW_TYPE_12: case BTW_TYPE_13: case BTW_TYPE_14: case BTW_TYPE_21: case BTW_TYPE_22: case BTW_TYPE_23: case BTW_TYPE_24: case BTW_TYPE_31: case BTW_TYPE_32: case BTW_TYPE_33: case BTW_TYPE_34: @@ -128,12 +124,12 @@ VpSetPlaceSizingLimit(20); } - virtual void OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt) + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) { VpSelectTilesWithMethod(pt.x, pt.y, select_method); } - virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) { if (pt.x != -1 && select_proc == DDSP_PLANT_TREES) { DoCommandP(end_tile, this->tree_to_plant, start_tile, NULL, @@ -179,7 +175,6 @@ WC_BUILD_TREES, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, _build_trees_widgets, - NULL }; void ShowBuildTreesToolbar() diff -r 68a692eacf22 -r 67db0d431d5e src/tunnelbridge_cmd.cpp --- a/src/tunnelbridge_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/tunnelbridge_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -169,7 +169,7 @@ if (b->avail_year > _cur_year) return false; max = b->max_length; - if (max >= 16 && _patches.longbridges) max = 100; + if (max >= 16 && _settings.construction.longbridges) max = 100; return b->min_length <= bridge_len && bridge_len <= max; } @@ -311,7 +311,7 @@ } else { /* Build a new bridge. */ - bool allow_on_slopes = (!_is_old_ai_player && _patches.build_on_slopes); + bool allow_on_slopes = (!_is_old_ai_player && _settings.construction.build_on_slopes); /* Try and clear the start landscape */ ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); @@ -576,7 +576,7 @@ /* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */ if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true; /* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */ - if (IsTileOwner(tile, OWNER_TOWN) && (_patches.extra_dynamite || _cheats.magic_bulldozer.value)) return true; + if (IsTileOwner(tile, OWNER_TOWN) && (_settings.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return true; return false; } @@ -1123,7 +1123,7 @@ DrawGroundSpriteAt(image, pal, x, y, z); } - } else if (_patches.bridge_pillars) { + } else if (_settings.gui.bridge_pillars) { /* draw pillars below for high bridges */ DrawBridgePillars(psid, ti, axis, type, x, y, z); } @@ -1188,7 +1188,7 @@ } else { //so it must be a bridge td->str = GetBridgeSpec(GetBridgeType(tile))->transport_name[GetTunnelBridgeTransportType(tile)]; } - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); } @@ -1200,7 +1200,7 @@ static void TileLoop_TunnelBridge(TileIndex tile) { bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile); - switch (_opt.landscape) { + switch (_settings.game_creation.landscape) { case LT_ARCTIC: if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) { SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert); @@ -1388,7 +1388,7 @@ static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) { - if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) { + if (_settings.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) { DiagDirection direction = GetTunnelBridgeDirection(tile); Axis axis = DiagDirToAxis(direction); CommandCost res; diff -r 68a692eacf22 -r 67db0d431d5e src/unmovable_cmd.cpp --- a/src/unmovable_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/unmovable_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -312,7 +312,7 @@ case UNMOVABLE_OWNED_LAND: td->str = STR_5805_COMPANY_OWNED_LAND; break; default: td->str = STR_5803_COMPANY_HEADQUARTERS; break; } - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); } static void AnimateTile_Unmovable(TileIndex tile) @@ -375,11 +375,11 @@ void GenerateUnmovables() { - if (_opt.landscape == LT_TOYLAND) return; + if (_settings.game_creation.landscape == LT_TOYLAND) return; /* add radio tower */ int radiotowser_to_build = ScaleByMapSize(15); // maximum number of radio towers on the map - int lighthouses_to_build = _opt.landscape == LT_TROPIC ? 0 : ScaleByMapSize1D((Random() & 3) + 7); + int lighthouses_to_build = _settings.game_creation.landscape == LT_TROPIC ? 0 : ScaleByMapSize1D((Random() & 3) + 7); SetGeneratingWorldProgress(GWP_UNMOVABLE, radiotowser_to_build + lighthouses_to_build); for (uint i = ScaleByMapSize(1000); i != 0; i--) { @@ -395,7 +395,7 @@ } } - if (_opt.landscape == LT_TROPIC) return; + if (_settings.game_creation.landscape == LT_TROPIC) return; /* add lighthouses */ uint maxx = MapMaxX(); diff -r 68a692eacf22 -r 67db0d431d5e src/vehicle.cpp --- a/src/vehicle.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/vehicle.cpp Tue May 27 00:50:55 2008 +0000 @@ -50,6 +50,7 @@ #include "depot_map.h" #include "animated_tile_func.h" #include "effectvehicle_base.h" +#include "core/alloc_func.hpp" #include "table/sprites.h" #include "table/strings.h" @@ -58,7 +59,7 @@ #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6)) VehicleID _vehicle_id_ctr_day; -Vehicle *_place_clicked_vehicle; +const Vehicle *_place_clicked_vehicle; VehicleID _new_vehicle_id; uint16 _returned_refit_capacity; @@ -126,20 +127,20 @@ { if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false; - if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) { + if (_settings.order.no_servicing_if_no_breakdowns && _settings.difficulty.vehicle_breakdowns == 0) { /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off. * Note: If servicing is enabled, we postpone replacement till next service. */ return EngineHasReplacementForPlayer(GetPlayer(this->owner), this->engine_type, this->group_id); } - return _patches.servint_ispercent ? + return _settings.vehicle.servint_ispercent ? (this->reliability < GetEngine(this->engine_type)->reliability * (100 - this->service_interval) / 100) : (this->date_of_last_service + this->service_interval < _date); } bool Vehicle::NeedsAutomaticServicing() const { - if (_patches.gotodepot && VehicleHasDepotOrders(this)) return false; + if (_settings.order.gotodepot && VehicleHasDepotOrders(this)) return false; if (this->current_order.IsType(OT_LOADING)) return false; if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false; return NeedsServicing(); @@ -531,6 +532,12 @@ return v; } +const Vehicle *GetLastVehicleInChain(const Vehicle *v) +{ + while (v->Next() != NULL) v = v->Next(); + return v; +} + uint CountVehiclesInChain(const Vehicle* v) { uint count = 0; @@ -906,7 +913,7 @@ if ((rel_old >> 8) != (rel >> 8)) InvalidateWindow(WC_VEHICLE_DETAILS, v->index); if (v->breakdown_ctr != 0 || v->vehstatus & VS_STOPPED || - _opt.diff.vehicle_breakdowns < 1 || + _settings.difficulty.vehicle_breakdowns < 1 || v->cur_speed < 5 || _game_mode == GM_MENU) { return; } @@ -923,7 +930,7 @@ if (v->type == VEH_SHIP) rel += 0x6666; /* reduced breakdowns? */ - if (_opt.diff.vehicle_breakdowns == 1) rel += 0x6666; + if (_settings.difficulty.vehicle_breakdowns == 1) rel += 0x6666; /* check if to break down */ if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) { @@ -982,9 +989,7 @@ */ CommandCost CmdMassStartStopVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - Vehicle **vl = NULL; - uint16 engine_list_length = 0; - uint16 engine_count = 0; + VehicleList list; CommandCost return_value = CMD_ERROR; uint stop_command; VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5); @@ -1003,14 +1008,14 @@ uint32 id = p1; uint16 window_type = p2 & VLW_MASK; - engine_count = GenerateVehicleSortList((const Vehicle***)&vl, &engine_list_length, vehicle_type, _current_player, id, window_type); + GenerateVehicleSortList(&list, vehicle_type, _current_player, id, window_type); } else { /* Get the list of vehicles in the depot */ - BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, NULL, NULL, NULL); + BuildDepotVehicleList(vehicle_type, tile, &list, NULL); } - for (uint i = 0; i < engine_count; i++) { - const Vehicle *v = vl[i]; + for (uint i = 0; i < list.Length(); i++) { + const Vehicle *v = list[i]; if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue; @@ -1032,7 +1037,6 @@ } } - free(vl); return return_value; } @@ -1044,15 +1048,10 @@ */ CommandCost CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - Vehicle **engines = NULL; - Vehicle **wagons = NULL; - uint16 engine_list_length = 0; - uint16 engine_count = 0; - uint16 wagon_list_length = 0; - uint16 wagon_count = 0; + VehicleList list; CommandCost cost(EXPENSES_NEW_VEHICLES); - uint sell_command, total_number_vehicles; + uint sell_command; VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); switch (vehicle_type) { @@ -1064,26 +1063,13 @@ } /* Get the list of vehicles in the depot */ - BuildDepotVehicleList(vehicle_type, tile, &engines, &engine_list_length, &engine_count, - &wagons, &wagon_list_length, &wagon_count); - - total_number_vehicles = engine_count + wagon_count; - for (uint i = 0; i < total_number_vehicles; i++) { - const Vehicle *v; - - if (i < engine_count) { - v = engines[i]; - } else { - v = wagons[i - engine_count]; - } - - CommandCost ret = DoCommand(tile, v->index, 1, flags, sell_command); - + BuildDepotVehicleList(vehicle_type, tile, &list, &list); + + for (uint i = 0; i < list.Length(); i++) { + CommandCost ret = DoCommand(tile, list[i]->index, 1, flags, sell_command); if (CmdSucceeded(ret)) cost.AddCost(ret); } - free(engines); - free(wagons); if (cost.GetCost() == 0) return CMD_ERROR; // no vehicles to sell return cost; } @@ -1099,9 +1085,7 @@ */ CommandCost CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { - Vehicle **vl = NULL; - uint16 engine_list_length = 0; - uint16 engine_count = 0; + VehicleList list; CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES); VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); bool all_or_nothing = HasBit(p2, 0); @@ -1109,10 +1093,10 @@ if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR; /* Get the list of vehicles in the depot */ - BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, &vl, &engine_list_length, &engine_count); - - for (uint i = 0; i < engine_count; i++) { - Vehicle *v = vl[i]; + BuildDepotVehicleList(vehicle_type, tile, &list, &list); + + for (uint i = 0; i < list.Length(); i++) { + Vehicle *v = (Vehicle*)list[i]; /* Ensure that the vehicle completely in the depot */ if (!v->IsInDepot()) continue; @@ -1127,22 +1111,18 @@ * We should never reach this if DC_EXEC is set since then it should * have failed the estimation guess. */ assert(!(flags & DC_EXEC)); - /* Now we will have to return an error. - * This goto will leave the loop and it's ok to do so because - * there is no point in the rest of the loop. */ - goto error; + /* Now we will have to return an error. */ + return CMD_ERROR; } } } if (cost.GetCost() == 0) { -error: /* Either we didn't replace anything or something went wrong. * Either way we want to return an error and not execute this command. */ cost = CMD_ERROR; } - free(vl); return cost; } @@ -1311,100 +1291,55 @@ return total_cost; } - -/* Extend the list size for BuildDepotVehicleList() */ -static inline void ExtendVehicleListSize(const Vehicle ***engine_list, uint16 *engine_list_length, uint16 step_size) -{ - *engine_list_length = min(*engine_list_length + step_size, GetMaxVehicleIndex() + 1); - *engine_list = ReallocT(*engine_list, *engine_list_length); -} - -/** Generates a list of vehicles inside a depot - * Will enlarge allocated space for the list if they are too small, so it's ok to call with (pointer to NULL array, pointer to uninitised uint16, pointer to 0) - * If one of the lists is not needed (say wagons when finding ships), all the pointers regarding that list should be set to NULL - * @param type Type of vehicle - * @param tile The tile the depot is located in - * @param ***engine_list Pointer to a pointer to an array of vehicles in the depot (old list is freed and a new one is malloced) - * @param *engine_list_length Allocated size of engine_list. Needs to be set to 0 when engine_list points to a NULL array - * @param *engine_count The number of engines stored in the list - * @param ***wagon_list Pointer to a pointer to an array of free wagons in the depot (old list is freed and a new one is malloced) - * @param *wagon_list_length Allocated size of wagon_list. Needs to be set to 0 when wagon_list points to a NULL array - * @param *wagon_count The number of engines stored in the list +/** + * Generate a list of vehicles inside a depot. + * @param type Type of vehicle + * @param tile The tile the depot is located on + * @param engines Pointer to list to add vehicles to + * @param wagons Pointer to list to add wagons to (can be NULL) */ -void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count) +void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engines, VehicleList *wagons) { - Vehicle *v; - - /* This function should never be called without an array to store results */ - assert(!(engine_list == NULL && type != VEH_TRAIN)); - assert(!(type == VEH_TRAIN && engine_list == NULL && wagon_list == NULL)); - - /* Both array and the length should either be NULL to disable the list or both should not be NULL */ - assert((engine_list == NULL && engine_list_length == NULL) || (engine_list != NULL && engine_list_length != NULL)); - assert((wagon_list == NULL && wagon_list_length == NULL) || (wagon_list != NULL && wagon_list_length != NULL)); - - assert(!(engine_list != NULL && engine_count == NULL)); - assert(!(wagon_list != NULL && wagon_count == NULL)); - - if (engine_count != NULL) *engine_count = 0; - if (wagon_count != NULL) *wagon_count = 0; - - switch (type) { - case VEH_TRAIN: - FOR_ALL_VEHICLES(v) { - if (v->tile == tile && v->type == VEH_TRAIN && v->u.rail.track == TRACK_BIT_DEPOT) { - if (IsFrontEngine(v)) { - if (engine_list == NULL) continue; - if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); - (*engine_list)[(*engine_count)++] = v; - } else if (IsFreeWagon(v)) { - if (wagon_list == NULL) continue; - if (*wagon_count == *wagon_list_length) ExtendVehicleListSize((const Vehicle***)wagon_list, wagon_list_length, 25); - (*wagon_list)[(*wagon_count)++] = v; - } + engines->Clear(); + if (wagons != NULL && wagons != engines) wagons->Clear(); + + const Vehicle *v; + FOR_ALL_VEHICLES(v) { + /* General tests for all vehicle types */ + if (v->type != type) continue; + if (v->tile != tile) continue; + + switch (type) { + case VEH_TRAIN: + if (v->u.rail.track != TRACK_BIT_DEPOT) continue; + if (wagons != NULL && IsFreeWagon(v)) { + *wagons->Append() = v; + continue; } - } - break; - - case VEH_ROAD: - FOR_ALL_VEHICLES(v) { - if (v->tile == tile && v->type == VEH_ROAD && v->IsInDepot() && IsRoadVehFront(v)) { - if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); - (*engine_list)[(*engine_count)++] = v; - } - } - break; - - case VEH_SHIP: - FOR_ALL_VEHICLES(v) { - if (v->tile == tile && v->type == VEH_SHIP && v->IsInDepot()) { - if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); - (*engine_list)[(*engine_count)++] = v; - } - } - break; - - case VEH_AIRCRAFT: - FOR_ALL_VEHICLES(v) { - if (v->tile == tile && - v->type == VEH_AIRCRAFT && IsNormalAircraft(v) && - v->IsInDepot()) { - if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); - (*engine_list)[(*engine_count)++] = v; - } - } - break; - - default: NOT_REACHED(); + break; + + default: + if (!v->IsInDepot()) continue; + break; + } + + if (!v->IsPrimaryVehicle()) continue; + + *engines->Append() = v; } + + /* Ensure the lists are not wasting too much space. If the lists are fresh + * (i.e. built within a command) then this will actually do nothing. */ + engines->Compact(); + if (wagons != NULL && wagons != engines) wagons->Compact(); } /** - * @param sort_list list to store the list in. Either NULL or the length length_of_array tells - * @param length_of_array informs the length allocated for sort_list. This is not the same as the number of vehicles in the list. Needs to be 0 when sort_list is NULL - * @param type type of vehicle - * @param owner PlayerID of owner to generate a list for - * @param index This parameter has different meanings depending on window_type + * Generate a list of vehicles based on window type. + * @param list Pointer to list to add vehicles to + * @param type Type of vehicle + * @param owner Player to generate list for + * @param index This parameter has different meanings depending on window_type *
    *
  • VLW_STATION_LIST: index of station to generate a list for
  • *
  • VLW_SHARED_ORDERS: index of order to generate a list for
  • @@ -1412,83 +1347,71 @@ *
  • VLW_DEPOT_LIST: TileIndex of the depot/hangar to make the list for
  • *
  • VLW_GROUP_LIST: index of group to generate a list for
  • *
- * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h - * @return the number of vehicles added to the list + * @param window_type The type of window the list is for, using the VLW_ flags in vehicle_gui.h */ -uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type) +void GenerateVehicleSortList(VehicleList *list, VehicleType type, PlayerID owner, uint32 index, uint16 window_type) { - uint n = 0; + list->Clear(); + const Vehicle *v; switch (window_type) { - case VLW_STATION_LIST: { + case VLW_STATION_LIST: FOR_ALL_VEHICLES(v) { if (v->type == type && v->IsPrimaryVehicle()) { const Order *order; FOR_VEHICLE_ORDERS(v, order) { if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == index) { - if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 50); - (*sort_list)[n++] = v; + *list->Append() = v; break; } } } } break; - } - - case VLW_SHARED_ORDERS: { + + case VLW_SHARED_ORDERS: FOR_ALL_VEHICLES(v) { /* Find a vehicle with the order in question */ - if (v->orders != NULL && v->orders->index == index) break; - } - - if (v != NULL && v->orders != NULL && v->orders->index == index) { - /* Only try to make the list if we found a vehicle using the order in question */ - for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) { - if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25); - (*sort_list)[n++] = v; + if (v->orders != NULL && v->orders->index == index) { + /* Add all vehicles from this vehicle's shared order list */ + for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) { + *list->Append() = v; + } + break; } } break; - } - - case VLW_STANDARD: { + + case VLW_STANDARD: FOR_ALL_VEHICLES(v) { if (v->type == type && v->owner == owner && v->IsPrimaryVehicle()) { - /* TODO find a better estimate on the total number of vehicles for current player */ - if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4); - (*sort_list)[n++] = v; + *list->Append() = v; } } break; - } - - case VLW_DEPOT_LIST: { + + case VLW_DEPOT_LIST: FOR_ALL_VEHICLES(v) { if (v->type == type && v->IsPrimaryVehicle()) { const Order *order; FOR_VEHICLE_ORDERS(v, order) { if (order->IsType(OT_GOTO_DEPOT) && order->GetDestination() == index) { - if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25); - (*sort_list)[n++] = v; + *list->Append() = v; break; } } } } break; - } case VLW_GROUP_LIST: FOR_ALL_VEHICLES(v) { if (v->type == type && v->IsPrimaryVehicle() && v->owner == owner && v->group_id == index) { - if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4); - - (*sort_list)[n++] = v; + *list->Append() = v; } } break; @@ -1496,16 +1419,7 @@ default: NOT_REACHED(); break; } - if ((n + 100) < *length_of_array) { - /* We allocated way too much for sort_list. - * Now we will reduce how much we allocated. - * We will still make it have room for 50 extra vehicles to prevent having - * to move the whole array if just one vehicle is added later */ - *length_of_array = n + 50; - *sort_list = ReallocT(*sort_list, (*length_of_array) * sizeof((*sort_list)[0])); - } - - return n; + list->Compact(); } /** @@ -1519,14 +1433,13 @@ */ CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id) { - const Vehicle **sort_list = NULL; - uint16 array_length = 0; - - uint n = GenerateVehicleSortList(&sort_list, &array_length, type, owner, id, vlw_flag); + VehicleList list; + + GenerateVehicleSortList(&list, type, owner, id, vlw_flag); /* Send all the vehicles to a depot */ - for (uint i = 0; i < n; i++) { - const Vehicle *v = sort_list[i]; + for (uint i = 0; i < list.Length(); i++) { + const Vehicle *v = list[i]; CommandCost ret = DoCommand(v->tile, v->index, (service ? 1 : 0) | DEPOT_DONT_CANCEL, flags, GetCmdSendToDepot(type)); /* Return 0 if DC_EXEC is not set this is a valid goto depot command) @@ -1534,12 +1447,10 @@ * and we will issue the command. We can now safely quit the loop, knowing * it will succeed at least once. With DC_EXEC we really need to send them to the depot */ if (CmdSucceeded(ret) && !(flags & DC_EXEC)) { - free((void*)sort_list); return CommandCost(); } } - free((void*)sort_list); return (flags & DC_EXEC) ? CommandCost() : CMD_ERROR; } @@ -1733,7 +1644,7 @@ if (flags & DC_EXEC) { free(v->name); v->name = strdup(_cmd_text); - ResortVehicleLists(); + InvalidateWindowClassesData(WC_TRAINS_LIST, 1); MarkWholeScreenDirty(); } @@ -1915,10 +1826,10 @@ static UnitID gmax = 0; switch (type) { - case VEH_TRAIN: max = _patches.max_trains; break; - case VEH_ROAD: max = _patches.max_roadveh; break; - case VEH_SHIP: max = _patches.max_ships; break; - case VEH_AIRCRAFT: max = _patches.max_aircraft; break; + case VEH_TRAIN: max = _settings.vehicle.max_trains; break; + case VEH_ROAD: max = _settings.vehicle.max_roadveh; break; + case VEH_SHIP: max = _settings.vehicle.max_ships; break; + case VEH_AIRCRAFT: max = _settings.vehicle.max_aircraft; break; default: NOT_REACHED(); } @@ -1968,14 +1879,14 @@ assert(IsPlayerBuildableVehicleType(type)); if (!IsValidPlayer(_current_player)) return false; - if (_patches.always_build_infrastructure) return true; + if (_settings.gui.always_build_infrastructure) return true; UnitID max; switch (type) { - case VEH_TRAIN: max = _patches.max_trains; break; - case VEH_ROAD: max = _patches.max_roadveh; break; - case VEH_SHIP: max = _patches.max_ships; break; - case VEH_AIRCRAFT: max = _patches.max_aircraft; break; + case VEH_TRAIN: max = _settings.vehicle.max_trains; break; + case VEH_ROAD: max = _settings.vehicle.max_roadveh; break; + case VEH_SHIP: max = _settings.vehicle.max_ships; break; + case VEH_AIRCRAFT: max = _settings.vehicle.max_aircraft; break; default: NOT_REACHED(); } @@ -2007,7 +1918,7 @@ /* The default livery is always available for use, but its in_use flag determines * whether any _other_ liveries are in use. */ - if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) { + if (p->livery[LS_DEFAULT].in_use && (_settings.gui.liveries == 2 || (_settings.gui.liveries == 1 && player == _local_player))) { /* Determine the livery scheme to use */ switch (GetEngine(engine_type)->type) { default: NOT_REACHED(); @@ -2576,7 +2487,7 @@ /* Not the first call for this tick, or still loading */ if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || - (_patches.timetabling && this->current_order_time < wait_time)) return; + (_settings.order.timetabling && this->current_order_time < wait_time)) return; this->PlayLeaveStationSound(); @@ -2807,11 +2718,11 @@ { if (!ContainsBackup()) return v; if (v != NULL) { - ChangeVehicleViewWindow(v, INVALID_VEHICLE); + ChangeVehicleViewWindow(v->index, INVALID_VEHICLE); DoCommand(0, v->index, 1, DC_EXEC, GetCmdSellVeh(v)); } v = RestoreBackupVehicle(this->vehicles, p); - ChangeVehicleViewWindow(INVALID_VEHICLE, v); + ChangeVehicleViewWindow(INVALID_VEHICLE, v->index); if (orders != NULL) RestoreVehicleOrdersBruteForce(v, orders); if (economy != NULL) economy->Restore(); /* If we stored cargo as well then we should restore it. */ diff -r 68a692eacf22 -r 67db0d431d5e src/vehicle_base.h --- a/src/vehicle_base.h Mon May 26 20:45:25 2008 +0000 +++ b/src/vehicle_base.h Tue May 27 00:50:55 2008 +0000 @@ -566,9 +566,6 @@ void Tick() {} }; -#define BEGIN_ENUM_WAGONS(v) do { -#define END_ENUM_WAGONS(v) } while ((v = v->Next()) != NULL); - static inline VehicleID GetMaxVehicleIndex() { /* TODO - This isn't the real content of the function, but diff -r 68a692eacf22 -r 67db0d431d5e src/vehicle_func.h --- a/src/vehicle_func.h Mon May 26 20:45:25 2008 +0000 +++ b/src/vehicle_func.h Tue May 27 00:50:55 2008 +0000 @@ -24,6 +24,7 @@ void VehicleServiceInDepot(Vehicle *v); void VehiclePositionChanged(Vehicle *v); Vehicle *GetLastVehicleInChain(Vehicle *v); +const Vehicle *GetLastVehicleInChain(const Vehicle *v); uint CountVehiclesInChain(const Vehicle *v); bool IsEngineCountable(const Vehicle *v); void DeleteVehicleChain(Vehicle *v); @@ -67,8 +68,8 @@ void TrainPowerChanged(Vehicle *v); Money GetTrainRunningCost(const Vehicle *v); -uint GenerateVehicleSortList(const Vehicle*** sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type); -void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count); +void GenerateVehicleSortList(VehicleList *list, VehicleType type, PlayerID owner, uint32 index, uint16 window_type); +void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine_list, VehicleList *wagon_list); CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id); void VehicleEnterDepot(Vehicle *v); @@ -173,7 +174,7 @@ void StopAllVehicles(); extern VehicleID _vehicle_id_ctr_day; -extern Vehicle *_place_clicked_vehicle; +extern const Vehicle *_place_clicked_vehicle; extern VehicleID _new_vehicle_id; extern uint16 _returned_refit_capacity; diff -r 68a692eacf22 -r 67db0d431d5e src/vehicle_gui.cpp --- a/src/vehicle_gui.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/vehicle_gui.cpp Tue May 27 00:50:55 2008 +0000 @@ -86,54 +86,13 @@ INVALID_STRING_ID }; -/** - * Set sort list flag for all vehicle list windows - * @param sl_flag Sort list flag to set - */ -static void SetVehicleListsFlag(SortListFlags sl_flag) -{ - Window* const *wz; - - FOR_ALL_WINDOWS(wz) { - Window *w = *wz; - - switch (w->window_class) { - case WC_TRAINS_LIST: - case WC_ROADVEH_LIST: - case WC_SHIPS_LIST: - case WC_AIRCRAFT_LIST: - dynamic_cast(w)->vehicles.flags |= sl_flag; - w->SetDirty(); - break; - - default: break; - } - } -} - -/** - * Rebuild all vehicle list windows - */ -void RebuildVehicleLists() -{ - SetVehicleListsFlag(VL_REBUILD); -} - -/** - * Resort all vehicle list windows - */ -void ResortVehicleLists() -{ - SetVehicleListsFlag(VL_RESORT); -} - void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type) { if (!(vl->vehicles.flags & VL_REBUILD)) return; DEBUG(misc, 3, "Building vehicle list for player %d at station %d", owner, index); - vl->vehicles.list_length = GenerateVehicleSortList(&vl->vehicles.sort_list, &vl->vehicles.list_length, vl->vehicle_type, owner, index, window_type); + GenerateVehicleSortList(&vl->vehicles, vl->vehicle_type, owner, index, window_type); vl->vehicles.flags &= ~VL_REBUILD; vl->vehicles.flags |= VL_RESORT; @@ -151,17 +110,18 @@ _last_vehicle[0] = _last_vehicle[1] = NULL; _internal_sort_order = (vl->vehicles.flags & VL_DESC) != 0; - qsort((void*)vl->vehicles.sort_list, vl->vehicles.list_length, sizeof(vl->vehicles.sort_list[0]), + qsort((void*)vl->vehicles.Begin(), vl->vehicles.Length(), sizeof(vl->vehicles.Begin()), _vehicle_sorter[vl->vehicles.sort_type]); vl->vehicles.resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; vl->vehicles.flags &= ~VL_RESORT; } -void DepotSortList(Vehicle **v, uint16 length) +void DepotSortList(VehicleList *list) { _internal_sort_order = 0; - qsort((void*)v, length, sizeof(v[0]), _vehicle_sorter[0]); + if (list->Length() < 2) return; + qsort((void*)list->Begin(), list->Length(), sizeof(list->Begin()), _vehicle_sorter[0]); } /** draw the vehicle profit button in the vehicle list window. */ @@ -473,7 +433,6 @@ WC_VEHICLE_REFIT, WC_VEHICLE_VIEW, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _vehicle_refit_widgets, - NULL }; /** Show the refit window for a vehicle @@ -847,8 +806,6 @@ PlayerID player = (PlayerID)GB(this->window_number, 0, 8); this->vehicle_type = (VehicleType)GB(this->window_number, 11, 5); - this->vehicles.list_length = 0; - this->vehicles.sort_list = NULL; this->caption_color = player; /* Hide the widgets that we will not use in this window @@ -966,7 +923,6 @@ ~VehicleListWindow() { - free((void*)this->vehicles.sort_list); } virtual void OnPaint() @@ -981,12 +937,12 @@ BuildVehicleList(this, owner, index, window_type); SortVehicleList(this); - SetVScrollCount(this, this->vehicles.list_length); + SetVScrollCount(this, this->vehicles.Length()); /* draw the widgets */ switch (window_type) { case VLW_SHARED_ORDERS: /* Shared Orders */ - if (this->vehicles.list_length == 0) { + if (this->vehicles.Length() == 0) { /* We can't open this window without vehicles using this order * and we should close the window when deleting the order */ NOT_REACHED(); @@ -1022,7 +978,7 @@ default: NOT_REACHED(); break; } - this->SetWidgetsDisabledState(this->vehicles.list_length == 0, + this->SetWidgetsDisabledState(this->vehicles.Length() == 0, VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN, VLW_WIDGET_STOP_ALL, VLW_WIDGET_START_ALL, @@ -1035,9 +991,9 @@ /* draw arrow pointing up/down for ascending/descending sorting */ this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP); - max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.list_length); + max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.Length()); for (i = this->vscroll.pos; i < max; ++i) { - const Vehicle *v = this->vehicles.sort_list[i]; + const Vehicle *v = this->vehicles[i]; StringID str; SetDParam(0, v->GetDisplayProfitThisYear()); @@ -1090,9 +1046,9 @@ id_v += this->vscroll.pos; - if (id_v >= this->vehicles.list_length) return; // click out of list bound + if (id_v >= this->vehicles.Length()) return; // click out of list bound - v = this->vehicles.sort_list[id_v]; + v = this->vehicles[id_v]; ShowVehicleViewWindow(v); } break; @@ -1141,7 +1097,7 @@ } break; case VLW_WIDGET_MANAGE_VEHICLES_DROPDOWN: - assert(this->vehicles.list_length != 0); + assert(this->vehicles.Length() != 0); switch (index) { case 0: /* Replace window */ @@ -1187,6 +1143,11 @@ this->vscroll.cap += delta.y / (int)this->resize.step_height; this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1; } + + virtual void OnInvalidateData(int data) + { + this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT); + } }; static const WindowDesc _player_vehicle_list_train_desc = { @@ -1194,7 +1155,6 @@ WC_TRAINS_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _vehicle_list_widgets, - NULL }; static const WindowDesc _player_vehicle_list_road_veh_desc = { @@ -1202,7 +1162,6 @@ WC_ROADVEH_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _vehicle_list_widgets, - NULL }; static const WindowDesc _player_vehicle_list_ship_desc = { @@ -1210,7 +1169,6 @@ WC_SHIPS_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _vehicle_list_widgets, - NULL }; static const WindowDesc _player_vehicle_list_aircraft_desc = { @@ -1218,7 +1176,6 @@ WC_AIRCRAFT_LIST, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _vehicle_list_widgets, - NULL }; static void ShowVehicleListWindowLocal(PlayerID player, uint16 VLW_flag, VehicleType vehicle_type, uint16 unique_number) @@ -1260,12 +1217,12 @@ void ShowVehicleListWindow(PlayerID player, VehicleType vehicle_type) { - /* If _patches.advanced_vehicle_list > 1, display the Advanced list - * if _patches.advanced_vehicle_list == 1, display Advanced list only for local player + /* If _settings.gui.advanced_vehicle_list > 1, display the Advanced list + * if _settings.gui.advanced_vehicle_list == 1, display Advanced list only for local player * if _ctrl_pressed, do the opposite action (Advanced list x Normal list) */ - if ((_patches.advanced_vehicle_list > (uint)(player != _local_player)) != _ctrl_pressed) { + if ((_settings.gui.advanced_vehicle_list > (uint)(player != _local_player)) != _ctrl_pressed) { ShowPlayerGroup(player, vehicle_type); } else { ShowVehicleListWindowLocal(player, VLW_STANDARD, vehicle_type, 0); @@ -1442,6 +1399,8 @@ this->caption_color = v->owner; this->tab = 0; + + this->FindWindowPlacementAndResize(desc); } /** Checks whether service interval is enabled for the vehicle. */ @@ -1449,10 +1408,10 @@ { switch (vehicle_type) { default: NOT_REACHED(); - case VEH_TRAIN: return _patches.servint_trains != 0; break; - case VEH_ROAD: return _patches.servint_roadveh != 0; break; - case VEH_SHIP: return _patches.servint_ships != 0; break; - case VEH_AIRCRAFT: return _patches.servint_aircraft != 0; break; + case VEH_TRAIN: return _settings.vehicle.servint_trains != 0; break; + case VEH_ROAD: return _settings.vehicle.servint_roadveh != 0; break; + case VEH_SHIP: return _settings.vehicle.servint_ships != 0; break; + case VEH_AIRCRAFT: return _settings.vehicle.servint_aircraft != 0; break; } return false; // kill a compiler warning } @@ -1524,7 +1483,7 @@ SetDParam(1, v->u.rail.cached_power); SetDParam(0, v->u.rail.cached_weight); SetDParam(3, v->u.rail.cached_max_te / 1000); - DrawString(2, 25, (_patches.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ? + DrawString(2, 25, (_settings.vehicle.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ? STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE : STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, TC_FROMSTRING); break; @@ -1552,7 +1511,7 @@ /* Draw service interval text */ SetDParam(0, v->service_interval); SetDParam(1, v->date_of_last_service); - DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _patches.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING); + DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _settings.vehicle.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING); switch (v->type) { case VEH_TRAIN: @@ -1649,7 +1608,6 @@ WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, _vehicle_details_widgets, - NULL }; /** Shows the vehicle details window of the given vehicle. */ @@ -1685,15 +1643,12 @@ }; -static void VehicleViewWndProc(Window *w, WindowEvent *e); - /** Vehicle view window descriptor for all vehicles but trains. */ static const WindowDesc _vehicle_view_desc = { WDP_AUTO, WDP_AUTO, 250, 116, 250, 116, WC_VEHICLE_VIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _vehicle_view_widgets, - VehicleViewWndProc }; /** Vehicle view window descriptor for trains. Only minimum_height and @@ -1704,7 +1659,6 @@ WC_VEHICLE_VIEW, WC_NONE, WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE, _vehicle_view_widgets, - VehicleViewWndProc }; @@ -1730,300 +1684,6 @@ static const int VV_INITIAL_VIEWPORT_HEIGHT = 84; static const int VV_INITIAL_VIEWPORT_HEIGHT_TRAIN = 102; -/** Shows the vehicle view window of the given vehicle. */ -void ShowVehicleViewWindow(const Vehicle *v) -{ - Window *w = AllocateWindowDescFront((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index); - - if (w != NULL) { - w->caption_color = v->owner; - InitializeWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH, - (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT, - w->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]); - } -} - -/** Initialize a newly created vehicle view window */ -static void CreateVehicleViewWindow(Window *w) -{ - const Vehicle *v = GetVehicle(w->window_number); - - /* - * fill in data and tooltip codes for the widgets and - * move some of the buttons for trains - */ - switch (v->type) { - case VEH_TRAIN: - w->widget[VVW_WIDGET_CAPTION].data = STR_882E; - - w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_8846_CURRENT_TRAIN_ACTION_CLICK; - - w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_8848_CENTER_MAIN_VIEW_ON_TRAIN; - - w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_TRAIN_TODEPOT; - w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_8849_SEND_TRAIN_TO_DEPOT; - - w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_RAIL_REFIT_VEHICLE_TO_CARRY; - - w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_8847_SHOW_TRAIN_S_ORDERS; - - w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_884C_SHOW_TRAIN_DETAILS; - - w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_TRAIN; - w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_TRAIN_INFO; - - w->widget[VVW_WIDGET_TURN_AROUND].tooltips = STR_884B_REVERSE_DIRECTION_OF_TRAIN; - - - /* due to more buttons we must modify the layout a bit for trains */ - w->widget[VVW_WIDGET_PANEL].bottom = 121; - w->widget[VVW_WIDGET_VIEWPORT].bottom = 119; - - w->widget[VVW_WIDGET_START_STOP_VEH].top = 122; - w->widget[VVW_WIDGET_START_STOP_VEH].bottom = 133; - - w->widget[VVW_WIDGET_REFIT_VEH].top = 68; - w->widget[VVW_WIDGET_REFIT_VEH].bottom = 85; - - w->widget[VVW_WIDGET_SHOW_ORDERS].top = 86; - w->widget[VVW_WIDGET_SHOW_ORDERS].bottom = 103; - - w->widget[VVW_WIDGET_SHOW_DETAILS].top = 104; - w->widget[VVW_WIDGET_SHOW_DETAILS].bottom = 121; - - w->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].top = 122; - w->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].bottom = 121; - - w->widget[VVW_WIDGET_RESIZE].top = 122; - w->widget[VVW_WIDGET_RESIZE].bottom = 133; - - w->widget[VVW_WIDGET_TURN_AROUND].top = 68; - w->widget[VVW_WIDGET_TURN_AROUND].bottom = 85; - break; - - case VEH_ROAD: - w->widget[VVW_WIDGET_CAPTION].data = STR_9002; - - w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_901C_CURRENT_VEHICLE_ACTION; - - w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE; - - w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_ROADVEH_TODEPOT; - w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_901F_SEND_VEHICLE_TO_DEPOT; - - w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY; - - w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_901D_SHOW_VEHICLE_S_ORDERS; - - w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_9021_SHOW_ROAD_VEHICLE_DETAILS; - - w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_ROADVEH; - w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_ROAD_VEHICLE_INFO; - - w->SetWidgetHiddenState(VVW_WIDGET_FORCE_PROCEED, true); - break; - - case VEH_SHIP: - w->widget[VVW_WIDGET_CAPTION].data = STR_980F; - - w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_9827_CURRENT_SHIP_ACTION_CLICK; - - w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_9829_CENTER_MAIN_VIEW_ON_SHIP; - - w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_SHIP_TODEPOT; - w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_982A_SEND_SHIP_TO_DEPOT; - - w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_983A_REFIT_CARGO_SHIP_TO_CARRY; - - w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_9828_SHOW_SHIP_S_ORDERS; - - w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_982B_SHOW_SHIP_DETAILS; - - w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_SHIP; - w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_SHIP_INFO; - - w->SetWidgetsHiddenState(true, - VVW_WIDGET_TURN_AROUND, - VVW_WIDGET_FORCE_PROCEED, - WIDGET_LIST_END); - break; - - case VEH_AIRCRAFT: - w->widget[VVW_WIDGET_CAPTION].data = STR_A00A; - - w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_A027_CURRENT_AIRCRAFT_ACTION; - - w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT; - - w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_AIRCRAFT_TODEPOT; - w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_A02A_SEND_AIRCRAFT_TO_HANGAR; - - w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_A03B_REFIT_AIRCRAFT_TO_CARRY; - - w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_A028_SHOW_AIRCRAFT_S_ORDERS; - - w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_A02B_SHOW_AIRCRAFT_DETAILS; - - w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_AIRCRAFT; - w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_AIRCRAFT_INFO; - - w->SetWidgetsHiddenState(true, - VVW_WIDGET_TURN_AROUND, - VVW_WIDGET_FORCE_PROCEED, - WIDGET_LIST_END); - break; - - default: NOT_REACHED(); - } -} - -/** Checks whether the vehicle may be refitted at the moment.*/ -static bool IsVehicleRefitable(const Vehicle *v) -{ - /* Why is this so different for different vehicles? - * Does maybe work one solution for all? - */ - switch (v->type) { - case VEH_TRAIN: return false; - case VEH_ROAD: return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot(); - case VEH_SHIP: return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot(); - case VEH_AIRCRAFT: return v->IsStoppedInDepot(); - default: NOT_REACHED(); - } -} - -/** Message strings for heading to depot indexed by vehicle type. */ -static const StringID _heading_for_depot_strings[] = { - STR_HEADING_FOR_TRAIN_DEPOT, - STR_HEADING_FOR_ROAD_DEPOT, - STR_HEADING_FOR_SHIP_DEPOT, - STR_HEADING_FOR_HANGAR, -}; - -/** Message strings for heading to depot and servicing indexed by vehicle type. */ -static const StringID _heading_for_depot_service_strings[] = { - STR_HEADING_FOR_TRAIN_DEPOT_SERVICE, - STR_HEADING_FOR_ROAD_DEPOT_SERVICE, - STR_HEADING_FOR_SHIP_DEPOT_SERVICE, - STR_HEADING_FOR_HANGAR_SERVICE, -}; - -/** Repaint vehicle view window. */ -static void DrawVehicleViewWindow(Window *w) -{ - const Vehicle *v = GetVehicle(w->window_number); - StringID str; - bool is_localplayer = v->owner == _local_player; - bool refitable_and_stopped_in_depot = IsVehicleRefitable(v); - - w->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localplayer); - w->SetWidgetDisabledState(VVW_WIDGET_REFIT_VEH, - !refitable_and_stopped_in_depot || !is_localplayer); - w->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localplayer); - - if (v->type == VEH_TRAIN) { - w->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localplayer); - w->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localplayer); - - /* Cargo refit button is disabled, until we know we can enable it below. */ - - if (is_localplayer) { - /* See if any vehicle can be refitted */ - for (const Vehicle *u = v; u != NULL; u = u->Next()) { - if (EngInfo(u->engine_type)->refit_mask != 0 || - (RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) { - w->EnableWidget(VVW_WIDGET_REFIT_VEH); - /* We have a refittable carriage, bail out */ - break; - } - } - } - } - - /* draw widgets & caption */ - SetDParam(0, v->index); - w->DrawWidgets(); - - if (v->vehstatus & VS_CRASHED) { - str = STR_8863_CRASHED; - } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary? - str = STR_885C_BROKEN_DOWN; - } else if (v->vehstatus & VS_STOPPED) { - if (v->type == VEH_TRAIN) { - if (v->cur_speed == 0) { - if (v->u.rail.cached_power == 0) { - str = STR_TRAIN_NO_POWER; - } else { - str = STR_8861_STOPPED; - } - } else { - SetDParam(0, v->GetDisplaySpeed()); - str = STR_TRAIN_STOPPING + _patches.vehicle_speed; - } - } else { // no train - str = STR_8861_STOPPED; - } - } else { // vehicle is in a "normal" state, show current order - switch (v->current_order.GetType()) { - case OT_GOTO_STATION: { - SetDParam(0, v->current_order.GetDestination()); - SetDParam(1, v->GetDisplaySpeed()); - str = STR_HEADING_FOR_STATION + _patches.vehicle_speed; - } break; - - case OT_GOTO_DEPOT: { - if (v->type == VEH_AIRCRAFT) { - /* Aircrafts always go to a station, even if you say depot */ - SetDParam(0, v->current_order.GetDestination()); - SetDParam(1, v->GetDisplaySpeed()); - } else { - Depot *depot = GetDepot(v->current_order.GetDestination()); - SetDParam(0, depot->town_index); - SetDParam(1, v->GetDisplaySpeed()); - } - if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) { - str = _heading_for_depot_strings[v->type] + _patches.vehicle_speed; - } else { - str = _heading_for_depot_service_strings[v->type] + _patches.vehicle_speed; - } - } break; - - case OT_LOADING: - str = STR_882F_LOADING_UNLOADING; - break; - - case OT_GOTO_WAYPOINT: { - assert(v->type == VEH_TRAIN); - SetDParam(0, v->current_order.GetDestination()); - str = STR_HEADING_FOR_WAYPOINT + _patches.vehicle_speed; - SetDParam(1, v->GetDisplaySpeed()); - break; - } - - case OT_LEAVESTATION: - if (v->type != VEH_AIRCRAFT) { - str = STR_LEAVING; - break; - } - /* fall-through if aircraft. Does this even happen? */ - - default: - if (v->num_orders == 0) { - str = STR_NO_ORDERS + _patches.vehicle_speed; - SetDParam(0, v->GetDisplaySpeed()); - } else { - str = STR_EMPTY; - } - break; - } - } - - /* draw the flag plus orders */ - DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, 2, w->widget[VVW_WIDGET_START_STOP_VEH].top + 1); - DrawStringCenteredTruncated(w->widget[VVW_WIDGET_START_STOP_VEH].left + 8, w->widget[VVW_WIDGET_START_STOP_VEH].right, w->widget[VVW_WIDGET_START_STOP_VEH].top + 1, str, TC_FROMSTRING); - w->DrawViewport(); -} - /** Command indices for the _vehicle_command_translation_table. */ enum VehicleCommandTranslation { VCT_CMD_START_STOP = 0, @@ -2061,104 +1721,389 @@ }, }; -/** Window event hook for vehicle view. */ -static void VehicleViewWndProc(Window *w, WindowEvent *e) +/** Checks whether the vehicle may be refitted at the moment.*/ +static bool IsVehicleRefitable(const Vehicle *v) { - switch (e->event) { - case WE_CREATE: - CreateVehicleViewWindow(w); - break; - - case WE_PAINT: - DrawVehicleViewWindow(w); - break; + /* Why is this so different for different vehicles? + * Does maybe work one solution for all? + */ + switch (v->type) { + case VEH_TRAIN: return false; + case VEH_ROAD: return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot(); + case VEH_SHIP: return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot(); + case VEH_AIRCRAFT: return v->IsStoppedInDepot(); + default: NOT_REACHED(); + } +} - case WE_CLICK: { - const Vehicle *v = GetVehicle(w->window_number); +struct VehicleViewWindow : Window { + VehicleViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number) + { + const Vehicle *v = GetVehicle(this->window_number); - switch (e->we.click.widget) { - case VVW_WIDGET_START_STOP_VEH: /* start stop */ - DoCommandP(v->tile, v->index, 0, NULL, - _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type]); - break; - case VVW_WIDGET_CENTER_MAIN_VIEH: {/* center main view */ - const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0); - /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */ - if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) { - mainwindow->viewport->follow_vehicle = v->index; + this->caption_color = v->owner; + InitializeWindowViewport(this, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH, + (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT, + this->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]); + + /* + * fill in data and tooltip codes for the widgets and + * move some of the buttons for trains + */ + switch (v->type) { + case VEH_TRAIN: + this->widget[VVW_WIDGET_CAPTION].data = STR_882E; + + this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_8846_CURRENT_TRAIN_ACTION_CLICK; + + this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_8848_CENTER_MAIN_VIEW_ON_TRAIN; + + this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_TRAIN_TODEPOT; + this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_8849_SEND_TRAIN_TO_DEPOT; + + this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_RAIL_REFIT_VEHICLE_TO_CARRY; + + this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_8847_SHOW_TRAIN_S_ORDERS; + + this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_884C_SHOW_TRAIN_DETAILS; + + this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_TRAIN; + this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_TRAIN_INFO; + + this->widget[VVW_WIDGET_TURN_AROUND].tooltips = STR_884B_REVERSE_DIRECTION_OF_TRAIN; + + + /* due to more buttons we must modify the layout a bit for trains */ + this->widget[VVW_WIDGET_PANEL].bottom = 121; + this->widget[VVW_WIDGET_VIEWPORT].bottom = 119; + + this->widget[VVW_WIDGET_START_STOP_VEH].top = 122; + this->widget[VVW_WIDGET_START_STOP_VEH].bottom = 133; + + this->widget[VVW_WIDGET_REFIT_VEH].top = 68; + this->widget[VVW_WIDGET_REFIT_VEH].bottom = 85; + + this->widget[VVW_WIDGET_SHOW_ORDERS].top = 86; + this->widget[VVW_WIDGET_SHOW_ORDERS].bottom = 103; + + this->widget[VVW_WIDGET_SHOW_DETAILS].top = 104; + this->widget[VVW_WIDGET_SHOW_DETAILS].bottom = 121; + + this->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].top = 122; + this->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].bottom = 121; + + this->widget[VVW_WIDGET_RESIZE].top = 122; + this->widget[VVW_WIDGET_RESIZE].bottom = 133; + + this->widget[VVW_WIDGET_TURN_AROUND].top = 68; + this->widget[VVW_WIDGET_TURN_AROUND].bottom = 85; + break; + + case VEH_ROAD: + this->widget[VVW_WIDGET_CAPTION].data = STR_9002; + + this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_901C_CURRENT_VEHICLE_ACTION; + + this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE; + + this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_ROADVEH_TODEPOT; + this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_901F_SEND_VEHICLE_TO_DEPOT; + + this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY; + + this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_901D_SHOW_VEHICLE_S_ORDERS; + + this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_9021_SHOW_ROAD_VEHICLE_DETAILS; + + this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_ROADVEH; + this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_ROAD_VEHICLE_INFO; + + this->SetWidgetHiddenState(VVW_WIDGET_FORCE_PROCEED, true); + break; + + case VEH_SHIP: + this->widget[VVW_WIDGET_CAPTION].data = STR_980F; + + this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_9827_CURRENT_SHIP_ACTION_CLICK; + + this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_9829_CENTER_MAIN_VIEW_ON_SHIP; + + this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_SHIP_TODEPOT; + this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_982A_SEND_SHIP_TO_DEPOT; + + this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_983A_REFIT_CARGO_SHIP_TO_CARRY; + + this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_9828_SHOW_SHIP_S_ORDERS; + + this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_982B_SHOW_SHIP_DETAILS; + + this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_SHIP; + this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_SHIP_INFO; + + this->SetWidgetsHiddenState(true, + VVW_WIDGET_TURN_AROUND, + VVW_WIDGET_FORCE_PROCEED, + WIDGET_LIST_END); + break; + + case VEH_AIRCRAFT: + this->widget[VVW_WIDGET_CAPTION].data = STR_A00A; + + this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_A027_CURRENT_AIRCRAFT_ACTION; + + this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT; + + this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_AIRCRAFT_TODEPOT; + this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_A02A_SEND_AIRCRAFT_TO_HANGAR; + + this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_A03B_REFIT_AIRCRAFT_TO_CARRY; + + this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_A028_SHOW_AIRCRAFT_S_ORDERS; + + this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_A02B_SHOW_AIRCRAFT_DETAILS; + + this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_AIRCRAFT; + this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_AIRCRAFT_INFO; + + this->SetWidgetsHiddenState(true, + VVW_WIDGET_TURN_AROUND, + VVW_WIDGET_FORCE_PROCEED, + WIDGET_LIST_END); + break; + + default: NOT_REACHED(); + } + + this->FindWindowPlacementAndResize(desc); + } + + ~VehicleViewWindow() + { + DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number); + DeleteWindowById(WC_VEHICLE_REFIT, this->window_number); + DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number); + DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number); + } + + virtual void OnPaint() + { + /** Message strings for heading to depot indexed by vehicle type. */ + static const StringID _heading_for_depot_strings[] = { + STR_HEADING_FOR_TRAIN_DEPOT, + STR_HEADING_FOR_ROAD_DEPOT, + STR_HEADING_FOR_SHIP_DEPOT, + STR_HEADING_FOR_HANGAR, + }; + + /** Message strings for heading to depot and servicing indexed by vehicle type. */ + static const StringID _heading_for_depot_service_strings[] = { + STR_HEADING_FOR_TRAIN_DEPOT_SERVICE, + STR_HEADING_FOR_ROAD_DEPOT_SERVICE, + STR_HEADING_FOR_SHIP_DEPOT_SERVICE, + STR_HEADING_FOR_HANGAR_SERVICE, + }; + + const Vehicle *v = GetVehicle(this->window_number); + StringID str; + bool is_localplayer = v->owner == _local_player; + bool refitable_and_stopped_in_depot = IsVehicleRefitable(v); + + this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localplayer); + this->SetWidgetDisabledState(VVW_WIDGET_REFIT_VEH, + !refitable_and_stopped_in_depot || !is_localplayer); + this->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localplayer); + + if (v->type == VEH_TRAIN) { + this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localplayer); + this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localplayer); + + /* Cargo refit button is disabled, until we know we can enable it below. */ + + if (is_localplayer) { + /* See if any vehicle can be refitted */ + for (const Vehicle *u = v; u != NULL; u = u->Next()) { + if (EngInfo(u->engine_type)->refit_mask != 0 || + (RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) { + this->EnableWidget(VVW_WIDGET_REFIT_VEH); + /* We have a refittable carriage, bail out */ + break; + } + } + } + } + + /* draw widgets & caption */ + SetDParam(0, v->index); + this->DrawWidgets(); + + if (v->vehstatus & VS_CRASHED) { + str = STR_8863_CRASHED; + } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary? + str = STR_885C_BROKEN_DOWN; + } else if (v->vehstatus & VS_STOPPED) { + if (v->type == VEH_TRAIN) { + if (v->cur_speed == 0) { + if (v->u.rail.cached_power == 0) { + str = STR_TRAIN_NO_POWER; } else { - ScrollMainWindowTo(v->x_pos, v->y_pos); + str = STR_8861_STOPPED; + } + } else { + SetDParam(0, v->GetDisplaySpeed()); + str = STR_TRAIN_STOPPING + _settings.gui.vehicle_speed; + } + } else { // no train + str = STR_8861_STOPPED; + } + } else { // vehicle is in a "normal" state, show current order + switch (v->current_order.GetType()) { + case OT_GOTO_STATION: { + SetDParam(0, v->current_order.GetDestination()); + SetDParam(1, v->GetDisplaySpeed()); + str = STR_HEADING_FOR_STATION + _settings.gui.vehicle_speed; + } break; + + case OT_GOTO_DEPOT: { + if (v->type == VEH_AIRCRAFT) { + /* Aircrafts always go to a station, even if you say depot */ + SetDParam(0, v->current_order.GetDestination()); + SetDParam(1, v->GetDisplaySpeed()); + } else { + Depot *depot = GetDepot(v->current_order.GetDestination()); + SetDParam(0, depot->town_index); + SetDParam(1, v->GetDisplaySpeed()); + } + if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) { + str = _heading_for_depot_strings[v->type] + _settings.gui.vehicle_speed; + } else { + str = _heading_for_depot_service_strings[v->type] + _settings.gui.vehicle_speed; } } break; - case VVW_WIDGET_GOTO_DEPOT: /* goto hangar */ - DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL, - _vehicle_command_translation_table[VCT_CMD_GOTO_DEPOT][v->type]); - break; - case VVW_WIDGET_REFIT_VEH: /* refit */ - ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID); - break; - case VVW_WIDGET_SHOW_ORDERS: /* show orders */ - if (_ctrl_pressed) { - ShowTimetableWindow(v); - } else { - ShowOrdersWindow(v); - } + case OT_LOADING: + str = STR_882F_LOADING_UNLOADING; break; - case VVW_WIDGET_SHOW_DETAILS: /* show details */ - ShowVehicleDetailsWindow(v); - break; - case VVW_WIDGET_CLONE_VEH: /* clone vehicle */ - DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle, - _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type]); + + case OT_GOTO_WAYPOINT: { + assert(v->type == VEH_TRAIN); + SetDParam(0, v->current_order.GetDestination()); + str = STR_HEADING_FOR_WAYPOINT + _settings.gui.vehicle_speed; + SetDParam(1, v->GetDisplaySpeed()); break; - case VVW_WIDGET_TURN_AROUND: /* turn around */ - assert(v->type == VEH_TRAIN || v->type == VEH_ROAD); - DoCommandP(v->tile, v->index, 0, NULL, - _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]); - break; - case VVW_WIDGET_FORCE_PROCEED: /* force proceed */ - assert(v->type == VEH_TRAIN); - DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL)); + } + + case OT_LEAVESTATION: + if (v->type != VEH_AIRCRAFT) { + str = STR_LEAVING; + break; + } + /* fall-through if aircraft. Does this even happen? */ + + default: + if (v->num_orders == 0) { + str = STR_NO_ORDERS + _settings.gui.vehicle_speed; + SetDParam(0, v->GetDisplaySpeed()); + } else { + str = STR_EMPTY; + } break; } - } break; - - case WE_RESIZE: - w->viewport->width += e->we.sizing.diff.x; - w->viewport->height += e->we.sizing.diff.y; - w->viewport->virtual_width += e->we.sizing.diff.x; - w->viewport->virtual_height += e->we.sizing.diff.y; - break; - - case WE_DESTROY: - DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number); - DeleteWindowById(WC_VEHICLE_REFIT, w->window_number); - DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number); - DeleteWindowById(WC_VEHICLE_TIMETABLE, w->window_number); - break; + } - case WE_TICK: { - const Vehicle *v = GetVehicle(w->window_number); - bool veh_stopped = v->IsStoppedInDepot(); + /* draw the flag plus orders */ + DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, 2, this->widget[VVW_WIDGET_START_STOP_VEH].top + 1); + DrawStringCenteredTruncated(this->widget[VVW_WIDGET_START_STOP_VEH].left + 8, this->widget[VVW_WIDGET_START_STOP_VEH].right, this->widget[VVW_WIDGET_START_STOP_VEH].top + 1, str, TC_FROMSTRING); + this->DrawViewport(); + } - /* Widget VVW_WIDGET_GOTO_DEPOT must be hidden if the vehicle is already - * stopped in depot. - * Widget VVW_WIDGET_CLONE_VEH should then be shown, since cloning is - * allowed only while in depot and stopped. - * This sytem allows to have two buttons, on top of each other. - * The same system applies to widget VVW_WIDGET_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/ - if (veh_stopped != w->IsWidgetHidden(VVW_WIDGET_GOTO_DEPOT) || veh_stopped == w->IsWidgetHidden(VVW_WIDGET_CLONE_VEH)) { - w->SetWidgetHiddenState( VVW_WIDGET_GOTO_DEPOT, veh_stopped); // send to depot - w->SetWidgetHiddenState(VVW_WIDGET_CLONE_VEH, !veh_stopped); // clone - if (v->type == VEH_ROAD || v->type == VEH_TRAIN) { - w->SetWidgetHiddenState( VVW_WIDGET_REFIT_VEH, !veh_stopped); // refit - w->SetWidgetHiddenState(VVW_WIDGET_TURN_AROUND, veh_stopped); // force turn around + virtual void OnClick(Point pt, int widget) + { + const Vehicle *v = GetVehicle(this->window_number); + + switch (widget) { + case VVW_WIDGET_START_STOP_VEH: // start stop + DoCommandP(v->tile, v->index, 0, NULL, + _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type]); + break; + case VVW_WIDGET_CENTER_MAIN_VIEH: {/* center main view */ + const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0); + /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */ + if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) { + mainwindow->viewport->follow_vehicle = v->index; + } else { + ScrollMainWindowTo(v->x_pos, v->y_pos); } - w->SetDirty(); + } break; + + case VVW_WIDGET_GOTO_DEPOT: // goto hangar + DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL, + _vehicle_command_translation_table[VCT_CMD_GOTO_DEPOT][v->type]); + break; + case VVW_WIDGET_REFIT_VEH: // refit + ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID); + break; + case VVW_WIDGET_SHOW_ORDERS: // show orders + if (_ctrl_pressed) { + ShowTimetableWindow(v); + } else { + ShowOrdersWindow(v); + } + break; + case VVW_WIDGET_SHOW_DETAILS: // show details + ShowVehicleDetailsWindow(v); + break; + case VVW_WIDGET_CLONE_VEH: // clone vehicle + DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle, + _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type]); + break; + case VVW_WIDGET_TURN_AROUND: // turn around + assert(v->type == VEH_TRAIN || v->type == VEH_ROAD); + DoCommandP(v->tile, v->index, 0, NULL, + _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]); + break; + case VVW_WIDGET_FORCE_PROCEED: // force proceed + assert(v->type == VEH_TRAIN); + DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL)); + break; + } + } + + virtual void OnResize(Point new_size, Point delta) + { + this->viewport->width += delta.x; + this->viewport->height += delta.y; + this->viewport->virtual_width += delta.x; + this->viewport->virtual_height += delta.y; + } + + virtual void OnTick() + { + const Vehicle *v = GetVehicle(this->window_number); + bool veh_stopped = v->IsStoppedInDepot(); + + /* Widget VVW_WIDGET_GOTO_DEPOT must be hidden if the vehicle is already + * stopped in depot. + * Widget VVW_WIDGET_CLONE_VEH should then be shown, since cloning is + * allowed only while in depot and stopped. + * This sytem allows to have two buttons, on top of each other. + * The same system applies to widget VVW_WIDGET_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/ + if (veh_stopped != this->IsWidgetHidden(VVW_WIDGET_GOTO_DEPOT) || veh_stopped == this->IsWidgetHidden(VVW_WIDGET_CLONE_VEH)) { + this->SetWidgetHiddenState( VVW_WIDGET_GOTO_DEPOT, veh_stopped); // send to depot + this->SetWidgetHiddenState(VVW_WIDGET_CLONE_VEH, !veh_stopped); // clone + if (v->type == VEH_ROAD || v->type == VEH_TRAIN) { + this->SetWidgetHiddenState( VVW_WIDGET_REFIT_VEH, !veh_stopped); // refit + this->SetWidgetHiddenState(VVW_WIDGET_TURN_AROUND, veh_stopped); // force turn around } - } break; + this->SetDirty(); + } } +}; + + +/** Shows the vehicle view window of the given vehicle. */ +void ShowVehicleViewWindow(const Vehicle *v) +{ + AllocateWindowDescFront((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index); } void DrawVehicleImage(const Vehicle *v, int x, int y, VehicleID selection, int count, int skip) diff -r 68a692eacf22 -r 67db0d431d5e src/vehicle_gui.h --- a/src/vehicle_gui.h Mon May 26 20:45:25 2008 +0000 +++ b/src/vehicle_gui.h Tue May 27 00:50:55 2008 +0000 @@ -11,7 +11,6 @@ #include "order_type.h" #include "station_type.h" #include "engine_type.h" -#include "vehicle_base.h" void DrawVehicleProfitButton(const Vehicle *v, int x, int y); void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order); @@ -90,21 +89,6 @@ * For ease of use it can be called with both Vehicle pointers and VehicleIDs. */ void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index); -static inline void ChangeVehicleViewWindow(const Vehicle *from_v, VehicleID to_index) -{ - ChangeVehicleViewWindow(from_v->index, to_index); -} - -static inline void ChangeVehicleViewWindow(VehicleID from_index, const Vehicle *to_v) -{ - ChangeVehicleViewWindow(from_index, to_v->index); -} - -static inline void ChangeVehicleViewWindow(const Vehicle *from_v, const Vehicle *to_v) -{ - ChangeVehicleViewWindow(from_v->index, to_v->index); -} - static inline uint GetVehicleListHeight(VehicleType type) { return (type == VEH_TRAIN || type == VEH_ROAD) ? 14 : 24; @@ -149,8 +133,6 @@ extern Sorting _sorting; /* sorter stuff */ -void RebuildVehicleLists(); -void ResortVehicleLists(); void SortVehicleList(VehicleListBase *vl); void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type); diff -r 68a692eacf22 -r 67db0d431d5e src/vehicle_type.h --- a/src/vehicle_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/vehicle_type.h Tue May 27 00:50:55 2008 +0000 @@ -6,6 +6,7 @@ #define VEHICLE_TYPE_H #include "core/enum_type.hpp" +#include "misc/smallvec.h" typedef uint16 VehicleID; @@ -56,4 +57,6 @@ DEPOT_COMMAND_MASK = 0xF, }; +typedef SmallVector VehicleList; + #endif /* VEHICLE_TYPE_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/video/cocoa/event.mm --- a/src/video/cocoa/event.mm Mon May 26 20:45:25 2008 +0000 +++ b/src/video/cocoa/event.mm Tue May 27 00:50:55 2008 +0000 @@ -288,9 +288,9 @@ } if (_current_mods & NSShiftKeyMask) key |= WKC_SHIFT; - if (_current_mods & NSControlKeyMask) key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META); + if (_current_mods & NSControlKeyMask) key |= (_settings.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META); if (_current_mods & NSAlternateKeyMask) key |= WKC_ALT; - if (_current_mods & NSCommandKeyMask) key |= (_patches.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL); + if (_current_mods & NSCommandKeyMask) key |= (_settings.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL); return key << 16; } @@ -459,8 +459,8 @@ case NSLeftMouseDown: { uint32 keymask = 0; - if (_patches.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask; - if (_patches.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask; + if (_settings.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask; + if (_settings.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask; pt = _cocoa_subdriver->GetMouseLocation(event); @@ -602,8 +602,8 @@ } /* else: deltaY was 0.0 and we don't want to do anything */ /* Set the scroll count for scrollwheel scrolling */ - _cursor.h_wheel -= (int)([ event deltaX ]* 5 * _patches.scrollwheel_multiplier); - _cursor.v_wheel -= (int)([ event deltaY ]* 5 * _patches.scrollwheel_multiplier); + _cursor.h_wheel -= (int)([ event deltaX ]* 5 * _settings.gui.scrollwheel_multiplier); + _cursor.v_wheel -= (int)([ event deltaY ]* 5 * _settings.gui.scrollwheel_multiplier); break; default: @@ -671,7 +671,7 @@ bool old_ctrl_pressed = _ctrl_pressed; - _ctrl_pressed = !!(_current_mods & ( _patches.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); + _ctrl_pressed = !!(_current_mods & ( _settings.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask)); _shift_pressed = !!(_current_mods & NSShiftKeyMask); if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); diff -r 68a692eacf22 -r 67db0d431d5e src/video/dedicated_v.cpp --- a/src/video/dedicated_v.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/video/dedicated_v.cpp Tue May 27 00:50:55 2008 +0000 @@ -11,7 +11,7 @@ #include "../gfx_func.h" #include "../network/network.h" #include "../network/network_internal.h" -#include "../console.h" +#include "../console_func.h" #include "../variables.h" #include "../genworld.h" #include "../fileio.h" diff -r 68a692eacf22 -r 67db0d431d5e src/viewport.cpp --- a/src/viewport.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/viewport.cpp Tue May 27 00:50:55 2008 +0000 @@ -1045,7 +1045,7 @@ right > t->sign.left && left < t->sign.left + t->sign.width_1) { AddStringToDraw(t->sign.left + 1, t->sign.top + 1, - _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL, + _settings.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL, t->index, t->population); } } @@ -1061,7 +1061,7 @@ right > t->sign.left && left < t->sign.left + t->sign.width_1 * 2) { AddStringToDraw(t->sign.left + 1, t->sign.top + 1, - _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL, + _settings.gui.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL, t->index, t->population); } } @@ -1616,7 +1616,7 @@ int delta_y = w->viewport->dest_scrollpos_y - w->viewport->scrollpos_y; if (delta_x != 0 || delta_y != 0) { - if (_patches.smooth_scroll) { + if (_settings.gui.smooth_scroll) { int max_scroll = ScaleByMapSize1D(512); /* Not at our desired positon yet... */ w->viewport->scrollpos_x += Clamp(delta_x / 4, -max_scroll, max_scroll); @@ -2535,7 +2535,7 @@ } } - if (_patches.measure_tooltip) { + if (_settings.gui.measure_tooltip) { TileIndex t0 = TileVirtXY(thd->selstart.x, thd->selstart.y); TileIndex t1 = TileVirtXY(x, y); uint distance = DistanceManhattan(t0, t1) + 1; @@ -2615,7 +2615,7 @@ style = HT_DIR_X; calc_heightdiff_single_direction:; - if (_patches.measure_tooltip) { + if (_settings.gui.measure_tooltip) { TileIndex t0 = TileVirtXY(sx, sy); TileIndex t1 = TileVirtXY(x, y); uint distance = DistanceManhattan(t0, t1) + 1; @@ -2643,7 +2643,7 @@ y = sy + Clamp(y - sy, -limit, limit); } /* Fallthrough */ case VPM_X_AND_Y: { /* drag an X by Y area */ - if (_patches.measure_tooltip) { + if (_settings.gui.measure_tooltip) { static const StringID measure_strings_area[] = { STR_NULL, STR_NULL, STR_MEASURE_AREA, STR_MEASURE_AREA_HEIGHTDIFF }; @@ -2686,7 +2686,10 @@ _thd.selend.y = y; } -/** while dragging */ +/** + * Handle the mouse while dragging for placement/resizing. + * @return Boolean whether search for a handler should continue + */ bool VpHandlePlaceSizingDrag() { if (_special_mouse_mode != WSM_SIZING) return true; diff -r 68a692eacf22 -r 67db0d431d5e src/water_cmd.cpp --- a/src/water_cmd.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/water_cmd.cpp Tue May 27 00:50:55 2008 +0000 @@ -738,7 +738,7 @@ default: assert(0); break; } - td->owner = GetTileOwner(tile); + td->owner[0] = GetTileOwner(tile); } static void AnimateTile_Water(TileIndex tile) @@ -774,7 +774,7 @@ } /* if non-uniform stations are disabled, flood some train in this train station (if there is any) */ - if (!_patches.nonuniform_stations && IsTileType(tile, MP_STATION) && GetStationType(tile) == STATION_RAIL) { + if (!_settings.station.nonuniform_stations && IsTileType(tile, MP_STATION) && GetStationType(tile) == STATION_RAIL) { const Station *st = GetStationByTile(tile); BEGIN_TILE_LOOP(t, st->trainst_w, st->trainst_h, st->train_tile) @@ -823,39 +823,36 @@ //TODO: airport->delta_z no longer used. need to get actual height of individual tile in layout //if (v->z_pos != airport->delta_z + 1) return; } - Vehicle *u; if (v->type != VEH_AIRCRAFT) v = v->First(); - u = v; /* crash all wagons, and count passengers */ - BEGIN_ENUM_WAGONS(v) - if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.Count(); - v->vehstatus |= VS_CRASHED; - MarkSingleVehicleDirty(v); - END_ENUM_WAGONS(v) - - v = u; + for (Vehicle *u = v; u != NULL; u = u->Next()) { + if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count(); + u->vehstatus |= VS_CRASHED; + MarkSingleVehicleDirty(u); + } switch (v->type) { default: NOT_REACHED(); case VEH_TRAIN: if (IsFrontEngine(v)) pass += 4; // driver v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast + InvalidateWindowClassesData(WC_TRAINS_LIST, 0); break; case VEH_ROAD: if (IsRoadVehFront(v)) pass += 1; // driver v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast + InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); break; case VEH_AIRCRAFT: pass += 2; // driver v->u.air.crashed_counter = 9000; // max 10000, disappear pretty fast + InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0); break; } - - RebuildVehicleLists(); } else { return; } diff -r 68a692eacf22 -r 67db0d431d5e src/waypoint.cpp --- a/src/waypoint.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/waypoint.cpp Tue May 27 00:50:55 2008 +0000 @@ -210,7 +210,7 @@ tileh = GetTileSlope(tile, NULL); if (tileh != SLOPE_FLAT && - (!_patches.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) { + (!_settings.construction.build_on_slopes || IsSteepSlope(tileh) || !(tileh & (0x3 << axis)) || !(tileh & ~(0x3 << axis)))) { return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); } diff -r 68a692eacf22 -r 67db0d431d5e src/widgets/dropdown.cpp --- a/src/widgets/dropdown.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/widgets/dropdown.cpp Tue May 27 00:50:55 2008 +0000 @@ -72,8 +72,9 @@ bool drag_mode; int scrolling; - DropdownWindow(int x, int y, int width, int height, const Widget *widget) : Window(x, y, width, height, NULL, WC_DROPDOWN_MENU, widget) + DropdownWindow(int x, int y, int width, int height, const Widget *widget) : Window(x, y, width, height, WC_DROPDOWN_MENU, widget) { + this->FindWindowPlacementAndResize(width, height); } ~DropdownWindow() diff -r 68a692eacf22 -r 67db0d431d5e src/window.cpp --- a/src/window.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/window.cpp Tue May 27 00:50:55 2008 +0000 @@ -8,7 +8,8 @@ #include "debug.h" #include "player_func.h" #include "gfx_func.h" -#include "console.h" +#include "console_func.h" +#include "console_gui.h" #include "viewport_func.h" #include "variables.h" #include "genworld.h" @@ -48,169 +49,6 @@ byte _special_mouse_mode; -/** - * Call the window event handler for handling event \a e. - * This is a temporary helper functions that will be removed - * once all windows that still rely on WindowEvent and - * WindowEventCodes have been rewritten to use the 'OnXXX' - * event handlers. - * @param e Window event to handle - */ -void Window::HandleWindowEvent(WindowEvent *e) -{ - if (wndproc != NULL) wndproc(this, e); -} - -void Window::OnPaint() -{ - WindowEvent e; - e.event = WE_PAINT; - this->HandleWindowEvent(&e); -} - -bool Window::OnKeyPress(uint16 key, uint16 keycode) -{ - WindowEvent e; - e.event = WE_KEYPRESS; - e.we.keypress.key = key; - e.we.keypress.keycode = keycode; - e.we.keypress.cont = true; - this->HandleWindowEvent(&e); - - return e.we.keypress.cont; -} - -bool Window::OnCTRLStateChange() -{ - WindowEvent e; - e.event = WE_CTRL_CHANGED; - e.we.ctrl.cont = true; - this->HandleWindowEvent(&e); - - return e.we.ctrl.cont; -} - -void Window::OnClick(Point pt, int widget) -{ - WindowEvent e; - e.event = WE_CLICK; - e.we.click.pt = pt; - e.we.click.widget = widget; - this->HandleWindowEvent(&e); -} - -void Window::OnMouseLoop() -{ - WindowEvent e; - e.event = WE_MOUSELOOP; - this->HandleWindowEvent(&e); -} - -void Window::OnTick() -{ - WindowEvent e; - e.event = WE_TICK; - this->HandleWindowEvent(&e); -} - -void Window::OnHundredthTick() -{ - WindowEvent e; - e.event = WE_100_TICKS; - this->HandleWindowEvent(&e); -} - -void Window::OnTimeout() -{ - WindowEvent e; - e.event = WE_TIMEOUT; - this->HandleWindowEvent(&e); -} - -void Window::OnResize(Point new_size, Point delta) -{ - WindowEvent e; - e.event = WE_RESIZE; - e.we.sizing.size = new_size; - e.we.sizing.diff = delta; - this->HandleWindowEvent(&e); -} - -void Window::OnDropdownSelect(int widget, int index) -{ - WindowEvent e; - e.event = WE_DROPDOWN_SELECT; - e.we.dropdown.button = widget; - e.we.dropdown.index = index; - this->HandleWindowEvent(&e); -} - -void Window::OnQueryTextFinished(char *str) -{ - WindowEvent e; - e.event = WE_ON_EDIT_TEXT; - e.we.edittext.str = str; - this->HandleWindowEvent(&e); -} - -void Window::OnInvalidateData(int data) -{ - WindowEvent e; - e.event = WE_INVALIDATE_DATA; - e.we.invalidate.data = data; - this->HandleWindowEvent(&e); -} - -void Window::OnPlaceObject(Point pt, TileIndex tile) -{ - WindowEvent e; - e.event = WE_PLACE_OBJ; - e.we.place.pt = pt; - e.we.place.tile = tile; - this->HandleWindowEvent(&e); -} - -void Window::OnPlaceObjectAbort() -{ - WindowEvent e; - e.event = WE_ABORT_PLACE_OBJ; - this->HandleWindowEvent(&e); -} - - -void Window::OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt) -{ - WindowEvent e; - e.event = WE_PLACE_DRAG; - e.we.place.select_method = select_method; - e.we.place.select_proc = select_proc; - e.we.place.pt = pt; - this->HandleWindowEvent(&e); -} - -void Window::OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) -{ - WindowEvent e; - e.event = WE_PLACE_MOUSEUP; - e.we.place.select_method = select_method; - e.we.place.select_proc = select_proc; - e.we.place.pt = pt; - e.we.place.tile = end_tile; - e.we.place.starttile = start_tile; - this->HandleWindowEvent(&e); -} - -void Window::OnPlacePresize(Point pt, TileIndex tile) -{ - WindowEvent e; - e.event = WE_PLACE_PRESIZE; - e.we.place.pt = pt; - e.we.place.tile = tile; - this->HandleWindowEvent(&e); -} - - - void CDECL Window::SetWidgetsDisabledState(bool disab_stat, int widgets, ...) { va_list wdg_list; @@ -581,9 +419,6 @@ child = FindChildWindow(this); } - WindowEvent e; - e.event = WE_DESTROY; - this->HandleWindowEvent(&e); if (this->viewport != NULL) DeleteWindowViewport(this); this->SetDirty(); @@ -831,14 +666,13 @@ * @param y offset in pixels from the top of the screen * @param min_width minimum width in pixels of the window * @param min_height minimum height in pixels of the window - * @param *proc see WindowProc function to call when any messages/updates happen to the window * @param cls see WindowClass class of the window, used for identification and grouping * @param *widget see Widget pointer to the window layout and various elements * @param window_number number being assigned to the new window * @return Window pointer of the newly created window */ void Window::Initialize(int x, int y, int min_width, int min_height, - WindowProc *proc, WindowClass cls, const Widget *widget, int window_number) + WindowClass cls, const Widget *widget, int window_number) { /* We have run out of windows, close one and use that as the place for our new one */ if (_last_z_window == endof(_z_windows)) { @@ -855,7 +689,6 @@ this->top = y; this->width = min_width; this->height = min_height; - this->wndproc = proc; AssignWidgetToWindow(this, widget); this->resize.width = min_width; this->resize.height = min_height; @@ -884,10 +717,6 @@ *wz = this; _last_z_window++; - - WindowEvent e; - e.event = WE_CREATE; - this->HandleWindowEvent(&e); } /** @@ -963,16 +792,13 @@ * @param y offset in pixels from the top of the screen * @param width width in pixels of the window * @param height height in pixels of the window - * @param *proc see WindowProc function to call when any messages/updates happen to the window * @param cls see WindowClass class of the window, used for identification and grouping * @param *widget see Widget pointer to the window layout and various elements * @return Window pointer of the newly created window */ -Window::Window(int x, int y, int width, int height, WindowProc *proc, WindowClass cls, const Widget *widget) +Window::Window(int x, int y, int width, int height, WindowClass cls, const Widget *widget) { - this->Initialize(x, y, width, height, proc, cls, widget, 0); - - if (proc != NULL) this->FindWindowPlacementAndResize(width, height); + this->Initialize(x, y, width, height, cls, widget, 0); } @@ -1164,10 +990,8 @@ Window::Window(const WindowDesc *desc, WindowNumber window_number) { Point pt = LocalGetWindowPlacement(desc, window_number); - this->Initialize(pt.x, pt.y, desc->minimum_width, desc->minimum_height, desc->proc, desc->cls, desc->widgets, window_number); + this->Initialize(pt.x, pt.y, desc->minimum_width, desc->minimum_height, desc->cls, desc->widgets, window_number); this->desc_flags = desc->flags; - - if (desc->proc != NULL) this->FindWindowPlacementAndResize(desc->default_width, desc->default_height); } /** Do a search for a window at specific coordinates. For this we start @@ -1393,11 +1217,11 @@ int nx = x; int ny = y; - if (_patches.window_snap_radius != 0) { + if (_settings.gui.window_snap_radius != 0) { Window* const *vz; - int hsnap = _patches.window_snap_radius; - int vsnap = _patches.window_snap_radius; + int hsnap = _settings.gui.window_snap_radius; + int vsnap = _settings.gui.window_snap_radius; int delta; FOR_ALL_WINDOWS(vz) { @@ -1643,7 +1467,7 @@ static bool HandleViewportScroll() { - bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0); + bool scrollwheel_scrolling = _settings.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0); if (!_scrolling_viewport) return true; @@ -1663,7 +1487,7 @@ } Point delta; - if (_patches.reverse_scroll) { + if (_settings.gui.reverse_scroll) { delta.x = -_cursor.delta.x; delta.y = -_cursor.delta.y; } else { @@ -1802,8 +1626,7 @@ w->window_class != WC_COMPANY_PASSWORD_WINDOW) { continue; } - ; - if (!w->OnKeyPress(key, keycode)) return; + if (w->OnKeyPress(key, keycode) == Window::ES_HANDLED) return; } Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0); @@ -1819,7 +1642,7 @@ /* Call the event, start with the uppermost window. */ for (Window* const *wz = _last_z_window; wz != _z_windows;) { Window *w = *--wz; - if (!w->OnCTRLStateChange()) break; + if (w->OnCTRLStateChange() == Window::ES_HANDLED) return; } } @@ -1844,7 +1667,7 @@ return; } - if (_patches.autoscroll && _game_mode != GM_MENU && !IsGeneratingWorld()) { + if (_settings.gui.autoscroll && _game_mode != GM_MENU && !IsGeneratingWorld()) { int x = _cursor.pos.x; int y = _cursor.pos.y; Window *w = FindWindowFromPt(x, y); @@ -1896,7 +1719,7 @@ if (!HandleViewportScroll()) return; if (!HandleMouseOver()) return; - bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0); + bool scrollwheel_scrolling = _settings.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0); if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return; int x = _cursor.pos.x; @@ -1911,7 +1734,7 @@ if (vp != NULL && (_game_mode == GM_MENU || IsGeneratingWorld())) return; if (mousewheel != 0) { - if (_patches.scrollwheel_scrolling == 0) { + if (_settings.gui.scrollwheel_scrolling == 0) { /* Send mousewheel event to window */ w->OnMouseWheel(mousewheel); } @@ -2236,7 +2059,7 @@ w = FindWindowById(WC_MAIN_TOOLBAR, 0); } - switch (_patches.toolbar_pos) { + switch (_settings.gui.toolbar_pos) { case 1: w->left = (_screen.width - w->width) / 2; break; case 2: w->left = _screen.width - w->width; break; default: w->left = 0; diff -r 68a692eacf22 -r 67db0d431d5e src/window_gui.h --- a/src/window_gui.h Mon May 26 20:45:25 2008 +0000 +++ b/src/window_gui.h Tue May 27 00:50:55 2008 +0000 @@ -20,8 +20,6 @@ */ static const int MAX_NUMBER_OF_WINDOWS = 25; -typedef void WindowProc(Window *w, WindowEvent *e); - /* How the resize system works: First, you need to add a WWT_RESIZEBOX to the widgets, and you need to add the flag WDF_RESIZABLE to the window. Now the window is ready @@ -106,86 +104,6 @@ void DrawFrameRect(int left, int top, int right, int bottom, int color, FrameFlags flags); /** - * Available window events - */ -enum WindowEventCodes { - WE_CREATE, ///< Initialize the Window - WE_DESTROY, ///< Prepare for deletion of the window - WE_PAINT, ///< Repaint the window contents - WE_KEYPRESS, ///< Key pressed - WE_CLICK, ///< Left mouse button click - WE_MOUSELOOP, ///< Event for each mouse event in the game (at least once every game tick) - WE_TICK, ///< Regularly occurring event (every game tick) - WE_100_TICKS, ///< Regularly occurring event (every 100 game ticks, approximatelly 3 seconds) - WE_TIMEOUT, - WE_PLACE_OBJ, - WE_ABORT_PLACE_OBJ, - WE_ON_EDIT_TEXT, - WE_PLACE_DRAG, - WE_PLACE_MOUSEUP, - WE_PLACE_PRESIZE, - WE_DROPDOWN_SELECT, - WE_RESIZE, ///< Request to resize the window, @see WindowEvent.we.resize - WE_INVALIDATE_DATA, ///< Notification that data displayed by the window is obsolete - WE_CTRL_CHANGED, ///< CTRL key has changed state -}; - -/** - * Data structures for additional data associated with a window event - * @see WindowEventCodes - */ -struct WindowEvent { - byte event; - union { - struct { - Point pt; - int widget; - } click; - - struct { - Point pt; - TileIndex tile; - TileIndex starttile; - ViewportPlaceMethod select_method; - byte select_proc; - } place; - - struct { - Point pt; - int widget; - } dragdrop; - - struct { - Point size; - Point diff; - } sizing; - - struct { - char *str; - } edittext; - - struct { - int button; - int index; - } dropdown; - - struct { - bool cont; ///< continue the search? (default true) - uint16 key; ///< 16-bit Unicode value of the key - uint16 keycode; ///< untranslated key (including shift-state) - } keypress; - - struct { - int data; - } invalidate; - - struct { - bool cont; ///< continue the search? (default true) - } ctrl; - } we; -}; - -/** * High level window description */ struct WindowDesc { @@ -199,7 +117,6 @@ WindowClass parent_cls; ///< Class of the parent window, @see WindowClass uint32 flags; ///< Flags, @see WindowDefaultFlags const Widget *widgets; ///< List of widgets with their position and size for the window - WindowProc *proc; ///< Window event handler function for the window }; /** @@ -266,18 +183,19 @@ * Data structure for an opened window */ struct Window : ZeroedMemoryAllocator { -private: - WindowProc *wndproc; ///< Event handler function for the window. Do not use directly, call HandleWindowEvent() instead. - void HandleWindowEvent(WindowEvent *e); + enum EventState { + ES_HANDLED, + ES_NOT_HANDLED, + }; protected: void Initialize(int x, int y, int min_width, int min_height, - WindowProc *proc, WindowClass cls, const Widget *widget, int window_number); + WindowClass cls, const Widget *widget, int window_number); void FindWindowPlacementAndResize(int def_width, int def_height); void FindWindowPlacementAndResize(const WindowDesc *desc); public: - Window(int x, int y, int width, int height, WindowProc *proc, WindowClass cls, const Widget *widget); + Window(int x, int y, int width, int height, WindowClass cls, const Widget *widget); Window(const WindowDesc *desc, WindowNumber number = 0); virtual ~Window(); @@ -338,24 +256,24 @@ /** * This window is currently being repainted. */ - virtual void OnPaint(); + virtual void OnPaint() {} /** * A key has been pressed. * @param key the Unicode value of the key. * @param keycode the untranslated key code including shift state. - * @return true if the key press has been handled and no other + * @return ES_HANDLED if the key press has been handled and no other * window should receive the event. */ - virtual bool OnKeyPress(uint16 key, uint16 keycode); + virtual EventState OnKeyPress(uint16 key, uint16 keycode) { return ES_NOT_HANDLED; } /** * The state of the control key has changed - * @return true if the change has been handled and no other + * @return ES_HANDLED if the change has been handled and no other * window should receive the event. */ - virtual bool OnCTRLStateChange(); + virtual EventState OnCTRLStateChange() { return ES_NOT_HANDLED; } /** @@ -363,7 +281,7 @@ * @param pt the point inside the window that has been clicked. * @param widget the clicked widget. */ - virtual void OnClick(Point pt, int widget); + virtual void OnClick(Point pt, int widget) {} /** * A double click with the left mouse button has been made on the window. @@ -410,22 +328,22 @@ /** * Called for every mouse loop run, which is at least once per (game) tick. */ - virtual void OnMouseLoop(); + virtual void OnMouseLoop() {} /** * Called once per (game) tick. */ - virtual void OnTick(); + virtual void OnTick() {} /** * Called once every 100 (game) ticks. */ - virtual void OnHundredthTick(); + virtual void OnHundredthTick() {} /** * Called when this window's timeout has been reached. */ - virtual void OnTimeout(); + virtual void OnTimeout() {} /** @@ -433,27 +351,27 @@ * @param new_size the new size of the window. * @param delta the amount of which the window size changed. */ - virtual void OnResize(Point new_size, Point delta); + virtual void OnResize(Point new_size, Point delta) {} /** * A dropdown option associated to this window has been selected. * @param widget the widget (button) that the dropdown is associated with. * @param index the element in the dropdown that is selected. */ - virtual void OnDropdownSelect(int widget, int index); + virtual void OnDropdownSelect(int widget, int index) {} /** * The query window opened from this window has closed. * @param str the new value of the string or NULL if the window * was cancelled. */ - virtual void OnQueryTextFinished(char *str); + virtual void OnQueryTextFinished(char *str) {} /** * Some data on this window has become invalid. * @param data information about the changed data. */ - virtual void OnInvalidateData(int data = 0); + virtual void OnInvalidateData(int data = 0) {} /** @@ -462,12 +380,12 @@ * @param pt the exact point on the map that has been clicked. * @param tile the tile on the map that has been clicked. */ - virtual void OnPlaceObject(Point pt, TileIndex tile); + virtual void OnPlaceObject(Point pt, TileIndex tile) {} /** * The user cancelled a tile highlight mode that has been set. */ - virtual void OnPlaceObjectAbort(); + virtual void OnPlaceObjectAbort() {} /** @@ -477,7 +395,7 @@ * @param select_proc what will be created when the drag is over. * @param pt the exact point on the map where the mouse is. */ - virtual void OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt); + virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) {} /** * The user has dragged over the map when the tile highlight mode @@ -488,7 +406,7 @@ * @param start_tile the begin tile of the drag. * @param end_tile the end tile of the drag. */ - virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile); + virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) {} /** * The user moves over the map when a tile highlight mode has been set @@ -497,7 +415,7 @@ * @param pt the exact point on the map where the mouse is. * @param tile the tile on the map where the mouse is. */ - virtual void OnPlacePresize(Point pt, TileIndex tile); + virtual void OnPlacePresize(Point pt, TileIndex tile) {} /*** End of the event handling ***/ }; @@ -508,7 +426,10 @@ class PickerWindowBase : public Window { public: - PickerWindowBase(const WindowDesc *desc) : Window(desc) {}; // nothing special yet, just propagation + PickerWindowBase(const WindowDesc *desc, Window *parent) : Window(desc) + { + this->parent = parent; + }; virtual ~PickerWindowBase(); }; diff -r 68a692eacf22 -r 67db0d431d5e src/window_type.h --- a/src/window_type.h Mon May 26 20:45:25 2008 +0000 +++ b/src/window_type.h Tue May 27 00:50:55 2008 +0000 @@ -99,7 +99,6 @@ }; struct Window; -struct WindowEvent; typedef int32 WindowNumber; #endif /* WINDOW_TYPE_H */ diff -r 68a692eacf22 -r 67db0d431d5e src/yapf/yapf_base.hpp --- a/src/yapf/yapf_base.hpp Mon May 26 20:45:25 2008 +0000 +++ b/src/yapf/yapf_base.hpp Tue May 27 00:50:55 2008 +0000 @@ -6,6 +6,7 @@ #define YAPF_BASE_HPP #include "../debug.h" +#include "../settings_type.h" extern int _total_pf_time_us; @@ -52,7 +53,7 @@ protected: Node* m_pBestDestNode; ///< pointer to the destination node found at last round Node* m_pBestIntermediateNode; ///< here should be node closest to the destination if path not found - const YapfSettings *m_settings; ///< current settings (_patches.yapf) + const YAPFSettings *m_settings; ///< current settings (_settings.yapf) int m_max_search_nodes; ///< maximum number of nodes we are allowed to visit before we give up const Vehicle* m_veh; ///< vehicle that we are trying to drive @@ -73,7 +74,7 @@ FORCEINLINE CYapfBaseT() : m_pBestDestNode(NULL) , m_pBestIntermediateNode(NULL) - , m_settings(&_patches.yapf) + , m_settings(&_settings.pf.yapf) , m_max_search_nodes(PfGetSettings().max_search_nodes) , m_veh(NULL) , m_stats_cost_calcs(0) @@ -91,7 +92,7 @@ public: /// return current settings (can be custom - player based - but later) - FORCEINLINE const YapfSettings& PfGetSettings() const + FORCEINLINE const YAPFSettings& PfGetSettings() const { return *m_settings; } diff -r 68a692eacf22 -r 67db0d431d5e src/yapf/yapf_rail.cpp --- a/src/yapf/yapf_rail.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/yapf/yapf_rail.cpp Tue May 27 00:50:55 2008 +0000 @@ -254,7 +254,7 @@ PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack; // check if non-default YAPF type needed - if (_patches.forbid_90_deg) { + if (_settings.pf.forbid_90_deg) { pfnChooseRailTrack = &CYapfRail2::stChooseRailTrack; // Trackdir, forbid 90-deg } @@ -311,7 +311,7 @@ PfnCheckReverseTrain pfnCheckReverseTrain = CYapfRail1::stCheckReverseTrain; // check if non-default YAPF type needed - if (_patches.forbid_90_deg) { + if (_settings.pf.forbid_90_deg) { pfnCheckReverseTrain = &CYapfRail2::stCheckReverseTrain; // Trackdir, forbid 90-deg } @@ -341,7 +341,7 @@ PfnFindNearestDepotTwoWay pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail1::stFindNearestDepotTwoWay; // check if non-default YAPF type needed - if (_patches.forbid_90_deg) { + if (_settings.pf.forbid_90_deg) { pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail2::stFindNearestDepotTwoWay; // Trackdir, forbid 90-deg } diff -r 68a692eacf22 -r 67db0d431d5e src/yapf/yapf_road.cpp --- a/src/yapf/yapf_road.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/yapf/yapf_road.cpp Tue May 27 00:50:55 2008 +0000 @@ -407,7 +407,7 @@ PfnChooseRoadTrack pfnChooseRoadTrack = &CYapfRoad2::stChooseRoadTrack; // default: ExitDir, allow 90-deg // check if non-default YAPF type should be used - if (_patches.yapf.disable_node_optimization) + if (_settings.pf.yapf.disable_node_optimization) pfnChooseRoadTrack = &CYapfRoad1::stChooseRoadTrack; // Trackdir, allow 90-deg Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir); @@ -421,7 +421,7 @@ PfnDistanceToTile pfnDistanceToTile = &CYapfRoad2::stDistanceToTile; // default: ExitDir, allow 90-deg // check if non-default YAPF type should be used - if (_patches.yapf.disable_node_optimization) + if (_settings.pf.yapf.disable_node_optimization) pfnDistanceToTile = &CYapfRoad1::stDistanceToTile; // Trackdir, allow 90-deg // measure distance in YAPF units @@ -450,7 +450,7 @@ PfnFindNearestDepot pfnFindNearestDepot = &CYapfRoadAnyDepot2::stFindNearestDepot; // check if non-default YAPF type should be used - if (_patches.yapf.disable_node_optimization) + if (_settings.pf.yapf.disable_node_optimization) pfnFindNearestDepot = &CYapfRoadAnyDepot1::stFindNearestDepot; // Trackdir, allow 90-deg Depot* ret = pfnFindNearestDepot(v, tile, trackdir); diff -r 68a692eacf22 -r 67db0d431d5e src/yapf/yapf_settings.h --- a/src/yapf/yapf_settings.h Mon May 26 20:45:25 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* $Id$ */ - -/** @file yapf_settings.h Penalty settings for YAPF. */ - -#if !defined(YAPF_SETTINGS_H) || defined(YS_DEF) - -# ifndef YAPF_SETTINGS_H -# define YAPF_SETTINGS_H -# endif - -# ifndef YS_DEF -/* - * if YS_DEF is not defined, we will only do following declaration: - * struct YapfSettings { - * bool disable_node_optimization; - * uint32 max_search_nodes; - * .... all other yapf related settings ... - * }; - * - * otherwise we will just expand YS_DEF_xx macros and then #undef them - */ -# define YS_DEF_BEGIN struct YapfSettings { -# define YS_DEF(type, name) type name; -# define YS_DEF_END }; - -# endif /* !YS_DEF */ - -# ifndef YS_DEF_BEGIN -# define YS_DEF_BEGIN -# endif // YS_DEF_BEGIN - -# ifndef YS_DEF_END -# define YS_DEF_END -# endif // YS_DEF_END - -YS_DEF_BEGIN - YS_DEF(bool , disable_node_optimization) ///< whether to use exit-dir instead of trackdir in node key - YS_DEF(uint32, max_search_nodes) ///< stop path-finding when this number of nodes visited - YS_DEF(bool , ship_use_yapf) ///< use YAPF for ships - YS_DEF(bool , road_use_yapf) ///< use YAPF for road - YS_DEF(bool , rail_use_yapf) ///< use YAPF for rail - YS_DEF(uint32, road_slope_penalty) ///< penalty for up-hill slope - YS_DEF(uint32, road_curve_penalty) ///< penalty for curves - YS_DEF(uint32, road_crossing_penalty) ///< penalty for level crossing - YS_DEF(uint32, road_stop_penalty) ///< penalty for going through a drive-through road stop - YS_DEF(bool , rail_firstred_twoway_eol) ///< treat first red two-way signal as dead end - YS_DEF(uint32, rail_firstred_penalty) ///< penalty for first red signal - YS_DEF(uint32, rail_firstred_exit_penalty) ///< penalty for first red exit signal - YS_DEF(uint32, rail_lastred_penalty) ///< penalty for last red signal - YS_DEF(uint32, rail_lastred_exit_penalty) ///< penalty for last red exit signal - YS_DEF(uint32, rail_station_penalty) ///< penalty for non-target station tile - YS_DEF(uint32, rail_slope_penalty) ///< penalty for up-hill slope - YS_DEF(uint32, rail_curve45_penalty) ///< penalty for curve - YS_DEF(uint32, rail_curve90_penalty) ///< penalty for 90-deg curve - YS_DEF(uint32, rail_depot_reverse_penalty) ///< penalty for reversing in the depot - YS_DEF(uint32, rail_crossing_penalty) ///< penalty for level crossing - YS_DEF(uint32, rail_look_ahead_max_signals)///< max. number of signals taken into consideration in look-ahead load balancer - YS_DEF(int32 , rail_look_ahead_signal_p0) ///< constant in polynomial penalty function - YS_DEF(int32 , rail_look_ahead_signal_p1) ///< constant in polynomial penalty function - YS_DEF(int32 , rail_look_ahead_signal_p2) ///< constant in polynomial penalty function - - YS_DEF(uint32, rail_longer_platform_penalty) ///< penalty for longer station platform than train - YS_DEF(uint32, rail_longer_platform_per_tile_penalty) ///< penalty for longer station platform than train (per tile) - YS_DEF(uint32, rail_shorter_platform_penalty) ///< penalty for shorter station platform than train - YS_DEF(uint32, rail_shorter_platform_per_tile_penalty) ///< penalty for shorter station platform than train (per tile) -YS_DEF_END - -#undef YS_DEF_BEGIN -#undef YS_DEF -#undef YS_DEF_END - -#endif /* !YAPF_SETTINGS_H || YS_DEF */ diff -r 68a692eacf22 -r 67db0d431d5e src/yapf/yapf_ship.cpp --- a/src/yapf/yapf_ship.cpp Mon May 26 20:45:25 2008 +0000 +++ b/src/yapf/yapf_ship.cpp Tue May 27 00:50:55 2008 +0000 @@ -154,9 +154,9 @@ PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg // check if non-default YAPF type needed - if (_patches.forbid_90_deg) + if (_settings.pf.forbid_90_deg) pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack; // Trackdir, forbid 90-deg - else if (_patches.yapf.disable_node_optimization) + else if (_settings.pf.yapf.disable_node_optimization) pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);