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:
Jonathan G Rennison
2016-02-14 00:52:42 +00:00
parent 769462f537
commit 6be2efc084
15 changed files with 1167 additions and 459 deletions

View File

@@ -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);
if (!front->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type);
/* 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