Move clone vehicle code to game command
This commit is contained in:
parent
e9aa64527a
commit
af3588ef6b
|
@ -2205,3 +2205,4 @@ strings:
|
|||
2150: Improved
|
||||
2151: "Modify vehicle"
|
||||
2152: "Clone vehicle"
|
||||
2153: "Can't clone vehicle..."
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace OpenLoco::GameCommands
|
|||
static loco_global<uintptr_t[80], 0x004F9548> _4F9548;
|
||||
|
||||
// 0x004F9688
|
||||
bool _gameCommandCanBeUsedWhenPaused[80] = {
|
||||
bool _gameCommandCanBeUsedWhenPaused[81] = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
|
@ -108,6 +108,7 @@ namespace OpenLoco::GameCommands
|
|||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
};
|
||||
|
||||
static loco_global<tile_element*, 0x009C68D0> _9C68D0;
|
||||
|
@ -119,87 +120,88 @@ namespace OpenLoco::GameCommands
|
|||
static loco_global<string_id[8], 0x112C826> _commonFormatArgs;
|
||||
|
||||
using GameCommandFunc = void (*)(registers& regs);
|
||||
static GameCommandFunc _gameCommandFunctions[80] = {
|
||||
nullptr, // vehicle_rearrange = 0, 0x004AF1DF
|
||||
nullptr, // vehicle_place = 1, 0x004B01B6
|
||||
nullptr, // vehicle_pickup = 2, 0x004B0826
|
||||
nullptr, // vehicle_reverse = 3, 0x004ADAA8
|
||||
nullptr, // 4 0x004B0B50
|
||||
Vehicles::create, // vehicle_create = 5,
|
||||
nullptr, // vehicle_sell = 6, 0x004AED34
|
||||
nullptr, // 7 0x0049BB98
|
||||
nullptr, // 8 0x0049C7F2
|
||||
nullptr, // build_vehicle = 9, 0x0046DE88
|
||||
nullptr, // vehicle_rename = 10, 0x004B6572
|
||||
nullptr, // change_station_name = 11, 0x00490756
|
||||
nullptr, // vehicle_local_express = 12, 0x004B694B
|
||||
nullptr, // 13 0x00488BDB
|
||||
nullptr, // 14 0x004891E4
|
||||
nullptr, // 15 0x0048BB20
|
||||
nullptr, // 16 0x0048C402
|
||||
nullptr, // 17 0x004A6479
|
||||
nullptr, // 18 0x004A668A
|
||||
nullptr, // change_company_colour_scheme = 19, 0x0043483D
|
||||
nullptr, // pause_game = 20, 0x00431E32
|
||||
nullptr, // load_save_quit_game = 21, 0x0043BFCB
|
||||
nullptr, // 22 0x004BB392
|
||||
nullptr, // 23 0x004BB138
|
||||
nullptr, // change_land_material = 24, 0x00468EDD
|
||||
nullptr, // raise_land = 25, 0x00463702
|
||||
nullptr, // lower_land = 26, 0x004638C6
|
||||
nullptr, // lower_raise_land_mountain = 27, 0x00462DCE
|
||||
nullptr, // raise_water = 28, 0x004C4F19
|
||||
nullptr, // lower_water = 29, 0x004C5126
|
||||
nullptr, // 30 0x00434914
|
||||
nullptr, // 31 0x00434A58
|
||||
nullptr, // 32 0x004C436C
|
||||
nullptr, // 33 0x004C466C
|
||||
nullptr, // 34 0x004C4717
|
||||
nullptr, // vehicle_order_insert = 35, 0x0047036E
|
||||
nullptr, // vehicle_order_delete = 36, 0x0047057A
|
||||
nullptr, // vehicle_order_skip = 37, 0x0047071A
|
||||
nullptr, // 38 0x00475FBC
|
||||
nullptr, // 39 0x004775A5
|
||||
nullptr, // 40 0x0047A21E
|
||||
nullptr, // 41 0x0047A42F
|
||||
nullptr, // 42 0x0048C708
|
||||
nullptr, // 43 0x0048D2AC
|
||||
nullptr, // 44 0x0042D133
|
||||
nullptr, // 45 0x0042D74E
|
||||
nullptr, // change_company_name = 46, 0x0049B11E
|
||||
nullptr, // 47 0x0045436B
|
||||
nullptr, // 48 0x00455943
|
||||
nullptr, // 49 0x00496C22
|
||||
nullptr, // 50 0x0049711F
|
||||
nullptr, // 51 0x004A6FDC
|
||||
nullptr, // 52 0x004A734F
|
||||
nullptr, // 53 0x0047AF0B
|
||||
nullptr, // remove_industry = 54, 0x0042ECFC
|
||||
nullptr, // build_company_headquarters = 55, 0x0042EEAF
|
||||
nullptr, // 56 0x00492C41
|
||||
nullptr, // 57 0x00493559
|
||||
nullptr, // 58 0x004267BE
|
||||
nullptr, // vehicle_abort_pickup_air = 59, 0x00426B29
|
||||
nullptr, // 60 0x00493AA7
|
||||
nullptr, // 61 0x00494570
|
||||
nullptr, // 62 0x0042773C
|
||||
nullptr, // vehicle_abort_pickup_water = 63, 0x004279CC
|
||||
nullptr, // 63 0x0042F6DB
|
||||
nullptr, // 64 0x00435506
|
||||
nullptr, // change_company_face = 66, 0x00469CCB
|
||||
nullptr, // load_multiplayer_map = 67, 0x00444DA0
|
||||
nullptr, // 68 0x0046F8A5
|
||||
nullptr, // 69 0x004454BE
|
||||
nullptr, // 70 0x004456C8
|
||||
nullptr, // send_chat_message = 71, 0x0046F976
|
||||
nullptr, // multiplayer_save = 72, 0x004A0ACD
|
||||
nullptr, // update_owner_status = 73, 0x004383CA
|
||||
nullptr, // vehicle_speed_control = 74, 0x004BAB63
|
||||
nullptr, // vehicle_order_up = 75, 0x00470CD2
|
||||
nullptr, // vehicle_order_down = 76, 0x00470E06
|
||||
nullptr, // vehicle_apply_shunt_cheat = 77, 0x004BAC53
|
||||
nullptr, // apply_free_cash_cheat = 78, 0x00438A08
|
||||
nullptr, // rename_industry = 79, 0x00455029
|
||||
static GameCommandFunc _gameCommandFunctions[81] = {
|
||||
nullptr, // vehicle_rearrange = 0, 0x004AF1DF
|
||||
nullptr, // vehicle_place = 1, 0x004B01B6
|
||||
nullptr, // vehicle_pickup = 2, 0x004B0826
|
||||
nullptr, // vehicle_reverse = 3, 0x004ADAA8
|
||||
nullptr, // 4 0x004B0B50
|
||||
Vehicles::create, // vehicle_create = 5,
|
||||
nullptr, // vehicle_sell = 6, 0x004AED34
|
||||
nullptr, // 7 0x0049BB98
|
||||
nullptr, // 8 0x0049C7F2
|
||||
nullptr, // build_vehicle = 9, 0x0046DE88
|
||||
nullptr, // vehicle_rename = 10, 0x004B6572
|
||||
nullptr, // change_station_name = 11, 0x00490756
|
||||
nullptr, // vehicle_local_express = 12, 0x004B694B
|
||||
nullptr, // 13 0x00488BDB
|
||||
nullptr, // 14 0x004891E4
|
||||
nullptr, // 15 0x0048BB20
|
||||
nullptr, // 16 0x0048C402
|
||||
nullptr, // 17 0x004A6479
|
||||
nullptr, // 18 0x004A668A
|
||||
nullptr, // change_company_colour_scheme = 19, 0x0043483D
|
||||
nullptr, // pause_game = 20, 0x00431E32
|
||||
nullptr, // load_save_quit_game = 21, 0x0043BFCB
|
||||
nullptr, // 22 0x004BB392
|
||||
nullptr, // 23 0x004BB138
|
||||
nullptr, // change_land_material = 24, 0x00468EDD
|
||||
nullptr, // raise_land = 25, 0x00463702
|
||||
nullptr, // lower_land = 26, 0x004638C6
|
||||
nullptr, // lower_raise_land_mountain = 27, 0x00462DCE
|
||||
nullptr, // raise_water = 28, 0x004C4F19
|
||||
nullptr, // lower_water = 29, 0x004C5126
|
||||
nullptr, // 30 0x00434914
|
||||
nullptr, // 31 0x00434A58
|
||||
nullptr, // 32 0x004C436C
|
||||
nullptr, // 33 0x004C466C
|
||||
nullptr, // 34 0x004C4717
|
||||
nullptr, // vehicle_order_insert = 35, 0x0047036E
|
||||
nullptr, // vehicle_order_delete = 36, 0x0047057A
|
||||
nullptr, // vehicle_order_skip = 37, 0x0047071A
|
||||
nullptr, // 38 0x00475FBC
|
||||
nullptr, // 39 0x004775A5
|
||||
nullptr, // 40 0x0047A21E
|
||||
nullptr, // 41 0x0047A42F
|
||||
nullptr, // 42 0x0048C708
|
||||
nullptr, // 43 0x0048D2AC
|
||||
nullptr, // 44 0x0042D133
|
||||
nullptr, // 45 0x0042D74E
|
||||
nullptr, // change_company_name = 46, 0x0049B11E
|
||||
nullptr, // 47 0x0045436B
|
||||
nullptr, // 48 0x00455943
|
||||
nullptr, // 49 0x00496C22
|
||||
nullptr, // 50 0x0049711F
|
||||
nullptr, // 51 0x004A6FDC
|
||||
nullptr, // 52 0x004A734F
|
||||
nullptr, // 53 0x0047AF0B
|
||||
nullptr, // remove_industry = 54, 0x0042ECFC
|
||||
nullptr, // build_company_headquarters = 55, 0x0042EEAF
|
||||
nullptr, // 56 0x00492C41
|
||||
nullptr, // 57 0x00493559
|
||||
nullptr, // 58 0x004267BE
|
||||
nullptr, // vehicle_abort_pickup_air = 59, 0x00426B29
|
||||
nullptr, // 60 0x00493AA7
|
||||
nullptr, // 61 0x00494570
|
||||
nullptr, // 62 0x0042773C
|
||||
nullptr, // vehicle_abort_pickup_water = 63, 0x004279CC
|
||||
nullptr, // 63 0x0042F6DB
|
||||
nullptr, // 64 0x00435506
|
||||
nullptr, // change_company_face = 66, 0x00469CCB
|
||||
nullptr, // load_multiplayer_map = 67, 0x00444DA0
|
||||
nullptr, // 68 0x0046F8A5
|
||||
nullptr, // 69 0x004454BE
|
||||
nullptr, // 70 0x004456C8
|
||||
nullptr, // send_chat_message = 71, 0x0046F976
|
||||
nullptr, // multiplayer_save = 72, 0x004A0ACD
|
||||
nullptr, // update_owner_status = 73, 0x004383CA
|
||||
nullptr, // vehicle_speed_control = 74, 0x004BAB63
|
||||
nullptr, // vehicle_order_up = 75, 0x00470CD2
|
||||
nullptr, // vehicle_order_down = 76, 0x00470E06
|
||||
nullptr, // vehicle_apply_shunt_cheat = 77, 0x004BAC53
|
||||
nullptr, // apply_free_cash_cheat = 78, 0x00438A08
|
||||
nullptr, // rename_industry = 79, 0x00455029
|
||||
Vehicles::cloneVehicle // vehicle_clone = 80, *NEW*
|
||||
};
|
||||
|
||||
void registerHooks()
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace OpenLoco::GameCommands
|
|||
vehicle_apply_shunt_cheat = 77,
|
||||
apply_free_cash_cheat = 78,
|
||||
rename_industry = 79,
|
||||
vehicle_clone = 80,
|
||||
};
|
||||
|
||||
constexpr uint32_t FAILURE = 0x80000000;
|
||||
|
@ -113,14 +114,14 @@ namespace OpenLoco::GameCommands
|
|||
}
|
||||
|
||||
// Build vehicle
|
||||
inline bool do_5(uint16_t vehicle_type, uint16_t vehicle_id = 0xFFFF)
|
||||
inline uint32_t do_5(uint16_t vehicle_type, uint16_t vehicle_id = 0xFFFF)
|
||||
{
|
||||
registers regs;
|
||||
regs.bl = GameCommandFlag::apply;
|
||||
regs.di = vehicle_id;
|
||||
regs.edx = vehicle_type;
|
||||
|
||||
return doCommand(5, regs) != FAILURE;
|
||||
return doCommand(5, regs);
|
||||
}
|
||||
|
||||
// Build vehicle
|
||||
|
@ -571,4 +572,12 @@ namespace OpenLoco::GameCommands
|
|||
regs.edi = edi; // part of name buffer
|
||||
doCommand(79, regs);
|
||||
}
|
||||
|
||||
inline bool do_80(uint16_t head)
|
||||
{
|
||||
registers regs;
|
||||
regs.bl = GameCommandFlag::apply;
|
||||
regs.ax = head;
|
||||
return GameCommands::doCommand(static_cast<int32_t>(GameCommand::vehicle_clone), regs) != FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1481,4 +1481,5 @@ namespace OpenLoco::StringIds
|
|||
constexpr string_id generator_improved = 2150;
|
||||
constexpr string_id dropdown_modify_vehicle = 2151;
|
||||
constexpr string_id dropdown_clone_vehicle = 2152;
|
||||
constexpr string_id cant_clone_vehicle = 2153;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
#include "../GameCommands.h"
|
||||
#include "../Interop/Interop.hpp"
|
||||
#include "../Things/ThingManager.h"
|
||||
#include "../Ui/WindowManager.h"
|
||||
#include "Orders.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
using namespace OpenLoco::Interop;
|
||||
|
||||
namespace OpenLoco::Vehicles
|
||||
{
|
||||
static uint32_t cloneVehicle(uint16_t head, uint8_t flags)
|
||||
{
|
||||
static loco_global<uint16_t, 0x0113642A> _113642A;
|
||||
Vehicles::Vehicle existingTrain(head);
|
||||
Vehicles::VehicleHead* newHead = nullptr;
|
||||
|
||||
// Get total cost for a new vehicle
|
||||
if (!(flags & GameCommands::apply))
|
||||
{
|
||||
uint32_t totalCost = 0;
|
||||
for (auto& car : existingTrain.cars)
|
||||
{
|
||||
auto cost = GameCommands::queryDo_5(car.front->object_id, -1);
|
||||
if (cost == GameCommands::FAILURE)
|
||||
{
|
||||
totalCost = GameCommands::FAILURE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalCost += cost;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalCost == GameCommands::FAILURE)
|
||||
{
|
||||
return GameCommands::FAILURE;
|
||||
}
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
uint32_t totalCost = 0;
|
||||
for (auto& car : existingTrain.cars)
|
||||
{
|
||||
uint32_t cost = 0;
|
||||
if (newHead == nullptr)
|
||||
{
|
||||
cost = GameCommands::do_5(car.front->object_id, -1);
|
||||
auto* newVeh = ThingManager::get<Vehicles::VehicleBase>(_113642A);
|
||||
if (newVeh == nullptr)
|
||||
{
|
||||
return GameCommands::FAILURE;
|
||||
}
|
||||
newHead = ThingManager::get<Vehicles::VehicleHead>(newVeh->getHead());
|
||||
}
|
||||
else
|
||||
{
|
||||
cost = GameCommands::do_5(car.front->object_id, newHead->head);
|
||||
}
|
||||
if (cost == GameCommands::FAILURE)
|
||||
{
|
||||
totalCost = GameCommands::FAILURE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalCost += cost;
|
||||
}
|
||||
}
|
||||
if (totalCost == GameCommands::FAILURE || newHead == nullptr)
|
||||
{
|
||||
return GameCommands::FAILURE;
|
||||
}
|
||||
|
||||
// Copy orders
|
||||
std::vector<std::shared_ptr<Vehicles::Order>> clonedOrders;
|
||||
for (auto& existingOrders : Vehicles::OrderTableView(existingTrain.head->orderTableOffset))
|
||||
{
|
||||
clonedOrders.push_back(existingOrders.clone());
|
||||
}
|
||||
|
||||
for (auto& order : clonedOrders)
|
||||
{
|
||||
auto chosenOffset = newHead->orderTableOffset + newHead->sizeOfOrderTable - 1;
|
||||
GameCommands::do_35(newHead->id, order->getRaw(), chosenOffset);
|
||||
}
|
||||
|
||||
// Copy express/local
|
||||
if (existingTrain.veh1->var_48 & (1 << 1))
|
||||
{
|
||||
GameCommands::do12(newHead->id, 2);
|
||||
}
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
void cloneVehicle(registers& regs)
|
||||
{
|
||||
regs.ebx = cloneVehicle(regs.ax, regs.bl);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ namespace OpenLoco::Vehicles
|
|||
constexpr auto max_vehicle_length = 176; // TODO: Units?
|
||||
|
||||
void create(OpenLoco::Interop::registers& regs);
|
||||
void cloneVehicle(OpenLoco::Interop::registers& regs);
|
||||
|
||||
namespace Flags0C // commands?
|
||||
{
|
||||
|
|
|
@ -759,7 +759,7 @@ namespace OpenLoco::Ui::BuildVehicle
|
|||
gGameCommandErrorTitle = StringIds::cant_add_pop_5_string_id_string_id;
|
||||
}
|
||||
|
||||
if (!GameCommands::do_5(item, _buildTargetVehicle))
|
||||
if (GameCommands::do_5(item, _buildTargetVehicle) == GameCommands::FAILURE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -185,8 +185,6 @@ namespace OpenLoco::Ui::Vehicle
|
|||
makeWidget({ 240, 152 }, { 24, 12 }, widget_type::wt_9, 1, ImageIds::red_arrow_down, StringIds::tooltip_route_move_order_down),
|
||||
widgetEnd(),
|
||||
};
|
||||
|
||||
static void addNewOrder(window* const self, const Vehicles::Order& order);
|
||||
}
|
||||
|
||||
static loco_global<uint8_t, 0x00525FC5> _525FC5;
|
||||
|
@ -948,72 +946,14 @@ namespace OpenLoco::Ui::Vehicle
|
|||
{
|
||||
static loco_global<uint16_t, 0x0113642A> _113642A;
|
||||
auto head = Common::getVehicle(self);
|
||||
Vehicles::Vehicle train(head);
|
||||
Vehicles::VehicleHead* newHead = nullptr;
|
||||
|
||||
// Get total cost for a new vehicle (note this should be removed when turned into a game command)
|
||||
uint32_t totalCost = 0;
|
||||
for (auto& car : train.cars)
|
||||
gGameCommandErrorTitle = StringIds::cant_clone_vehicle;
|
||||
if (GameCommands::do_80(head->head))
|
||||
{
|
||||
auto cost = GameCommands::queryDo_5(car.front->object_id, -1);
|
||||
if (cost == GameCommands::FAILURE)
|
||||
auto* newVehicle = ThingManager::get<Vehicles::VehicleBase>(_113642A);
|
||||
if (newVehicle != nullptr)
|
||||
{
|
||||
totalCost = GameCommands::FAILURE;
|
||||
break;
|
||||
OpenLoco::Ui::Vehicle::Details::open(newVehicle);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalCost += cost;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalCost == GameCommands::FAILURE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check total cost for a new vehicle, taken from GameCommands::loc_4313C6 (note this should be removed when turned into a game command)
|
||||
registers regs2;
|
||||
regs2.ebp = totalCost;
|
||||
call(0x0046DD06, regs2);
|
||||
if (static_cast<uint32_t>(regs2.ebp) == GameCommands::FAILURE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& car : train.cars)
|
||||
{
|
||||
if (newHead == nullptr)
|
||||
{
|
||||
GameCommands::do_5(car.front->object_id, -1);
|
||||
newHead = ThingManager::get<Vehicles::VehicleHead>(ThingManager::get<Vehicles::VehicleBase>(_113642A)->getHead());
|
||||
}
|
||||
else
|
||||
{
|
||||
GameCommands::do_5(car.front->object_id, newHead->head);
|
||||
}
|
||||
}
|
||||
auto* newWnd = Vehicle::Details::open(newHead);
|
||||
|
||||
// Copy orders
|
||||
// Route::addNewOrder expects window on Route tab but we can just pretend
|
||||
// TODO: Change this in the future.
|
||||
newWnd->var_842 = 0;
|
||||
std::vector<std::shared_ptr<Vehicles::Order>> clonedOrders;
|
||||
for (auto& existingOrders : Vehicles::OrderTableView(head->orderTableOffset))
|
||||
{
|
||||
clonedOrders.push_back(existingOrders.clone());
|
||||
}
|
||||
for (auto& order : clonedOrders)
|
||||
{
|
||||
Route::addNewOrder(newWnd, *order);
|
||||
}
|
||||
newWnd->var_842 = 0;
|
||||
|
||||
// Copy express/local
|
||||
if (train.veh1->var_48 & (1 << 1))
|
||||
{
|
||||
GameCommands::do12(newHead->id, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
<ClCompile Include="Ui\WindowManager.cpp" />
|
||||
<ClCompile Include="Utility\Numeric.cpp" />
|
||||
<ClCompile Include="Utility\String.cpp" />
|
||||
<ClCompile Include="Vehicles\CloneVehicle.cpp" />
|
||||
<ClCompile Include="Vehicles\CreateVehicle.cpp" />
|
||||
<ClCompile Include="Vehicles\Orders.cpp" />
|
||||
<ClCompile Include="Vehicles\Vehicle.cpp" />
|
||||
|
|
Loading…
Reference in New Issue