Allow cloning trains directly from the template train list

See: #312
This commit is contained in:
Jonathan G Rennison
2021-08-22 14:59:33 +01:00
parent a4c73e71c3
commit a026d82c6b
7 changed files with 88 additions and 0 deletions

View File

@@ -215,6 +215,7 @@ CommandProc CmdIssueTemplateReplacement;
CommandProc CmdDeleteTemplateReplacement; CommandProc CmdDeleteTemplateReplacement;
CommandProc CmdCloneVehicle; CommandProc CmdCloneVehicle;
CommandProc CmdCloneVehicleFromTemplate;
CommandProc CmdStartStopVehicle; CommandProc CmdStartStopVehicle;
CommandProc CmdMassStartStopVehicle; CommandProc CmdMassStartStopVehicle;
CommandProc CmdAutoreplaceVehicle; CommandProc CmdAutoreplaceVehicle;
@@ -450,6 +451,7 @@ static const Command _command_proc_table[] = {
DEF_CMD(CmdDeleteTemplateReplacement, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_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(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(CmdCloneVehicleFromTemplate, CMD_NO_TEST, CMDT_VEHICLE_CONSTRUCTION ), // CMD_CLONE_VEHICLE_FROM_TEMPLATE; 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(CmdStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_START_STOP_VEHICLE
DEF_CMD(CmdMassStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_MASS_START_STOP DEF_CMD(CmdMassStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_MASS_START_STOP
DEF_CMD(CmdAutoreplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_AUTOREPLACE_VEHICLE DEF_CMD(CmdAutoreplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT ), // CMD_AUTOREPLACE_VEHICLE

View File

@@ -396,6 +396,7 @@ enum Commands {
CMD_DELETE_TEMPLATE_REPLACEMENT, ///< delete a template replacement from a vehicle group CMD_DELETE_TEMPLATE_REPLACEMENT, ///< delete a template replacement from a vehicle group
CMD_CLONE_VEHICLE, ///< clone a vehicle CMD_CLONE_VEHICLE, ///< clone a vehicle
CMD_CLONE_VEHICLE_FROM_TEMPLATE, ///< clone a vehicle from a template
CMD_START_STOP_VEHICLE, ///< start or stop a vehicle CMD_START_STOP_VEHICLE, ///< start or stop a vehicle
CMD_MASS_START_STOP, ///< start/stop all vehicles (in a depot) 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_AUTOREPLACE_VEHICLE, ///< replace/renew a vehicle while it is in a depot

View File

@@ -28,6 +28,7 @@
#include "infrastructure_func.h" #include "infrastructure_func.h"
#include "order_backup.h" #include "order_backup.h"
#include "zoom_func.h" #include "zoom_func.h"
#include "tbtr_template_vehicle.h"
#include "widgets/depot_widget.h" #include "widgets/depot_widget.h"
@@ -917,6 +918,21 @@ struct DepotWindow : Window {
return true; return true;
} }
/**
* Clones a vehicle
* @param v the original vehicle to clone
* @return Always true.
*/
bool OnTemplateVehicleSelect(const TemplateVehicle *v) override
{
/* Copy-clone, open viewport for new vehicle, and deselect the tool (assume player wants to changs things on new vehicle) */
if (DoCommandP(this->window_number, v->index, 0, CMD_CLONE_VEHICLE_FROM_TEMPLATE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN), CcCloneVehicle)) {
ResetObjectToPlace();
}
return true;
}
void OnPlaceObjectAbort() override void OnPlaceObjectAbort() override
{ {
/* abort clone */ /* abort clone */

View File

@@ -447,6 +447,8 @@ public:
if (newindex == this->selected_template_index || newindex >= templates.size()) { if (newindex == this->selected_template_index || newindex >= templates.size()) {
this->selected_template_index = -1; this->selected_template_index = -1;
} else if (newindex < templates.size()) { } else if (newindex < templates.size()) {
const TemplateVehicle *tmp = this->templates[newindex];
if (tmp != nullptr && TemplateVehicleClicked(tmp)) return;
this->selected_template_index = newindex; this->selected_template_index = newindex;
} }
this->UpdateButtonState(); this->UpdateButtonState();
@@ -840,3 +842,19 @@ void ShowTemplateReplaceWindow()
new TemplateReplaceWindow(&_replace_rail_vehicle_desc); new TemplateReplaceWindow(&_replace_rail_vehicle_desc);
} }
} }
/**
* Dispatch a "template vehicle selected" event if any window waits for it.
* @param v selected vehicle;
* @return did any window accept vehicle selection?
*/
bool TemplateVehicleClicked(const TemplateVehicle *v)
{
assert(v != nullptr);
if (!(_thd.place_mode & HT_VEHICLE)) return false;
v = v->First();
if (!v->IsPrimaryVehicle()) return false;
return _thd.GetCallbackWnd()->OnTemplateVehicleSelect(v);
}

View File

@@ -23,4 +23,6 @@ typedef GUIList<const Group*> GUIGroupList;
void ShowTemplateReplaceWindow(); void ShowTemplateReplaceWindow();
bool TemplateVehicleClicked(const TemplateVehicle *v);
#endif #endif

View File

@@ -33,6 +33,7 @@
#include "core/random_func.hpp" #include "core/random_func.hpp"
#include "tbtr_template_vehicle.h" #include "tbtr_template_vehicle.h"
#include "tbtr_template_vehicle_func.h" #include "tbtr_template_vehicle_func.h"
#include "scope.h"
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <cctype> #include <cctype>
@@ -1537,6 +1538,47 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
return total_cost; return total_cost;
} }
/**
* Clone a vehicle from a template.
* @param tile tile of the depot where the cloned vehicle is build
* @param flags type of operation
* @param p1 the original template vehicle's index
* @param p2 unused
* @param text unused
* @return the cost of this operation or an error
*/
CommandCost CmdCloneVehicleFromTemplate(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
TemplateVehicle* tv = TemplateVehicle::GetIfValid(p1);
if (tv == nullptr) {
return CMD_ERROR;
}
CommandCost ret = CheckOwnership(tv->owner);
if (ret.Failed()) return ret;
/* Vehicle construction needs random bits, so we have to save the random
* seeds to prevent desyncs. */
SavedRandomSeeds saved_seeds;
SaveRandomSeeds(&saved_seeds);
auto guard = scope_guard([&]() {
if (!(flags & DC_EXEC)) RestoreRandomSeeds(saved_seeds);
});
ret = DoCommand(0, tv->index, 0, DC_EXEC, CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN));
if (ret.Failed()) return ret;
Train* virt = Train::From(Vehicle::Get(_new_vehicle_id));
ret = DoCommand(tile, _new_vehicle_id, 0, flags, CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN));
delete virt;
return ret;
}
/** /**
* Send all vehicles of type to depots * Send all vehicles of type to depots
* @param flags the flags used for DoCommand() * @param flags the flags used for DoCommand()

View File

@@ -823,6 +823,13 @@ public:
*/ */
virtual bool OnVehicleSelect(const struct Vehicle *v) { return false; } virtual bool OnVehicleSelect(const struct Vehicle *v) { return false; }
/**
* The user clicked on a template vehicle while HT_VEHICLE has been set.
* @param v clicked vehicle. It is guaranteed to be v->IsPrimaryVehicle() == true
* @return True if the click is handled, false if it is ignored.
*/
virtual bool OnTemplateVehicleSelect(const struct TemplateVehicle *v) { return false; }
/** /**
* The user cancelled a tile highlight mode that has been set. * The user cancelled a tile highlight mode that has been set.
*/ */