summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aircraft_cmd.c24
-rw-r--r--aircraft_gui.c46
-rw-r--r--command.c6
-rw-r--r--command.h3
-rw-r--r--engine.c38
-rw-r--r--engine.h1
-rw-r--r--gui.h1
-rw-r--r--lang/english.txt22
-rw-r--r--misc.c8
-rw-r--r--misc_gui.c9
-rw-r--r--network_gui.c8
-rw-r--r--roadveh_cmd.c6
-rw-r--r--roadveh_gui.c44
-rw-r--r--settings_gui.c18
-rw-r--r--ship_cmd.c24
-rw-r--r--ship_gui.c45
-rw-r--r--train_cmd.c24
-rw-r--r--train_gui.c80
-rw-r--r--ttd.h1
-rw-r--r--variables.h3
-rw-r--r--vehicle.c180
-rw-r--r--vehicle.h2
-rw-r--r--vehicle_gui.c644
-rw-r--r--vehicle_gui.h12
-rw-r--r--widget.c250
-rw-r--r--window.c5
-rw-r--r--window.h17
27 files changed, 1249 insertions, 272 deletions
diff --git a/aircraft_cmd.c b/aircraft_cmd.c
index 8236e414a..37c4e56d3 100644
--- a/aircraft_cmd.c
+++ b/aircraft_cmd.c
@@ -406,29 +406,32 @@ int32 CmdChangeAircraftServiceInt(int x, int y, uint32 flags, uint32 p1, uint32
}
// p1 = vehicle
-// p2 = new cargo type
+// p2 = new cargo type(0xFF)
+// p2 = skip check for stopped in hanger (0x0100)
int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v,*u;
int pass, mail;
int32 cost;
+ byte SkipStoppedInHangerCheck = (p2 & 0x100) >> 8; //excludes the cargo value
+ byte new_cargo_type = p2 & 0xFF; //gets the cargo number
SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
v = &_vehicles[p1];
- if (!CheckOwnership(v->owner) || !CheckStoppedInHangar(v))
+ if (!CheckOwnership(v->owner) || (!CheckStoppedInHangar(v) && !(SkipStoppedInHangerCheck)))
return CMD_ERROR;
pass = AircraftVehInfo(v->engine_type)->passanger_capacity;
- if (p2 != 0) {
+ if (new_cargo_type != CT_PASSENGERS) {
pass >>= 1;
- if (p2 != 5)
+ if (new_cargo_type != CT_GOODS)
pass >>= 1;
}
_aircraft_refit_capacity = pass;
cost = 0;
- if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) {
+ if (IS_HUMAN_PLAYER(v->owner) && new_cargo_type != v->cargo_type) {
cost = _price.aircraft_base >> 7;
}
@@ -437,12 +440,15 @@ int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2)
u = v->next;
mail = AircraftVehInfo(v->engine_type)->mail_capacity;
- if (p2 != 0) {
+ if (new_cargo_type != CT_PASSENGERS) {
mail = 0;
}
u->cargo_cap = mail;
- v->cargo_count = u->cargo_count = 0;
- v->cargo_type = (byte)p2;
+ //autorefitted planes wants to keep the cargo
+ //it will be checked if the cargo is valid in CmdReplaceVehicle
+ if (!(SkipStoppedInHangerCheck))
+ v->cargo_count = u->cargo_count = 0;
+ v->cargo_type = new_cargo_type;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
@@ -1157,7 +1163,7 @@ static void AircraftEnterHangar(Vehicle *v)
ServiceAircraft(v);
- MaybeRenewVehicle(v);
+ MaybeReplaceVehicle(v);
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
diff --git a/aircraft_gui.c b/aircraft_gui.c
index 41e9767a5..2dd567724 100644
--- a/aircraft_gui.c
+++ b/aircraft_gui.c
@@ -13,6 +13,26 @@
#include "player.h"
+void Set_DPARAM_Aircraft_Build_Window(uint16 engine_number)
+{
+ const AircraftVehicleInfo *avi = AircraftVehInfo(engine_number);
+ Engine *e;
+ YearMonthDay ymd;
+
+ SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
+ SetDParam(1, avi->max_speed * 8);
+ SetDParam(2, avi->passanger_capacity);
+ SetDParam(3, avi->mail_capacity);
+ SetDParam(4, avi->running_cost * _price.aircraft_running >> 8);
+
+ e = &_engines[engine_number];
+ SetDParam(6, e->lifelength);
+ SetDParam(7, e->reliability * 100 >> 16);
+ ConvertDayToYMD(&ymd, e->intro_date);
+ SetDParam(5, ymd.year + 1920);
+
+}
+
static void DrawAircraftImage(Vehicle *v, int x, int y, VehicleID selection)
{
int image = GetAircraftImage(v, 6);
@@ -43,8 +63,6 @@ void CcBuildAircraft(bool success, uint tile, uint32 p1, uint32 p2)
static void NewAircraftWndProc(Window *w, WindowEvent *e)
{
- YearMonthDay ymd;
-
switch(e->event) {
case WE_PAINT: {
@@ -89,20 +107,7 @@ static void NewAircraftWndProc(Window *w, WindowEvent *e)
WP(w,buildtrain_d).sel_engine = selected_id;
if (selected_id != -1) {
- const AircraftVehicleInfo *avi = AircraftVehInfo(selected_id);
- Engine *e;
-
- SetDParam(0, avi->base_cost * (_price.aircraft_base>>3)>>5);
- SetDParam(1, avi->max_speed * 8);
- SetDParam(2, avi->passanger_capacity);
- SetDParam(3, avi->mail_capacity);
- SetDParam(4, avi->running_cost * _price.aircraft_running >> 8);
-
- e = &_engines[selected_id];
- SetDParam(6, e->lifelength);
- SetDParam(7, e->reliability * 100 >> 16);
- ConvertDayToYMD(&ymd, e->intro_date);
- SetDParam(5, ymd.year + 1920);
+ Set_DPARAM_Aircraft_Build_Window(selected_id);
DrawString(2, 111, STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0);
}
@@ -899,7 +904,7 @@ static Widget _player_aircraft_widgets[] = {
{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT},
{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES},
-{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 130, 259, 170, 181, STR_REPLACE_VEHICLES, STR_REPLACE_HELP},
{ WIDGETS_END},
};
@@ -1005,7 +1010,7 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
break;
case 4: case 5:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
return;
case 7: { /* Matrix to show vehicles */
@@ -1044,6 +1049,11 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e)
ShowBuildAircraftWindow(0);
} break;
+
+ case 10:
+ ShowReplaceVehicleWindow(VEH_Aircraft);
+ break;
+
}
} break;
diff --git a/command.c b/command.c
index 76fbfca19..09b803b84 100644
--- a/command.c
+++ b/command.c
@@ -167,7 +167,7 @@ DEF_COMMAND(CmdStartScenario);
DEF_COMMAND(CmdBuildManySignals);
-DEF_COMMAND(CmdRenewVehicle);
+DEF_COMMAND(CmdReplaceVehicle);
/* The master command table */
static CommandProc * const _command_proc_table[] = {
@@ -309,7 +309,7 @@ static CommandProc * const _command_proc_table[] = {
CmdDestroyCompanyHQ, /* 111 */
CmdGiveMoney, /* 112 */
CmdChangePatchSetting, /* 113 */
- CmdRenewVehicle, /* 114 */
+ CmdReplaceVehicle, /* 114 */
};
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
@@ -431,7 +431,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
_docommand_recursive = 1;
// cost estimation only?
- if (_shift_pressed && _current_player == _local_player && !(cmd & CMD_NETWORK_COMMAND)) {
+ if (_shift_pressed && _current_player == _local_player && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
// estimate the cost.
res = proc(x, y, flags, p1, p2);
if ((uint32)res >> 16 == 0x8000) {
diff --git a/command.h b/command.h
index 4fadc362c..c2aad5a2f 100644
--- a/command.h
+++ b/command.h
@@ -149,7 +149,7 @@ enum {
CMD_GIVE_MONEY = 112,
CMD_CHANGE_PATCH_SETTING = 113,
- CMD_RENEW_VEHICLE = 114,
+ CMD_REPLACE_VEHICLE = 114,
};
enum {
@@ -172,6 +172,7 @@ enum {
CMD_NO_WATER = 0x400,
CMD_NETWORK_COMMAND = 0x800, // execute the command without sending it on the network
CMD_NO_TEST_IF_IN_NETWORK = 0x1000, // When enabled, the command will bypass the no-DC_EXEC round if in network
+ CMD_SHOW_NO_ERROR = 0x2000,
};
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
diff --git a/engine.c b/engine.c
index 7286e0c80..bd3a3fd08 100644
--- a/engine.c
+++ b/engine.c
@@ -115,6 +115,29 @@ static void CalcEngineReliability(Engine *e)
}
}
+void AddTypeToEngines()
+{
+ Engine *e;
+ uint32 counter = 0;
+
+ for(e=_engines; e != endof(_engines); e++, counter++) {
+
+ e->type = VEH_Train;
+ if (counter >= ROAD_ENGINES_INDEX) {
+ e->type = VEH_Road;
+ if (counter >= SHIP_ENGINES_INDEX) {
+ e->type = VEH_Ship;
+ if (counter >= AIRCRAFT_ENGINES_INDEX) {
+ e->type = VEH_Aircraft;
+ if (counter >= TOTAL_NUM_ENGINES) {
+ e->type = VEH_Special;
+ }
+ }
+ }
+ }
+ }
+}
+
void StartupEngines()
{
Engine *e;
@@ -123,8 +146,8 @@ void StartupEngines()
SetupEngineNames();
-
for(e=_engines, ei=_engine_info; e != endof(_engines); e++, ei++, counter++) {
+
e->age = 0;
e->railtype = ei->railtype_climates >> 4;
e->flags = 0;
@@ -170,19 +193,6 @@ void StartupEngines()
It should hopefully be the same as when you ask a vehicle what it is
but using this, you can ask what type an engine number is
even if it is not a vehicle (yet)*/
- e->type = VEH_Train;
- if (counter >= ROAD_ENGINES_INDEX) {
- e->type = VEH_Road;
- if (counter >= SHIP_ENGINES_INDEX) {
- e->type = VEH_Ship;
- if (counter >= AIRCRAFT_ENGINES_INDEX) {
- e->type = VEH_Aircraft;
- if (counter >= TOTAL_NUM_ENGINES) {
- e->type = VEH_Special;
- }
- }
- }
- }
}
AdjustAvailAircraft();
diff --git a/engine.h b/engine.h
index 7ed1fe6c5..b5d9d3d97 100644
--- a/engine.h
+++ b/engine.h
@@ -80,6 +80,7 @@ enum {
};
+void AddTypeToEngines();
void StartupEngines();
diff --git a/gui.h b/gui.h
index 0786c8c53..0d2c8dda8 100644
--- a/gui.h
+++ b/gui.h
@@ -85,6 +85,7 @@ void CheckRedrawStationCoverage(Window *w);
void ShowSmallMap();
void ShowExtraViewPortWindow();
void SetVScrollCount(Window *w, int num);
+void SetVScroll2Count(Window *w, int num);
void SetHScrollCount(Window *w, int num);
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we);
diff --git a/lang/english.txt b/lang/english.txt
index f12cb61ea..1a9167cef 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -2763,3 +2763,25 @@ STR_SCHEDULED_TRAINS_TIP :{BLACK}Show all trains which have this station on
STR_SCHEDULED_ROAD_VEHICLES_TIP :{BLACK}Show all road vehicles which have this station on their schedule
STR_SCHEDULED_AIRCRAFT_TIP :{BLACK}Show all aircraft which have this station on their schedule
STR_SCHEDULED_SHIPS_TIP :{BLACK}Show all ships which have this station on their schedule
+
+STR_REPLACE_VEHICLES :{BLACK}Replace Vehicles
+STR_REPLACE_VEHICLES_START :{BLACK}Start Replacing Vehicles
+STR_REPLACE_VEHICLES_STOP :{BLACK}Stop Replaing Vehicles
+STR_NOT_REPLACING :{BLACK}Not replacing
+STR_NOT_REPLACING_VEHICLE_SELECTED :{BLACK}No vehicle selected
+STR_REPLACE_HELP_LEFT_ARRAY :{BLACK}Select a type of engine to replace{}Select an engine on the right side to replace to
+STR_REPLACE_HELP_RIGHT_ARRAY :{BLACK}Select an engine to replace to{}It will replace the engines selected on the left side
+STR_REPLACE_HELP_STOP_BUTTON :{BLACK}Press this button if you don't want to replace the engine, you selected on the left
+STR_REPLACE_HELP_START_BUTTON :{BLACK}Press this button if you want to replace the engine selected on the left with the one selected on the right
+STR_REPLACE_HELP_RAILTYPE :{BLACK}Select a railtype you want to select engines for
+STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}This displays what engine the selected engine on the left are being replaced to
+STR_REPLACE_HELP :{BLACK}This feature allows you to select an enginetype and replace that one with another one. This will then be done automatically when the vehicles enters a depot anyway
+
+############ Lists rail types
+
+STR_RAIL_VEHICLES :{BLACK}Rail Vehicles
+STR_MONORAIL_VEHICLES :{BLACK}Monorail Vehicles
+STR_MAGLEV_VEHICLES :{BLACK}Maglev Vehicles
+
+############ End of list of rail types
+
diff --git a/misc.c b/misc.c
index 922a3f157..4a9789ede 100644
--- a/misc.c
+++ b/misc.c
@@ -9,6 +9,7 @@
#include "network.h"
#include "network_data.h"
#include "network_server.h"
+#include "engine.h"
extern void StartupEconomy();
extern void InitNewsItemStructs();
@@ -182,6 +183,13 @@ void ConvertGroundTilesIntoWaterTiles();
void InitializeGame()
{
+ // Initialize the autoreplace array. Needs to be cleared between each game
+ int i;
+ for (i = 0; i < 256; i++) {
+ _autoreplace_array[i] = i;
+ }
+ AddTypeToEngines(); // make sure all engines have a type
+
SetObjectToPlace(1, 0, 0, 0);
_pause = 0;
diff --git a/misc_gui.c b/misc_gui.c
index a5e7db7a0..1b17cc449 100644
--- a/misc_gui.c
+++ b/misc_gui.c
@@ -692,6 +692,14 @@ void SetVScrollCount(Window *w, int num)
if (num < w->vscroll.pos) w->vscroll.pos = num;
}
+void SetVScroll2Count(Window *w, int num)
+{
+ w->vscroll2.count = num;
+ num -= w->vscroll2.cap;
+ if (num < 0) num = 0;
+ if (num < w->vscroll2.pos) w->vscroll2.pos = num;
+}
+
void SetHScrollCount(Window *w, int num)
{
w->hscroll.count = num;
@@ -700,7 +708,6 @@ void SetHScrollCount(Window *w, int num)
if (num < w->hscroll.pos) w->hscroll.pos = num;
}
-
int HandleEditBoxKey(Window *w, int wid, WindowEvent *we)
{
byte *p;
diff --git a/network_gui.c b/network_gui.c
index 5f62b29a5..172eea23a 100644
--- a/network_gui.c
+++ b/network_gui.c
@@ -231,7 +231,7 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
DeleteWindowById(WC_NETWORK_WINDOW, 0);
break;
case 4: case 5:
- ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0); // do it for widget 5
+ ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0, 0); // do it for widget 5
break;
case 10: { /* Matrix to show networkgames */
uint32 id_v = (e->click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
@@ -540,13 +540,13 @@ static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
SetWindowDirty(w);
} break;
case 7: case 8: /* Connection type */
- ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0); // do it for widget 8
+ ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
break;
case 9: case 10: /* Number of Players */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max - 2, 10, 0); // do it for widget 10
+ ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max - 2, 10, 0, 0); // do it for widget 10
return;
case 11: case 12: /* Language */
- ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 12, 0); // do it for widget 12
+ ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 12, 0, 0); // do it for widget 12
return;
case 13: /* Start game */
_is_network_server = true;
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index 72adbade1..37196cc86 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -105,6 +105,8 @@ int32 EstimateRoadVehCost(byte engine_type)
return ((_price.roadveh_base >> 3) * RoadVehInfo(engine_type)->base_cost) >> 5;
}
+// p1 = engine_type
+// p2 not used
int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
int32 cost;
@@ -211,6 +213,8 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
+// p1 = vehicle index in &_vehicles[]
+// p2 not used
int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
@@ -1379,7 +1383,7 @@ void RoadVehEnterDepot(Vehicle *v)
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
- MaybeRenewVehicle(v);
+ MaybeReplaceVehicle(v);
VehicleServiceInDepot(v);
diff --git a/roadveh_gui.c b/roadveh_gui.c
index ed7f2201b..09e8b5a95 100644
--- a/roadveh_gui.c
+++ b/roadveh_gui.c
@@ -12,6 +12,25 @@
#include "player.h"
#include "engine.h"
+void Set_DPARAM_Road_Veh_Build_Window(uint16 engine_number)
+{
+ const RoadVehicleInfo *rvi = RoadVehInfo(engine_number);
+ Engine *e;
+ YearMonthDay ymd;
+
+ SetDParam(0, rvi->base_cost * (_price.roadveh_base>>3)>>5);
+ SetDParam(1, rvi->max_speed * 10 >> 5);
+ SetDParam(2, rvi->running_cost * _price.roadveh_running >> 8);
+ SetDParam(4, rvi->capacity);
+ SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
+
+ e = &_engines[engine_number];
+ SetDParam(6, e->lifelength);
+ SetDParam(7, e->reliability * 100 >> 16);
+ ConvertDayToYMD(&ymd, e->intro_date);
+ SetDParam(5, ymd.year + 1920);
+}
+
static void DrawRoadVehImage(Vehicle *v, int x, int y, VehicleID selection)
{
int image = GetRoadVehImage(v, 6);
@@ -307,8 +326,6 @@ void ShowRoadVehViewWindow(Vehicle *v)
static void DrawNewRoadVehWindow(Window *w)
{
- YearMonthDay ymd;
-
if (w->window_number == 0)
w->disabled_state = 1 << 5;
@@ -350,20 +367,7 @@ static void DrawNewRoadVehWindow(Window *w)
WP(w,buildtrain_d).sel_engine = selected_id;
if (selected_id != -1) {
- const RoadVehicleInfo *rvi = RoadVehInfo(selected_id);
- Engine *e;
-
- SetDParam(0, rvi->base_cost * (_price.roadveh_base>>3)>>5);
- SetDParam(1, rvi->max_speed * 10 >> 5);
- SetDParam(2, rvi->running_cost * _price.roadveh_running >> 8);
- SetDParam(4, rvi->capacity);
- SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
-
- e = &_engines[selected_id];
- SetDParam(6, e->lifelength);
- SetDParam(7, e->reliability * 100 >> 16);
- ConvertDayToYMD(&ymd, e->intro_date);
- SetDParam(5, ymd.year + 1920);
+ Set_DPARAM_Road_Veh_Build_Window(selected_id);
DrawString(2, 127, STR_9008_COST_SPEED_RUNNING_COST, 0);
}
@@ -714,7 +718,7 @@ static Widget _player_roadveh_widgets[] = {
{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
/* only for our road list, a 'Build Vehicle' button that opens the depot of the last built depot */
{ WWT_PUSHTXTBTN, 14, 0, 129, 208, 219, STR_8815_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES},
-{ WWT_PANEL, 14, 130, 259, 208, 219, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 130, 259, 208, 219, STR_REPLACE_VEHICLES, STR_REPLACE_HELP},
{ WIDGETS_END},
};
@@ -818,7 +822,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
break;
case 4: case 5:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
return;
case 7: { /* Matrix to show vehicles */
uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL;
@@ -856,6 +860,10 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e)
ShowBuildRoadVehWindow(0);
} break;
+ case 10: {
+ ShowReplaceVehicleWindow(VEH_Road);
+ break;
+ }
}
} break;
diff --git a/settings_gui.c b/settings_gui.c
index 253b3acf5..e6cf1f93c 100644
--- a/settings_gui.c
+++ b/settings_gui.c
@@ -92,35 +92,35 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e)
case WE_CLICK:
switch(e->click.widget) {
case 5:
- ShowDropDownMenu(w, _currency_string_list, _opt_mod_ptr->currency, e->click.widget, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies());
+ ShowDropDownMenu(w, _currency_string_list, _opt_mod_ptr->currency, e->click.widget, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0);
return;
case 8:
- ShowDropDownMenu(w, _distances_dropdown, _opt_mod_ptr->kilometers, e->click.widget, 0);
+ ShowDropDownMenu(w, _distances_dropdown, _opt_mod_ptr->kilometers, e->click.widget, 0, 0);
return;
case 11: {
int i = _opt_mod_ptr->road_side;
- ShowDropDownMenu(w, _driveside_dropdown, i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i));
+ ShowDropDownMenu(w, _driveside_dropdown, i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i), 0);
return;
}
case 14: {
int i = _opt_mod_ptr->town_name;
- ShowDropDownMenu(w, BuildDynamicDropdown(STR_TOWNNAME_ORIGINAL_ENGLISH, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1), i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i));
+ ShowDropDownMenu(w, BuildDynamicDropdown(STR_TOWNNAME_ORIGINAL_ENGLISH, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1), i, e->click.widget, (_game_mode == GM_MENU) ? 0 : (-1) ^ (1 << i), 0);
return;
}
case 17:
- ShowDropDownMenu(w, _autosave_dropdown, _opt_mod_ptr->autosave, e->click.widget, 0);
+ ShowDropDownMenu(w, _autosave_dropdown, _opt_mod_ptr->autosave, e->click.widget, 0, 0);
return;
case 20:
- ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names&1)?1:0, e->click.widget, (_vehicle_design_names&2)?0:2);
+ ShowDropDownMenu(w, _designnames_dropdown, (_vehicle_design_names&1)?1:0, e->click.widget, (_vehicle_design_names&2)?0:2, 0);
return;
case 21:
return;
case 24:
- ShowDropDownMenu(w, _dynlang.dropdown, _dynlang.curr, e->click.widget, 0);
+ ShowDropDownMenu(w, _dynlang.dropdown, _dynlang.curr, e->click.widget, 0, 0);
return;
case 27:
// setup resolution dropdown
- ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), e->click.widget, 0);
+ ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), e->click.widget, 0, 0);
return;
case 28: /* Click fullscreen on/off */
(_fullscreen) ? CLRBIT(w->click_state, 28) : SETBIT(w->click_state, 28);
@@ -128,7 +128,7 @@ static void GameOptionsWndProc(Window *w, WindowEvent *e)
SetWindowDirty(w);
return;
case 31: /* Setup screenshot format dropdown */
- ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, e->click.widget, 0);
+ ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, e->click.widget, 0, 0);
return;
}
diff --git a/ship_cmd.c b/ship_cmd.c
index 3c350d938..9d7a8553e 100644
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -400,7 +400,7 @@ static void ShipEnterDepot(Vehicle *v)
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
- MaybeRenewVehicle(v);
+ MaybeReplaceVehicle(v);
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
@@ -975,30 +975,38 @@ int32 CmdChangeShipServiceInt(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// p1 = vehicle
-// p2 = new cargo
+// p2 = new cargo (0xFF)
+// p2 = skip check for stopped in hanger (0x0100)
int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
int32 cost;
+ byte SkipStoppedInDepotCheck = (p2 & 0x100) >> 8; //excludes the cargo value
+ p2 = p2 & 0xFF;
SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN);
v = &_vehicles[p1];
if (!CheckOwnership(v->owner))
return CMD_ERROR;
- if (!IsShipDepotTile(v->tile) ||
- !(v->vehstatus&VS_STOPPED) ||
- v->u.ship.state != 0x80)
- return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
-
+ if (!( SkipStoppedInDepotCheck )) {
+ if (!IsShipDepotTile(v->tile) ||
+ !(v->vehstatus&VS_STOPPED) ||
+ v->u.ship.state != 0x80)
+ return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN);
+ }
+
cost = 0;
if (IS_HUMAN_PLAYER(v->owner) && (byte)p2 != v->cargo_type) {
cost = _price.ship_base >> 7;
}
if (flags & DC_EXEC) {
- v->cargo_count = 0;
+ //autorefitted ships wants to keep the cargo
+ //it will be checked if the cargo is valid in CmdRenewVehicle
+ if (!(SkipStoppedInDepotCheck))
+ v->cargo_count = 0;
v->cargo_type = (byte)p2;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
diff --git a/ship_gui.c b/ship_gui.c
index 98e53f559..881fd47fd 100644
--- a/ship_gui.c
+++ b/ship_gui.c
@@ -12,6 +12,25 @@
#include "player.h"
#include "engine.h"
+void Set_DPARAM_Ship_Build_Window(uint16 engine_number)
+{
+ YearMonthDay ymd;
+ const ShipVehicleInfo *svi = ShipVehInfo(engine_number);
+ Engine *e;
+
+ SetDParam(0, svi->base_cost * (_price.ship_base>>3)>>5);
+ SetDParam(1, svi->max_speed * 10 >> 5);
+ SetDParam(2, _cargoc.names_long_p[svi->cargo_type]);
+ SetDParam(3, svi->capacity);
+ SetDParam(4, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
+ SetDParam(5, svi->running_cost * _price.ship_running >> 8);
+
+ e = &_engines[engine_number];
+ SetDParam(7, e->lifelength);
+ SetDParam(8, e->reliability * 100 >> 16);
+ ConvertDayToYMD(&ymd, e->intro_date);
+ SetDParam(6, ymd.year + 1920);
+}
static void DrawShipImage(Vehicle *v, int x, int y, VehicleID selection);
@@ -317,7 +336,6 @@ void CcBuildShip(bool success, uint tile, uint32 p1, uint32 p2)
static void NewShipWndProc(Window *w, WindowEvent *e)
{
- YearMonthDay ymd;
switch(e->event) {
case WE_PAINT:
if (w->window_number == 0)
@@ -362,21 +380,7 @@ static void NewShipWndProc(Window *w, WindowEvent *e)
WP(w,buildtrain_d).sel_engine = selected_id;
if (selected_id != -1) {
- const ShipVehicleInfo *svi = ShipVehInfo(selected_id);
- Engine *e;
-
- SetDParam(0, svi->base_cost * (_price.ship_base>>3)>>5);
- SetDParam(1, svi->max_speed * 10 >> 5);
- SetDParam(2, _cargoc.names_long_p[svi->cargo_type]);
- SetDParam(3, svi->capacity);
- SetDParam(4, svi->refittable ? STR_9842_REFITTABLE : STR_EMPTY);
- SetDParam(5, svi->running_cost * _price.ship_running >> 8);
-
- e = &_engines[selected_id];
- SetDParam(7, e->lifelength);
- SetDParam(8, e->reliability * 100 >> 16);
- ConvertDayToYMD(&ymd, e->intro_date);
- SetDParam(6, ymd.year + 1920);
+ Set_DPARAM_Ship_Build_Window(selected_id);
DrawString(2, 111, STR_980A_COST_SPEED_CAPACITY_RUNNING, 0);
}
@@ -881,7 +885,7 @@ static Widget _player_ships_widgets[] = {
{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR},
{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES},
-{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 130, 259, 170, 181, STR_REPLACE_VEHICLES, STR_REPLACE_HELP},
{ WIDGETS_END},
};
@@ -986,7 +990,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
SetWindowDirty(w);
break;
case 4: case 5:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
return;
case 7: { /* Matrix to show vehicles */
uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG;
@@ -1024,7 +1028,12 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e)
ShowBuildShipWindow(0);
} break;
+
+ case 10: {
+ ShowReplaceVehicleWindow(VEH_Ship);
+ break;
}
+ }
} break;
case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
diff --git a/train_cmd.c b/train_cmd.c
index 5386addf4..4700ab4d4 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -1057,23 +1057,27 @@ int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
// p1 = vehicle to refit
-// p2 = new cargo
-
+// p2 = new cargo (0xFF)
+// p2 = skip check for stopped in hanger (0x0100)
int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
Vehicle *v;
int32 cost;
uint num;
- SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
+ byte SkipStoppedInDepotCheck = (p2 & 0x100) >> 8;
+
+ p2 = p2 & 0xFF;
+ SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
+
v = &_vehicles[p1];
- if (!CheckOwnership(v->owner) || CheckStoppedInDepot(v) < 0)
+ if (!CheckOwnership(v->owner) || ((CheckStoppedInDepot(v) < 0) && !(SkipStoppedInDepotCheck)))
return CMD_ERROR;
cost = 0;
num = 0;
-
+
do {
/* XXX: We also refit all the attached wagons en-masse if they
* can be refitted. This is how TTDPatch does it. TODO: Have
@@ -1084,12 +1088,16 @@ int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
cost += (_price.build_railvehicle >> 8);
num += v->cargo_cap;
if (flags & DC_EXEC) {
- v->cargo_count = 0;
+ //autorefitted train cars wants to keep the cargo
+ //it will be checked if the cargo is valid in CmdReplaceVehicle
+ if (!(SkipStoppedInDepotCheck))
+ v->cargo_count = 0;
v->cargo_type = (byte)p2;
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
}
- } while ( (v=v->next) != NULL);
+ // SkipStoppedInDepotCheck is called by CmdReplace and it should only apply to the single car it is called for
+ } while ( (v=v->next) != NULL || SkipStoppedInDepotCheck );
_returned_refit_amount = num;
@@ -2618,7 +2626,7 @@ void TrainEnterDepot(Vehicle *v, uint tile)
v->load_unload_time_rem = 0;
v->cur_speed = 0;
- MaybeRenewVehicle(v);
+ MaybeReplaceVehicle(v);
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
diff --git a/train_gui.c b/train_gui.c
index 3e1de7bae..78095eb35 100644
--- a/train_gui.c
+++ b/train_gui.c
@@ -16,6 +16,44 @@
int _traininfo_vehicle_pitch = 0;
+void Set_DPARAM_Train_Engine_Build_Window(uint16 engine_number)
+{
+ const RailVehicleInfo *rvi = RailVehInfo(engine_number);
+ Engine *e;
+ int multihead = (rvi->flags&RVI_MULTIHEAD?1:0);
+ YearMonthDay ymd;
+
+
+ SetDParam(0, rvi->base_cost * (_price.build_railvehicle >> 3) >> 5);
+ SetDParam(2, rvi->max_speed * 10 >> 4);
+ SetDParam(3, rvi->power << multihead);
+ SetDParam(1, rvi->weight << multihead);
+ SetDParam(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead);
+
+ SetDParam(5, STR_8838_N_A);
+ if (rvi->capacity != 0) {
+ SetDParam(6, rvi->capacity << multihead);
+ SetDParam(5, _cargoc.names_long_p[rvi->cargo_type]);
+ }
+
+ e = &_engines[engine_number];
+
+ SetDParam(8, e->lifelength);
+ SetDParam(9, e->reliability * 100 >> 16);
+ ConvertDayToYMD(&ymd, e->intro_date);
+ SetDParam(7, ymd.year + 1920);
+}
+
+void Set_DPARAM_Train_Car_Build_Window(Window *w, uint16 engine_number)
+{
+ const RailVehicleInfo *rvi = RailVehInfo(engine_number);
+
+ SetDParam(0, DoCommandByTile(w->window_number, engine_number, 0, DC_QUERY_COST, CMD_BUILD_RAIL_VEHICLE) );
+ SetDParam(4, rvi->capacity);
+ SetDParam(1, rvi->weight);
+ SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
+ SetDParam(2, (_cargoc.weights[rvi->cargo_type] * rvi->capacity >> 4) + rvi->weight);
+}
void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2)
{
@@ -131,43 +169,16 @@ static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
if (selected_id != -1) {
const RailVehicleInfo *rvi = RailVehInfo(selected_id);
- Engine *e;
- YearMonthDay ymd;
if (!(rvi->flags & RVI_WAGON)) {
/* it's an engine */
- int multihead = (rvi->flags&RVI_MULTIHEAD?1:0);
-
- SetDParam(0, rvi->base_cost * (_price.build_railvehicle >> 3) >> 5);
- SetDParam(2, rvi->max_speed * 10 >> 4);
- SetDParam(3, rvi->power << multihead);
- SetDParam(1, rvi->weight << multihead);
- SetDParam(4, (rvi->running_cost_base * _price.running_rail[rvi->engclass] >> 8) << multihead);
-
- SetDParam(5, STR_8838_N_A);
- if (rvi->capacity != 0) {
- SetDParam(6, rvi->capacity << multihead);
- SetDParam(5, _cargoc.names_long_p[rvi->cargo_type]);
- }
-
- e = &_engines[selected_id];
-
- SetDParam(8, e->lifelength);
- SetDParam(9, e->reliability * 100 >> 16);
- ConvertDayToYMD(&ymd, e->intro_date);
- SetDParam(7, ymd.year + 1920);
+ Set_DPARAM_Train_Engine_Build_Window(selected_id);
DrawString(2, 0x7F, STR_8817_COST_WEIGHT_T_SPEED_POWER, 0);
} else {
/* it's a wagon */
-
- SetDParam(0,
- DoCommandByTile(w->window_number, selected_id, 0, DC_QUERY_COST, CMD_BUILD_RAIL_VEHICLE)
- );
- SetDParam(4, rvi->capacity);
- SetDParam(1, rvi->weight);
- SetDParam(3, _cargoc.names_long_p[rvi->cargo_type]);
- SetDParam(2, (_cargoc.weights[rvi->cargo_type] * rvi->capacity >> 4) + rvi->weight);
+ Set_DPARAM_Train_Car_Build_Window(w, selected_id);
+
DrawString(2, 0x7F, STR_8821_COST_WEIGHT_T_T_CAPACITY, 0);
}
}
@@ -1183,7 +1194,7 @@ static Widget _player_trains_widgets[] = {
{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR},
{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WWT_PUSHTXTBTN, 14, 0, 161, 208, 219, STR_8815_NEW_VEHICLES, STR_883E_BUILD_NEW_TRAINS_REQUIRES},
-{ WWT_PANEL, 14, 162, 324, 208, 219, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 162, 324, 208, 219, STR_REPLACE_VEHICLES, STR_REPLACE_HELP},
{ WIDGETS_END},
};
@@ -1289,7 +1300,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
break;
case 4: case 5:/* Select sorting criteria dropdown menu */
- ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0);
+ ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 5, 0, 0);
return;
case 7: { /* Matrix to show vehicles */
@@ -1328,6 +1339,11 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e)
ShowBuildTrainWindow(0);
} break;
+ case 10: {
+ ShowReplaceVehicleWindow(VEH_Train);
+ break;
+ }
+
}
} break;
diff --git a/ttd.h b/ttd.h
index 35bcc6354..45880270f 100644
--- a/ttd.h
+++ b/ttd.h
@@ -439,6 +439,7 @@ enum {
WC_CLIENT_LIST = 0x49,
WC_NETWORK_STATUS_WINDOW = 0x4A,
WC_CUSTOM_CURRENCY = 0x4B,
+ WC_REPLACE_VEHICLE = 0x4C,
};
diff --git a/variables.h b/variables.h
index c62cc78fa..3d6b7a5fd 100644
--- a/variables.h
+++ b/variables.h
@@ -431,6 +431,9 @@ VARDEF SignStruct *_new_sign_struct;
/* tunnelbridge */
#define MAX_BRIDGES 13
+/* Autoreplace vehicle stuff*/
+VARDEF byte _autoreplace_array[255];
+
/* Debugging levels */
VARDEF int _debug_spritecache_level;
VARDEF int _debug_misc_level;
diff --git a/vehicle.c b/vehicle.c
index e029c985a..0680581e8 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -4,7 +4,6 @@
#include "map.h"
#include "vehicle.h"
#include "gfx.h"
-//#include "station.h"
#include "viewport.h"
#include "news.h"
#include "command.h"
@@ -1394,35 +1393,45 @@ extern int32 EstimateTrainCost(const RailVehicleInfo *rvi);
extern int32 EstimateRoadVehCost(byte engine_type);
extern int32 EstimateShipCost(uint16 engine_type);
extern int32 EstimateAircraftCost(uint16 engine_type);
+extern int32 CmdRefitRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+extern int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2);
+extern int32 CmdRefitAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2);
-/* Renews a vehicle
+/* Replaces a vehicle (used to be called autorenew)
p1 - Index of vehicle
p2 - Type of new engine */
-int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
-{
- byte new_engine_type = p2;
+int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+{
+ /* makesvariables to inform about how much money the player wants to have left after replacing
+ and which engine to replace with out of p2.
+ the first 16 bit is the money. The last 5 digits (all 0) were removed when sent, so we add them again.
+ This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches
+ This is a nice way to send 32 bit and only use 16 bit
+ the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */
+ uint16 new_engine_type = (uint16)(p2 & 0xFFFF);
+ uint32 autorefit_money = (p2 >> 16) * 100000;
Vehicle *v = DEREF_VEHICLE(p1);
int cost, build_cost;
-
- SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
+
+ if (v->type != _engines[new_engine_type].type) return CMD_ERROR;
switch (v->type) {
- case VEH_Train: build_cost = EstimateTrainCost(RailVehInfo(v->engine_type)); break;
- case VEH_Road: build_cost = EstimateRoadVehCost(new_engine_type); break;
- case VEH_Ship: build_cost = EstimateShipCost(v->engine_type); break;
- case VEH_Aircraft: build_cost = EstimateAircraftCost(new_engine_type); break;
+ case VEH_Train: build_cost = EstimateTrainCost(RailVehInfo(new_engine_type)); break;
+ case VEH_Road: build_cost = EstimateRoadVehCost(new_engine_type); break;
+ case VEH_Ship: build_cost = EstimateShipCost(new_engine_type); break;
+ case VEH_Aircraft: build_cost = EstimateAircraftCost(new_engine_type); break;
default: return CMD_ERROR;
}
/* In a rare situation, when 2 clients are connected to 1 company and have the same
settings, a vehicle can be replaced twice.. check if this is the situation here */
- if (v->age == 0)
+ if (v->engine_type == new_engine_type && v->age == 0)
return CMD_ERROR;
/* Check if there is money for the upgrade.. if not, give a nice news-item
(that is needed, because this CMD is called automaticly) */
- if (DEREF_PLAYER(v->owner)->money64 < _patches.autorenew_money + build_cost - v->value) {
- if (_local_player == v->owner) {
+ if ( DEREF_PLAYER(v->owner)->money64 < (int32)(autorefit_money + build_cost - v->value)) {
+ if (( _local_player == v->owner ) && ( v->unitnumber != 0 )) { //v->unitnumber = 0 for train cars
int message;
SetDParam(0, v->unitnumber);
switch (v->type) {
@@ -1439,21 +1448,106 @@ int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return CMD_ERROR;
}
-
cost = build_cost - v->value;
- if (flags & DC_QUERY_COST)
- return cost;
if (flags & DC_EXEC) {
Engine *e;
+ e = &_engines[new_engine_type];
+
+ // TODO make it check if refit is possible before actually doing it
/* We do not really buy a new vehicle, we upgrade the old one */
if (v->engine_type != new_engine_type) {
- /* XXX - We need to do some more stuff here, when we are going to upgrade
- to a new engine! */
+ byte cargo_type = v->cargo_type;
+ v->engine_type = new_engine_type;
+ v->max_age = e->lifelength * 366;
+
+ /* Update limits of the vehicle (for when upgraded) */
+ switch (v->type) {
+ case VEH_Train:
+ // using if (true) to declare the const
+ {
+ const RailVehicleInfo *rvi = RailVehInfo(new_engine_type);
+ byte capacity = rvi->capacity;
+
+ v->spritenum = rvi->image_index;
+ v->cargo_type = rvi->cargo_type;
+ v->cargo_cap = rvi->capacity;
+ v->max_speed = rvi->max_speed;
+
+ v->u.rail.railtype = e->railtype;
+
+ // 0x0100 means that we skip the check for being stopped inside the depot
+ // since we do not stop it for autorefitting
+ if (v->cargo_type != cargo_type && capacity) {
+ // BUG: somehow v->index is not transfered properly
+ //CmdRefitRailVehicle(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 );
+ v->cargo_type = cargo_type; // workaround, but it do not check the refit table
+ } else {
+ v->cargo_type = rvi->cargo_type;
+ }
+ break;
+ }
+ case VEH_Road:
+ // using if (true) to declare the const
+ if (true) {
+ const RoadVehicleInfo *rvi = RoadVehInfo(new_engine_type);
+
+ v->spritenum = rvi->image_index;
+ v->cargo_type = rvi->cargo_type;
+ v->cargo_cap = rvi->capacity;
+ v->max_speed = rvi->max_speed;
+ break;
+ }
+ case VEH_Ship:
+ // using if (true) to declare the const
+ if (true) {
+ const ShipVehicleInfo *svi = ShipVehInfo(new_engine_type);
+
+ v->spritenum = svi->image_index;
+ v->cargo_type = svi->cargo_type;
+ v->cargo_cap = svi->capacity;
+ v->max_speed = svi->max_speed;
+
+ // 0x0100 means that we skip the check for being stopped inside the depot
+ // since we do not stop it for autorefitting
+ if (v->cargo_type != cargo_type)
+ CmdRefitShip(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 );
+ break;
+ }
+ case VEH_Aircraft:
+ // using if (true) to declare the const
+ if (true) {
+ const AircraftVehicleInfo *avi = AircraftVehInfo(new_engine_type);
+ Vehicle *u;
+
+ v->max_speed = avi->max_speed;
+ v->acceleration = avi->acceleration;
+ v->spritenum = avi->image_index;
+
+ if ( cargo_type == CT_PASSENGERS ) {
+ v->cargo_cap = avi->passanger_capacity;
+ u = v->next;
+ u->cargo_cap = avi->mail_capacity;
+ } else {
+ // 0x0100 means that we skip the check for being stopped inside the hangar
+ // since we do not stop it for autorefitting
+ CmdRefitAircraft(v->x_pos, v->y_pos, DC_EXEC, v->index , cargo_type + 0x0100 );
+ }
+ break;
+ }
+ default: return CMD_ERROR;
+ }
+ // makes sure that the cargo is still valid compared to new capacity
+ if (v->cargo_count != 0) {
+ if ( v->cargo_type != cargo_type )
+ v->cargo_count = 0;
+ else if ( v->cargo_count > v->cargo_cap )
+ v->cargo_count = v->cargo_cap;
+ }
}
- e = &_engines[new_engine_type];
+
v->reliability = e->reliability;
v->reliability_spd_dec = e->reliability_spd_dec;
v->age = 0;
@@ -1465,26 +1559,58 @@ int32 CmdRenewVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
+ //needs to be down here because refitting will change SET_EXPENSES_TYPE if called
+ SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
return cost;
}
-void MaybeRenewVehicle(Vehicle *v)
+void MaybeReplaceVehicle(Vehicle *v)
{
+ uint32 new_engine_and_autoreplace_money;
+
if (v->owner != _local_player)
return;
+ // uncomment next line if you want to see what engine type just entered a depot
+ //printf("engine type: %d\n", v->engine_type);
// A vehicle is autorenewed when it it gets the amount of months
// give by _patches.autorenew_months away for his max age.
// Standard is -6, meaning 6 months before his max age
// It can be any value between -12 and 12.
- if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30))
- return;
-
+ // Here it also checks if the vehicles is listed for replacement
+ if (!_patches.autorenew || v->age - v->max_age < (_patches.autorenew_months * 30)) { //replace if engine is too old
+ if (_autoreplace_array[v->engine_type] == v->engine_type && v->type != VEH_Train) //updates to a new model
+ return;
+ }
+ /* Now replace the vehicle */
_current_player = v->owner;
-
- /* Now renew the vehicle */
- DoCommandP(v->tile, v->index, v->engine_type, NULL, CMD_RENEW_VEHICLE);
+
+ /* makes the variable to inform about how much money the player wants to have left after replacing
+ and which engine to replace with
+ the first 16 bit is the money. Since we know the last 5 digits is 0, they are thrown away.
+ This way the max is 6553 millions and it is more than the 32 bit that is stored in _patches
+ This is a nice way to send 32 bit and only use 16 bit
+ the last 8 bit is the engine. The 8 bits in front of the engine is free so it have room for 16 bit engine entries */
+ new_engine_and_autoreplace_money = (((_patches.autorenew_money / 100000) & 0xFFFF) << 16)
+ + _autoreplace_array[v->engine_type];
+
+ assert(v->type == _engines[ _autoreplace_array[v->engine_type] ].type);
+
+ if ( v->type != VEH_Train ) {
+ DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money, NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR);
+ } else {
+ // checks if the front engine is outdated
+ if (v->engine_type != _autoreplace_array[v->engine_type] )
+ DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money, NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR);
+ //we will check all the cars and engines if they should be replaced
+ while (v->next != NULL){
+ v = v->next;
+ if (v->engine_type != _autoreplace_array[v->engine_type] || v->age - v->max_age < (_patches.autorenew_months * 30))
+ DoCommandP(v->tile, v->index, new_engine_and_autoreplace_money , NULL, CMD_REPLACE_VEHICLE | CMD_SHOW_NO_ERROR);
+ }
+ }
+ _current_player = OWNER_NONE;
}
diff --git a/vehicle.h b/vehicle.h
index 09fbac9f5..bceeff763 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -361,7 +361,7 @@ Vehicle *CheckClickOnVehicle(ViewPort *vp, int x, int y);
void DecreaseVehicleValue(Vehicle *v);
void CheckVehicleBreakdown(Vehicle *v);
void AgeVehicle(Vehicle *v);
-void MaybeRenewVehicle(Vehicle *v);
+void MaybeReplaceVehicle(Vehicle *v);
void DeleteCommandFromVehicleSchedule(Order cmd);
diff --git a/vehicle_gui.c b/vehicle_gui.c
index 09dcb9e84..83c13c3c9 100644
--- a/vehicle_gui.c
+++ b/vehicle_gui.c
@@ -3,6 +3,10 @@
#include "table/strings.h"
#include "vehicle.h"
#include "window.h"
+#include "engine.h"
+#include "gui.h"
+#include "command.h"
+#include "gfx.h"
VehicleSortListingTypeFunctions * const _vehicle_sorter[] = {
&VehicleUnsortedSorter,
@@ -29,6 +33,13 @@ const StringID _vehicle_sort_listing[] = {
INVALID_STRING_ID
};
+const StringID _rail_types_list[] = {
+ STR_RAIL_VEHICLES,
+ STR_MONORAIL_VEHICLES,
+ STR_MAGLEV_VEHICLES,
+ INVALID_STRING_ID
+};
+
void RebuildVehicleLists(void)
{
Window *w;
@@ -294,3 +305,636 @@ int CDECL VehicleMaxSpeedSorter(const void *a, const void *b)
return (_internal_sort_order & 1) ? -r : r;
}
+
+// this define is to match engine.c, but engine.c keeps it to itself
+// ENGINE_AVAILABLE is used in ReplaceVehicleWndProc
+#define ENGINE_AVAILABLE ((e->flags & 1 && HASBIT(info->railtype_climates, _opt.landscape)) || HASBIT(e->player_avail, _local_player))
+
+/* if show_outdated is selected, it do not sort psudo engines properly but it draws all engines
+ * if used compined with show_cars set to false, it will work as intended. Replace window do it like that
+ * this was a big hack even before show_outdated was added. Stupid newgrf :p */
+static void train_engine_drawing_loop(int *x, int *y, int *pos, int *sel, int *selected_id, byte railtype,
+ uint8 lines_drawn, bool is_engine, bool show_cars, bool show_outdated)
+{
+ int i;
+ byte colour;
+
+ for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
+ const Engine *e = DEREF_ENGINE(i);
+ const RailVehicleInfo *rvi = RailVehInfo(i);
+ const EngineInfo *info = &_engine_info[i];
+
+ if ( rvi->power == 0 && !(show_cars) ) // disables display of cars (works since they do not have power)
+ continue;
+
+ if (*sel == 0) *selected_id = i;
+
+
+ colour = *sel == 0 ? 0xC : 0x10;
+ if (!(ENGINE_AVAILABLE && show_outdated && RailVehInfo(i)->power && e->railtype == railtype)) {
+ if (e->railtype != railtype || !(rvi->flags & RVI_WAGON) != is_engine ||
+ !HASBIT(e->player_avail, _local_player))
+ continue;
+ } /*else {
+ // TODO find a nice red colour for vehicles being replaced
+ if ( _autoreplace_array[i] != i )
+ colour = *sel == 0 ? 0x44 : 0x45;
+ } */
+
+ if (IS_INT_INSIDE(--*pos, -lines_drawn, 0)) {
+ DrawString(*x + 59, *y + 2, GetCustomEngineName(i),
+ colour);
+ DrawTrainEngine(*x + 29, *y + 6, i,
+ SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ *y += 14;
+ }
+ --*sel;
+ }
+}
+
+
+static void SetupScrollStuffForReplaceWindow(Window *w)
+{
+ byte railtype;
+ int selected_id[2] = {-1,-1};
+ int sel[2] = { WP(w,replaceveh_d).sel_index[0], WP(w,replaceveh_d).sel_index[1]};
+ int count = 0;
+ int count2 = 0;
+ int engine_id;
+
+ switch (WP(w,replaceveh_d).vehicletype) {
+ case VEH_Train: {
+ railtype = WP(w,replaceveh_d).railtype;
+ for (engine_id = 0; engine_id < NUM_TRAIN_ENGINES; engine_id++) {
+ const Engine *e = DEREF_ENGINE(engine_id);
+ const EngineInfo *info = &_engine_info[engine_id];
+
+ if (ENGINE_AVAILABLE && RailVehInfo(engine_id)->power && e->railtype == railtype) {
+ count++;
+ if (sel[0]==0) selected_id[0] = engine_id;
+ sel[0]--;
+ if (HASBIT(e->player_avail, _local_player)) {
+ if (sel[1]==0) selected_id[1] = engine_id;
+ count2++;
+ sel[1]--;
+ }
+ }
+ }
+ break;
+ }
+ case VEH_Road: {
+ int num = NUM_ROAD_ENGINES;
+ Engine *e = &_engines[ROAD_ENGINES_INDEX];
+ byte cargo;
+ EngineInfo *info;
+ engine_id = ROAD_ENGINES_INDEX;
+
+ do {
+ info = &_engine_info[engine_id];
+ if (ENGINE_AVAILABLE) {
+ if (sel[0]==0) selected_id[0] = engine_id;
+ count++;
+ sel[0]--;
+ }
+ } while (++engine_id,++e,--num);
+
+ if ( selected_id[0] != -1 ) { // only draw right array if we have anything in the left one
+ num = NUM_ROAD_ENGINES;
+ engine_id = ROAD_ENGINES_INDEX;
+ e = &_engines[ROAD_ENGINES_INDEX];
+ cargo = RoadVehInfo(selected_id[0])->cargo_type;
+
+ do {
+ if ( cargo == RoadVehInfo(engine_id)->cargo_type && HASBIT(e->player_avail, _local_player)) {
+ count2++;
+ if (sel[1]==0) selected_id[1] = engine_id;
+ sel[1]--;
+ }
+ } while (++engine_id,++e,--num);
+ }
+ break;
+ }
+
+ case VEH_Ship: {
+ int num = NUM_SHIP_ENGINES;
+ Engine *e = &_engines[SHIP_ENGINES_INDEX];
+ byte cargo;
+ EngineInfo *info;
+ engine_id = SHIP_ENGINES_INDEX;
+ byte refittable;
+
+ do {
+ info = &_engine_info[engine_id];
+ if (ENGINE_AVAILABLE) {
+ if ( sel[0] == 0 ) selected_id[0] = engine_id;
+ count++;
+ sel[0]--;
+ }
+ } while (++engine_id,++e,--num);
+
+ if ( selected_id[0] != -1 ) {
+ num = NUM_SHIP_ENGINES;
+ e = &_engines[SHIP_ENGINES_INDEX];
+ engine_id = SHIP_ENGINES_INDEX;
+ cargo = ShipVehInfo(selected_id[0])->cargo_type;
+ refittable = ShipVehInfo(selected_id[0])->refittable;
+
+ do {
+ if (HASBIT(e->player_avail, _local_player)
+ && ( cargo == ShipVehInfo(engine_id)->cargo_type || refittable & ShipVehInfo(engine_id)->refittable)) {
+
+ if ( sel[1]==0) selected_id[1] = engine_id;
+ sel[1]--;
+ count2++;
+ }
+ } while (++engine_id,++e,--num);
+ }
+ break;
+ } //end of ship
+
+ case VEH_Aircraft:{
+ int num = NUM_AIRCRAFT_ENGINES;
+ Engine *e = &_engines[AIRCRAFT_ENGINES_INDEX];
+ EngineInfo *info;
+ engine_id = AIRCRAFT_ENGINES_INDEX;
+ byte subtype;
+
+ do {
+ info = &_engine_info[engine_id];
+ if (ENGINE_AVAILABLE) {
+ count++;
+ if (sel[0]==0) selected_id[0] = engine_id;
+ sel[0]--;
+ }
+ } while (++engine_id,++e,--num);
+
+ if ( selected_id[0] != -1 ) {
+ num = NUM_AIRCRAFT_ENGINES;
+ e = &_engines[AIRCRAFT_ENGINES_INDEX];
+ subtype = AircraftVehInfo(selected_id[0])->subtype;
+ engine_id = AIRCRAFT_ENGINES_INDEX;
+ do {
+ if (HASBIT(e->player_avail, _local_player)) {
+ if ( (subtype && AircraftVehInfo(engine_id)->subtype) || (!(subtype) && !AircraftVehInfo(engine_id)->subtype) ) {
+ count2++;
+ if (sel[1]==0) selected_id[1] = engine_id;
+ sel[1]--;
+ }
+ }
+ } while (++engine_id,++e,--num);
+ }
+ break;
+ }
+ }
+ // sets up the number of items in each list
+ SetVScrollCount(w, count);
+ SetVScroll2Count(w, count2);
+ WP(w,replaceveh_d).sel_engine[0] = selected_id[0];
+ WP(w,replaceveh_d).sel_engine[1] = selected_id[1];
+
+ WP(w,replaceveh_d).count[0] = count;
+ WP(w,replaceveh_d).count[1] = count2;
+ return;
+}
+
+
+static void DrawEngineArrayInReplaceWindow(Window *w, int x, int y, int x2, int y2, int pos, int pos2,
+ int sel1, int sel2, int selected_id1, int selected_id2)
+{
+ int sel[2] = {sel1, sel2};
+ int selected_id[2] = {selected_id1, selected_id2};
+ switch (WP(w,replaceveh_d).vehicletype) {
+ case VEH_Train: {
+ byte railtype = WP(w,replaceveh_d).railtype;
+ DrawString(157, 89 + (14 * w->vscroll.cap), _rail_types_list[railtype], 0x10);
+ /* draw sorting criteria string */
+
+ /* Ensure that custom engines which substituted wagons
+ * are sorted correctly.
+ * XXX - DO NOT EVER DO THIS EVER AGAIN! GRRR hacking in wagons as
+ * engines to get more types.. Stays here until we have our own format
+ * then it is exit!!! */
+ train_engine_drawing_loop(&x, &y, &pos, &sel[0], &selected_id[0], railtype, w->vscroll.cap, true, false, true); // True engines
+ train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, true, false, false); // True engines
+ train_engine_drawing_loop(&x2, &y2, &pos2, &sel[1], &selected_id[1], railtype, w->vscroll.cap, false, false, false); // Feeble wagons
+ break;
+ }
+
+ case VEH_Road: {
+ int num = NUM_ROAD_ENGINES;
+ Engine *e = &_engines[ROAD_ENGINES_INDEX];
+ int engine_id = ROAD_ENGINES_INDEX;
+ byte cargo;
+ EngineInfo *info;
+
+ if ( selected_id[0] >= ROAD_ENGINES_INDEX && selected_id[0] <= SHIP_ENGINES_INDEX )
+ cargo = RoadVehInfo(selected_id[0])->cargo_type;
+
+ do {
+ info = &_engine_info[engine_id];
+ if (ENGINE_AVAILABLE) {
+ if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
+ DrawString(x+59, y+2, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
+ DrawRoadVehEngine(x+29, y+6, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ y += 14;
+ }
+
+ if ( RoadVehInfo(engine_id)->cargo_type == cargo && HASBIT(e->player_avail, _local_player) ) {
+ if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0) && RoadVehInfo(engine_id)->cargo_type == cargo) {
+ DrawString(x2+59, y2+2, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
+ DrawRoadVehEngine(x2+29, y2+6, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ y2 += 14;
+ }
+ sel[1]--;
+ }
+ sel[0]--;
+ }
+ } while (++engine_id, ++e,--num);
+
+ break;
+ }
+
+ case VEH_Ship: {
+ int num = NUM_SHIP_ENGINES;
+ Engine *e = &_engines[SHIP_ENGINES_INDEX];
+ int engine_id = SHIP_ENGINES_INDEX;
+ byte cargo, refittable;
+ EngineInfo *info;
+
+ if ( selected_id[0] != -1 ) {
+ cargo = ShipVehInfo(selected_id[0])->cargo_type;
+ refittable = ShipVehInfo(selected_id[0])->refittable;
+ }
+
+ do {
+ info = &_engine_info[engine_id];
+ if (ENGINE_AVAILABLE) {
+ if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
+ DrawString(x+75, y+7, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
+ DrawShipEngine(x+35, y+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ y += 24;
+ }
+ if ( selected_id[0] != -1 ) {
+ if (HASBIT(e->player_avail, _local_player) && ( cargo == ShipVehInfo(engine_id)->cargo_type || refittable & ShipVehInfo(engine_id)->refittable)) {
+ if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0)) {
+ DrawString(x2+75, y2+7, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
+ DrawShipEngine(x2+35, y2+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ y2 += 24;
+ }
+ sel[1]--;
+ }
+ }
+ sel[0]--;
+ }
+ } while (++engine_id, ++e,--num);
+ break;
+ } //end of ship
+
+ case VEH_Aircraft: {
+ if ( selected_id[0] != -1 ) {
+ int num = NUM_AIRCRAFT_ENGINES;
+ Engine *e = &_engines[AIRCRAFT_ENGINES_INDEX];
+ int engine_id = AIRCRAFT_ENGINES_INDEX;
+ byte subtype = AircraftVehInfo(selected_id[0])->subtype;
+ EngineInfo *info;
+
+ do {
+ info = &_engine_info[engine_id];
+ if (ENGINE_AVAILABLE) {
+ if (sel[0]==0) selected_id[0] = engine_id;
+ if (IS_INT_INSIDE(--pos, -w->vscroll.cap, 0)) {
+ DrawString(x+62, y+7, GetCustomEngineName(engine_id), sel[0]==0 ? 0xC : 0x10);
+ DrawAircraftEngine(x+29, y+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ y += 24;
+ }
+ if ( ((subtype && AircraftVehInfo(engine_id)->subtype) || (!(subtype) && !AircraftVehInfo(engine_id)->subtype))
+ && HASBIT(e->player_avail, _local_player) ) {
+ if (sel[1]==0) selected_id[1] = engine_id;
+ if (IS_INT_INSIDE(--pos2, -w->vscroll.cap, 0)) {
+ DrawString(x2+62, y2+7, GetCustomEngineName(engine_id), sel[1]==0 ? 0xC : 0x10);
+ DrawAircraftEngine(x2+29, y2+10, engine_id, SPRITE_PALETTE(PLAYER_SPRITE_COLOR(_local_player)));
+ y2 += 24;
+ }
+ sel[1]--;
+ }
+ sel[0]--;
+ }
+ } while (++engine_id, ++e,--num);
+ }
+ break;
+ } // end of aircraft
+ }
+
+}
+static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
+{
+ // these 3 variables is used if any of the lists is clicked
+ uint16 click_scroll_pos = w->vscroll2.pos;
+ uint16 click_scroll_cap = w->vscroll2.cap;
+ byte click_side = 1;
+
+ switch(e->event) {
+ case WE_PAINT:
+ {
+ int pos = w->vscroll.pos;
+ int selected_id[2] = {-1,-1};
+ int x = 1;
+ int y = 15;
+ int pos2 = w->vscroll2.pos;
+ int x2 = 1 + 228;
+ int y2 = 15;
+ int sel[2] = { WP(w,replaceveh_d).sel_index[0], WP(w,replaceveh_d).sel_index[1]};
+
+ SetupScrollStuffForReplaceWindow(w);
+
+ selected_id[0] = WP(w,replaceveh_d).sel_engine[0];
+ selected_id[1] = WP(w,replaceveh_d).sel_engine[1];
+
+ // sets the selected left item to the top one if it's greater than the number of vehicles in the left side
+
+ if ( WP(w,replaceveh_d).count[0] <= sel[0] ) {
+ if (WP(w,replaceveh_d).count[0]) {
+ sel[0] = 0;
+ WP(w,replaceveh_d).sel_index[0] = 0;
+ w->vscroll.pos = 0;
+ // now we go back to set selected_id[1] properly
+ SetWindowDirty(w);
+ return;
+ } else { //there are no vehicles in the left window
+ selected_id[1] = -1;
+ }
+ }
+
+ if ( WP(w,replaceveh_d).count[1] <= sel[1] ) {
+ if (WP(w,replaceveh_d).count[1]) {
+ sel[1] = 0;
+ WP(w,replaceveh_d).sel_index[1] = 0;
+ w->vscroll2.pos = 0;
+ // now we go back to set selected_id[1] properly
+ SetWindowDirty(w);
+ return;
+ } else { //there are no vehicles in the right window
+ selected_id[1] = -1;
+ }
+ }
+
+ if ( selected_id[0] == selected_id[1] || _autoreplace_array[selected_id[0]] == selected_id[1]
+ || selected_id[0] == -1 || selected_id[1] == -1 )
+ SETBIT(w->disabled_state, 4);
+ else
+ CLRBIT(w->disabled_state, 4);
+
+ if ( _autoreplace_array[selected_id[0]] == selected_id[0] || selected_id[0] == -1 )
+ SETBIT(w->disabled_state, 6);
+ else
+ CLRBIT(w->disabled_state, 6);
+
+ // now the actual drawing of the window itself takes place
+ DrawWindowWidgets(w);
+
+
+
+ // sets up the string for the vehicle that is being replaced to
+ if ( selected_id[0] != -1 ) {
+ if ( selected_id[0] == _autoreplace_array[selected_id[0]] )
+ SetDParam(0, STR_NOT_REPLACING);
+ else
+ SetDParam(0, GetCustomEngineName(_autoreplace_array[selected_id[0]]));
+ } else {
+ SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
+ }
+
+
+ DrawString(145, (WP(w,replaceveh_d).line_height == 24 ? 67 : 77 ) + ( WP(w,replaceveh_d).line_height * w->vscroll.cap), STR_02BD, 0x10);
+
+
+ /* now we draw the two arrays according to what we just counted */
+ DrawEngineArrayInReplaceWindow(w, x, y, x2, y2, pos, pos2, sel[0], sel[1], selected_id[0], selected_id[1]);
+
+ WP(w,replaceveh_d).sel_engine[0] = selected_id[0];
+ WP(w,replaceveh_d).sel_engine[1] = selected_id[1];
+ /* now we draw the info about the vehicles we selected */
+ switch (WP(w,replaceveh_d).vehicletype) {
+ case VEH_Train: {
+ byte i = 0;
+ int offset = 0;
+
+ for ( i = 0 ; i < 2 ; i++) {
+ if ( i )
+ offset = 228;
+ if (selected_id[i] != -1) {
+ if (!(RailVehInfo(selected_id[i])->flags & RVI_WAGON)) {
+ /* it's an engine */
+ Set_DPARAM_Train_Engine_Build_Window(selected_id[i]);
+ DrawString(2 + offset, 15 + (14 * w->vscroll.cap), STR_8817_COST_WEIGHT_T_SPEED_POWER, 0);
+ } else {
+ /* it's a wagon. Train cars are not replaced with the current GUI, but this code is ready for newgrf if anybody adds that*/
+ Set_DPARAM_Train_Car_Build_Window(w, selected_id[i]);
+ DrawString(2 + offset, 15 + (14 * w->vscroll.cap), STR_8821_COST_WEIGHT_T_T_CAPACITY, 0);
+ }
+ }
+ }
+ break;
+ } //end if case VEH_Train
+
+ case VEH_Road: {
+ if (selected_id[0] != -1) {
+ Set_DPARAM_Road_Veh_Build_Window(selected_id[0]);
+ DrawString(2, 15 + (14 * w->vscroll.cap), STR_9008_COST_SPEED_RUNNING_COST, 0);
+ if (selected_id[1] != -1) {
+ Set_DPARAM_Road_Veh_Build_Window(selected_id[1]);
+ DrawString(2 + 228, 15 + (14 * w->vscroll.cap), STR_9008_COST_SPEED_RUNNING_COST, 0);
+ }
+ }
+ break;
+ } // end of VEH_Road
+
+ case VEH_Ship: {
+ if (selected_id[0] != -1) {
+ Set_DPARAM_Ship_Build_Window(selected_id[0]);
+ DrawString(2, 15 + (24 * w->vscroll.cap), STR_980A_COST_SPEED_CAPACITY_RUNNING, 0);
+ if (selected_id[1] != -1) {
+ Set_DPARAM_Ship_Build_Window(selected_id[1]);
+ DrawString(2 + 228, 15 + (24 * w->vscroll.cap), STR_980A_COST_SPEED_CAPACITY_RUNNING, 0);
+ }
+ }
+ break;
+ } // end of VEH_Ship
+
+ case VEH_Aircraft: {
+ if (selected_id[0] != -1) {
+ Set_DPARAM_Aircraft_Build_Window(selected_id[0]);
+ DrawString(2, 15 + (24 * w->vscroll.cap), STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0);
+ if (selected_id[1] != -1) {
+ Set_DPARAM_Aircraft_Build_Window(selected_id[1]);
+ DrawString(2 + 228, 15 + (24 * w->vscroll.cap), STR_A007_COST_SPEED_CAPACITY_PASSENGERS, 0);
+ }
+ }
+ break;
+ } // end of VEH_Aircraft
+ }
+ } // end of paint
+
+ case WE_CLICK: {
+ switch(e->click.widget) {
+ /*case 0:
+ DeleteWindowById(WC_REPLACE_VEHICLE, WP(w,replaceveh_d).vehicletype );
+ break;*/
+
+ case 14: case 15:/* Select sorting criteria dropdown menu */
+ // finds mask for available engines
+ {
+ int engine_avail = 0;
+ if ( !(HASBIT(_engines[NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES].player_avail, _local_player))) {
+ engine_avail = 4;
+ if ( !(HASBIT(_engines[NUM_NORMAL_RAIL_ENGINES].player_avail, _local_player)))
+ engine_avail = 6;
+ }
+ ShowDropDownMenu(w, _rail_types_list, WP(w,replaceveh_d).railtype, 15, engine_avail, 1);
+ return;
+ }
+ case 4: {
+ _autoreplace_array[WP(w,replaceveh_d).sel_engine[0]] = WP(w,replaceveh_d).sel_engine[1];
+ SetWindowDirty(w);
+ break;
+ }
+
+ case 6: {
+ _autoreplace_array[WP(w,replaceveh_d).sel_engine[0]] = WP(w,replaceveh_d).sel_engine[0];
+ SetWindowDirty(w);
+ break;
+ }
+
+ case 7:
+ // sets up that the left one was clicked. The default values are for the right one (9)
+ // this way, the code for 9 handles both sides
+ click_scroll_pos = w->vscroll.pos;
+ click_scroll_cap = w->vscroll.cap;
+ click_side = 0;
+ case 9: {
+ uint i = (e->click.pt.y - 14) / WP(w,replaceveh_d).line_height;
+ if (i < click_scroll_cap) {
+ WP(w,replaceveh_d).sel_index[click_side] = i + click_scroll_pos;
+ SetWindowDirty(w);
+ }
+ } break;
+ }
+
+ } break;
+
+ case WE_DROPDOWN_SELECT: { /* we have selected a dropdown item in the list */
+ //potiential bug: railtypes needs to be activated 0, 1, 2... If one is skipped, it messes up
+ WP(w,replaceveh_d).railtype = e->dropdown.index;
+ SetWindowDirty(w);
+ break;
+ }
+ }
+}
+
+static const Widget _replace_rail_vehicle_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 443, 0, 13, STR_REPLACE_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_STICKYBOX, 14, 444, 455, 0, 13, 0x0, STR_STICKY_BUTTON},
+{ WWT_PANEL, 14, 0, 227, 126, 187, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 0, 138, 200, 211, STR_REPLACE_VEHICLES_START,STR_REPLACE_HELP_START_BUTTON},
+{ WWT_PANEL, 14, 139, 316, 188, 199, 0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB},
+{ WWT_PUSHTXTBTN, 14, 317, 455, 200, 211, STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON},
+{ WWT_MATRIX, 14, 0, 216, 14, 125, 0x801, STR_REPLACE_HELP_LEFT_ARRAY},
+{ WWT_SCROLLBAR, 14, 217, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_MATRIX, 14, 228, 455, 14, 125, 0x801, STR_REPLACE_HELP_RIGHT_ARRAY},
+{ WWT_SCROLL2BAR, 14, 445, 455, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PANEL, 14, 228, 455, 126, 187, 0x0, STR_NULL},
+// the rest are train specific stuff
+{ WWT_PANEL, 14, 0, 138, 188, 199, 0x0, STR_NULL},
+{ WWT_PANEL, 3, 139, 153, 200, 211, 0x0, STR_NULL},
+{ WWT_PANEL, 14, 154, 290, 200, 211, 0x0, STR_REPLACE_HELP_RAILTYPE},
+{ WWT_CLOSEBOX, 14, 291, 301, 200, 210, STR_0225, STR_REPLACE_HELP_RAILTYPE},
+{ WWT_PANEL, 3, 301, 316, 200, 211, 0x0, STR_NULL},
+{ WWT_PANEL, 14, 317, 455, 188, 199, 0x0, STR_NULL},
+
+{ WIDGETS_END},
+};
+
+static const Widget _replace_road_vehicle_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 443, 0, 13, STR_REPLACE_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_STICKYBOX, 14, 444, 455, 0, 13, 0x0, STR_STICKY_BUTTON},
+{ WWT_PANEL, 14, 0, 227, 126, 187, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 0, 138, 188, 199, STR_REPLACE_VEHICLES_START,STR_REPLACE_HELP_START_BUTTON},
+{ WWT_PANEL, 14, 139, 316, 188, 199, 0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB},
+{ WWT_PUSHTXTBTN, 14, 317, 455, 188, 199, STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON},
+{ WWT_MATRIX, 14, 0, 216, 14, 125, 0x801, STR_REPLACE_HELP_LEFT_ARRAY},
+{ WWT_SCROLLBAR, 14, 217, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_MATRIX, 14, 228, 455, 14, 125, 0x801, STR_REPLACE_HELP_RIGHT_ARRAY},
+{ WWT_SCROLL2BAR, 14, 445, 455, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PANEL, 14, 228, 455, 126, 187, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
+
+static const Widget _replace_ship_aircraft_vehicle_widgets[] = {
+{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, 14, 11, 443, 0, 13, STR_REPLACE_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_STICKYBOX, 14, 444, 455, 0, 13, 0x0, STR_STICKY_BUTTON},
+{ WWT_PANEL, 14, 0, 227, 110, 161, 0x0, STR_NULL},
+{ WWT_PUSHTXTBTN, 14, 0, 138, 162, 173, STR_REPLACE_VEHICLES_START,STR_REPLACE_HELP_START_BUTTON},
+{ WWT_PANEL, 14, 139, 316, 162, 173, 0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB},
+{ WWT_PUSHTXTBTN, 14, 317, 455, 162, 173, STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON},
+{ WWT_MATRIX, 14, 0, 216, 14, 109, 0x401, STR_REPLACE_HELP_LEFT_ARRAY},
+{ WWT_SCROLLBAR, 14, 217, 227, 14, 109, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_MATRIX, 14, 228, 455, 14, 109, 0x401, STR_REPLACE_HELP_RIGHT_ARRAY},
+{ WWT_SCROLL2BAR, 14, 445, 455, 14, 109, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_PANEL, 14, 228, 455, 110, 161, 0x0, STR_NULL},
+{ WIDGETS_END},
+};
+
+static const WindowDesc _replace_rail_vehicle_desc = {
+ -1, -1, 456, 212,
+ WC_REPLACE_VEHICLE,0,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+ _replace_rail_vehicle_widgets,
+ ReplaceVehicleWndProc
+};
+
+static const WindowDesc _replace_road_vehicle_desc = {
+ -1, -1, 456, 200,
+ WC_REPLACE_VEHICLE,0,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+ _replace_road_vehicle_widgets,
+ ReplaceVehicleWndProc
+};
+
+static const WindowDesc _replace_ship_aircraft_vehicle_desc = {
+ -1, -1, 456, 174,
+ WC_REPLACE_VEHICLE,0,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON,
+ _replace_ship_aircraft_vehicle_widgets,
+ ReplaceVehicleWndProc
+};
+
+
+void ShowReplaceVehicleWindow(byte vehicletype)
+{
+ Window *w;
+
+ DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype );
+
+ switch (vehicletype) {
+ case VEH_Train:
+ w = AllocateWindowDescFront(&_replace_rail_vehicle_desc, vehicletype);
+ w->vscroll.cap = 8;
+ WP(w,replaceveh_d).line_height = 14;
+ break;
+ case VEH_Road:
+ w = AllocateWindowDescFront(&_replace_road_vehicle_desc, vehicletype);
+ w->vscroll.cap = 8;
+ WP(w,replaceveh_d).line_height = 14;
+ break;
+ case VEH_Ship: case VEH_Aircraft:
+ w = AllocateWindowDescFront(&_replace_ship_aircraft_vehicle_desc, vehicletype);
+ w->vscroll.cap = 4;
+ WP(w,replaceveh_d).line_height = 24;
+ break;
+ }
+ WP(w,replaceveh_d).vehicletype = vehicletype;
+ w->vscroll2.cap = w->vscroll.cap; // these two are always the same
+}
diff --git a/vehicle_gui.h b/vehicle_gui.h
index 9339d4647..46747d6bf 100644
--- a/vehicle_gui.h
+++ b/vehicle_gui.h
@@ -42,12 +42,13 @@ typedef DEF_SORTER(VehicleSortListingTypeFunctions);
#define SORT_BY_UNSORTED 0
extern VehicleSortListingTypeFunctions * const _vehicle_sorter[];
extern const StringID _vehicle_sort_listing[];
+extern const StringID _rail_types_list[];
enum VehicleSortTypes {
VEHTRAIN = 0,
VEHROAD = 1,
VEHSHIP = 2,
- VEHAIRCRAFT = 3
+ VEHAIRCRAFT = 3
};
enum {
@@ -56,4 +57,13 @@ enum {
PLY_WND_PRC__SIZE_OF_ROW_BIG = 36,
};
+void ShowReplaceVehicleWindow(byte vehicletype);
+
+void Set_DPARAM_Train_Engine_Build_Window(uint16 engine_number);
+void Set_DPARAM_Train_Car_Build_Window(Window *w, uint16 engine_number);
+void Set_DPARAM_Road_Veh_Build_Window(uint16 engine_number);
+void Set_DPARAM_Aircraft_Build_Window(uint16 engine_number);
+void Set_DPARAM_Ship_Build_Window(uint16 engine_number);
+
+
#endif /* VEHICLE_GUI_H */
diff --git a/widget.c b/widget.c
index 013083ef2..9f998df45 100644
--- a/widget.c
+++ b/widget.c
@@ -46,23 +46,37 @@ void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y)
int mi, ma, pos;
Scrollbar *sb;
- if (wi->type == WWT_SCROLLBAR) {
- // vertical scroller
- w->flags4 &= ~WF_HSCROLL;
- mi = wi->top;
- ma = wi->bottom;
- pos = y;
- sb = &w->vscroll;
- } else {
- // horizontal scroller
- assert(wi->type == WWT_HSCROLLBAR);
- w->flags4 |= WF_HSCROLL;
- mi = wi->left;
- ma = wi->right;
- pos = x;
- sb = &w->hscroll;
+ switch (wi->type) {
+ case WWT_SCROLLBAR: {
+ // vertical scroller
+ w->flags4 &= ~WF_HSCROLL;
+ w->flags4 &= ~WF_SCROLL2;
+ mi = wi->top;
+ ma = wi->bottom;
+ pos = y;
+ sb = &w->vscroll;
+ break;
+ }
+ case WWT_SCROLL2BAR: {
+ // 2nd vertical scroller
+ w->flags4 &= ~WF_HSCROLL;
+ w->flags4 |= WF_SCROLL2;
+ mi = wi->top;
+ ma = wi->bottom;
+ pos = y;
+ sb = &w->vscroll2;
+ break;
+ }
+ case WWT_HSCROLLBAR: {
+ // horizontal scroller
+ assert(wi->type == WWT_HSCROLLBAR);
+ w->flags4 |= WF_HSCROLL;
+ mi = wi->left;
+ ma = wi->right;
+ pos = x;
+ sb = &w->hscroll;
+ }
}
-
if (pos <= mi+9) {
// Pressing the upper button?
if (!_demo_mode) {
@@ -258,8 +272,8 @@ void DrawWindowWidgets(Window *w)
int c1,c2;
// draw up/down buttons
- DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == WF_SCROLL_UP ? 0x20 : 0);
- DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == WF_SCROLL_DOWN ? 0x20 : 0);
+ DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP ? 0x20 : 0);
+ DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN ? 0x20 : 0);
// draw icons in up/down buttons
DoDrawString("\xA0", r.left+2, r.top, 0x10);
@@ -279,7 +293,36 @@ void DrawWindowWidgets(Window *w)
GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2);
pt = HandleScrollbarHittest(&w->vscroll, r.top, r.bottom);
- DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == WF_SCROLL_MIDDLE ? 0x20 : 0);
+ DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE ? 0x20 : 0);
+ break;
+ }
+ case WWT_SCROLL2BAR: {
+ Point pt;
+ int c1,c2;
+
+ // draw up/down buttons
+ DrawFrameRect(r.left, r.top, r.right, r.top+9, wi->color, (w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2) ? 0x20 : 0);
+ DrawFrameRect(r.left, r.bottom-9, r.right, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2) ? 0x20 : 0);
+
+ // draw icons in up/down buttons
+ DoDrawString("\xA0", r.left+2, r.top, 0x10);
+ DoDrawString("\xAA", r.left+2, r.bottom-9, 0x10);
+
+ c1 = _color_list[wi->color&0xF].window_color_1a;
+ c2 = _color_list[wi->color&0xF].window_color_2;
+
+ // draw "shaded" background
+ GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2);
+ GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | 0x8000);
+
+ // draw shaded lines
+ GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1);
+ GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2);
+ GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1);
+ GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2);
+
+ pt = HandleScrollbarHittest(&w->vscroll2, r.top, r.bottom);
+ DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? 0x20 : 0);
break;
}
@@ -383,6 +426,7 @@ draw_default:;
static uint _dropdown_item_count;
static uint32 _dropdown_disabled;
+static bool _dropdown_hide_disabled;
static const StringID *_dropdown_items;
static int _dropdown_selindex;
static byte _dropdown_button;
@@ -421,95 +465,100 @@ void DropdownMenuWndProc(Window *w, WindowEvent *e)
int item;
switch(e->event) {
- case WE_PAINT: {
- int x,y,i,sel;
- uint32 dis;
-
- DrawWindowWidgets(w);
-
- x = 1;
- y = 2;
- sel = _dropdown_selindex;
- dis = _dropdown_disabled;
+ case WE_PAINT: {
+ int x,y,i,sel;
+ uint32 dis;
+ bool hidden;
+
+ DrawWindowWidgets(w);
+
+ x = 1;
+ y = 2;
+ sel = _dropdown_selindex;
+ dis = _dropdown_disabled;
+ hidden = _dropdown_hide_disabled;
+
- for(i=0; _dropdown_items[i] != INVALID_STRING_ID; i++) {
- if (_dropdown_items[i] != 0) {
- if (sel == 0) {
- GfxFillRect(x+1, y, x+w->width-4, y + 9, 0);
+ for(i=0; _dropdown_items[i] != INVALID_STRING_ID; i++) {
+ if (!(hidden) | !(dis & 1)) {
+ if (_dropdown_items[i] != 0) {
+ if (sel == 0) {
+ GfxFillRect(x+1, y, x+w->width-4, y + 9, 0);
+ }
+ DrawString(x+2, y, _dropdown_items[i], sel==0 ? 12 : 16);
+
+ if (dis & 1) {
+ GfxFillRect(x, y, x+w->width-3, y + 9, 0x8000 +
+ _color_list[_dropdown_menu_widgets[0].color].window_color_bga);
+ }
+ } else {
+ int color_1 = _color_list[_dropdown_menu_widgets[0].color].window_color_1a;
+ int color_2 = _color_list[_dropdown_menu_widgets[0].color].window_color_2;
+ GfxFillRect(x+1, y+3, x+w->width-5, y+3, color_1);
+ GfxFillRect(x+1, y+4, x+w->width-5, y+4, color_2);
+ }
+ y += 10;
+ sel--;
}
- DrawString(x+2, y, _dropdown_items[i], sel==0 ? 12 : 16);
+ dis>>=1;
+ }
+ } break;
- if (dis & 1) {
- GfxFillRect(x, y, x+w->width-3, y + 9, 0x8000 +
- _color_list[_dropdown_menu_widgets[0].color].window_color_bga);
- }
- } else {
- int color_1 = _color_list[_dropdown_menu_widgets[0].color].window_color_1a;
- int color_2 = _color_list[_dropdown_menu_widgets[0].color].window_color_2;
- GfxFillRect(x+1, y+3, x+w->width-5, y+3, color_1);
- GfxFillRect(x+1, y+4, x+w->width-5, y+4, color_2);
+ case WE_CLICK: {
+ item = GetDropdownItem(w);
+ if (item >= 0) {
+ _dropdown_var1 = 4;
+ _dropdown_selindex = item;
+ SetWindowDirty(w);
}
- y += 10;
- sel--;
- dis>>=1;
- }
- } break;
-
- case WE_CLICK: {
- item = GetDropdownItem(w);
- if (item >= 0) {
- _dropdown_var1 = 4;
- _dropdown_selindex = item;
- SetWindowDirty(w);
- }
- } break;
+ } break;
- case WE_MOUSELOOP: {
- Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
- if (w2 == NULL) {
- DeleteWindow(w);
- return;
- }
+ case WE_MOUSELOOP: {
+ Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
+ if (w2 == NULL) {
+ DeleteWindow(w);
+ return;
+ }
- if (_dropdown_var1 != 0 && --_dropdown_var1 == 0) {
- WindowEvent e;
- e.event = WE_DROPDOWN_SELECT;
- e.dropdown.button = _dropdown_button;
- e.dropdown.index = _dropdown_selindex;
- w2->wndproc(w2, &e);
- DeleteWindow(w);
- return;
- }
+ if (_dropdown_var1 != 0 && --_dropdown_var1 == 0) {
+ WindowEvent e;
+ e.event = WE_DROPDOWN_SELECT;
+ e.dropdown.button = _dropdown_button;
+ e.dropdown.index = _dropdown_selindex;
+ w2->wndproc(w2, &e);
+ DeleteWindow(w);
+ return;
+ }
- if (_dropdown_var2 != 0) {
- item = GetDropdownItem(w);
+ if (_dropdown_var2 != 0) {
+ item = GetDropdownItem(w);
+
+ if (!_left_button_clicked) {
+ _dropdown_var2 = 0;
+ if (item < 0)
+ return;
+ _dropdown_var1 = 2;
+ } else {
+ if (item < 0)
+ return;
+ }
- if (!_left_button_clicked) {
- _dropdown_var2 = 0;
- if (item < 0)
- return;
- _dropdown_var1 = 2;
- } else {
- if (item < 0)
- return;
+ _dropdown_selindex = item;
+ SetWindowDirty(w);
}
+ } break;
- _dropdown_selindex = item;
- SetWindowDirty(w);
- }
- } break;
-
- case WE_DESTROY: {
- Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
- if (w2 != NULL) {
- CLRBIT(w2->click_state, _dropdown_button);
- InvalidateWidget(w2, _dropdown_button);
- }
- } break;
+ case WE_DESTROY: {
+ Window *w2 = FindWindowById(_dropdown_windowclass, _dropdown_windownum);
+ if (w2 != NULL) {
+ CLRBIT(w2->click_state, _dropdown_button);
+ InvalidateWidget(w2, _dropdown_button);
+ }
+ } break;
}
}
-void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask)
+void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, bool remove_filtered_strings)
{
WindowNumber num;
WindowClass cls;
@@ -519,6 +568,7 @@ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int butt
uint32 old_click_state = w->click_state;
_dropdown_disabled = disabled_mask;
+ _dropdown_hide_disabled = remove_filtered_strings;
cls = w->window_class;
num = w->window_number;
@@ -549,6 +599,16 @@ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int butt
wi = &w->widget[button];
+ if ( remove_filtered_strings ) {
+ int j;
+ for(j=0; _dropdown_items[j] != INVALID_STRING_ID; j++) {
+ if ( disabled_mask & ( 1 << j )) {
+ _dropdown_item_count--;
+ i--;
+ }
+ }
+ }
+
_dropdown_menu_widgets[0].color = wi->color;
w2 = AllocateWindow(
diff --git a/window.c b/window.c
index 8bcb690f5..4474b8604 100644
--- a/window.c
+++ b/window.c
@@ -44,7 +44,7 @@ void DispatchLeftClickEvent(Window *w, int x, int y) {
case WWT_NODISTXTBTN:
break;
}
- } else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_HSCROLLBAR) {
+ } else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_SCROLL2BAR || wi->type == WWT_HSCROLLBAR) {
ScrollbarClickHandler(w, wi, e.click.pt.x, e.click.pt.y);
}
@@ -953,6 +953,9 @@ static bool HandleScrollbarScrolling()
if (w->flags4 & WF_HSCROLL) {
sb = &w->hscroll;
i = _cursor.pos.x - _cursorpos_drag_start.x;
+ } else if (w->flags4 & WF_SCROLL2){
+ sb = &w->vscroll2;
+ i = _cursor.pos.y - _cursorpos_drag_start.y;
} else {
sb = &w->vscroll;
i = _cursor.pos.y - _cursorpos_drag_start.y;
diff --git a/window.h b/window.h
index 943335443..0d7c8be54 100644
--- a/window.h
+++ b/window.h
@@ -200,7 +200,7 @@ struct Window {
int left,top;
int width,height;
- Scrollbar hscroll, vscroll;
+ Scrollbar hscroll, vscroll, vscroll2;
byte caption_color;
@@ -255,6 +255,15 @@ typedef struct {
} buildtrain_d;
typedef struct {
+ byte railtype;
+ byte vehicletype;
+ byte sel_index[2];
+ int16 sel_engine[2];
+ uint16 count[2];
+ byte line_height;
+} replaceveh_d;
+
+typedef struct {
VehicleID sel;
} traindepot_d;
@@ -358,7 +367,8 @@ enum WindowWidgetTypes {
WWT_HSCROLLBAR = 11,
WWT_STICKYBOX = 12,
- WWT_LAST = 13, /* Last Item. use WIDGETS_END to fill up padding!! */
+ WWT_SCROLL2BAR = 13, /* 2nd vertical scrollbar*/
+ WWT_LAST = 14, /* Last Item. use WIDGETS_END to fill up padding!! */
WWT_MASK = 31,
@@ -384,6 +394,7 @@ enum WindowFlags {
WF_WHITE_BORDER_ONE = 1 << 11,
WF_WHITE_BORDER_MASK = 3 << 11,
+ WF_SCROLL2 = 1 << 13,
};
@@ -453,7 +464,7 @@ int PositionMainToolbar(Window *w);
/* widget.c */
int GetWidgetFromPos(Window *w, int x, int y);
void DrawWindowWidgets(Window *w);
-void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask);
+void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int button, uint32 disabled_mask, bool remove_filtered_strings);
void HandleButtonClick(Window *w, byte widget);