summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--train_cmd.c2
-rw-r--r--vehicle.c71
-rw-r--r--vehicle.h1
3 files changed, 61 insertions, 13 deletions
diff --git a/train_cmd.c b/train_cmd.c
index c85c90540..7ca2ba5db 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -961,7 +961,7 @@ int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2)
* engine is 'started', first 'close' that before 'closing' our
* searched engine
*/
-static Vehicle *GetRearEngine(const Vehicle *v, EngineID engine)
+Vehicle *GetRearEngine(const Vehicle *v, EngineID engine)
{
Vehicle *u;
int en_count = 1;
diff --git a/vehicle.c b/vehicle.c
index 21742b4bf..ae21c5b19 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -1446,6 +1446,32 @@ void AgeVehicle(Vehicle *v)
}
}
+/*
+ * This function returns the next vehicle in an engine that consists of more than one vehicle
+ * This is planes, multiheaded train engines and so on. It's NOT whole trains as it is only the engines, that are linked together
+ */
+static Vehicle *GetNextEnginePart(Vehicle *v)
+{
+ switch (v->type) {
+ case VEH_Train:
+ {
+ const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
+ if (rvi->flags & RVI_MULTIHEAD)
+ return GetRearEngine(v, v->engine_type);
+ }
+ break;
+ case VEH_Aircraft:
+ return v->next;
+ break;
+ case VEH_Road:
+ case VEH_Ship:
+ break;
+ default: NOT_REACHED();
+ }
+ return NULL;
+}
+
+
/** Clone a vehicle. If it is a train, it will clone all the cars too
* @param x,y depot where the cloned vehicle is build
* @param p1 the original vehicle's index
@@ -1525,6 +1551,37 @@ int32 CmdCloneVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return total_cost;
}
+/*
+ * move the cargo from one engine to another if possible
+ */
+static void MoveVehicleCargo(Vehicle *dest, Vehicle *source)
+{
+ Vehicle *v = dest;
+ int units_moved;
+
+ do {
+ do {
+ if (source->cargo_type != dest->cargo_type)
+ continue; // cargo not compatible
+
+ if (dest->cargo_count == dest->cargo_cap)
+ continue; // the destination vehicle is already full
+
+ units_moved = min(source->cargo_count, dest->cargo_cap - dest->cargo_count);
+ source->cargo_count -= units_moved;
+ dest->cargo_count += units_moved;
+ dest->cargo_source = source->cargo_source;
+
+ // copy the age of the cargo
+ dest->cargo_days = source->cargo_days;
+ dest->day_counter = source->day_counter;
+ dest->tick_counter = source->tick_counter;
+
+ } while (source->cargo_count > 0 && (dest = GetNextEnginePart(dest)) != NULL);
+ dest = v;
+ } while ((source = GetNextEnginePart(source)) != NULL);
+}
+
/* Replaces a vehicle (used to be called autorenew)
* This function is only called from MaybeReplaceVehicle(), which is the next one
* Must be called with _current_player set to the owner of the vehicle
@@ -1535,7 +1592,7 @@ int32 CmdCloneVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
static int32 ReplaceVehicle(Vehicle **w, byte flags)
{
int32 cost;
- const Vehicle *old_v = *w;
+ Vehicle *old_v = *w;
const Player *p = GetPlayer(old_v->owner);
EngineID new_engine_type;
const UnitID cached_unitnumber = old_v->unitnumber;
@@ -1560,17 +1617,7 @@ static int32 ReplaceVehicle(Vehicle **w, byte flags)
}
}
- /* move the cargo to the new vehicle */
- if (old_v->cargo_type == new_v->cargo_type && old_v->cargo_count != 0) {
- // move the cargo to the new vehicle
- new_v->cargo_count = min(old_v->cargo_count, new_v->cargo_cap);
- new_v->cargo_source = old_v->cargo_source;
-
- // copy the age of the cargo
- new_v->cargo_days = old_v->cargo_days;
- new_v->day_counter = old_v->day_counter;
- new_v->tick_counter = old_v->tick_counter;
- }
+ MoveVehicleCargo(new_v, old_v);
if (old_v->type == VEH_Train && old_v->u.rail.first_engine != INVALID_VEHICLE) {
/* this is a railcar. We need to move the car into the train
diff --git a/vehicle.h b/vehicle.h
index 9954216ff..0773d9231 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -325,6 +325,7 @@ void DecreaseVehicleValue(Vehicle *v);
void CheckVehicleBreakdown(Vehicle *v);
void AgeVehicle(Vehicle *v);
void VehicleEnteredDepotThisTick(Vehicle *v);
+Vehicle *GetRearEngine(const Vehicle *v, EngineID engine);
void BeginVehicleMove(Vehicle *v);
void EndVehicleMove(Vehicle *v);