From 783e20a263a5e72bfed81ef7a9535a2caefebf79 Mon Sep 17 00:00:00 2001 From: bjarni Date: Sun, 27 Apr 2008 20:09:29 +0000 Subject: (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 --- src/vehicle.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 6 deletions(-) (limited to 'src/vehicle.cpp') diff --git a/src/vehicle.cpp b/src/vehicle.cpp index ec4908669..03351b149 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -712,12 +712,7 @@ void CallVehicleTicks() v->leave_depot_instantly = false; v->vehstatus &= ~VS_STOPPED; } - - 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); - } + MaybeReplaceVehicle(v, DC_EXEC, true); v = w; } _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(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() { Vehicle *v; -- cgit v1.2.3-54-g00ecf