--- a/src/autoreplace_cmd.cpp Fri Apr 25 02:15:34 2008 +0000
+++ b/src/autoreplace_cmd.cpp Mon May 26 20:45:25 2008 +0000
@@ -206,7 +206,11 @@
/* 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);
/* 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 {
// copy/clone the orders
@@ -232,15 +236,21 @@
}
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));
+ }
}
}
}
- /* We are done setting up the new vehicle. Now we move the cargo from the old one to the new one */
- MoveVehicleCargo(new_v->type == VEH_TRAIN ? new_v->First() : new_v, old_v);
+ if (CmdSucceeded(cost)) {
+ /* We are done setting up the new vehicle. Now we move the cargo from the old one to the new one */
+ MoveVehicleCargo(new_v->type == VEH_TRAIN ? new_v->First() : new_v, old_v);
- // Get the name of the old vehicle if it has a custom name.
- if (old_v->name != NULL) vehicle_name = strdup(old_v->name);
+ /* Get the name of the old vehicle if it has a custom name. */
+ if (old_v->name != NULL) vehicle_name = strdup(old_v->name);
+ }
} else { // flags & DC_EXEC not set
CommandCost tmp_move;
@@ -274,6 +284,8 @@
/* sell the engine/ find out how much you get for the old engine (income is returned as negative cost) */
cost.AddCost(DoCommand(0, old_v->index, 0, flags, GetCmdSellVeh(old_v)));
+ if (CmdFailed(cost)) return cost;
+
if (new_front) {
/* now we assign the old unitnumber to the new vehicle */
new_v->unitnumber = cached_unitnumber;
@@ -311,7 +323,7 @@
if (v == NULL) {
/* We sold all the wagons and the train is still not short enough */
SetDParam(0, front->unitnumber);
- AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, front->index, 0);
+ AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NS_ADVICE, front->index, 0);
return cost;
}
@@ -363,9 +375,10 @@
CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs)
{
Vehicle *w;
- const Player *p = GetPlayer(v->owner);
+ Player *p = GetPlayer(v->owner);
CommandCost cost;
bool stopped = false;
+ BackuppedVehicle backup(true);
/* We only want "real" vehicle types. */
assert(IsPlayerBuildableVehicleType(v));
@@ -410,31 +423,46 @@
EngineID new_engine = GetNewEngineType(w, p);
if (new_engine == INVALID_ENGINE) continue;
- /* Now replace the vehicle */
- cost.AddCost(ReplaceVehicle(&w, flags, cost.GetCost(), p, new_engine));
+ 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.
+ * First we need to cache if it's the front vehicle as we need to update the v pointer if it is.
+ * If the replacement fails then we can't trust the data in the vehicle hence the reason to cache the result. */
+ bool IsFront = w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE;
- if (flags & DC_EXEC &&
- (w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE)) {
+ cost.AddCost(ReplaceVehicle(&w, DC_EXEC, cost.GetCost(), p, new_engine));
+
+ if (IsFront) {
/* 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 should point to the front engine and not the cars
*/
v = w;
}
- } while (w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
+ } while (CmdSucceeded(cost) && w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL);
+
+ if (CmdSucceeded(cost) && 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) {
/* We didn't do anything during the replace so we will just exit here */
+ v = backup.Restore(v, p);
if (stopped) v->vehstatus &= ~VS_STOPPED;
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 will not actually pay this amount. It's for display and checks only. */
- cost.AddCost((Money)p->engine_renew_money);
- if (CmdSucceeded(cost) && GetAvailableMoneyForCommand() < cost.GetCost()) {
+ CommandCost tmp = cost;
+ 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 */
+ cost.AddCost((Money)p->engine_renew_money);
cost.AddCost(CMD_ERROR);
}
}
@@ -452,20 +480,17 @@
default: NOT_REACHED(); message = 0; break;
}
- AddNewsItem(message, NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0);
+ AddNewsItem(message, NS_ADVICE, v->index, 0);
}
}
}
- if (flags & DC_EXEC && CmdSucceeded(cost)) {
- 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 (display_costs && IsLocalPlayer() && (flags & DC_EXEC) && CmdSucceeded(cost)) {
+ ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
+ }
- if (display_costs && IsLocalPlayer()) {
- ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
- }
+ if (!(flags & DC_EXEC) || CmdFailed(cost)) {
+ v = backup.Restore(v, p);
}
/* Start the vehicle if we stopped it earlier */