summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--train_cmd.c57
-rw-r--r--vehicle.c105
-rw-r--r--vehicle.h2
3 files changed, 111 insertions, 53 deletions
diff --git a/train_cmd.c b/train_cmd.c
index 73fd22399..0f0fd6c5a 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -365,6 +365,35 @@ int32 EstimateTrainCost(const RailVehicleInfo *rvi)
return (rvi->base_cost * (_price.build_railvehicle >> 3)) >> 5;
}
+void AddRearEngineToMultiheadedTrain(Vehicle *v, Vehicle *u, bool building)
+{
+ u->direction = v->direction;
+ u->owner = v->owner;
+ u->tile = v->tile;
+ u->x_pos = v->x_pos;
+ u->y_pos = v->y_pos;
+ u->z_pos = v->z_pos;
+ u->z_height = 6;
+ u->u.rail.track = 0x80;
+ v->u.rail.first_engine = 0xffff;
+ u->vehstatus = v->vehstatus & ~VS_STOPPED;
+ u->subtype = 2;
+ u->spritenum = v->spritenum + 1;
+ u->cargo_type = v->cargo_type;
+ u->cargo_cap = v->cargo_cap;
+ u->u.rail.railtype = v->u.rail.railtype;
+ if (building) v->next = u;
+ u->engine_type = v->engine_type;
+ u->build_year = v->build_year;
+ if (building)
+ v->value = u->value = v->value >> 1;
+ else
+ u->value = v->value;
+ u->type = VEH_Train;
+ u->cur_image = 0xAC2;
+ VehiclePositionChanged(u);
+}
+
/* Build a railroad vehicle
* p1 = vehicle type id
*/
@@ -442,32 +471,8 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
VehiclePositionChanged(v);
- if (rvi->flags&RVI_MULTIHEAD && (u=AllocateVehicle()) != NULL) {
- u->direction = v->direction;
- u->owner = v->owner;
- u->tile = v->tile;
- u->x_pos = v->x_pos;
- u->y_pos = v->y_pos;
- u->z_pos = v->z_pos;
- u->z_height = 6;
- u->u.rail.track = 0x80;
- v->u.rail.first_engine = 0xffff;
- u->vehstatus = VS_HIDDEN | VS_DEFPAL;
- u->subtype = 2;
- u->spritenum = v->spritenum + 1;
- u->cargo_type = v->cargo_type;
- u->cargo_cap = v->cargo_cap;
- u->u.rail.railtype = v->u.rail.railtype;
-// u->next_in_chain = 0xffff;
- v->next = u;
- u->engine_type = v->engine_type;
- u->build_year = v->build_year;
- v->value = u->value = v->value >> 1;
-// u->day_counter = 0;
- u->type = VEH_Train;
- u->cur_image = 0xAC2;
- VehiclePositionChanged(u);
- }
+ if (rvi->flags&RVI_MULTIHEAD && (u = AllocateVehicle()) != NULL)
+ AddRearEngineToMultiheadedTrain(v, u, true);
UpdateTrainAcceleration(v);
NormalizeTrainVehInDepot(v);
diff --git a/vehicle.c b/vehicle.c
index b0a86e6a6..4e1f9f0d9 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -1321,7 +1321,9 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
uint16 new_engine_type = (uint16)(p2 & 0xFFFF);
uint32 autorefit_money = (p2 >> 16) * 100000;
Vehicle *v = GetVehicle(p1);
- int cost, build_cost;
+ int cost, build_cost, rear_engine_cost = 0;
+ Vehicle *u = v;
+ byte old_engine_type = v->engine_type;
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
@@ -1347,12 +1349,42 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
/* In a rare situation, when 2 clients are connected to 1 company and have the same
settings, a vehicle can be replaced twice.. check if this is the situation here */
- if (v->engine_type == new_engine_type && v->age == 0)
+ if (old_engine_type == new_engine_type && v->age == 0)
return CMD_ERROR;
+
+ if ( v->type == VEH_Train ) {
+ u = GetLastVehicleInChain(v);
+ if ( RailVehInfo(new_engine_type)->flags & RVI_MULTIHEAD )
+ build_cost = build_cost >> 1; //multiheaded engines have EstimateTrainCost() for both engines
+
+ if ( old_engine_type != new_engine_type ) {
+
+ // prevent that the rear engine can get replaced to something else than the front engine
+ if ( v->u.rail.first_engine != 0xffff && RailVehInfo(old_engine_type)->flags & RVI_MULTIHEAD && RailVehInfo(old_engine_type)->flags ) {
+ Vehicle *first = GetFirstVehicleInChain(v);
+ if ( first->engine_type != new_engine_type ) return CMD_ERROR;
+ }
+
+ // checks if the engine is the first one
+ if ( v->u.rail.first_engine == 0xffff ) {
+ if ( RailVehInfo(new_engine_type)->flags & RVI_MULTIHEAD ) {
+ if ( u->engine_type == old_engine_type && v->next != NULL) {
+ rear_engine_cost = build_cost - u->value;
+ } else {
+ rear_engine_cost = build_cost;
+ }
+ } else {
+ if ( u->engine_type == old_engine_type && RailVehInfo(old_engine_type)->flags & RVI_MULTIHEAD) {
+ if (v->next != NULL) rear_engine_cost = -u->value;
+ }
+ }
+ }
+ }
+ }
/* Check if there is money for the upgrade.. if not, give a nice news-item
(that is needed, because this CMD is called automaticly) */
- if ( DEREF_PLAYER(v->owner)->money64 < (int32)(autorefit_money + build_cost - v->value)) {
+ if ( DEREF_PLAYER(v->owner)->money64 < (int32)(autorefit_money + build_cost + rear_engine_cost - v->value)) {
if (( _local_player == v->owner ) && ( v->unitnumber != 0 )) { //v->unitnumber = 0 for train cars
int message;
SetDParam(0, v->unitnumber);
@@ -1370,18 +1402,27 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return CMD_ERROR;
}
- cost = build_cost - v->value;
+ cost = build_cost - v->value + rear_engine_cost;
if (flags & DC_EXEC) {
+ /* We do not really buy a new vehicle, we upgrade the old one */
Engine *e;
e = DEREF_ENGINE(new_engine_type);
- // TODO make it check if refit is possible before actually doing it
+ v->reliability = e->reliability;
+ v->reliability_spd_dec = e->reliability_spd_dec;
+ v->age = 0;
+
+ v->date_of_last_service = _date;
+ v->build_year = _cur_year;
+
+ v->value = build_cost;
- /* We do not really buy a new vehicle, we upgrade the old one */
+ InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
+
+
if (v->engine_type != new_engine_type) {
- byte old_engine = v->engine_type;
byte sprite = v->spritenum;
byte cargo_type = v->cargo_type;
v->engine_type = new_engine_type;
@@ -1390,11 +1431,11 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
/* Update limits of the vehicle (for when upgraded) */
switch (v->type) {
case VEH_Train:
- // using if (true) to declare the const
{
const RailVehicleInfo *rvi = RailVehInfo(new_engine_type);
- const RailVehicleInfo *rvi2 = RailVehInfo(old_engine);
+ const RailVehicleInfo *rvi2 = RailVehInfo(old_engine_type);
byte capacity = rvi->capacity;
+ Vehicle *first = GetFirstVehicleInChain(v);
/* rvi->image_index is the new sprite for the engine. Adding +1 makes the engine head the other way
if it is a multiheaded engine (rear engine)
@@ -1402,7 +1443,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
v->spritenum = rvi->image_index + (( rvi->flags & RVI_MULTIHEAD && sprite - rvi2->image_index) ? 1 : 0);
// turn the last engine in a multiheaded train if needed
- if ( v->next == NULL && rvi->flags & RVI_MULTIHEAD && v->spritenum == rvi->image_index )
+ if ( v->next == NULL && v->u.rail.first_engine != 0xffff && rvi->flags & RVI_MULTIHEAD && v->spritenum == rvi->image_index )
v->spritenum++;
v->cargo_type = rvi->cargo_type;
@@ -1420,11 +1461,34 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
} else {
v->cargo_type = rvi->cargo_type;
}
+
+ if ( rvi2->flags & RVI_MULTIHEAD && !(rvi->flags & RVI_MULTIHEAD) && v->index == first->index) {
+ if (old_engine_type == u->engine_type ) {
+ u = GetLastVehicleInChain(v);
+ Vehicle *w = GetPrevVehicleInChain(u);
+ w->next = NULL;
+ DeleteVehicle(u);
+ }
+ }
+
+ if ( rvi->flags & RVI_MULTIHEAD && rvi2->flags & RVI_MULTIHEAD && v->index == first->index ) {
+ CmdReplaceVehicle(x, y, flags, u->index, p2);
+ }
+
+ if ( rvi->flags & RVI_MULTIHEAD && !(rvi2->flags & RVI_MULTIHEAD) && v->index == first->index ) {
+ if ( old_engine_type != u->engine_type ) {
+ Vehicle *w;
+ if ( (w=AllocateVehicle()) != NULL ) {
+ AddRearEngineToMultiheadedTrain(v,w, false);
+ u->next = w;
+ }
+ }
+ }
+
break;
}
case VEH_Road:
- // using if (true) to declare the const
- if (true) {
+ {
const RoadVehicleInfo *rvi = RoadVehInfo(new_engine_type);
v->spritenum = rvi->image_index;
@@ -1434,8 +1498,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
break;
}
case VEH_Ship:
- // using if (true) to declare the const
- if (true) {
+ {
const ShipVehicleInfo *svi = ShipVehInfo(new_engine_type);
v->spritenum = svi->image_index;
@@ -1450,8 +1513,7 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
break;
}
case VEH_Aircraft:
- // using if (true) to declare the const
- if (true) {
+ {
const AircraftVehicleInfo *avi = AircraftVehInfo(new_engine_type);
Vehicle *u;
@@ -1480,17 +1542,6 @@ int32 CmdReplaceVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
v->cargo_count = v->cargo_cap;
}
}
-
- v->reliability = e->reliability;
- v->reliability_spd_dec = e->reliability_spd_dec;
- v->age = 0;
-
- v->date_of_last_service = _date;
- v->build_year = _cur_year;
-
- v->value = build_cost;
-
- InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
}
//needs to be down here because refitting will change SET_EXPENSES_TYPE if called
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
diff --git a/vehicle.h b/vehicle.h
index 864d382cf..a5803750c 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -284,6 +284,8 @@ void ViewportAddVehicles(DrawPixelInfo *dpi);
void TrainEnterDepot(Vehicle *v, uint tile);
+void AddRearEngineToMultiheadedTrain(Vehicle *v, Vehicle *u, bool building) ;
+
/* train_cmd.h */
int GetTrainImage(Vehicle *v, byte direction);
int GetAircraftImage(Vehicle *v, byte direction);