mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r12913) -Add: ability to backup and restore a player's economic data and data for a vehicle (or chain of vehicles)
Autoreplace uses this with the following benefits: -Mass autoreplace (the button in the depot window) will now estimate costs correctly -Autoreplace now either replaces correctly or manages to keep the original vehicle (no more broken trains) Thanks to Ammler for testing this
This commit is contained in:
parent
9f5f4e59cd
commit
757de2bdf5
|
@ -206,7 +206,11 @@ static CommandCost ReplaceVehicle(Vehicle **w, byte flags, Money total_cost, con
|
||||||
/* Now we move the old one out of the train */
|
/* Now we move the old one out of the train */
|
||||||
DoCommand(0, (INVALID_VEHICLE << 16) | old_v->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
DoCommand(0, (INVALID_VEHICLE << 16) | old_v->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
||||||
/* Add the new vehicle */
|
/* Add the new vehicle */
|
||||||
DoCommand(0, (front->index << 16) | new_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
CommandCost tmp_move = DoCommand(0, (front->index << 16) | new_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
||||||
|
if (CmdFailed(tmp_move)) {
|
||||||
|
cost.AddCost(tmp_move);
|
||||||
|
DoCommand(0, new_v->index, 1, DC_EXEC, GetCmdSellVeh(VEH_TRAIN));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// copy/clone the orders
|
// copy/clone the orders
|
||||||
|
@ -232,7 +236,11 @@ static CommandCost ReplaceVehicle(Vehicle **w, byte flags, Money total_cost, con
|
||||||
}
|
}
|
||||||
|
|
||||||
if (temp_v != NULL) {
|
if (temp_v != NULL) {
|
||||||
DoCommand(0, (new_v->index << 16) | temp_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
CommandCost tmp_move = DoCommand(0, (new_v->index << 16) | temp_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
|
||||||
|
if (CmdFailed(tmp_move)) {
|
||||||
|
cost.AddCost(tmp_move);
|
||||||
|
DoCommand(0, temp_v->index, 1, DC_EXEC, GetCmdSellVeh(VEH_TRAIN));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,9 +371,10 @@ static EngineID GetNewEngineType(const Vehicle *v, const Player *p)
|
||||||
CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
|
CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
|
||||||
{
|
{
|
||||||
Vehicle *w;
|
Vehicle *w;
|
||||||
const Player *p = GetPlayer(v->owner);
|
Player *p = GetPlayer(v->owner);
|
||||||
CommandCost cost;
|
CommandCost cost;
|
||||||
bool stopped = false;
|
bool stopped = false;
|
||||||
|
BackuppedVehicle backup(true);
|
||||||
|
|
||||||
/* We only want "real" vehicle types. */
|
/* We only want "real" vehicle types. */
|
||||||
assert(IsPlayerBuildableVehicleType(v));
|
assert(IsPlayerBuildableVehicleType(v));
|
||||||
|
@ -410,11 +419,14 @@ CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
|
||||||
EngineID new_engine = GetNewEngineType(w, p);
|
EngineID new_engine = GetNewEngineType(w, p);
|
||||||
if (new_engine == INVALID_ENGINE) continue;
|
if (new_engine == INVALID_ENGINE) continue;
|
||||||
|
|
||||||
|
if (!backup.ContainsBackup()) {
|
||||||
|
/* We are going to try to replace a vehicle but we don't have any backup so we will make one. */
|
||||||
|
backup.Backup(v, p);
|
||||||
|
}
|
||||||
/* Now replace the vehicle */
|
/* Now replace the vehicle */
|
||||||
cost.AddCost(ReplaceVehicle(&w, flags, cost.GetCost(), p, new_engine));
|
cost.AddCost(ReplaceVehicle(&w, DC_EXEC, cost.GetCost(), p, new_engine));
|
||||||
|
|
||||||
if (flags & DC_EXEC &&
|
if (w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE) {
|
||||||
(w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE)) {
|
|
||||||
/* now we bought a new engine and sold the old one. We need to fix the
|
/* now we bought a new engine and sold the old one. We need to fix the
|
||||||
* pointers in order to avoid pointing to the old one for trains: these
|
* pointers in order to avoid pointing to the old one for trains: these
|
||||||
* pointers should point to the front engine and not the cars
|
* pointers should point to the front engine and not the cars
|
||||||
|
@ -423,18 +435,26 @@ CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
|
||||||
}
|
}
|
||||||
} while (w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
|
} while (w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
|
||||||
|
|
||||||
|
if (v->type == VEH_TRAIN && p->renew_keep_length) {
|
||||||
|
/* Remove wagons until the wanted length is reached */
|
||||||
|
cost.AddCost(WagonRemoval(v, old_total_length));
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & DC_QUERY_COST || cost.GetCost() == 0) {
|
if (flags & DC_QUERY_COST || cost.GetCost() == 0) {
|
||||||
/* We didn't do anything during the replace so we will just exit here */
|
/* We didn't do anything during the replace so we will just exit here */
|
||||||
|
v = backup.Restore(v);
|
||||||
if (stopped) v->vehstatus &= ~VS_STOPPED;
|
if (stopped) v->vehstatus &= ~VS_STOPPED;
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display_costs && !(flags & DC_EXEC)) {
|
if (display_costs) {
|
||||||
/* We want to ensure that we will not get below p->engine_renew_money.
|
/* We want to ensure that we will not get below p->engine_renew_money.
|
||||||
* We will not actually pay this amount. It's for display and checks only. */
|
* We will not actually pay this amount. It's for display and checks only. */
|
||||||
cost.AddCost((Money)p->engine_renew_money);
|
CommandCost tmp = cost;
|
||||||
if (CmdSucceeded(cost) && GetAvailableMoneyForCommand() < cost.GetCost()) {
|
tmp.AddCost((Money)p->engine_renew_money);
|
||||||
|
if (CmdSucceeded(tmp) && GetAvailableMoneyForCommand() < tmp.GetCost()) {
|
||||||
/* We don't have enough money so we will set cost to failed */
|
/* We don't have enough money so we will set cost to failed */
|
||||||
|
cost.AddCost((Money)p->engine_renew_money);
|
||||||
cost.AddCost(CMD_ERROR);
|
cost.AddCost(CMD_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,15 +477,12 @@ CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DC_EXEC && CmdSucceeded(cost)) {
|
if (display_costs && IsLocalPlayer() && (flags & DC_EXEC) && CmdSucceeded(cost)) {
|
||||||
if (v->type == VEH_TRAIN && p->renew_keep_length) {
|
ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
|
||||||
/* Remove wagons until the wanted length is reached */
|
}
|
||||||
cost.AddCost(WagonRemoval(v, old_total_length));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display_costs && IsLocalPlayer()) {
|
if (!(flags & DC_EXEC) || CmdFailed(cost)) {
|
||||||
ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
|
v = backup.Restore(v);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the vehicle if we stopped it earlier */
|
/* Start the vehicle if we stopped it earlier */
|
||||||
|
|
|
@ -542,16 +542,12 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
|
||||||
* fact will trigger an assertion failure. --pasky
|
* fact will trigger an assertion failure. --pasky
|
||||||
* CMD_CLONE_VEHICLE: Both building new vehicles and refitting them can be
|
* CMD_CLONE_VEHICLE: Both building new vehicles and refitting them can be
|
||||||
* influenced by newgrf callbacks, which makes it impossible to accurately
|
* influenced by newgrf callbacks, which makes it impossible to accurately
|
||||||
* estimate the cost of cloning a vehicle.
|
* estimate the cost of cloning a vehicle. */
|
||||||
* CMD_DEPOT_MASS_AUTOREPLACE: we can't predict wagon removal so
|
|
||||||
* the test will not include income from any sold wagons.
|
|
||||||
* This means that the costs can sometimes be lower than estimated. */
|
|
||||||
notest =
|
notest =
|
||||||
(cmd & 0xFF) == CMD_CLEAR_AREA ||
|
(cmd & 0xFF) == CMD_CLEAR_AREA ||
|
||||||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
|
(cmd & 0xFF) == CMD_LEVEL_LAND ||
|
||||||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD ||
|
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD ||
|
||||||
(cmd & 0xFF) == CMD_CLONE_VEHICLE ||
|
(cmd & 0xFF) == CMD_CLONE_VEHICLE;
|
||||||
(cmd & 0xFF) == CMD_DEPOT_MASS_AUTOREPLACE;
|
|
||||||
|
|
||||||
_docommand_recursive = 1;
|
_docommand_recursive = 1;
|
||||||
|
|
||||||
|
|
|
@ -1233,7 +1233,7 @@ void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *bak)
|
||||||
|
|
||||||
/* Copy the orders */
|
/* Copy the orders */
|
||||||
FOR_VEHICLE_ORDERS(v, order) {
|
FOR_VEHICLE_ORDERS(v, order) {
|
||||||
*dest = *order;
|
memcpy(dest, order, sizeof(Order));
|
||||||
dest++;
|
dest++;
|
||||||
}
|
}
|
||||||
/* End the list with an empty order */
|
/* End the list with an empty order */
|
||||||
|
@ -1285,6 +1285,42 @@ void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *bak)
|
||||||
DoCommandP(0, bak->group, v->index, NULL, CMD_ADD_VEHICLE_GROUP);
|
DoCommandP(0, bak->group, v->index, NULL, CMD_ADD_VEHICLE_GROUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Restores vehicle orders that was previously backed up by BackupVehicleOrders()
|
||||||
|
* This will restore to the point where it was at the time of the backup meaning
|
||||||
|
* it will presume the same order indexes can be used.
|
||||||
|
* This is needed when restoring a backed up vehicle
|
||||||
|
* @param v The vehicle that should gain the orders
|
||||||
|
* @param bak the backup of the orders
|
||||||
|
*/
|
||||||
|
void RestoreVehicleOrdersBruteForce(Vehicle *v, const BackuppedOrders *bak)
|
||||||
|
{
|
||||||
|
if (bak->name != NULL) {
|
||||||
|
/* Restore the name. */
|
||||||
|
v->name = strdup(bak->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we had shared orders, recover that */
|
||||||
|
if (bak->clone != INVALID_VEHICLE) {
|
||||||
|
/* We will place it at the same location in the linked list as it previously was. */
|
||||||
|
if (v->prev_shared != NULL) {
|
||||||
|
assert(v->prev_shared->next_shared == v->next_shared);
|
||||||
|
v->prev_shared->next_shared = v;
|
||||||
|
}
|
||||||
|
if (v->next_shared != NULL) {
|
||||||
|
assert(v->next_shared->prev_shared == v->prev_shared);
|
||||||
|
v->next_shared->prev_shared = v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Restore the orders at the indexes they originally were. */
|
||||||
|
for (Order *order = bak->order; order->IsValid(); order++) {
|
||||||
|
Order *dst = GetOrder(order->index);
|
||||||
|
/* Since we are restoring something we removed a moment ago all the orders should be free. */
|
||||||
|
assert(!dst->IsValid());
|
||||||
|
memcpy(dst, order, sizeof(Order));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Restore the current order-index of a vehicle and sets service-interval.
|
/** Restore the current order-index of a vehicle and sets service-interval.
|
||||||
* @param tile unused
|
* @param tile unused
|
||||||
* @param flags operation to perform
|
* @param flags operation to perform
|
||||||
|
|
|
@ -28,6 +28,7 @@ extern BackuppedOrders _backup_orders_data;
|
||||||
|
|
||||||
void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *order = &_backup_orders_data);
|
void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *order = &_backup_orders_data);
|
||||||
void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *order = &_backup_orders_data);
|
void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *order = &_backup_orders_data);
|
||||||
|
void RestoreVehicleOrdersBruteForce(Vehicle *v, const BackuppedOrders *bak);
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination);
|
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination);
|
||||||
|
|
|
@ -73,6 +73,18 @@ struct Player {
|
||||||
uint16 num_engines[TOTAL_NUM_ENGINES]; ///< caches the number of engines of each type the player owns (no need to save this)
|
uint16 num_engines[TOTAL_NUM_ENGINES]; ///< caches the number of engines of each type the player owns (no need to save this)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlayerMoneyBackup {
|
||||||
|
private:
|
||||||
|
Money backup_yearly_expenses[EXPENSES_END];
|
||||||
|
PlayerEconomyEntry backup_cur_economy;
|
||||||
|
Player *p;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlayerMoneyBackup(Player *player);
|
||||||
|
|
||||||
|
void Restore();
|
||||||
|
};
|
||||||
|
|
||||||
extern Player _players[MAX_PLAYERS];
|
extern Player _players[MAX_PLAYERS];
|
||||||
#define FOR_ALL_PLAYERS(p) for (p = _players; p != endof(_players); p++)
|
#define FOR_ALL_PLAYERS(p) for (p = _players; p != endof(_players); p++)
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,24 @@ bool CheckPlayerHasMoney(CommandCost cost)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Backs up current economic data for a player
|
||||||
|
*/
|
||||||
|
PlayerMoneyBackup::PlayerMoneyBackup(Player *player)
|
||||||
|
{
|
||||||
|
p = player;
|
||||||
|
memcpy(backup_yearly_expenses, p->yearly_expenses, EXPENSES_END * sizeof(Money));
|
||||||
|
backup_cur_economy = p->cur_economy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restore the economic data from last backup
|
||||||
|
* This should only be used right after Player::BackupEconomy()
|
||||||
|
*/
|
||||||
|
void PlayerMoneyBackup::Restore()
|
||||||
|
{
|
||||||
|
memcpy(p->yearly_expenses, backup_yearly_expenses, EXPENSES_END * sizeof(Money));
|
||||||
|
p->cur_economy = backup_cur_economy;
|
||||||
|
}
|
||||||
|
|
||||||
static void SubtractMoneyFromAnyPlayer(Player *p, CommandCost cost)
|
static void SubtractMoneyFromAnyPlayer(Player *p, CommandCost cost)
|
||||||
{
|
{
|
||||||
if (cost.GetCost() == 0) return;
|
if (cost.GetCost() == 0) return;
|
||||||
|
|
|
@ -712,12 +712,7 @@ void CallVehicleTicks()
|
||||||
v->leave_depot_instantly = false;
|
v->leave_depot_instantly = false;
|
||||||
v->vehstatus &= ~VS_STOPPED;
|
v->vehstatus &= ~VS_STOPPED;
|
||||||
}
|
}
|
||||||
|
MaybeReplaceVehicle(v, DC_EXEC, true);
|
||||||
CommandCost cost = MaybeReplaceVehicle(v, 0, true);
|
|
||||||
if (CmdSucceeded(cost) && cost.GetCost() != 0) {
|
|
||||||
/* Looks like we can replace this vehicle so we go ahead and do so */
|
|
||||||
MaybeReplaceVehicle(v, DC_EXEC, true);
|
|
||||||
}
|
|
||||||
v = w;
|
v = w;
|
||||||
}
|
}
|
||||||
_current_player = OWNER_NONE;
|
_current_player = OWNER_NONE;
|
||||||
|
@ -2689,6 +2684,87 @@ void Vehicle::SetNext(Vehicle *next)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Backs up a chain of vehicles
|
||||||
|
* @return a pointer to the chain
|
||||||
|
*/
|
||||||
|
Vehicle* Vehicle::BackupVehicle() const
|
||||||
|
{
|
||||||
|
int length = CountVehiclesInChain(this);
|
||||||
|
|
||||||
|
Vehicle *list = MallocT<Vehicle>(length);
|
||||||
|
Vehicle *copy = list; // store the pointer so we have something to return later
|
||||||
|
|
||||||
|
const Vehicle *original = this;
|
||||||
|
|
||||||
|
for (; 0 < length; original = original->next, copy++, length--) {
|
||||||
|
memcpy(copy, original, sizeof(Vehicle));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restore a backed up row of vehicles
|
||||||
|
* @return a pointer to the first vehicle in chain
|
||||||
|
*/
|
||||||
|
Vehicle* Vehicle::RestoreBackupVehicle()
|
||||||
|
{
|
||||||
|
Vehicle *backup = this;
|
||||||
|
|
||||||
|
Player *p = GetPlayer(backup->owner);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Vehicle *dest = GetVehicle(backup->index);
|
||||||
|
/* The vehicle should be free since we are restoring something we just sold. */
|
||||||
|
assert(!dest->IsValid());
|
||||||
|
memcpy(dest, backup, sizeof(Vehicle));
|
||||||
|
|
||||||
|
/* We decreased the engine count when we sold the engines so we will increase it again. */
|
||||||
|
if (IsEngineCountable(backup)) p->num_engines[backup->engine_type]++;
|
||||||
|
|
||||||
|
Vehicle *dummy = dest;
|
||||||
|
dest->old_new_hash = &dummy;
|
||||||
|
dest->left_coord = INVALID_COORD;
|
||||||
|
UpdateVehiclePosHash(dest, INVALID_COORD, 0);
|
||||||
|
|
||||||
|
if (backup->next == NULL) break;
|
||||||
|
backup++;
|
||||||
|
}
|
||||||
|
return GetVehicle(this->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Restores a backed up vehicle
|
||||||
|
* @param *v A vehicle we should sell and take the windows from (NULL for not using this)
|
||||||
|
* @return The vehicle we restored (front for trains) or v if we didn't have anything to restore
|
||||||
|
*/
|
||||||
|
Vehicle *BackuppedVehicle::Restore(Vehicle *v)
|
||||||
|
{
|
||||||
|
if (!ContainsBackup()) return v;
|
||||||
|
if (v != NULL) {
|
||||||
|
ChangeVehicleViewWindow(v, INVALID_VEHICLE);
|
||||||
|
DoCommand(0, v->index, 1, DC_EXEC, GetCmdSellVeh(v));
|
||||||
|
}
|
||||||
|
v = this->vehicles->RestoreBackupVehicle();
|
||||||
|
ChangeVehicleViewWindow(INVALID_VEHICLE, v);
|
||||||
|
if (orders != NULL) RestoreVehicleOrdersBruteForce(v, orders);
|
||||||
|
if (economy != NULL) economy->Restore();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Backs up a vehicle
|
||||||
|
* This should never be called when the object already contains a backup
|
||||||
|
* @param v the vehicle to backup
|
||||||
|
* @param p If it's set to the vehicle's owner then economy is backed up. If NULL then economy backup will be skipped.
|
||||||
|
*/
|
||||||
|
void BackuppedVehicle::Backup(const Vehicle *v, Player *p)
|
||||||
|
{
|
||||||
|
assert(!ContainsBackup());
|
||||||
|
if (p != NULL) {
|
||||||
|
assert(p->index == v->owner);
|
||||||
|
economy = new PlayerMoneyBackup(p);
|
||||||
|
}
|
||||||
|
vehicles = v->BackupVehicle();
|
||||||
|
if (orders != NULL) BackupVehicleOrders(v, orders);
|
||||||
|
}
|
||||||
|
|
||||||
void StopAllVehicles()
|
void StopAllVehicles()
|
||||||
{
|
{
|
||||||
Vehicle *v;
|
Vehicle *v;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "gfx_type.h"
|
#include "gfx_type.h"
|
||||||
#include "command_type.h"
|
#include "command_type.h"
|
||||||
#include "date_type.h"
|
#include "date_type.h"
|
||||||
|
#include "player_base.h"
|
||||||
#include "player_type.h"
|
#include "player_type.h"
|
||||||
#include "oldpool.h"
|
#include "oldpool.h"
|
||||||
#include "order_base.h"
|
#include "order_base.h"
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
#include "texteff.hpp"
|
#include "texteff.hpp"
|
||||||
#include "group_type.h"
|
#include "group_type.h"
|
||||||
#include "engine_type.h"
|
#include "engine_type.h"
|
||||||
|
#include "order_func.h"
|
||||||
|
|
||||||
/** Road vehicle states */
|
/** Road vehicle states */
|
||||||
enum RoadVehicleStates {
|
enum RoadVehicleStates {
|
||||||
|
@ -520,6 +522,9 @@ public:
|
||||||
* @return the cost of the depot action.
|
* @return the cost of the depot action.
|
||||||
*/
|
*/
|
||||||
CommandCost SendToDepot(uint32 flags, DepotCommand command);
|
CommandCost SendToDepot(uint32 flags, DepotCommand command);
|
||||||
|
|
||||||
|
Vehicle* BackupVehicle() const;
|
||||||
|
Vehicle* RestoreBackupVehicle();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -649,4 +654,21 @@ Trackdir GetVehicleTrackdir(const Vehicle* v);
|
||||||
|
|
||||||
void CheckVehicle32Day(Vehicle *v);
|
void CheckVehicle32Day(Vehicle *v);
|
||||||
|
|
||||||
|
struct BackuppedVehicle {
|
||||||
|
private:
|
||||||
|
Vehicle *vehicles;
|
||||||
|
BackuppedOrders *orders;
|
||||||
|
PlayerMoneyBackup *economy;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BackuppedVehicle(bool include_orders) : vehicles(NULL), economy(NULL) {
|
||||||
|
orders = include_orders ? new BackuppedOrders() : NULL;
|
||||||
|
}
|
||||||
|
~BackuppedVehicle() { free(vehicles); delete orders; delete economy; }
|
||||||
|
|
||||||
|
void Backup(const Vehicle *v, Player *p = NULL);
|
||||||
|
Vehicle *Restore(Vehicle *v);
|
||||||
|
bool ContainsBackup() { return vehicles != NULL; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* VEHICLE_BASE_H */
|
#endif /* VEHICLE_BASE_H */
|
||||||
|
|
Loading…
Reference in New Issue