Update from KeldorKatarn branch
This approximately corresponds to 971ba4928a5c7c7916fea55d91a3b6dd5bba140c, excluding the different virtual train build GUI, but including the basic changes to the original train build GUI for multiplayer to work. Fixup
This commit is contained in:
@@ -106,6 +106,8 @@ CommandProc CmdDecreaseLoan;
|
||||
|
||||
CommandProc CmdWantEnginePreview;
|
||||
|
||||
CommandProc CmdSetVehicleUnitNumber;
|
||||
|
||||
CommandProc CmdRenameVehicle;
|
||||
CommandProc CmdRenameEngine;
|
||||
|
||||
@@ -175,10 +177,27 @@ CommandProc CmdRemoveSignalTrack;
|
||||
|
||||
CommandProc CmdSetAutoReplace;
|
||||
|
||||
CommandProc CmdToggleReuseDepotVehicles;
|
||||
CommandProc CmdToggleKeepRemainingVehicles;
|
||||
CommandProc CmdToggleRefitAsTemplate;
|
||||
|
||||
CommandProc CmdVirtualTrainFromTemplateVehicle;
|
||||
CommandProc CmdVirtualTrainFromTrain;
|
||||
CommandProc CmdDeleteVirtualTrain;
|
||||
CommandProc CmdBuildVirtualRailVehicle;
|
||||
CommandProc CmdReplaceTemplateVehicle;
|
||||
|
||||
CommandProc CmdTemplateVehicleFromTrain;
|
||||
CommandProc CmdDeleteTemplateVehicle;
|
||||
|
||||
CommandProc CmdIssueTemplateReplacement;
|
||||
CommandProc CmdDeleteTemplateReplacement;
|
||||
|
||||
CommandProc CmdCloneVehicle;
|
||||
CommandProc CmdStartStopVehicle;
|
||||
CommandProc CmdMassStartStopVehicle;
|
||||
CommandProc CmdAutoreplaceVehicle;
|
||||
CommandProc CmdTemplateReplaceVehicle;
|
||||
CommandProc CmdDepotSellAllVehicles;
|
||||
CommandProc CmdDepotMassAutoReplace;
|
||||
|
||||
@@ -267,6 +286,8 @@ static const Command _command_proc_table[] = {
|
||||
|
||||
DEF_CMD(CmdWantEnginePreview, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_WANT_ENGINE_PREVIEW
|
||||
|
||||
DEF_CMD(CmdSetVehicleUnitNumber, 0, CMDT_OTHER_MANAGEMENT ), // CMD_SET_VEHICLE_UNIT_NUMBER
|
||||
|
||||
DEF_CMD(CmdRenameVehicle, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_VEHICLE
|
||||
DEF_CMD(CmdRenameEngine, CMD_SERVER, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_ENGINE
|
||||
|
||||
@@ -334,10 +355,28 @@ static const Command _command_proc_table[] = {
|
||||
DEF_CMD(CmdChangeSetting, CMD_SERVER, CMDT_SERVER_SETTING ), // CMD_CHANGE_SETTING
|
||||
DEF_CMD(CmdChangeCompanySetting, 0, CMDT_COMPANY_SETTING ), // CMD_CHANGE_COMPANY_SETTING
|
||||
DEF_CMD(CmdSetAutoReplace, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_SET_AUTOREPLACE
|
||||
|
||||
DEF_CMD(CmdToggleReuseDepotVehicles, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_REUSE_DEPOT_VEHICLES
|
||||
DEF_CMD(CmdToggleKeepRemainingVehicles, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_KEEP_REMAINING_VEHICLES
|
||||
DEF_CMD(CmdToggleRefitAsTemplate, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_REFIT_AS_TEMPLATE
|
||||
|
||||
DEF_CMD(CmdVirtualTrainFromTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE
|
||||
DEF_CMD(CmdVirtualTrainFromTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_VIRTUAL_TRAIN_FROM_TRAIN
|
||||
DEF_CMD(CmdDeleteVirtualTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_VIRTUAL_TRAIN
|
||||
DEF_CMD(CmdBuildVirtualRailVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_BUILD_VIRTUAL_RAIL_VEHICLE
|
||||
DEF_CMD(CmdReplaceTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_REPLACE_TEMPLATE_VEHICLE
|
||||
|
||||
DEF_CMD(CmdTemplateVehicleFromTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN
|
||||
DEF_CMD(CmdDeleteTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_TEMPLATE_VEHICLE
|
||||
|
||||
DEF_CMD(CmdIssueTemplateReplacement, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_ISSUE_TEMPLATE_REPLACEMENT
|
||||
DEF_CMD(CmdDeleteTemplateReplacement, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_TEMPLATE_REPLACEMENT
|
||||
|
||||
DEF_CMD(CmdCloneVehicle, CMD_NO_TEST, CMDT_VEHICLE_CONSTRUCTION ), // CMD_CLONE_VEHICLE; NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost
|
||||
DEF_CMD(CmdStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_START_STOP_VEHICLE
|
||||
DEF_CMD(CmdMassStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_MASS_START_STOP
|
||||
DEF_CMD(CmdAutoreplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_AUTOREPLACE_VEHICLE
|
||||
DEF_CMD(CmdTemplateReplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_TEMPLATE_REPLACE_VEHICLE
|
||||
DEF_CMD(CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_SELL_ALL_VEHICLES
|
||||
DEF_CMD(CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION ), // CMD_DEPOT_MASS_AUTOREPLACE
|
||||
DEF_CMD(CmdCreateGroup, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_CREATE_GROUP
|
||||
|
@@ -125,4 +125,12 @@ CommandCallback CcFoundRandomTown;
|
||||
CommandCallback CcBuildPrimaryVehicle;
|
||||
CommandCallback CcStartStopVehicle;
|
||||
|
||||
/* tbtr_template_gui_create.cpp */
|
||||
CommandCallback CcSetVirtualTrain;
|
||||
CommandCallback CcVirtualTrainWaggonsMoved;
|
||||
CommandCallback CcDeleteVirtualTrain;
|
||||
|
||||
/* tbtr_template_gui_create_virtualtrain.cpp */
|
||||
CommandCallback CcAddVirtualEngine;
|
||||
|
||||
#endif /* COMMAND_FUNC_H */
|
||||
|
@@ -240,6 +240,8 @@ enum Commands {
|
||||
|
||||
CMD_WANT_ENGINE_PREVIEW, ///< confirm the preview of an engine
|
||||
|
||||
CMD_SET_VEHICLE_UNIT_NUMBER, ///< sets the unit number of a vehicle
|
||||
|
||||
CMD_RENAME_VEHICLE, ///< rename a whole vehicle
|
||||
CMD_RENAME_ENGINE, ///< rename a engine (in the engine list)
|
||||
CMD_RENAME_COMPANY, ///< change the company name
|
||||
@@ -306,10 +308,27 @@ enum Commands {
|
||||
|
||||
CMD_SET_AUTOREPLACE, ///< set an autoreplace entry
|
||||
|
||||
CMD_TOGGLE_REUSE_DEPOT_VEHICLES, ///< toggle 'reuse depot vehicles' on template
|
||||
CMD_TOGGLE_KEEP_REMAINING_VEHICLES, ///< toggle 'keep remaining vehicles' on template
|
||||
CMD_TOGGLE_REFIT_AS_TEMPLATE, ///< toggle 'refit as template' on template
|
||||
|
||||
CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE, ///< Creates a virtual train from a template
|
||||
CMD_VIRTUAL_TRAIN_FROM_TRAIN, ///< Creates a virtual train from a regular train
|
||||
CMD_DELETE_VIRTUAL_TRAIN, ///< Delete a virtual train
|
||||
CMD_BUILD_VIRTUAL_RAIL_VEHICLE, ///< Build a virtual train
|
||||
CMD_REPLACE_TEMPLATE_VEHICLE, ///< Replace a template vehicle with another one based on a virtual train
|
||||
|
||||
CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN, ///< clone a train and create a new template vehicle based on it
|
||||
CMD_DELETE_TEMPLATE_VEHICLE, ///< delete a template vehicle
|
||||
|
||||
CMD_ISSUE_TEMPLATE_REPLACEMENT, ///< issue a template replacement for a vehicle group
|
||||
CMD_DELETE_TEMPLATE_REPLACEMENT, ///< delete a template replacement from a vehicle group
|
||||
|
||||
CMD_CLONE_VEHICLE, ///< clone a vehicle
|
||||
CMD_START_STOP_VEHICLE, ///< start or stop a vehicle
|
||||
CMD_MASS_START_STOP, ///< start/stop all vehicles (in a depot)
|
||||
CMD_AUTOREPLACE_VEHICLE, ///< replace/renew a vehicle while it is in a depot
|
||||
CMD_TEMPLATE_REPLACE_VEHICLE, ///< template replace a vehicle while it is in a depot
|
||||
CMD_DEPOT_SELL_ALL_VEHICLES, ///< sell all vehicles which are in a given depot
|
||||
CMD_DEPOT_MASS_AUTOREPLACE, ///< force the autoreplace to take action in a given depot
|
||||
|
||||
|
@@ -295,6 +295,16 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
|
||||
*/
|
||||
inline void ClearFreeWagon() { ClrBit(this->subtype, GVSF_FREE_WAGON); }
|
||||
|
||||
/**
|
||||
* Set a vehicle as a virtual vehicle.
|
||||
*/
|
||||
inline void SetVirtual() { SetBit(this->subtype, GVSF_VIRTUAL); }
|
||||
|
||||
/**
|
||||
* Clear a vehicle from being a virtual vehicle.
|
||||
*/
|
||||
inline void ClearVirtual() { ClrBit(this->subtype, GVSF_VIRTUAL); }
|
||||
|
||||
/**
|
||||
* Set a vehicle as a multiheaded engine.
|
||||
*/
|
||||
@@ -329,6 +339,12 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
|
||||
*/
|
||||
inline bool IsMultiheaded() const { return HasBit(this->subtype, GVSF_MULTIHEADED); }
|
||||
|
||||
/**
|
||||
* Tell if we are dealing with a virtual vehicle (used for templates).
|
||||
* @return True if the vehicle is a virtual vehicle.
|
||||
*/
|
||||
inline bool IsVirtual() const { return HasBit(this->subtype, GVSF_VIRTUAL); }
|
||||
|
||||
/**
|
||||
* Tell if we are dealing with the rear end of a multiheaded engine.
|
||||
* @return True if the engine is the rear part of a dualheaded engine.
|
||||
|
@@ -51,6 +51,10 @@ static CommandCallback * const _callback_table[] = {
|
||||
/* 0x19 */ CcStartStopVehicle,
|
||||
/* 0x1A */ CcGame,
|
||||
/* 0x1B */ CcAddVehicleNewGroup,
|
||||
/* 0x1C */ CcSetVirtualTrain,
|
||||
/* 0x1D */ CcVirtualTrainWaggonsMoved,
|
||||
/* 0x1E */ CcDeleteVirtualTrain,
|
||||
/* 0x1F */ CcAddVirtualEngine,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -43,9 +43,10 @@ uint16 TRAIN_FRONT_SPACE = 16;
|
||||
|
||||
enum TemplateReplaceWindowWidgets {
|
||||
TCW_CAPTION,
|
||||
TCW_MATRIX_NEW_TMPL,
|
||||
TCW_NEW_TMPL_PANEL,
|
||||
TCW_INFO_PANEL,
|
||||
TCW_SCROLLBAR_NEW_TMPL,
|
||||
TCW_SCROLLBAR_H_NEW_TMPL,
|
||||
TCW_SCROLLBAR_V_NEW_TMPL,
|
||||
TCW_SELL_TMPL,
|
||||
TCW_NEW,
|
||||
TCW_OK,
|
||||
@@ -59,22 +60,24 @@ static const NWidgetPart _widgets[] = {
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, TCW_CAPTION), SetDataTip(STR_TMPL_CREATEGUI_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, TCW_MATRIX_NEW_TMPL), SetMinimalSize(216, 60), SetFill(1, 0), SetDataTip(0x1, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 0), SetScrollbar(TCW_SCROLLBAR_NEW_TMPL),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TCW_INFO_PANEL), SetMinimalSize(216,80), SetResize(1,1), EndContainer(),
|
||||
NWidget(NWID_HSCROLLBAR, COLOUR_GREY, TCW_SCROLLBAR_NEW_TMPL), SetResize(1,0),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TCW_NEW_TMPL_PANEL), SetMinimalSize(250, 30), SetResize(1, 0), SetScrollbar(TCW_SCROLLBAR_H_NEW_TMPL), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TCW_INFO_PANEL), SetMinimalSize(250, 100), SetResize(1, 1), SetScrollbar(TCW_SCROLLBAR_V_NEW_TMPL), EndContainer(),
|
||||
NWidget(NWID_HSCROLLBAR, COLOUR_GREY, TCW_SCROLLBAR_H_NEW_TMPL),
|
||||
EndContainer(),
|
||||
NWidget(WWT_IMGBTN, COLOUR_GREY, TCW_SELL_TMPL), SetDataTip(0x0, STR_NULL), SetMinimalSize(23,23), SetResize(0, 1), SetFill(0, 1),
|
||||
NWidget(WWT_IMGBTN, COLOUR_GREY, TCW_SELL_TMPL), SetMinimalSize(40, 40), SetDataTip(0x0, STR_NULL), SetResize(0, 1), SetFill(0, 1),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TCW_SCROLLBAR_V_NEW_TMPL),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_OK), SetMinimalSize(52, 12), SetResize(1,0), SetDataTip(STR_TMPL_CONFIRM, STR_TMPL_CONFIRM),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_NEW), SetMinimalSize(52, 12), SetResize(1,0), SetDataTip(STR_TMPL_NEW, STR_TMPL_NEW),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, TCW_CLONE), SetMinimalSize(52, 12), SetResize(1,0), SetDataTip(STR_TMPL_CREATE_CLONE_VEH, STR_TMPL_CREATE_CLONE_VEH),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_REFIT), SetMinimalSize(52, 12), SetResize(1,0), SetDataTip(STR_TMPL_REFIT, STR_TMPL_REFIT),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_CANCEL), SetMinimalSize(52, 12), SetResize(1,0), SetDataTip(STR_TMPL_CANCEL, STR_TMPL_CANCEL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_OK), SetMinimalSize(52, 12), SetResize(1, 0), SetDataTip(STR_TMPL_CONFIRM, STR_TMPL_CONFIRM),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_NEW), SetMinimalSize(52, 12), SetResize(1, 0), SetDataTip(STR_TMPL_NEW, STR_TMPL_NEW),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, TCW_CLONE), SetMinimalSize(52, 12), SetResize(1, 0), SetDataTip(STR_TMPL_CREATE_CLONE_VEH, STR_TMPL_CREATE_CLONE_VEH),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_REFIT), SetMinimalSize(52, 12), SetResize(1, 0), SetDataTip(STR_TMPL_REFIT, STR_TMPL_REFIT),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TCW_CANCEL), SetMinimalSize(52, 12), SetResize(1, 0), SetDataTip(STR_TMPL_CANCEL, STR_TMPL_CANCEL),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
};
|
||||
@@ -84,7 +87,7 @@ static WindowDesc _template_create_window_desc(
|
||||
"template create window", // const char* ini_key
|
||||
456, 100, // window size
|
||||
WC_CREATE_TEMPLATE, // window class
|
||||
WC_TEMPLATEGUI_MAIN, // parent window class
|
||||
WC_NONE, // parent window class
|
||||
WDF_CONSTRUCTION, // window flags
|
||||
_widgets, lengthof(_widgets) // widgets + num widgets
|
||||
);
|
||||
@@ -104,12 +107,13 @@ static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Veh
|
||||
|
||||
if (wagon == v) return;
|
||||
|
||||
CmdMoveRailVehicle(INVALID_TILE, DC_EXEC, (_ctrl_pressed ? 1:0)<<20 | (1<<21) | v->index, wagon == NULL ? INVALID_VEHICLE : wagon->index, 0);
|
||||
DoCommandP(v->tile, v->index | (_ctrl_pressed ? 1 : 0) << 20 | 1 << 21, wagon == NULL ? INVALID_VEHICLE : wagon->index, CMD_MOVE_RAIL_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_MOVE_VEHICLE), CcVirtualTrainWaggonsMoved);
|
||||
}
|
||||
|
||||
class TemplateCreateWindow : public Window {
|
||||
private:
|
||||
Scrollbar *hscroll;
|
||||
Scrollbar *vscroll;
|
||||
int line_height;
|
||||
Train* virtual_train;
|
||||
bool editMode;
|
||||
@@ -124,8 +128,9 @@ public:
|
||||
TemplateCreateWindow(WindowDesc* _wdesc, TemplateVehicle *to_edit, bool *notice, bool *windowOpen, int step_h) : Window(_wdesc)
|
||||
{
|
||||
this->line_height = step_h;
|
||||
this->CreateNestedTree(_wdesc);
|
||||
this->hscroll = this->GetScrollbar(TCW_SCROLLBAR_NEW_TMPL);
|
||||
this->CreateNestedTree(_wdesc != NULL);
|
||||
this->hscroll = this->GetScrollbar(TCW_SCROLLBAR_H_NEW_TMPL);
|
||||
this->vscroll = this->GetScrollbar(TCW_SCROLLBAR_V_NEW_TMPL);
|
||||
this->FinishInitNested(VEH_TRAIN);
|
||||
/* a sprite */
|
||||
this->GetWidget<NWidgetCore>(TCW_SELL_TMPL)->widget_data = SPR_SELL_TRAIN;
|
||||
@@ -137,20 +142,25 @@ public:
|
||||
virtualTrainChangedNotice = false;
|
||||
this->editTemplate = to_edit;
|
||||
|
||||
if ( to_edit ) editMode = true;
|
||||
if (to_edit) editMode = true;
|
||||
else editMode = false;
|
||||
|
||||
this->sel = INVALID_VEHICLE;
|
||||
this->vehicle_over = INVALID_VEHICLE;
|
||||
|
||||
this->virtual_train = VirtualTrainFromTemplateVehicle(to_edit);
|
||||
if (to_edit) {
|
||||
DoCommandP(0, to_edit->index, 0, CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE, CcSetVirtualTrain);
|
||||
}
|
||||
|
||||
this->resize.step_height = 1;
|
||||
}
|
||||
|
||||
~TemplateCreateWindow()
|
||||
{
|
||||
if ( virtual_train )
|
||||
delete virtual_train;
|
||||
if (virtual_train != nullptr) {
|
||||
DoCommandP(0, virtual_train->index, 0, CMD_DELETE_VIRTUAL_TRAIN);
|
||||
virtual_train = nullptr;
|
||||
}
|
||||
|
||||
SetWindowClassesDirty(WC_TRAINS_LIST);
|
||||
|
||||
@@ -160,19 +170,22 @@ public:
|
||||
|
||||
}
|
||||
|
||||
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||
void SetVirtualTrain(Train* const train)
|
||||
{
|
||||
switch (widget) {
|
||||
case TCW_MATRIX_NEW_TMPL:
|
||||
size->height = 20;
|
||||
break;
|
||||
if (virtual_train != nullptr) {
|
||||
DoCommandP(0, virtual_train->index, 0, CMD_DELETE_VIRTUAL_TRAIN);
|
||||
}
|
||||
|
||||
virtual_train = train;
|
||||
}
|
||||
|
||||
virtual void OnResize()
|
||||
{
|
||||
NWidgetCore *nwi = this->GetWidget<NWidgetCore>(TCW_MATRIX_NEW_TMPL);
|
||||
this->hscroll->SetCapacity(nwi->current_x);
|
||||
nwi->widget_data = (this->hscroll->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
|
||||
NWidgetCore *template_panel = this->GetWidget<NWidgetCore>(TCW_NEW_TMPL_PANEL);
|
||||
this->hscroll->SetCapacity(template_panel->current_x);
|
||||
|
||||
NWidgetCore *info_panel = this->GetWidget<NWidgetCore>(TCW_INFO_PANEL);
|
||||
this->vscroll->SetCapacity(info_panel->current_y);
|
||||
}
|
||||
|
||||
|
||||
@@ -180,12 +193,13 @@ public:
|
||||
{
|
||||
virtualTrainChangedNotice = true;
|
||||
}
|
||||
|
||||
virtual void OnClick(Point pt, int widget, int click_count)
|
||||
{
|
||||
switch(widget) {
|
||||
case TCW_MATRIX_NEW_TMPL: {
|
||||
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(TCW_MATRIX_NEW_TMPL);
|
||||
ClickedOnVehiclePanel(pt.x - nwi->pos_x-TRAIN_FRONT_SPACE, pt.y - nwi->pos_y);
|
||||
case TCW_NEW_TMPL_PANEL: {
|
||||
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(TCW_NEW_TMPL_PANEL);
|
||||
ClickedOnVehiclePanel(pt.x - nwi->pos_x, pt.y - nwi->pos_y);
|
||||
break;
|
||||
}
|
||||
case TCW_NEW: {
|
||||
@@ -204,10 +218,14 @@ public:
|
||||
break;
|
||||
}
|
||||
case TCW_OK: {
|
||||
TemplateVehicle *tv = NULL;
|
||||
if ( editMode ) tv = DeleteTemplateVehicle(editTemplate);
|
||||
editTemplate = TemplateVehicleFromVirtualTrain(virtual_train);
|
||||
if ( tv ) *noticeParent = true;
|
||||
uint32 templateIndex = (editTemplate != nullptr) ? editTemplate->index : INVALID_VEHICLE;
|
||||
|
||||
if (virtual_train != nullptr) {
|
||||
DoCommandP(0, templateIndex, virtual_train->index, CMD_REPLACE_TEMPLATE_VEHICLE);
|
||||
virtual_train = nullptr;
|
||||
} else if (templateIndex != INVALID_VEHICLE) {
|
||||
DoCommandP(0, templateIndex, 0, CMD_DELETE_TEMPLATE_VEHICLE);
|
||||
}
|
||||
delete this;
|
||||
break;
|
||||
}
|
||||
@@ -221,25 +239,30 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool OnVehicleSelect(const Vehicle *v)
|
||||
{
|
||||
// throw away the current virtual train
|
||||
if ( virtual_train )
|
||||
delete this->virtual_train;
|
||||
if (virtual_train != nullptr) {
|
||||
DoCommandP(0, virtual_train->index, 0, CMD_DELETE_VIRTUAL_TRAIN);
|
||||
virtual_train = nullptr;
|
||||
}
|
||||
|
||||
// create a new one
|
||||
this->virtual_train = CloneVirtualTrainFromTrain((const Train*)v);
|
||||
DoCommandP(0, v->index, 0, CMD_VIRTUAL_TRAIN_FROM_TRAIN, CcSetVirtualTrain);
|
||||
this->ToggleWidgetLoweredState(TCW_CLONE);
|
||||
ResetObjectToPlace();
|
||||
this->SetDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void DrawWidget(const Rect &r, int widget) const
|
||||
{
|
||||
switch(widget) {
|
||||
case TCW_MATRIX_NEW_TMPL: {
|
||||
case TCW_NEW_TMPL_PANEL: {
|
||||
if ( this->virtual_train ) {
|
||||
DrawTrainImage(virtual_train, r.left+TRAIN_FRONT_SPACE, r.right, r.top+2, this->sel, EIT_PURCHASE, this->hscroll->GetPosition(), this->vehicle_over);
|
||||
DrawTrainImage(virtual_train, r.left+TRAIN_FRONT_SPACE, r.right-25, r.top+2, this->sel, EIT_PURCHASE, this->hscroll->GetPosition(), this->vehicle_over);
|
||||
SetDParam(0, CeilDiv(virtual_train->gcache.cached_total_length * 10, TILE_SIZE));
|
||||
SetDParam(1, 1);
|
||||
DrawString(r.left, r.right, r.top, STR_TINY_BLACK_DECIMAL, TC_BLACK, SA_RIGHT);
|
||||
@@ -248,27 +271,36 @@ public:
|
||||
}
|
||||
case TCW_INFO_PANEL: {
|
||||
if ( this->virtual_train ) {
|
||||
DrawPixelInfo tmp_dpi, *old_dpi;
|
||||
|
||||
if (!FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.right - r.left, r.bottom - r.top)) break;
|
||||
|
||||
old_dpi = _cur_dpi;
|
||||
_cur_dpi = &tmp_dpi;
|
||||
|
||||
/* Draw vehicle performance info */
|
||||
const GroundVehicleCache *gcache = this->virtual_train->GetGroundVehicleCache();
|
||||
SetDParam(2, this->virtual_train->GetDisplayMaxSpeed());
|
||||
SetDParam(1, gcache->cached_power);
|
||||
SetDParam(0, gcache->cached_weight);
|
||||
SetDParam(3, gcache->cached_max_te / 1000);
|
||||
DrawString(r.left+8, r.right, r.top+4, STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE);
|
||||
DrawString(8, r.right, 4 - this->vscroll->GetPosition(), STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE);
|
||||
/* Draw cargo summary */
|
||||
CargoArray cargo_caps;
|
||||
for ( const Train *tmp=this->virtual_train; tmp; tmp=tmp->Next() )
|
||||
cargo_caps[tmp->cargo_type] += tmp->cargo_cap;
|
||||
int y = r.top+24;
|
||||
int y = 30 - this->vscroll->GetPosition();
|
||||
for (CargoID i = 0; i < NUM_CARGO; ++i) {
|
||||
if ( cargo_caps[i] > 0 ) {
|
||||
SetDParam(0, i);
|
||||
SetDParam(1, cargo_caps[i]);
|
||||
SetDParam(2, _settings_game.vehicle.freight_trains);
|
||||
DrawString(r.left+8, r.right, y, STR_TMPL_CARGO_SUMMARY, TC_WHITE, SA_LEFT);
|
||||
y += this->line_height/2;
|
||||
DrawString(8, r.right, y, STR_TMPL_CARGO_SUMMARY, TC_LIGHT_BLUE, SA_LEFT);
|
||||
y += this->line_height/3;
|
||||
}
|
||||
}
|
||||
|
||||
_cur_dpi = old_dpi;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -278,7 +310,7 @@ public:
|
||||
}
|
||||
virtual void OnTick()
|
||||
{
|
||||
if ( virtualTrainChangedNotice ) {
|
||||
if (virtualTrainChangedNotice) {
|
||||
this->SetDirty();
|
||||
virtualTrainChangedNotice = false;
|
||||
}
|
||||
@@ -286,22 +318,20 @@ public:
|
||||
virtual void OnDragDrop(Point pt, int widget)
|
||||
{
|
||||
switch (widget) {
|
||||
case TCW_MATRIX_NEW_TMPL: {
|
||||
case TCW_NEW_TMPL_PANEL: {
|
||||
const Vehicle *v = NULL;
|
||||
VehicleID sel;
|
||||
if ( virtual_train ) sel = virtual_train->index;
|
||||
else sel = INVALID_VEHICLE;
|
||||
VehicleID sel = this->sel;
|
||||
|
||||
this->sel = INVALID_VEHICLE;
|
||||
this->SetDirty();
|
||||
|
||||
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(TCW_MATRIX_NEW_TMPL);
|
||||
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(TCW_NEW_TMPL_PANEL);
|
||||
GetDepotVehiclePtData gdvp = { NULL, NULL };
|
||||
|
||||
if (this->GetVehicleFromDepotWndPt(pt.x - nwi->pos_x, pt.y - nwi->pos_y, &v, &gdvp) == MODE_DRAG_VEHICLE && sel != INVALID_VEHICLE) {
|
||||
if (gdvp.wagon == NULL || gdvp.wagon->index != sel) {
|
||||
this->vehicle_over = INVALID_VEHICLE;
|
||||
TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
|
||||
virtual_train = virtual_train->First();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -310,7 +340,14 @@ public:
|
||||
if (this->IsWidgetDisabled(widget)) return;
|
||||
if (this->sel == INVALID_VEHICLE) return;
|
||||
|
||||
virtual_train = DeleteVirtualTrain(virtual_train, Train::Get(this->sel));
|
||||
int sell_cmd = (_ctrl_pressed) ? 1 : 0;
|
||||
|
||||
Train* train_to_delete = Train::Get(this->sel);
|
||||
|
||||
if (virtual_train == train_to_delete)
|
||||
virtual_train = (_ctrl_pressed) ? nullptr : virtual_train->GetNextUnit();
|
||||
|
||||
DoCommandP(0, this->sel | sell_cmd << 20 | 1 << 21, 0, GetCmdSellVeh(VEH_TRAIN));
|
||||
|
||||
this->sel = INVALID_VEHICLE;
|
||||
|
||||
@@ -325,14 +362,15 @@ public:
|
||||
this->sel = INVALID_VEHICLE;
|
||||
this->SetDirty();
|
||||
}
|
||||
|
||||
virtual void OnMouseDrag(Point pt, int widget)
|
||||
{
|
||||
if (this->sel == INVALID_VEHICLE) return;
|
||||
/* A rail vehicle is dragged.. */
|
||||
if (widget != TCW_MATRIX_NEW_TMPL) { // ..outside of the depot matrix.
|
||||
if (widget != TCW_NEW_TMPL_PANEL) { // ..outside of the depot matrix.
|
||||
if (this->vehicle_over != INVALID_VEHICLE) {
|
||||
this->vehicle_over = INVALID_VEHICLE;
|
||||
this->SetWidgetDirty(TCW_MATRIX_NEW_TMPL);
|
||||
this->SetWidgetDirty(TCW_NEW_TMPL_PANEL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -361,16 +399,33 @@ public:
|
||||
this->vehicle_over = new_vehicle_over;
|
||||
this->SetWidgetDirty(widget);
|
||||
}
|
||||
|
||||
virtual void OnPaint()
|
||||
{
|
||||
uint max_width = 32;
|
||||
uint min_width = 32;
|
||||
uint min_height = 30;
|
||||
uint width = 0;
|
||||
if ( virtual_train )
|
||||
for (Train *v = virtual_train; v != NULL; v = v->Next())
|
||||
width += v->GetDisplayImageWidth();
|
||||
uint height = 30;
|
||||
CargoArray cargo_caps;
|
||||
|
||||
max_width = max(max_width, width);
|
||||
this->hscroll->SetCount(max_width+25);
|
||||
if (virtual_train != nullptr) {
|
||||
for (Train *train = virtual_train; train != nullptr; train = train->Next()) {
|
||||
width += train->GetDisplayImageWidth();
|
||||
cargo_caps[train->cargo_type] += train->cargo_cap;
|
||||
}
|
||||
|
||||
for (CargoID i = 0; i < NUM_CARGO; ++i) {
|
||||
if ( cargo_caps[i] > 0 ) {
|
||||
height += this->line_height/3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
min_width = max(min_width, width);
|
||||
this->hscroll->SetCount(min_width + 50);
|
||||
|
||||
min_height = max(min_height, height);
|
||||
this->vscroll->SetCount(min_height);
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
@@ -388,12 +443,15 @@ public:
|
||||
|
||||
uint count_width;
|
||||
uint header_width;
|
||||
|
||||
DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, const Vehicle **veh, GetDepotVehiclePtData *d) const
|
||||
{
|
||||
const NWidgetCore *matrix_widget = this->GetWidget<NWidgetCore>(TCW_MATRIX_NEW_TMPL);
|
||||
const NWidgetCore *matrix_widget = this->GetWidget<NWidgetCore>(TCW_NEW_TMPL_PANEL);
|
||||
/* In case of RTL the widgets are swapped as a whole */
|
||||
if (_current_text_dir == TD_RTL) x = matrix_widget->current_x - x;
|
||||
|
||||
x -= TRAIN_FRONT_SPACE;
|
||||
|
||||
uint xm = x;
|
||||
|
||||
bool wagon = false;
|
||||
@@ -436,6 +494,7 @@ public:
|
||||
|
||||
if (sel != INVALID_VEHICLE) {
|
||||
this->sel = INVALID_VEHICLE;
|
||||
TrainDepotMoveVehicle(v, sel, gdvp.head);
|
||||
} else if (v != NULL) {
|
||||
int image = v->GetImage(_current_text_dir == TD_RTL ? DIR_E : DIR_W, EIT_PURCHASE);
|
||||
SetObjectToPlaceWnd(image, GetVehiclePalette(v), HT_DRAG, this);
|
||||
@@ -448,6 +507,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void RearrangeVirtualTrain()
|
||||
{
|
||||
virtual_train = virtual_train->First();
|
||||
}
|
||||
};
|
||||
|
||||
void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *noticeParent, bool *createWindowOpen, int step_h)
|
||||
@@ -456,4 +519,31 @@ void ShowTemplateCreateWindow(TemplateVehicle *to_edit, bool *noticeParent, bool
|
||||
new TemplateCreateWindow(&_template_create_window_desc, to_edit, noticeParent, createWindowOpen, step_h);
|
||||
}
|
||||
|
||||
void CcSetVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (result.Failed()) return;
|
||||
|
||||
Window* window = FindWindowById(WC_CREATE_TEMPLATE, 0);
|
||||
if (window) {
|
||||
Train* train = Train::From(Vehicle::Get(_new_vehicle_id));
|
||||
((TemplateCreateWindow*)window)->SetVirtualTrain(train);
|
||||
window->InvalidateData();
|
||||
}
|
||||
}
|
||||
|
||||
void CcVirtualTrainWaggonsMoved(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (result.Failed()) return;
|
||||
|
||||
Window* window = FindWindowById(WC_CREATE_TEMPLATE, 0);
|
||||
if (window) {
|
||||
((TemplateCreateWindow*)window)->RearrangeVirtualTrain();
|
||||
window->InvalidateData();
|
||||
}
|
||||
}
|
||||
|
||||
void CcDeleteVirtualTrain(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
VehicleID virtual_train_id = p2;
|
||||
DoCommandP(0, virtual_train_id, 0, CMD_DELETE_VIRTUAL_TRAIN);
|
||||
}
|
@@ -650,8 +650,7 @@ struct BuildVirtualTrainWindow : Window {
|
||||
case WID_BV_BUILD: {
|
||||
EngineID sel_eng = this->sel_engine;
|
||||
if (sel_eng != INVALID_ENGINE) {
|
||||
Train *tmp = CmdBuildVirtualRailVehicle(sel_eng);
|
||||
if (tmp) AddVirtualEngine(tmp);
|
||||
DoCommandP(0, sel_engine, 0, CMD_BUILD_VIRTUAL_RAIL_VEHICLE, CcAddVirtualEngine);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -667,12 +666,7 @@ struct BuildVirtualTrainWindow : Window {
|
||||
{
|
||||
if (!gui_scope) return;
|
||||
/* When switching to original acceleration model for road vehicles, clear the selected sort criteria if it is not available now. */
|
||||
if (this->vehicle_type == VEH_ROAD &&
|
||||
_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL &&
|
||||
this->sort_criteria > 7) {
|
||||
this->sort_criteria = 0;
|
||||
_last_sort_criteria[VEH_ROAD] = 0;
|
||||
}
|
||||
|
||||
this->eng_list.ForceRebuild();
|
||||
}
|
||||
|
||||
@@ -796,18 +790,29 @@ struct BuildVirtualTrainWindow : Window {
|
||||
|
||||
void AddVirtualEngine(Train *toadd)
|
||||
{
|
||||
if ( !*virtual_train ) {
|
||||
if (*virtual_train == NULL) {
|
||||
*virtual_train = toadd;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
VehicleID target = (*(this->virtual_train))->GetLastUnit()->index;
|
||||
CommandCost movec;
|
||||
movec = CmdMoveRailVehicle(INVALID_TILE, DC_EXEC, (1<<21) | toadd->index, target, 0);
|
||||
|
||||
DoCommandP(0, (1<<21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE);
|
||||
}
|
||||
*noticeParent = true;
|
||||
}
|
||||
};
|
||||
|
||||
void CcAddVirtualEngine(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
||||
{
|
||||
if (result.Failed()) return;
|
||||
|
||||
Window* window = FindWindowById(WC_BUILD_VIRTUAL_TRAIN, 0);
|
||||
if (window) {
|
||||
Train* train = Train::From(Vehicle::Get(_new_vehicle_id));
|
||||
((BuildVirtualTrainWindow*)window)->AddVirtualEngine(train);
|
||||
window->InvalidateData();
|
||||
}
|
||||
}
|
||||
|
||||
static WindowDesc _build_vehicle_desc(
|
||||
WDP_AUTO, // window position
|
||||
"template create virtual train",// const char* ini_key
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "settings_func.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "rail_gui.h"
|
||||
#include "network/network.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
@@ -60,6 +61,7 @@ enum TemplateReplaceWindowWidgets {
|
||||
|
||||
TRW_WIDGET_INSET_TEMPLATES,
|
||||
TRW_WIDGET_BOTTOM_MATRIX,
|
||||
TRW_WIDGET_MIDDLE_SCROLLBAR,
|
||||
TRW_WIDGET_BOTTOM_SCROLLBAR,
|
||||
|
||||
TRW_WIDGET_TMPL_INFO_INSET,
|
||||
@@ -76,7 +78,7 @@ enum TemplateReplaceWindowWidgets {
|
||||
TRW_WIDGET_TMPL_BUTTONS_EDIT,
|
||||
TRW_WIDGET_TMPL_BUTTONS_CLONE,
|
||||
TRW_WIDGET_TMPL_BUTTONS_DELETE,
|
||||
TRW_WIDGET_TMPL_BUTTONS_RPLALL,
|
||||
//TRW_WIDGET_TMPL_BUTTONS_RPLALL,
|
||||
TRW_WIDGET_TMPL_BUTTON_FLUFF,
|
||||
TRW_WIDGET_TMPL_BUTTONS_EDIT_RIGHTPANEL,
|
||||
|
||||
@@ -103,11 +105,12 @@ static const NWidgetPart _widgets[] = {
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, TRW_CAPTION), SetDataTip(STR_TMPL_RPL_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
//Top Matrix
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_INSET, COLOUR_GREY, TRW_WIDGET_INSET_GROUPS), SetMinimalSize(216,12), SetDataTip(STR_TMPL_MAINGUI_DEFINEDGROUPS, STR_TMPL_MAINGUI_DEFINEDGROUPS), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TRW_WIDGET_INSET_GROUPS), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, TRW_WIDGET_TOP_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetDataTip(0x1, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 0), SetScrollbar(TRW_WIDGET_TOP_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TRW_WIDGET_TOP_SCROLLBAR),
|
||||
@@ -115,16 +118,19 @@ static const NWidgetPart _widgets[] = {
|
||||
EndContainer(),
|
||||
// Template Display
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_INSET, COLOUR_GREY, TRW_WIDGET_INSET_TEMPLATES), SetMinimalSize(216,12), SetDataTip(STR_TMPL_AVAILABLE_TEMPLATES, STR_TMPL_AVAILABLE_TEMPLATES), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TRW_WIDGET_INSET_TEMPLATES), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, TRW_WIDGET_BOTTOM_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetDataTip(0x1, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(TRW_WIDGET_BOTTOM_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TRW_WIDGET_BOTTOM_SCROLLBAR),
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, TRW_WIDGET_BOTTOM_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetDataTip(0x1, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(TRW_WIDGET_MIDDLE_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TRW_WIDGET_MIDDLE_SCROLLBAR),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
// Info Area
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_INSET, COLOUR_GREY, TRW_WIDGET_TMPL_INFO_INSET), SetMinimalSize(216,12), SetResize(1,0), SetDataTip(STR_TMPL_AVAILABLE_TEMPLATES, STR_TMPL_AVAILABLE_TEMPLATES), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TRW_WIDGET_TMPL_INFO_PANEL), SetMinimalSize(216,50), SetResize(1,0), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TRW_WIDGET_TMPL_INFO_INSET), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM), SetResize(1,0), EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TRW_WIDGET_TMPL_INFO_PANEL), SetMinimalSize(216,120), SetResize(1,0), SetScrollbar(TRW_WIDGET_BOTTOM_SCROLLBAR), EndContainer(),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, TRW_WIDGET_BOTTOM_SCROLLBAR),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
// Control Area
|
||||
NWidget(NWID_VERTICAL),
|
||||
@@ -139,11 +145,10 @@ static const NWidgetPart _widgets[] = {
|
||||
EndContainer(),
|
||||
// Edit buttons
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_DEFINE), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_DEFINE_TEMPLATE, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_EDIT), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_EDIT_TEMPLATE, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_CLONE), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_CREATE_CLONE_VEH, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_DELETE), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_DELETE_TEMPLATE, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_RPLALL), SetMinimalSize(150,12), SetResize(0,0), SetDataTip(STR_TMPL_RPL_ALL_TMPL, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_DEFINE), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_DEFINE_TEMPLATE, STR_TMPL_DEFINE_TEMPLATE),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_EDIT), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_EDIT_TEMPLATE, STR_TMPL_EDIT_TEMPLATE),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_CLONE), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_CREATE_CLONE_VEH, STR_TMPL_CREATE_CLONE_VEH),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_DELETE), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_DELETE_TEMPLATE, STR_TMPL_DELETE_TEMPLATE),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_EDIT_RIGHTPANEL), SetMinimalSize(50,12), SetResize(1,0), EndContainer(),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
@@ -174,12 +179,14 @@ private:
|
||||
GUIGroupList groups; ///< List of groups
|
||||
byte unitnumber_digits;
|
||||
|
||||
SmallVector<int, 16> indents; ///< Indentation levels
|
||||
|
||||
short line_height;
|
||||
short matrixContentLeftMargin;
|
||||
|
||||
int details_height; ///< Minimal needed height of the details panels (found so far).
|
||||
RailType sel_railtype; ///< Type of rail tracks selected.
|
||||
Scrollbar *vscroll[2];
|
||||
Scrollbar *vscroll[3];
|
||||
// listing/sorting continued
|
||||
GUITemplateList templates;
|
||||
GUITemplateList::SortFunction **template_sorter_funcs;
|
||||
@@ -204,11 +211,10 @@ public:
|
||||
|
||||
this->line_height = step_h;
|
||||
|
||||
this->CreateNestedTree(wdesc);
|
||||
this->CreateNestedTree(wdesc != NULL);
|
||||
this->vscroll[0] = this->GetScrollbar(TRW_WIDGET_TOP_SCROLLBAR);
|
||||
this->vscroll[1] = this->GetScrollbar(TRW_WIDGET_BOTTOM_SCROLLBAR);
|
||||
this->vscroll[0]->SetStepSize(step_h / 2);
|
||||
this->vscroll[1]->SetStepSize(step_h);
|
||||
this->vscroll[1] = this->GetScrollbar(TRW_WIDGET_MIDDLE_SCROLLBAR);
|
||||
this->vscroll[2] = this->GetScrollbar(TRW_WIDGET_BOTTOM_SCROLLBAR);
|
||||
this->FinishInitNested(VEH_TRAIN);
|
||||
|
||||
this->owner = _local_company;
|
||||
@@ -216,8 +222,6 @@ public:
|
||||
this->groups.ForceRebuild();
|
||||
this->groups.NeedResort();
|
||||
this->BuildGroupList(_local_company);
|
||||
this->groups.Sort(&GroupNameSorter);
|
||||
|
||||
|
||||
this->matrixContentLeftMargin = 40;
|
||||
this->selected_template_index = -1;
|
||||
@@ -286,6 +290,18 @@ public:
|
||||
DrawTemplateInfo(this->line_height, r);
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_INSET_GROUPS: {
|
||||
DrawString(r.left + 2, r.right - 2, r.top + 2, STR_TMPL_MAINGUI_DEFINEDGROUPS);
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_INSET_TEMPLATES: {
|
||||
DrawString(r.left + 2, r.right - 2, r.top + 2, STR_TMPL_AVAILABLE_TEMPLATES);
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_TMPL_INFO_INSET: {
|
||||
DrawString(r.left + 2, r.right - 2, r.top + 2, STR_TMPL_TEMPLATE_INFO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +310,6 @@ public:
|
||||
BuildTemplateGuiList(&this->templates, this->vscroll[1], this->owner, this->sel_railtype);
|
||||
|
||||
this->BuildGroupList(_local_company);
|
||||
this->groups.Sort(&GroupNameSorter);
|
||||
|
||||
if ( templateNotice ) {
|
||||
BuildTemplateGuiList(&this->templates, vscroll[1], _local_company, this->sel_railtype);
|
||||
@@ -308,6 +323,34 @@ public:
|
||||
/* Show the selected railtype in the pulldown menu */
|
||||
this->GetWidget<NWidgetCore>(TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN)->widget_data = GetRailTypeInfo(sel_railtype)->strings.replace_text;
|
||||
|
||||
if ((this->selected_template_index < 0) || (this->selected_template_index >= (short)this->templates.Length())) {
|
||||
this->vscroll[2]->SetCount(24);
|
||||
} else {
|
||||
const TemplateVehicle *tmp = this->templates[this->selected_template_index];
|
||||
uint min_height = 30;
|
||||
uint height = 30;
|
||||
CargoArray cargo_caps;
|
||||
short count_columns = 0;
|
||||
short max_columns = 2;
|
||||
|
||||
for ( ; tmp; tmp=tmp->Next()) {
|
||||
cargo_caps[tmp->cargo_type] += tmp->cargo_cap;
|
||||
}
|
||||
|
||||
for (CargoID i = 0; i < NUM_CARGO; ++i) {
|
||||
if ( cargo_caps[i] > 0 ) {
|
||||
if (count_columns % max_columns == 0) {
|
||||
height += this->line_height/3;
|
||||
}
|
||||
|
||||
++count_columns;
|
||||
}
|
||||
}
|
||||
|
||||
min_height = max(min_height, height);
|
||||
this->vscroll[2]->SetCount(min_height);
|
||||
}
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
||||
@@ -317,31 +360,35 @@ public:
|
||||
|
||||
switch (widget) {
|
||||
case TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE: {
|
||||
if ( this->selected_template_index >= 0 ) {
|
||||
TemplateVehicle *sel = TemplateVehicle::Get(((this->templates)[selected_template_index])->index);
|
||||
sel->ToggleReuseDepotVehicles();
|
||||
if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length())) {
|
||||
uint32 template_index = ((this->templates)[selected_template_index])->index;
|
||||
|
||||
DoCommandP(0, template_index, 0, CMD_TOGGLE_REUSE_DEPOT_VEHICLES, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP: {
|
||||
if ( this->selected_template_index >= 0 ) {
|
||||
TemplateVehicle *sel = TemplateVehicle::Get(((this->templates)[selected_template_index])->index);
|
||||
sel->ToggleKeepRemainingVehicles();
|
||||
if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length())) {
|
||||
uint32 template_index = ((this->templates)[selected_template_index])->index;
|
||||
|
||||
DoCommandP(0, template_index, 0, CMD_TOGGLE_KEEP_REMAINING_VEHICLES, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT: {
|
||||
if ( this->selected_template_index >= 0 ) {
|
||||
TemplateVehicle *sel = TemplateVehicle::Get(((this->templates)[selected_template_index])->index);
|
||||
sel->ToggleRefitAsTemplate();
|
||||
if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length())) {
|
||||
uint32 template_index = ((this->templates)[selected_template_index])->index;
|
||||
|
||||
DoCommandP(0, template_index, 0, CMD_TOGGLE_REFIT_AS_TEMPLATE, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_TMPL_BUTTONS_DEFINE:
|
||||
case TRW_WIDGET_TMPL_BUTTONS_DEFINE: {
|
||||
ShowTemplateCreateWindow(0, &templateNotice, &editInProgress, this->line_height);
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_TMPL_BUTTONS_EDIT: {
|
||||
if ( this->selected_template_index >= 0 ) {
|
||||
if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length())) {
|
||||
editInProgress = true;
|
||||
TemplateVehicle *sel = TemplateVehicle::Get(((this->templates)[selected_template_index])->index);
|
||||
ShowTemplateCreateWindow(sel, &templateNotice, &editInProgress, this->line_height);
|
||||
@@ -361,23 +408,18 @@ public:
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_TMPL_BUTTONS_DELETE:
|
||||
if ( selected_template_index >= 0 && !editInProgress ) {
|
||||
// identify template to delete
|
||||
TemplateVehicle *del = TemplateVehicle::Get(((this->templates)[selected_template_index])->index);
|
||||
// remove a corresponding template replacement if existing
|
||||
TemplateReplacement *tr = GetTemplateReplacementByTemplateID(del->index);
|
||||
if ( tr ) {
|
||||
delete tr;
|
||||
}
|
||||
delete del;
|
||||
if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length()) && !editInProgress) {
|
||||
|
||||
uint32 template_index = ((this->templates)[selected_template_index])->index;
|
||||
|
||||
bool succeeded = DoCommandP(0, template_index, 0, CMD_DELETE_TEMPLATE_VEHICLE, NULL);
|
||||
|
||||
if (succeeded) {
|
||||
BuildTemplateGuiList(&this->templates, this->vscroll[1], this->owner, this->sel_railtype);
|
||||
selected_template_index = -1;
|
||||
}
|
||||
break;
|
||||
case TRW_WIDGET_TMPL_BUTTONS_RPLALL: {
|
||||
ShowTemplateReplaceAllGui();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN: // Railtype selection dropdown menu
|
||||
ShowDropDownList(this, GetRailTypeDropDownList(true), sel_railtype, TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN);
|
||||
break;
|
||||
@@ -386,7 +428,7 @@ public:
|
||||
if ( newindex == this->selected_group_index || newindex >= this->groups.Length() ) {
|
||||
this->selected_group_index = -1;
|
||||
}
|
||||
else if ( newindex < this->groups.Length() ) {
|
||||
else if ((newindex >= 0) && (newindex < this->groups.Length())) {
|
||||
this->selected_group_index = newindex;
|
||||
}
|
||||
break;
|
||||
@@ -396,26 +438,28 @@ public:
|
||||
if ( newindex == this->selected_template_index || newindex >= templates.Length() ) {
|
||||
this->selected_template_index = -1;
|
||||
}
|
||||
else if ( newindex < templates.Length() ) {
|
||||
else if ((newindex >= 0) && (newindex < templates.Length())) {
|
||||
this->selected_template_index = newindex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_START: {
|
||||
if ( this->selected_template_index >= 0 && this->selected_group_index >= 0) {
|
||||
if ((this->selected_template_index >= 0) && (this->selected_template_index < (short)this->templates.Length()) &&
|
||||
(this->selected_group_index >= 0) && (this->selected_group_index < (short)this->groups.Length())) {
|
||||
uint32 tv_index = ((this->templates)[selected_template_index])->index;
|
||||
int current_group_index = (this->groups)[this->selected_group_index]->index;
|
||||
IssueTemplateReplacement(current_group_index, tv_index);
|
||||
|
||||
DoCommandP(0, current_group_index, tv_index, CMD_ISSUE_TEMPLATE_REPLACEMENT, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRW_WIDGET_STOP:
|
||||
if ( this->selected_group_index == -1 )
|
||||
if ((this->selected_group_index < 0) || (this->selected_group_index >= (short)this->groups.Length()))
|
||||
return;
|
||||
|
||||
int current_group_index = (this->groups)[this->selected_group_index]->index;
|
||||
TemplateReplacement *tr = GetTemplateReplacementByGroupID(current_group_index);
|
||||
if ( tr )
|
||||
delete tr;
|
||||
|
||||
DoCommandP(0, current_group_index, 0, CMD_DELETE_TEMPLATE_REPLACEMENT, NULL);
|
||||
break;
|
||||
}
|
||||
this->SetDirty();
|
||||
@@ -423,9 +467,9 @@ public:
|
||||
|
||||
virtual bool OnVehicleSelect(const Vehicle *v)
|
||||
{
|
||||
// create a new template from the clicked vehicle
|
||||
TemplateVehicle *tv = CloneTemplateVehicleFromTrain((const Train*)v);
|
||||
if ( !tv ) return false;
|
||||
bool succeeded = DoCommandP(0, v->index, 0, CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN, NULL);
|
||||
|
||||
if (!succeeded) return false;
|
||||
|
||||
BuildTemplateGuiList(&this->templates, vscroll[1], _local_company, this->sel_railtype);
|
||||
this->ToggleWidgetLoweredState(TRW_WIDGET_TMPL_BUTTONS_CLONE);
|
||||
@@ -457,6 +501,9 @@ public:
|
||||
NWidgetCore *nwi2 = this->GetWidget<NWidgetCore>(TRW_WIDGET_BOTTOM_MATRIX);
|
||||
this->vscroll[1]->SetCapacityFromWidget(this, TRW_WIDGET_BOTTOM_MATRIX);
|
||||
nwi2->widget_data = (this->vscroll[1]->GetCapacity() << MAT_ROW_START) + (1 << MAT_COL_START);
|
||||
/* Info panel */
|
||||
NWidgetCore *nwi3 = this->GetWidget<NWidgetCore>(TRW_WIDGET_TMPL_INFO_PANEL);
|
||||
this->vscroll[2]->SetCapacity(nwi3->current_y);
|
||||
}
|
||||
|
||||
virtual void OnTick()
|
||||
@@ -489,6 +536,17 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AddParents(GUIGroupList *source, GroupID parent, int indent)
|
||||
{
|
||||
for (const Group **g = source->Begin(); g != source->End(); g++) {
|
||||
if ((*g)->parent == parent) {
|
||||
*this->groups.Append() = *g;
|
||||
*this->indents.Append() = indent;
|
||||
AddParents(source, (*g)->index, indent + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sort the groups by their name */
|
||||
static int CDECL GroupNameSorter(const Group * const *a, const Group * const *b)
|
||||
{
|
||||
@@ -514,18 +572,25 @@ public:
|
||||
|
||||
void BuildGroupList(Owner owner)
|
||||
{
|
||||
if (!this->groups.NeedRebuild()) {
|
||||
return;
|
||||
}
|
||||
if (!this->groups.NeedRebuild()) return;
|
||||
|
||||
this->groups.Clear();
|
||||
this->indents.Clear();
|
||||
|
||||
GUIGroupList list;
|
||||
|
||||
const Group *g;
|
||||
FOR_ALL_GROUPS(g) {
|
||||
if (g->owner == owner ) {
|
||||
*this->groups.Append() = g;
|
||||
if (g->owner == owner && g->vehicle_type == VEH_TRAIN) {
|
||||
*list.Append() = g;
|
||||
}
|
||||
}
|
||||
|
||||
list.ForceResort();
|
||||
list.Sort(&GroupNameSorter);
|
||||
|
||||
AddParents(&list, INVALID_GROUP, 0);
|
||||
|
||||
this->groups.Compact();
|
||||
this->groups.RebuildDone();
|
||||
this->vscroll[0]->SetCount(groups.Length());
|
||||
@@ -550,7 +615,7 @@ public:
|
||||
|
||||
SetDParam(0, g_id);
|
||||
StringID str = STR_GROUP_NAME;
|
||||
DrawString(left+30, right, y+2, str, TC_BLACK);
|
||||
DrawString(left+30+ this->indents[i] * 10, right, y+2, str, TC_BLACK);
|
||||
|
||||
/* Draw the template in use for this group, if there is one */
|
||||
short template_in_use = FindTemplateIndexForGroup(g_id);
|
||||
@@ -621,24 +686,24 @@ public:
|
||||
|
||||
/* Index of current template vehicle in the list of all templates for its company */
|
||||
SetDParam(0, i);
|
||||
DrawString(left+5, left+25, y + line_height/2, STR_BLACK_INT, TC_BLACK, SA_RIGHT);
|
||||
DrawString(left+5, left+25, y + 2, STR_BLACK_INT, TC_BLACK, SA_RIGHT);
|
||||
|
||||
/* Draw whether the current template is in use by any group */
|
||||
if ( v->NumGroupsUsingTemplate() > 0 ) {
|
||||
DrawString(left+200, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMP_TEMPLATE_IN_USE, TC_GREEN, SA_LEFT);
|
||||
DrawString(left+35, right, y + line_height - FONT_HEIGHT_SMALL * 2 - 4 - WD_FRAMERECT_BOTTOM - 2, STR_TMP_TEMPLATE_IN_USE, TC_GREEN, SA_LEFT);
|
||||
}
|
||||
|
||||
/* Draw information about template configuration settings */
|
||||
TextColour color;
|
||||
if ( v->IsSetReuseDepotVehicles() ) color = TC_LIGHT_BLUE;
|
||||
else color = TC_GREY;
|
||||
DrawString(left+200, right, y+2, STR_TMPL_CONFIG_USEDEPOT, color, SA_LEFT);
|
||||
DrawString(left+300, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_CONFIG_USEDEPOT, color, SA_LEFT);
|
||||
if ( v->IsSetKeepRemainingVehicles() ) color = TC_LIGHT_BLUE;
|
||||
else color = TC_GREY;
|
||||
DrawString(left+275, right, y+2, STR_TMPL_CONFIG_KEEPREMAINDERS, color, SA_LEFT);
|
||||
DrawString(left+400, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_CONFIG_KEEPREMAINDERS, color, SA_LEFT);
|
||||
if ( v->IsSetRefitAsTemplate() ) color = TC_LIGHT_BLUE;
|
||||
else color = TC_GREY;
|
||||
DrawString(left+350, right, y+2, STR_TMPL_CONFIG_REFIT, color, SA_LEFT);
|
||||
DrawString(left+500, right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 2, STR_TMPL_CONFIG_REFIT, color, SA_LEFT);
|
||||
|
||||
y += line_height;
|
||||
}
|
||||
@@ -646,9 +711,17 @@ public:
|
||||
|
||||
void DrawTemplateInfo(int line_height, const Rect &r) const
|
||||
{
|
||||
if ( this->selected_template_index == -1 || (short)this->templates.Length() <= this->selected_template_index )
|
||||
if ((this->selected_template_index < 0) || (this->selected_template_index >= (short)this->templates.Length()))
|
||||
return;
|
||||
|
||||
DrawPixelInfo tmp_dpi, *old_dpi;
|
||||
|
||||
if (!FillDrawPixelInfo(&tmp_dpi, r.left, r.top, r.right - r.left, r.bottom - r.top))
|
||||
return;
|
||||
|
||||
old_dpi = _cur_dpi;
|
||||
_cur_dpi = &tmp_dpi;
|
||||
|
||||
const TemplateVehicle *tmp = this->templates[this->selected_template_index];
|
||||
|
||||
/* Draw vehicle performance info */
|
||||
@@ -656,32 +729,34 @@ public:
|
||||
SetDParam(1, tmp->power);
|
||||
SetDParam(0, tmp->weight);
|
||||
SetDParam(3, tmp->max_te);
|
||||
DrawString(r.left+8, r.right, r.top+4, STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE);
|
||||
DrawString(8, r.right, 4 - this->vscroll[2]->GetPosition(), STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE);
|
||||
|
||||
/* Draw cargo summary */
|
||||
short top = r.top + 24;
|
||||
short left = r.left + 8;
|
||||
short count_rows = 0;
|
||||
short max_rows = 2;
|
||||
short top = 30 - this->vscroll[2]->GetPosition();
|
||||
short left = 8;
|
||||
short count_columns = 0;
|
||||
short max_columns = 2;
|
||||
|
||||
CargoArray cargo_caps;
|
||||
for ( ; tmp; tmp=tmp->Next() )
|
||||
cargo_caps[tmp->cargo_type] += tmp->cargo_cap;
|
||||
int y = top;
|
||||
int x = left;
|
||||
for (CargoID i = 0; i < NUM_CARGO; ++i) {
|
||||
if ( cargo_caps[i] > 0 ) {
|
||||
count_rows++;
|
||||
count_columns++;
|
||||
SetDParam(0, i);
|
||||
SetDParam(1, cargo_caps[i]);
|
||||
SetDParam(2, _settings_game.vehicle.freight_trains);
|
||||
DrawString(left, r.right, y, FreightWagonMult(i) > 1 ? STR_TMPL_CARGO_SUMMARY_MULTI : STR_TMPL_CARGO_SUMMARY, TC_WHITE, SA_LEFT);
|
||||
y += this->line_height/2;
|
||||
if ( count_rows % max_rows == 0 ) {
|
||||
y = top;
|
||||
left += 150;
|
||||
DrawString(x, r.right, top, FreightWagonMult(i) > 1 ? STR_TMPL_CARGO_SUMMARY_MULTI : STR_TMPL_CARGO_SUMMARY, TC_LIGHT_BLUE, SA_LEFT);
|
||||
x += 250;
|
||||
if ( count_columns % max_columns == 0 ) {
|
||||
x = left;
|
||||
top += this->line_height/3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cur_dpi = old_dpi;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -145,8 +145,7 @@ private:
|
||||
public:
|
||||
TemplateReplacementReplaceAllWindow(WindowDesc *wdesc) : Window(wdesc)
|
||||
{
|
||||
|
||||
this->CreateNestedTree(wdesc);
|
||||
this->CreateNestedTree(wdesc != nullptr);
|
||||
|
||||
this->vscroll_tl = this->GetScrollbar(RPLALL_GUI_SCROLL_TL);
|
||||
this->vscroll_tr = this->GetScrollbar(RPLALL_GUI_SCROLL_TR);
|
||||
|
@@ -27,8 +27,6 @@
|
||||
struct TemplateVehicle;
|
||||
struct TemplateReplacement;
|
||||
|
||||
CommandCost CmdBuildTemplateVehicle(uint i, DoCommandFlag flags, uint p1, uint p2, char const* text);
|
||||
CommandCost CmdTemplateReplaceVehicle(uint i, DoCommandFlag flags, uint p1, uint p2, char const* text);
|
||||
typedef uint16 TemplateID;
|
||||
|
||||
|
||||
|
@@ -142,52 +142,6 @@ inline void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicl
|
||||
tmp->image_width = virt->GetDisplayImageWidth(p);
|
||||
}
|
||||
|
||||
// create a new virtual train as clone of a real train
|
||||
Train* CloneVirtualTrainFromTrain(const Train *clicked)
|
||||
{
|
||||
if ( !clicked ) return 0;
|
||||
CommandCost c;
|
||||
Train *tmp, *head, *tail;
|
||||
|
||||
head = CmdBuildVirtualRailVehicle(clicked->engine_type);
|
||||
if ( !head ) return 0;
|
||||
|
||||
tail = head;
|
||||
clicked = clicked->GetNextUnit();
|
||||
while ( clicked ) {
|
||||
tmp = CmdBuildVirtualRailVehicle(clicked->engine_type);
|
||||
if ( tmp ) {
|
||||
tmp->cargo_type = clicked->cargo_type;
|
||||
tmp->cargo_subtype = clicked->cargo_subtype;
|
||||
CmdMoveRailVehicle(0, DC_EXEC, (1<<21) | tmp->index, tail->index, 0);
|
||||
tail = tmp;
|
||||
}
|
||||
clicked = clicked->GetNextUnit();
|
||||
}
|
||||
return head;
|
||||
}
|
||||
TemplateVehicle* CloneTemplateVehicleFromTrain(const Train *t)
|
||||
{
|
||||
Train *clicked = Train::Get(t->index);
|
||||
if ( !clicked )
|
||||
return 0;
|
||||
|
||||
Train *init_clicked = clicked;
|
||||
|
||||
int len = CountVehiclesInChain(clicked);
|
||||
if ( !TemplateVehicle::CanAllocateItem(len) )
|
||||
return 0;
|
||||
|
||||
TemplateVehicle *tmp, *prev=0;
|
||||
for ( ; clicked; clicked=clicked->Next() ) {
|
||||
tmp = new TemplateVehicle(clicked->engine_type);
|
||||
SetupTemplateVehicleFromVirtual(tmp, prev, clicked);
|
||||
prev = tmp;
|
||||
}
|
||||
|
||||
tmp->First()->SetRealLength(CeilDiv(init_clicked->gcache.cached_total_length * 10, TILE_SIZE));
|
||||
return tmp->First();
|
||||
}
|
||||
// create a full TemplateVehicle based train according to a virtual train
|
||||
TemplateVehicle* TemplateVehicleFromVirtualTrain(Train *virt)
|
||||
{
|
||||
@@ -211,32 +165,6 @@ TemplateVehicle* TemplateVehicleFromVirtualTrain(Train *virt)
|
||||
return tmp->First();
|
||||
}
|
||||
|
||||
// attempt to buy a train after a given template vehicle
|
||||
// this might fail if the template e.g. deprecated and contains engines that are not sold anymore
|
||||
Train* VirtualTrainFromTemplateVehicle(TemplateVehicle *tv)
|
||||
{
|
||||
if ( !tv ) return 0;
|
||||
CommandCost c;
|
||||
Train *tmp, *head, *tail;
|
||||
|
||||
head = CmdBuildVirtualRailVehicle(tv->engine_type);
|
||||
if ( !head ) return 0;
|
||||
|
||||
tail = head;
|
||||
tv = tv->GetNextUnit();
|
||||
while ( tv ) {
|
||||
tmp = CmdBuildVirtualRailVehicle(tv->engine_type);
|
||||
if ( tmp ) {
|
||||
tmp->cargo_type = tv->cargo_type;
|
||||
tmp->cargo_subtype = tv->cargo_subtype;
|
||||
CmdMoveRailVehicle(INVALID_TILE, DC_EXEC, (1<<21) | tmp->index, tail->index, 0);
|
||||
tail = tmp;
|
||||
}
|
||||
tv = tv->GetNextUnit();
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
// return last in a chain (really last, so even a singular articulated part of a vehicle if the last one is artic)
|
||||
inline TemplateVehicle* Last(TemplateVehicle *chain) {
|
||||
if ( !chain ) return 0;
|
||||
@@ -366,8 +294,9 @@ void CopyStatus(Train *from, Train *to) {
|
||||
}
|
||||
void NeutralizeStatus(Train *t) {
|
||||
DoCommand(t->tile, DEFAULT_GROUP, t->index, DC_EXEC, CMD_ADD_VEHICLE_GROUP);
|
||||
|
||||
t->name = 0;
|
||||
DoCommand(0, t->index | CO_UNSHARE << 30, 0, DC_EXEC, CMD_CLONE_ORDER);
|
||||
DoCommand(0, t->index, FreeUnitIDGenerator(VEH_TRAIN, t->owner).NextID(), DC_EXEC, CMD_SET_VEHICLE_UNIT_NUMBER);
|
||||
DoCommand(0, t->index, 0, DC_EXEC, CMD_RENAME_VEHICLE, NULL);
|
||||
}
|
||||
bool TrainMatchesTemplate(const Train *t, TemplateVehicle *tv) {
|
||||
while ( t && tv ) {
|
||||
@@ -494,13 +423,13 @@ int NumTrainsNeedTemplateReplacement(GroupID g_id, TemplateVehicle *tv)
|
||||
return count;
|
||||
}
|
||||
// refit each vehicle in t as is in tv, assume t and tv contain the same types of vehicles
|
||||
static void RefitTrainFromTemplate(Train *t, TemplateVehicle *tv)
|
||||
void CmdRefitTrainFromTemplate(Train *t, TemplateVehicle *tv, DoCommandFlag flags)
|
||||
{
|
||||
while ( t && tv ) {
|
||||
// refit t as tv
|
||||
uint32 cb = GetCmdRefitVeh(t);
|
||||
|
||||
DoCommandP(t->tile, t->index, tv->cargo_type | tv->cargo_subtype << 8 | 1 << 16 , cb);
|
||||
DoCommand(t->tile, t->index, tv->cargo_type | tv->cargo_subtype << 8 | 1 << 16 | (1 << 5), flags, cb);
|
||||
|
||||
// next
|
||||
t = t->GetNextUnit();
|
||||
@@ -546,7 +475,7 @@ void TransferCargoForTrain(Train *old_veh, Train *new_head)
|
||||
{
|
||||
// calculate the free space for new cargo on the current vehicle
|
||||
uint curCap = tmp->cargo_cap - tmp->cargo.TotalCount();
|
||||
uint moveAmount = std::min(remainingAmount, curCap);
|
||||
uint moveAmount = min(remainingAmount, curCap);
|
||||
// move (parts of) the old vehicle's cargo onto the current vehicle of the new chain
|
||||
if (moveAmount > 0)
|
||||
{
|
||||
@@ -562,184 +491,7 @@ void TransferCargoForTrain(Train *old_veh, Train *new_head)
|
||||
//if (src->cargo_cap < src->cargo.TotalCount()) src->cargo.Truncate(src->cargo.TotalCount() - src->cargo_cap);
|
||||
|
||||
/* Update train weight etc., the old vehicle will be sold anyway */
|
||||
new_head->ConsistChanged(ConsistChangeFlags::CCF_LOADUNLOAD);
|
||||
}
|
||||
|
||||
// TODO: fit signature to regular cmd-structure
|
||||
// do something with move_cost, it is not used right now
|
||||
// if exec==DC_EXEC, test first and execute if sucessful
|
||||
CommandCost CmdTemplateReplaceVehicle(Train *incoming, bool stayInDepot, DoCommandFlag flags) {
|
||||
Train *new_chain=0,
|
||||
*remainder_chain=0,
|
||||
*tmp_chain=0;
|
||||
TileIndex tile = incoming->tile;
|
||||
TemplateVehicle *tv = GetTemplateVehicleByGroupID(incoming->group_id);
|
||||
EngineID eid = tv->engine_type;
|
||||
|
||||
CommandCost buy(EXPENSES_NEW_VEHICLES);
|
||||
CommandCost move_cost(EXPENSES_NEW_VEHICLES);
|
||||
CommandCost tmp_result(EXPENSES_NEW_VEHICLES);
|
||||
|
||||
|
||||
/* first some tests on necessity and sanity */
|
||||
if ( !tv )
|
||||
return buy;
|
||||
bool need_replacement = !TrainMatchesTemplate(incoming, tv);
|
||||
bool need_refit = !TrainMatchesTemplateRefit(incoming, tv);
|
||||
bool use_refit = tv->refit_as_template;
|
||||
CargoID store_refit_ct = CT_INVALID;
|
||||
short store_refit_csubt = 0;
|
||||
// if a train shall keep its old refit, store the refit setting of its first vehicle
|
||||
if ( !use_refit ) {
|
||||
for ( Train *getc=incoming; getc; getc=getc->GetNextUnit() )
|
||||
if ( getc->cargo_type != CT_INVALID ) {
|
||||
store_refit_ct = getc->cargo_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: set result status to success/no success before returning
|
||||
if ( !need_replacement ) {
|
||||
if ( !need_refit || !use_refit ) {
|
||||
/* before returning, release incoming train first if 2nd param says so */
|
||||
if ( !stayInDepot ) incoming->vehstatus &= ~VS_STOPPED;
|
||||
return buy;
|
||||
}
|
||||
} else {
|
||||
CommandCost buyCost = TestBuyAllTemplateVehiclesInChain(tv, tile);
|
||||
if ( !buyCost.Succeeded() || !CheckCompanyHasMoney(buyCost) ) {
|
||||
if ( !stayInDepot ) incoming->vehstatus &= ~VS_STOPPED;
|
||||
return buy;
|
||||
}
|
||||
}
|
||||
|
||||
/* define replacement behaviour */
|
||||
bool reuseDepot = tv->IsSetReuseDepotVehicles();
|
||||
bool keepRemainders = tv->IsSetKeepRemainingVehicles();
|
||||
|
||||
if ( need_replacement ) {
|
||||
/// step 1: generate primary for newchain and generate remainder_chain
|
||||
// 1. primary of incoming might already fit the template
|
||||
// leave incoming's primary as is and move the rest to a free chain = remainder_chain
|
||||
// 2. needed primary might be one of incoming's member vehicles
|
||||
// 3. primary might be available as orphan vehicle in the depot
|
||||
// 4. we need to buy a new engine for the primary
|
||||
// all options other than 1. need to make sure to copy incoming's primary's status
|
||||
if ( eid == incoming->engine_type ) { // 1
|
||||
new_chain = incoming;
|
||||
remainder_chain = incoming->GetNextUnit();
|
||||
if ( remainder_chain )
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, remainder_chain->index|(1<<20), INVALID_VEHICLE, 0));
|
||||
}
|
||||
else if ( (tmp_chain = ChainContainsEngine(eid, incoming)) && tmp_chain!=NULL ) { // 2
|
||||
// new_chain is the needed engine, move it to an empty spot in the depot
|
||||
new_chain = tmp_chain;
|
||||
move_cost.AddCost(DoCommand(tile, new_chain->index, INVALID_VEHICLE, flags,CMD_MOVE_RAIL_VEHICLE));
|
||||
remainder_chain = incoming;
|
||||
}
|
||||
else if ( reuseDepot && (tmp_chain = DepotContainsEngine(tile, eid, incoming)) && tmp_chain!=NULL ) { // 3
|
||||
new_chain = tmp_chain;
|
||||
move_cost.AddCost(DoCommand(tile, new_chain->index, INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE));
|
||||
remainder_chain = incoming;
|
||||
}
|
||||
else { // 4
|
||||
tmp_result = DoCommand(tile, eid, 0, flags, CMD_BUILD_VEHICLE);
|
||||
/* break up in case buying the vehicle didn't succeed */
|
||||
if ( !tmp_result.Succeeded() )
|
||||
return tmp_result;
|
||||
buy.AddCost(tmp_result);
|
||||
new_chain = Train::Get(_new_vehicle_id);
|
||||
/* make sure the newly built engine is not attached to any free wagons inside the depot */
|
||||
move_cost.AddCost ( DoCommand(tile, new_chain->index, INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE) );
|
||||
/* prepare the remainder chain */
|
||||
remainder_chain = incoming;
|
||||
}
|
||||
// If we bought a new engine or reused one from the depot, copy some parameters from the incoming primary engine
|
||||
if ( incoming != new_chain && flags == DC_EXEC) {
|
||||
CopyHeadSpecificThings(incoming, new_chain, flags);
|
||||
NeutralizeStatus(incoming);
|
||||
// additionally, if we don't want to use the template refit, refit as incoming
|
||||
// the template refit will be set further down, if we use it at all
|
||||
if ( !use_refit ) {
|
||||
uint32 cb = GetCmdRefitVeh(new_chain);
|
||||
DoCommandP(new_chain->tile, new_chain->index, store_refit_ct | store_refit_csubt << 8 | 1 << 16 , cb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// step 2: fill up newchain according to the template
|
||||
// foreach member of template (after primary):
|
||||
// 1. needed engine might be within remainder_chain already
|
||||
// 2. needed engine might be orphaned within the depot (copy status)
|
||||
// 3. we need to buy (again) (copy status)
|
||||
TemplateVehicle *cur_tmpl = tv->GetNextUnit();
|
||||
Train *last_veh = new_chain;
|
||||
while (cur_tmpl) {
|
||||
// 1. engine contained in remainder chain
|
||||
if ( (tmp_chain = ChainContainsEngine(cur_tmpl->engine_type, remainder_chain)) && tmp_chain!=NULL ) {
|
||||
// advance remainder_chain (if necessary) to not lose track of it
|
||||
if ( tmp_chain == remainder_chain )
|
||||
remainder_chain = remainder_chain->GetNextUnit();
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, tmp_chain->index, last_veh->index, 0));
|
||||
}
|
||||
// 2. engine contained somewhere else in the depot
|
||||
else if ( reuseDepot && (tmp_chain = DepotContainsEngine(tile, cur_tmpl->engine_type, new_chain)) && tmp_chain!=NULL ) {
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, tmp_chain->index, last_veh->index, 0));
|
||||
}
|
||||
// 3. must buy new engine
|
||||
else {
|
||||
tmp_result = DoCommand(tile, cur_tmpl->engine_type, 0, flags, CMD_BUILD_VEHICLE);
|
||||
if ( !tmp_result.Succeeded() )
|
||||
return tmp_result;
|
||||
buy.AddCost(tmp_result);
|
||||
tmp_chain = Train::Get(_new_vehicle_id);
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, tmp_chain->index, last_veh->index, 0));
|
||||
}
|
||||
// TODO: is this enough ? might it be that we bought a new wagon here and it now has std refit ?
|
||||
if ( need_refit && flags == DC_EXEC ) {
|
||||
if ( use_refit ) {
|
||||
uint32 cb = GetCmdRefitVeh(tmp_chain);
|
||||
DoCommandP(tmp_chain->tile, tmp_chain->index, cur_tmpl->cargo_type | cur_tmpl->cargo_subtype << 8 | 1 << 16 , cb);
|
||||
// old
|
||||
// CopyWagonStatus(cur_tmpl, tmp_chain);
|
||||
} else {
|
||||
uint32 cb = GetCmdRefitVeh(tmp_chain);
|
||||
DoCommandP(tmp_chain->tile, tmp_chain->index, store_refit_ct | store_refit_csubt << 8 | 1 << 16 , cb);
|
||||
}
|
||||
}
|
||||
cur_tmpl = cur_tmpl->GetNextUnit();
|
||||
last_veh = tmp_chain;
|
||||
}
|
||||
}
|
||||
/* no replacement done */
|
||||
else {
|
||||
new_chain = incoming;
|
||||
}
|
||||
/// step 3: reorder and neutralize the remaining vehicles from incoming
|
||||
// wagons remaining from remainder_chain should be filled up in as few freewagonchains as possible
|
||||
// each locos might be left as singular in the depot
|
||||
// neutralize each remaining engine's status
|
||||
|
||||
// refit, only if the template option is set so
|
||||
if ( use_refit && (need_refit || need_replacement) ) {
|
||||
RefitTrainFromTemplate(new_chain, tv);
|
||||
}
|
||||
|
||||
if ( new_chain && remainder_chain )
|
||||
for ( Train *ct=remainder_chain; ct; ct=ct->GetNextUnit() )
|
||||
TransferCargoForTrain(ct, new_chain);
|
||||
|
||||
// point incoming to the newly created train so that starting/stopping from the calling function can be done
|
||||
incoming = new_chain;
|
||||
if ( !stayInDepot && flags == DC_EXEC )
|
||||
new_chain->vehstatus &= ~VS_STOPPED;
|
||||
|
||||
if ( remainder_chain && keepRemainders && flags == DC_EXEC )
|
||||
BreakUpRemainders(remainder_chain);
|
||||
else if ( remainder_chain ) {
|
||||
buy.AddCost(DoCommand(tile, remainder_chain->index | (1<<20), 0, flags, CMD_SELL_VEHICLE));
|
||||
}
|
||||
return buy;
|
||||
new_head->ConsistChanged(CCF_LOADUNLOAD);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -8,6 +8,10 @@
|
||||
#include "tbtr_template_vehicle.h"
|
||||
|
||||
//void DrawTemplateVehicle(TemplateVehicle*, int, const Rect&);
|
||||
|
||||
|
||||
Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv);
|
||||
|
||||
void DrawTemplateVehicle(const TemplateVehicle*, int, int, int, VehicleID, int, VehicleID);
|
||||
|
||||
void BuildTemplateGuiList(GUITemplateList*, Scrollbar*, Owner, RailType);
|
||||
@@ -26,9 +30,9 @@ TemplateVehicle *CreateNewTemplateVehicle(EngineID);
|
||||
|
||||
void setupVirtTrain(const TemplateVehicle*, Train*);
|
||||
|
||||
TemplateVehicle* TemplateVehicleFromVirtualTrain(Train*);
|
||||
TemplateVehicle* TemplateVehicleFromVirtualTrain(Train *virt);
|
||||
|
||||
Train* VirtualTrainFromTemplateVehicle(TemplateVehicle*);
|
||||
//Train* VirtualTrainFromTemplateVehicle(TemplateVehicle*);
|
||||
|
||||
inline TemplateVehicle* Last(TemplateVehicle*);
|
||||
|
||||
@@ -51,16 +55,21 @@ Train* DepotContainsEngine(TileIndex, EngineID, Train*);
|
||||
|
||||
int NumTrainsNeedTemplateReplacement(GroupID, TemplateVehicle*);
|
||||
|
||||
CommandCost TestBuyAllTemplateVehiclesInChain(Train*);
|
||||
CommandCost CalculateTemplateReplacementCost(Train*);
|
||||
CommandCost TestBuyAllTemplateVehiclesInChain(TemplateVehicle *tv, TileIndex tile);
|
||||
|
||||
void CmdRefitTrainFromTemplate(Train *t, TemplateVehicle *tv, DoCommandFlag);
|
||||
void BreakUpRemainders(Train *t);
|
||||
|
||||
short CountEnginesInChain(Train*);
|
||||
|
||||
bool TemplateVehicleContainsEngineOfRailtype(const TemplateVehicle*, RailType);
|
||||
|
||||
Train* CloneVirtualTrainFromTrain(const Train *);
|
||||
TemplateVehicle* CloneTemplateVehicleFromTrain(const Train *);
|
||||
|
||||
void TransferCargoForTrain(Train*, Train*);
|
||||
|
||||
void NeutralizeStatus(Train *t);
|
||||
|
||||
bool TrainMatchesTemplate(const Train *t, TemplateVehicle *tv);
|
||||
bool TrainMatchesTemplateRefit(const Train *t, TemplateVehicle *tv);
|
||||
|
||||
#endif
|
||||
|
@@ -35,14 +35,15 @@
|
||||
#include "order_backup.h"
|
||||
#include "zoom_func.h"
|
||||
#include "newgrf_debug.h"
|
||||
#include "tbtr_template_vehicle_func.h"
|
||||
#include "autoreplace_func.h"
|
||||
#include "engine_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/train_cmd.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
#include "engine_func.h"
|
||||
|
||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
|
||||
static bool TrainCheckIfLineEnds(Train *v, bool reverse = true);
|
||||
bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // Also used in vehicle_sl.cpp.
|
||||
@@ -4119,23 +4120,19 @@ Train* CmdBuildVirtualRailWagon(const Engine *e)
|
||||
|
||||
AddArticulatedParts(v);
|
||||
|
||||
// Make sure we set EVERYTHING to virtual, even articulated parts.
|
||||
for (Train* train_part = v; train_part != NULL; train_part = train_part->Next()) {
|
||||
train_part->SetVirtual();
|
||||
}
|
||||
|
||||
_new_vehicle_id = v->index;
|
||||
|
||||
// from revision r22xxx
|
||||
// VehicleMove(v, false);
|
||||
// new
|
||||
v->UpdateViewport(true, false);
|
||||
|
||||
v->First()->ConsistChanged(ConsistChangeFlags::CCF_ARRANGE);
|
||||
//UpdateTrainGroupID(v->First());
|
||||
v->First()->ConsistChanged(CCF_ARRANGE);
|
||||
|
||||
CheckConsistencyOfArticulatedVehicle(v);
|
||||
|
||||
/* The GVSF_VIRTUAL flag is used to prevent depot-tile sanity checks */
|
||||
SetBit(v->subtype, GVSF_VIRTUAL);
|
||||
|
||||
// GroupStatistics::CountVehicle( v, -1 );
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -4150,13 +4147,18 @@ Train* CmdBuildVirtualRailWagon(const Engine *e)
|
||||
*/
|
||||
Train* CmdBuildVirtualRailVehicle(EngineID eid)
|
||||
{
|
||||
if ( !IsEngineBuildable(eid, VEH_TRAIN, _current_company) ) return 0;
|
||||
if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company))
|
||||
return nullptr;
|
||||
|
||||
const Engine* e = Engine::Get(eid);
|
||||
const RailVehicleInfo *rvi = &e->u.rail;
|
||||
|
||||
int num_vehicles = (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false);
|
||||
if ( !Train::CanAllocateItem(num_vehicles) ) return 0;
|
||||
if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildVirtualRailWagon(e);
|
||||
if (!Train::CanAllocateItem(num_vehicles))
|
||||
return nullptr;
|
||||
|
||||
if (rvi->railveh_type == RAILVEH_WAGON)
|
||||
return CmdBuildVirtualRailWagon(e);
|
||||
|
||||
Train *v = new Train();
|
||||
|
||||
@@ -4191,9 +4193,6 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid)
|
||||
v->SetFrontEngine();
|
||||
v->SetEngine();
|
||||
|
||||
// from revision r22xxx
|
||||
// VehicleMove(v, false);
|
||||
// new
|
||||
v->UpdateViewport(true, false);
|
||||
|
||||
if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
|
||||
@@ -4202,14 +4201,246 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid)
|
||||
AddArticulatedParts(v);
|
||||
}
|
||||
|
||||
v->ConsistChanged(ConsistChangeFlags::CCF_ARRANGE);
|
||||
//UpdateTrainGroupID(v);
|
||||
// Make sure we set EVERYTHING to virtual, even articulated parts.
|
||||
for (Train* train_part = v; train_part != NULL; train_part = train_part->Next()) {
|
||||
train_part->SetVirtual();
|
||||
}
|
||||
|
||||
v->ConsistChanged(CCF_ARRANGE);
|
||||
|
||||
CheckConsistencyOfArticulatedVehicle(v);
|
||||
|
||||
SetBit(v->subtype, GVSF_VIRTUAL);
|
||||
|
||||
// GroupStatistics::CountVehicle( v, -1 );
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a virtual train vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the engine ID to build
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdBuildVirtualRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
EngineID eid = p1;
|
||||
CommandCost cost = CommandCost();
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
Train* train = CmdBuildVirtualRailVehicle(eid);
|
||||
|
||||
if (train == nullptr)
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a vehicle based on a template replacement order.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the ID of the vehicle to replace.
|
||||
* @param p2 whether the vehicle should stay in the depot.
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdTemplateReplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
VehicleID vehicle_id = p1;
|
||||
|
||||
Vehicle* vehicle = Vehicle::GetIfValid(vehicle_id);
|
||||
|
||||
if (vehicle == nullptr || vehicle->type != VEH_TRAIN)
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (!should_execute)
|
||||
return CommandCost();
|
||||
|
||||
Train* incoming = Train::From(vehicle);
|
||||
bool stayInDepot = p2 != 0;
|
||||
|
||||
Train *new_chain = 0,
|
||||
*remainder_chain = 0,
|
||||
*tmp_chain = 0;
|
||||
TemplateVehicle *tv = GetTemplateVehicleByGroupID(incoming->group_id);
|
||||
EngineID eid = tv->engine_type;
|
||||
|
||||
CommandCost buy(EXPENSES_NEW_VEHICLES);
|
||||
CommandCost move_cost(EXPENSES_NEW_VEHICLES);
|
||||
CommandCost tmp_result(EXPENSES_NEW_VEHICLES);
|
||||
|
||||
|
||||
/* first some tests on necessity and sanity */
|
||||
if (!tv)
|
||||
return buy;
|
||||
bool need_replacement = !TrainMatchesTemplate(incoming, tv);
|
||||
bool need_refit = !TrainMatchesTemplateRefit(incoming, tv);
|
||||
bool use_refit = tv->refit_as_template;
|
||||
CargoID store_refit_ct = CT_INVALID;
|
||||
short store_refit_csubt = 0;
|
||||
// if a train shall keep its old refit, store the refit setting of its first vehicle
|
||||
if (!use_refit) {
|
||||
for (Train *getc = incoming; getc; getc = getc->GetNextUnit())
|
||||
if (getc->cargo_type != CT_INVALID) {
|
||||
store_refit_ct = getc->cargo_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: set result status to success/no success before returning
|
||||
if (!need_replacement) {
|
||||
if (!need_refit || !use_refit) {
|
||||
/* before returning, release incoming train first if 2nd param says so */
|
||||
if (!stayInDepot) incoming->vehstatus &= ~VS_STOPPED;
|
||||
return buy;
|
||||
}
|
||||
}
|
||||
else {
|
||||
CommandCost buyCost = TestBuyAllTemplateVehiclesInChain(tv, tile);
|
||||
if (!buyCost.Succeeded() || !CheckCompanyHasMoney(buyCost)) {
|
||||
if (!stayInDepot) incoming->vehstatus &= ~VS_STOPPED;
|
||||
return buy;
|
||||
}
|
||||
}
|
||||
|
||||
/* define replacement behavior */
|
||||
bool reuseDepot = tv->IsSetReuseDepotVehicles();
|
||||
bool keepRemainders = tv->IsSetKeepRemainingVehicles();
|
||||
|
||||
if (need_replacement) {
|
||||
/// step 1: generate primary for newchain and generate remainder_chain
|
||||
// 1. primary of incoming might already fit the template
|
||||
// leave incoming's primary as is and move the rest to a free chain = remainder_chain
|
||||
// 2. needed primary might be one of incoming's member vehicles
|
||||
// 3. primary might be available as orphan vehicle in the depot
|
||||
// 4. we need to buy a new engine for the primary
|
||||
// all options other than 1. need to make sure to copy incoming's primary's status
|
||||
if (eid == incoming->engine_type) { // 1
|
||||
new_chain = incoming;
|
||||
remainder_chain = incoming->GetNextUnit();
|
||||
if (remainder_chain)
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, remainder_chain->index | (1 << 20), INVALID_VEHICLE, 0));
|
||||
}
|
||||
else if ((tmp_chain = ChainContainsEngine(eid, incoming)) && tmp_chain != NULL) { // 2
|
||||
// new_chain is the needed engine, move it to an empty spot in the depot
|
||||
new_chain = tmp_chain;
|
||||
move_cost.AddCost(DoCommand(tile, new_chain->index, INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE));
|
||||
remainder_chain = incoming;
|
||||
}
|
||||
else if (reuseDepot && (tmp_chain = DepotContainsEngine(tile, eid, incoming)) && tmp_chain != NULL) { // 3
|
||||
new_chain = tmp_chain;
|
||||
move_cost.AddCost(DoCommand(tile, new_chain->index, INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE));
|
||||
remainder_chain = incoming;
|
||||
}
|
||||
else { // 4
|
||||
tmp_result = DoCommand(tile, eid, 0, flags, CMD_BUILD_VEHICLE);
|
||||
/* break up in case buying the vehicle didn't succeed */
|
||||
if (!tmp_result.Succeeded())
|
||||
return tmp_result;
|
||||
buy.AddCost(tmp_result);
|
||||
new_chain = Train::Get(_new_vehicle_id);
|
||||
/* make sure the newly built engine is not attached to any free wagons inside the depot */
|
||||
move_cost.AddCost(DoCommand(tile, new_chain->index, INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE));
|
||||
/* prepare the remainder chain */
|
||||
remainder_chain = incoming;
|
||||
}
|
||||
// If we bought a new engine or reused one from the depot, copy some parameters from the incoming primary engine
|
||||
if (incoming != new_chain && flags == DC_EXEC) {
|
||||
CopyHeadSpecificThings(incoming, new_chain, flags);
|
||||
NeutralizeStatus(incoming);
|
||||
|
||||
|
||||
// additionally, if we don't want to use the template refit, refit as incoming
|
||||
// the template refit will be set further down, if we use it at all
|
||||
if (!use_refit) {
|
||||
uint32 cb = GetCmdRefitVeh(new_chain);
|
||||
DoCommand(new_chain->tile, new_chain->index, store_refit_ct | store_refit_csubt << 8 | 1 << 16 | (1 << 5), flags, cb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// step 2: fill up newchain according to the template
|
||||
// foreach member of template (after primary):
|
||||
// 1. needed engine might be within remainder_chain already
|
||||
// 2. needed engine might be orphaned within the depot (copy status)
|
||||
// 3. we need to buy (again) (copy status)
|
||||
TemplateVehicle *cur_tmpl = tv->GetNextUnit();
|
||||
Train *last_veh = new_chain;
|
||||
while (cur_tmpl) {
|
||||
// 1. engine contained in remainder chain
|
||||
if ((tmp_chain = ChainContainsEngine(cur_tmpl->engine_type, remainder_chain)) && tmp_chain != NULL) {
|
||||
// advance remainder_chain (if necessary) to not lose track of it
|
||||
if (tmp_chain == remainder_chain)
|
||||
remainder_chain = remainder_chain->GetNextUnit();
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, tmp_chain->index, last_veh->index, 0));
|
||||
}
|
||||
// 2. engine contained somewhere else in the depot
|
||||
else if (reuseDepot && (tmp_chain = DepotContainsEngine(tile, cur_tmpl->engine_type, new_chain)) && tmp_chain != NULL) {
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, tmp_chain->index, last_veh->index, 0));
|
||||
}
|
||||
// 3. must buy new engine
|
||||
else {
|
||||
tmp_result = DoCommand(tile, cur_tmpl->engine_type, 0, flags, CMD_BUILD_VEHICLE);
|
||||
if (!tmp_result.Succeeded())
|
||||
return tmp_result;
|
||||
buy.AddCost(tmp_result);
|
||||
tmp_chain = Train::Get(_new_vehicle_id);
|
||||
move_cost.AddCost(CmdMoveRailVehicle(tile, flags, tmp_chain->index, last_veh->index, 0));
|
||||
}
|
||||
// TODO: is this enough ? might it be that we bought a new wagon here and it now has std refit ?
|
||||
if (need_refit && flags == DC_EXEC) {
|
||||
if (use_refit) {
|
||||
uint32 cb = GetCmdRefitVeh(tmp_chain);
|
||||
DoCommand(tmp_chain->tile, tmp_chain->index, cur_tmpl->cargo_type | cur_tmpl->cargo_subtype << 8 | 1 << 16 | (1 << 5), flags, cb);
|
||||
// old
|
||||
// CopyWagonStatus(cur_tmpl, tmp_chain);
|
||||
}
|
||||
else {
|
||||
uint32 cb = GetCmdRefitVeh(tmp_chain);
|
||||
DoCommand(tmp_chain->tile, tmp_chain->index, store_refit_ct | store_refit_csubt << 8 | 1 << 16 | (1 << 5), flags, cb);
|
||||
}
|
||||
}
|
||||
cur_tmpl = cur_tmpl->GetNextUnit();
|
||||
last_veh = tmp_chain;
|
||||
}
|
||||
}
|
||||
/* no replacement done */
|
||||
else {
|
||||
new_chain = incoming;
|
||||
}
|
||||
/// step 3: reorder and neutralize the remaining vehicles from incoming
|
||||
// wagons remaining from remainder_chain should be filled up in as few freewagonchains as possible
|
||||
// each locos might be left as singular in the depot
|
||||
// neutralize each remaining engine's status
|
||||
|
||||
// refit, only if the template option is set so
|
||||
if (use_refit && (need_refit || need_replacement)) {
|
||||
CmdRefitTrainFromTemplate(new_chain, tv, flags);
|
||||
}
|
||||
|
||||
if (new_chain && remainder_chain)
|
||||
for (Train *ct = remainder_chain; ct; ct = ct->GetNextUnit())
|
||||
TransferCargoForTrain(ct, new_chain);
|
||||
|
||||
// point incoming to the newly created train so that starting/stopping from the calling function can be done
|
||||
incoming = new_chain;
|
||||
if (!stayInDepot && flags == DC_EXEC)
|
||||
new_chain->vehstatus &= ~VS_STOPPED;
|
||||
|
||||
if (remainder_chain && keepRemainders && flags == DC_EXEC)
|
||||
BreakUpRemainders(remainder_chain);
|
||||
else if (remainder_chain) {
|
||||
buy.AddCost(DoCommand(tile, remainder_chain->index | (1 << 20), 0, flags, CMD_SELL_VEHICLE));
|
||||
}
|
||||
|
||||
/* Redraw main gui for changed statistics */
|
||||
SetWindowClassesDirty(WC_TEMPLATEGUI_MAIN);
|
||||
|
||||
return buy;
|
||||
}
|
||||
|
@@ -1032,9 +1032,7 @@ void CallVehicleTicks()
|
||||
bool stayInDepot = it->second;
|
||||
|
||||
it->first->vehstatus |= VS_STOPPED;
|
||||
CmdTemplateReplaceVehicle(t, stayInDepot, DC_EXEC);
|
||||
/* Redraw main gui for changed statistics */
|
||||
SetWindowClassesDirty(WC_TEMPLATEGUI_MAIN);
|
||||
DoCommand(t->tile, t->index, stayInDepot ? 1 : 0, DC_EXEC, CMD_TEMPLATE_REPLACE_VEHICLE);
|
||||
}
|
||||
tmpl_cur_company.Restore();
|
||||
}
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#include "ship.h"
|
||||
#include "newgrf.h"
|
||||
#include "company_base.h"
|
||||
#include "tbtr_template_vehicle.h"
|
||||
#include "tbtr_template_vehicle_func.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
@@ -174,7 +176,10 @@ CommandCost CmdSellVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
|
||||
if (front->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED);
|
||||
|
||||
/* Do this check only if the vehicle to be moved is non-virtual */
|
||||
if (!HasBit(p1, 21)) {
|
||||
if (!front->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type);
|
||||
}
|
||||
|
||||
/* Can we actually make the order backup, i.e. are there enough orders? */
|
||||
if (p1 & MAKE_ORDER_BACKUP_FLAG &&
|
||||
@@ -776,6 +781,442 @@ static void CloneVehicleName(const Vehicle *src, Vehicle *dst)
|
||||
/* All done. If we didn't find a name, it'll just use its default. */
|
||||
}
|
||||
|
||||
inline void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev, Train *virt)
|
||||
{
|
||||
if (prev) {
|
||||
prev->SetNext(tmp);
|
||||
tmp->SetPrev(prev);
|
||||
tmp->SetFirst(prev->First());
|
||||
}
|
||||
tmp->railtype = virt->railtype;
|
||||
tmp->owner = virt->owner;
|
||||
tmp->value = virt->value;
|
||||
|
||||
// set the subtype but also clear the virtual flag while doing it
|
||||
tmp->subtype = virt->subtype & ~(1 << GVSF_VIRTUAL);
|
||||
// set the cargo type and capacity
|
||||
tmp->cargo_type = virt->cargo_type;
|
||||
tmp->cargo_subtype = virt->cargo_subtype;
|
||||
tmp->cargo_cap = virt->cargo_cap;
|
||||
|
||||
const GroundVehicleCache *gcache = virt->GetGroundVehicleCache();
|
||||
tmp->max_speed = virt->GetDisplayMaxSpeed();
|
||||
tmp->power = gcache->cached_power;
|
||||
tmp->weight = gcache->cached_weight;
|
||||
tmp->max_te = gcache->cached_max_te / 1000;
|
||||
|
||||
tmp->spritenum = virt->spritenum;
|
||||
tmp->cur_image = virt->GetImage(DIR_W, EIT_PURCHASE);
|
||||
Point *p = new Point();
|
||||
tmp->image_width = virt->GetDisplayImageWidth(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles 'reuse depot vehicles' on a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the template vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdToggleReuseDepotVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
// Identify template to toggle
|
||||
TemplateVehicle *template_vehicle = TemplateVehicle::GetIfValid(p1);
|
||||
|
||||
if (template_vehicle == NULL)
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
template_vehicle->ToggleReuseDepotVehicles();
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles 'keep remaining vehicles' on a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the template vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdToggleKeepRemainingVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
// Identify template to toggle
|
||||
TemplateVehicle *template_vehicle = TemplateVehicle::GetIfValid(p1);
|
||||
|
||||
if (template_vehicle == NULL)
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
template_vehicle->ToggleKeepRemainingVehicles();
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles 'refit as template' on a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the template vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdToggleRefitAsTemplate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
// Identify template to toggle
|
||||
TemplateVehicle *template_vehicle = TemplateVehicle::GetIfValid(p1);
|
||||
|
||||
if (template_vehicle == NULL)
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
template_vehicle->ToggleRefitAsTemplate();
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a virtual train from a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the original vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdVirtualTrainFromTemplateVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
VehicleID template_vehicle_id = p1;
|
||||
|
||||
TemplateVehicle* tv = TemplateVehicle::GetIfValid(template_vehicle_id);
|
||||
|
||||
if (tv == NULL)
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
Train* train = VirtualTrainFromTemplateVehicle(tv);
|
||||
|
||||
if (train == nullptr)
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv)
|
||||
{
|
||||
CommandCost c;
|
||||
Train *tmp, *head, *tail;
|
||||
|
||||
head = CmdBuildVirtualRailVehicle(tv->engine_type);
|
||||
if ( !head ) return nullptr;
|
||||
|
||||
tail = head;
|
||||
tv = tv->GetNextUnit();
|
||||
while ( tv ) {
|
||||
tmp = CmdBuildVirtualRailVehicle(tv->engine_type);
|
||||
if ( tmp ) {
|
||||
tmp->cargo_type = tv->cargo_type;
|
||||
tmp->cargo_subtype = tv->cargo_subtype;
|
||||
CmdMoveRailVehicle(INVALID_TILE, DC_EXEC, (1<<21) | tmp->index, tail->index, 0);
|
||||
tail = tmp;
|
||||
}
|
||||
tv = tv->GetNextUnit();
|
||||
}
|
||||
|
||||
_new_vehicle_id = head->index;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a virtual train from a regular train.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the train index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdVirtualTrainFromTrain(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
VehicleID vehicle_id = p1;
|
||||
Vehicle* vehicle = Vehicle::GetIfValid(vehicle_id);
|
||||
|
||||
if (vehicle == nullptr || vehicle->type != VEH_TRAIN)
|
||||
return CMD_ERROR;
|
||||
|
||||
Train* train = Train::From(vehicle);
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
CommandCost c;
|
||||
Train *tmp, *head, *tail;
|
||||
|
||||
head = CmdBuildVirtualRailVehicle(train->engine_type);
|
||||
if ( !head ) return CMD_ERROR;
|
||||
|
||||
tail = head;
|
||||
train = train->GetNextUnit();
|
||||
while ( train ) {
|
||||
tmp = CmdBuildVirtualRailVehicle(train->engine_type);
|
||||
if ( tmp ) {
|
||||
tmp->cargo_type = train->cargo_type;
|
||||
tmp->cargo_subtype = train->cargo_subtype;
|
||||
CmdMoveRailVehicle(0, DC_EXEC, (1<<21) | tmp->index, tail->index, 0);
|
||||
tail = tmp;
|
||||
}
|
||||
train = train->GetNextUnit();
|
||||
}
|
||||
|
||||
_new_vehicle_id = head->index;
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a virtual train from a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdDeleteVirtualTrain(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
VehicleID vehicle_id = p1;
|
||||
|
||||
Vehicle* vehicle = Vehicle::GetIfValid(vehicle_id);
|
||||
|
||||
if (vehicle == nullptr || vehicle->type != VEH_TRAIN)
|
||||
return CMD_ERROR;
|
||||
|
||||
Train* train = Train::From(vehicle);
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
delete train;
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a template vehicle with another one based on a virtual train.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the template vehicle's index
|
||||
* @param p2 the virtual train's index
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdReplaceTemplateVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
VehicleID template_vehicle_id = p1;
|
||||
VehicleID virtual_train_id = p2;
|
||||
|
||||
TemplateVehicle* template_vehicle = TemplateVehicle::GetIfValid(template_vehicle_id);
|
||||
Vehicle* vehicle = Vehicle::GetIfValid(virtual_train_id);
|
||||
|
||||
if (vehicle == nullptr || vehicle->type != VEH_TRAIN)
|
||||
return CMD_ERROR;
|
||||
|
||||
Train* train = Train::From(vehicle);
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
VehicleID old_ID = INVALID_VEHICLE;
|
||||
|
||||
if (template_vehicle != nullptr) {
|
||||
old_ID = template_vehicle->index;
|
||||
delete template_vehicle;
|
||||
template_vehicle = nullptr;
|
||||
}
|
||||
|
||||
template_vehicle = TemplateVehicleFromVirtualTrain(train);
|
||||
|
||||
if (template_vehicle == nullptr)
|
||||
return CMD_ERROR;
|
||||
|
||||
// Make sure our replacements still point to the correct thing.
|
||||
if (old_ID != template_vehicle->index) {
|
||||
TemplateReplacement* tr;
|
||||
FOR_ALL_TEMPLATE_REPLACEMENTS(tr) {
|
||||
if (tr->GetTemplateVehicleID() == old_ID) {
|
||||
tr->SetTemplate(template_vehicle->index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a vehicle to create a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the original vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdTemplateVehicleFromTrain(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
// create a new template from the clicked vehicle
|
||||
TemplateVehicle *tv;
|
||||
|
||||
Vehicle *t = Vehicle::GetIfValid(p1);
|
||||
|
||||
Train *clicked = Train::GetIfValid(t->index);
|
||||
if (!clicked)
|
||||
return CMD_ERROR;
|
||||
|
||||
Train *init_clicked = clicked;
|
||||
|
||||
int len = CountVehiclesInChain(clicked);
|
||||
if (!TemplateVehicle::CanAllocateItem(len))
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
TemplateVehicle *tmp, *prev=0;
|
||||
for (; clicked; clicked=clicked->Next()) {
|
||||
tmp = new TemplateVehicle(clicked->engine_type);
|
||||
SetupTemplateVehicleFromVirtual(tmp, prev, clicked);
|
||||
prev = tmp;
|
||||
}
|
||||
|
||||
tmp->First()->SetRealLength(CeilDiv(init_clicked->gcache.cached_total_length * 10, TILE_SIZE));
|
||||
tv = tmp->First();
|
||||
|
||||
if (!tv) return CMD_ERROR;
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a template vehicle.
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the template vehicle's index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdDeleteTemplateVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
// Identify template to delete
|
||||
TemplateVehicle *del = TemplateVehicle::GetIfValid(p1);
|
||||
|
||||
if (del == NULL)
|
||||
return CMD_ERROR;
|
||||
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
if (should_execute) {
|
||||
// Remove a corresponding template replacement if existing
|
||||
TemplateReplacement *tr = GetTemplateReplacementByTemplateID(del->index);
|
||||
if (tr != NULL) {
|
||||
delete tr;
|
||||
}
|
||||
|
||||
delete del;
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a template replacement for a vehicle group
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the group index
|
||||
* @param p2 the template vehicle's index
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdIssueTemplateReplacement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
GroupID group_id = p1;
|
||||
TemplateID template_id = p2;
|
||||
|
||||
if (should_execute) {
|
||||
bool succeeded = IssueTemplateReplacement(group_id, template_id);
|
||||
|
||||
if (!succeeded)
|
||||
return CMD_ERROR;
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a template replacement from a vehicle group
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 the group index
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdDeleteTemplateReplacement(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
bool should_execute = (flags & DC_EXEC) != 0;
|
||||
|
||||
GroupID group_id = p1;
|
||||
|
||||
if (should_execute) {
|
||||
TemplateReplacement* tr = GetTemplateReplacementByGroupID(group_id);
|
||||
if (tr != NULL)
|
||||
delete tr;
|
||||
|
||||
InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN, 0);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clone a vehicle. If it is a train, it will clone all the cars too
|
||||
* @param tile tile of the depot where the cloned vehicle is build
|
||||
@@ -1020,6 +1461,30 @@ CommandCost CmdSendVehicleToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1
|
||||
return v->SendToDepot(flags, (DepotCommand)(p1 & DEPOT_COMMAND_MASK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vehicle unit number
|
||||
* @param tile unused
|
||||
* @param flags type of operation
|
||||
* @param p1 vehicle ID to set number on
|
||||
* @param p2 vehicle unit number
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdSetVehicleUnitNumber(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
Vehicle *v = Vehicle::GetIfValid(p1);
|
||||
if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
|
||||
|
||||
CommandCost ret = CheckOwnership(v->owner);
|
||||
if (ret.Failed()) return ret;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
v->unitnumber = (UnitID)p2;
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Give a custom name to your vehicle
|
||||
* @param tile unused
|
||||
|
Reference in New Issue
Block a user