equal
deleted
inserted
replaced
159 v->u.rail.compatible_railtypes = 0; |
159 v->u.rail.compatible_railtypes = 0; |
160 |
160 |
161 for (Vehicle *u = v; u != NULL; u = u->Next()) { |
161 for (Vehicle *u = v; u != NULL; u = u->Next()) { |
162 const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); |
162 const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); |
163 |
163 |
164 /* Update the v->first cache. This is faster than having to brute force it later. */ |
164 /* Check the v->first cache. */ |
165 if (u->first == NULL) u->first = v; |
165 assert(u->First() == v); |
166 |
166 |
167 /* update the 'first engine' */ |
167 /* update the 'first engine' */ |
168 u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine; |
168 u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine; |
169 u->u.rail.railtype = rvi_u->railtype; |
169 u->u.rail.railtype = rvi_u->railtype; |
170 |
170 |
581 AddArticulatedParts(vl, VEH_TRAIN); |
581 AddArticulatedParts(vl, VEH_TRAIN); |
582 |
582 |
583 _new_vehicle_id = v->index; |
583 _new_vehicle_id = v->index; |
584 |
584 |
585 VehiclePositionChanged(v); |
585 VehiclePositionChanged(v); |
586 TrainConsistChanged(GetFirstVehicleInChain(v)); |
586 TrainConsistChanged(v->First()); |
587 UpdateTrainGroupID(GetFirstVehicleInChain(v)); |
587 UpdateTrainGroupID(v->First()); |
588 |
588 |
589 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
589 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
590 if (IsLocalPlayer()) { |
590 if (IsLocalPlayer()) { |
591 InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window |
591 InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window |
592 } |
592 } |
618 return CommandCost(GetEngineProperty(engine, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5); |
618 return CommandCost(GetEngineProperty(engine, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5); |
619 } |
619 } |
620 |
620 |
621 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building) |
621 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building) |
622 { |
622 { |
|
623 u = new (u) Train(); |
623 u->direction = v->direction; |
624 u->direction = v->direction; |
624 u->owner = v->owner; |
625 u->owner = v->owner; |
625 u->tile = v->tile; |
626 u->tile = v->tile; |
626 u->x_pos = v->x_pos; |
627 u->x_pos = v->x_pos; |
627 u->y_pos = v->y_pos; |
628 u->y_pos = v->y_pos; |
628 u->z_pos = v->z_pos; |
629 u->z_pos = v->z_pos; |
629 u->u.rail.track = TRACK_BIT_DEPOT; |
630 u->u.rail.track = TRACK_BIT_DEPOT; |
630 u->vehstatus = v->vehstatus & ~VS_STOPPED; |
631 u->vehstatus = v->vehstatus & ~VS_STOPPED; |
631 u = new (u) Train(); |
|
632 u->subtype = 0; |
632 u->subtype = 0; |
633 SetMultiheaded(u); |
633 SetMultiheaded(u); |
634 u->spritenum = v->spritenum + 1; |
634 u->spritenum = v->spritenum + 1; |
635 u->cargo_type = v->cargo_type; |
635 u->cargo_type = v->cargo_type; |
636 u->cargo_subtype = v->cargo_subtype; |
636 u->cargo_subtype = v->cargo_subtype; |
839 } |
839 } |
840 |
840 |
841 Vehicle *u; |
841 Vehicle *u; |
842 for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {} |
842 for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {} |
843 GetLastEnginePart(u)->SetNext(GetNextVehicle(v)); |
843 GetLastEnginePart(u)->SetNext(GetNextVehicle(v)); |
844 v->first = NULL; // we shouldn't point to the old first, since the vehicle isn't in that chain anymore |
|
845 return first; |
844 return first; |
846 } |
845 } |
847 |
846 |
848 static Vehicle *FindGoodVehiclePos(const Vehicle *src) |
847 static Vehicle *FindGoodVehiclePos(const Vehicle *src) |
849 { |
848 { |
870 * add a vehicle v behind vehicle dest |
869 * add a vehicle v behind vehicle dest |
871 * use this function since it sets flags as needed |
870 * use this function since it sets flags as needed |
872 */ |
871 */ |
873 static void AddWagonToConsist(Vehicle *v, Vehicle *dest) |
872 static void AddWagonToConsist(Vehicle *v, Vehicle *dest) |
874 { |
873 { |
875 UnlinkWagon(v, GetFirstVehicleInChain(v)); |
874 UnlinkWagon(v, v->First()); |
876 if (dest == NULL) return; |
875 if (dest == NULL) return; |
877 |
876 |
878 v->SetNext(dest->Next()); |
877 Vehicle *next = dest->Next(); |
879 dest->SetNext(v); |
878 dest->SetNext(v); |
|
879 v->SetNext(next); |
880 ClearFreeWagon(v); |
880 ClearFreeWagon(v); |
881 ClearFrontEngine(v); |
881 ClearFrontEngine(v); |
882 } |
882 } |
883 |
883 |
884 /* |
884 /* |
931 dst = GetVehicle(d); |
931 dst = GetVehicle(d); |
932 if (dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR; |
932 if (dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR; |
933 } |
933 } |
934 |
934 |
935 /* if an articulated part is being handled, deal with its parent vehicle */ |
935 /* if an articulated part is being handled, deal with its parent vehicle */ |
936 while (IsArticulatedPart(src)) src = GetPrevVehicleInChain(src); |
936 while (IsArticulatedPart(src)) src = src->Previous(); |
937 if (dst != NULL) { |
937 if (dst != NULL) { |
938 while (IsArticulatedPart(dst)) dst = GetPrevVehicleInChain(dst); |
938 while (IsArticulatedPart(dst)) dst = dst->Previous(); |
939 } |
939 } |
940 |
940 |
941 /* don't move the same vehicle.. */ |
941 /* don't move the same vehicle.. */ |
942 if (src == dst) return CommandCost(); |
942 if (src == dst) return CommandCost(); |
943 |
943 |
944 /* locate the head of the two chains */ |
944 /* locate the head of the two chains */ |
945 Vehicle *src_head = GetFirstVehicleInChain(src); |
945 Vehicle *src_head = src->First(); |
946 Vehicle *dst_head; |
946 Vehicle *dst_head; |
947 if (dst != NULL) { |
947 if (dst != NULL) { |
948 dst_head = GetFirstVehicleInChain(dst); |
948 dst_head = dst->First(); |
949 if (dst_head->tile != src_head->tile) return CMD_ERROR; |
949 if (dst_head->tile != src_head->tile) return CMD_ERROR; |
950 /* Now deal with articulated part of destination wagon */ |
950 /* Now deal with articulated part of destination wagon */ |
951 dst = GetLastEnginePart(dst); |
951 dst = GetLastEnginePart(dst); |
952 } else { |
952 } else { |
953 dst_head = NULL; |
953 dst_head = NULL; |
1020 } |
1020 } |
1021 } |
1021 } |
1022 |
1022 |
1023 /* do it? */ |
1023 /* do it? */ |
1024 if (flags & DC_EXEC) { |
1024 if (flags & DC_EXEC) { |
1025 /* clear the ->first cache */ |
|
1026 for (Vehicle *u = src_head; u != NULL; u = u->Next()) u->first = NULL; |
|
1027 for (Vehicle *u = dst_head; u != NULL; u = u->Next()) u->first = NULL; |
|
1028 |
|
1029 /* If we move the front Engine and if the second vehicle is not an engine |
1025 /* If we move the front Engine and if the second vehicle is not an engine |
1030 add the whole vehicle to the DEFAULT_GROUP */ |
1026 add the whole vehicle to the DEFAULT_GROUP */ |
1031 if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) { |
1027 if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) { |
1032 const Vehicle *v = GetNextVehicle(src); |
1028 const Vehicle *v = GetNextVehicle(src); |
1033 |
1029 |
1099 for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v)); |
1095 for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v)); |
1100 GetLastEnginePart(v)->SetNext(dst->Next()); |
1096 GetLastEnginePart(v)->SetNext(dst->Next()); |
1101 } |
1097 } |
1102 dst->SetNext(src); |
1098 dst->SetNext(src); |
1103 } |
1099 } |
|
1100 |
1104 if (src->u.rail.other_multiheaded_part != NULL) { |
1101 if (src->u.rail.other_multiheaded_part != NULL) { |
1105 if (src->u.rail.other_multiheaded_part == src_head) { |
1102 if (src->u.rail.other_multiheaded_part == src_head) { |
1106 src_head = src_head->Next(); |
1103 src_head = src_head->Next(); |
1107 } |
1104 } |
1108 AddWagonToConsist(src->u.rail.other_multiheaded_part, src); |
1105 AddWagonToConsist(src->u.rail.other_multiheaded_part, src); |
1109 /* previous line set the front engine to the old front. We need to clear that */ |
|
1110 src->u.rail.other_multiheaded_part->first = NULL; |
|
1111 } |
1106 } |
1112 |
1107 |
1113 /* If there is an engine behind first_engine we moved away, it should become new first_engine |
1108 /* If there is an engine behind first_engine we moved away, it should become new first_engine |
1114 * To do this, CmdMoveRailVehicle must be called once more |
1109 * To do this, CmdMoveRailVehicle must be called once more |
1115 * we can't loop forever here because next time we reach this line we will have a front engine */ |
1110 * we can't loop forever here because next time we reach this line we will have a front engine */ |
1216 |
1211 |
1217 if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR; |
1212 if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR; |
1218 |
1213 |
1219 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
1214 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
1220 |
1215 |
1221 while (IsArticulatedPart(v)) v = GetPrevVehicleInChain(v); |
1216 while (IsArticulatedPart(v)) v = v->Previous(); |
1222 Vehicle *first = GetFirstVehicleInChain(v); |
1217 Vehicle *first = v->First(); |
1223 |
1218 |
1224 /* make sure the vehicle is stopped in the depot */ |
1219 /* make sure the vehicle is stopped in the depot */ |
1225 if (CheckTrainStoppedInDepot(first) < 0) { |
1220 if (CheckTrainStoppedInDepot(first) < 0) { |
1226 return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); |
1221 return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); |
1227 } |
1222 } |
1259 |
1254 |
1260 /* 2. We are selling the first engine, some special action might be required |
1255 /* 2. We are selling the first engine, some special action might be required |
1261 * here, so take attention */ |
1256 * here, so take attention */ |
1262 if ((flags & DC_EXEC) && v == first) { |
1257 if ((flags & DC_EXEC) && v == first) { |
1263 Vehicle *new_f = GetNextVehicle(first); |
1258 Vehicle *new_f = GetNextVehicle(first); |
1264 |
|
1265 /* 2.1 If the first wagon is sold, update the first-> pointers to NULL */ |
|
1266 for (Vehicle *tmp = first; tmp != NULL; tmp = tmp->Next()) tmp->first = NULL; |
|
1267 |
1259 |
1268 /* 2.2 If there are wagons present after the deleted front engine, check |
1260 /* 2.2 If there are wagons present after the deleted front engine, check |
1269 * if the second wagon (which will be first) is an engine. If it is one, |
1261 * if the second wagon (which will be first) is an engine. If it is one, |
1270 * promote it as a new train, retaining the unitnumber, orders */ |
1262 * promote it as a new train, retaining the unitnumber, orders */ |
1271 if (new_f != NULL && IsTrainEngine(new_f)) { |
1263 if (new_f != NULL && IsTrainEngine(new_f)) { |
1631 |
1623 |
1632 if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) { |
1624 if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) { |
1633 return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT); |
1625 return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT); |
1634 } |
1626 } |
1635 |
1627 |
1636 Vehicle *front = GetFirstVehicleInChain(v); |
1628 Vehicle *front = v->First(); |
1637 /* make sure the vehicle is stopped in the depot */ |
1629 /* make sure the vehicle is stopped in the depot */ |
1638 if (CheckTrainStoppedInDepot(front) < 0) { |
1630 if (CheckTrainStoppedInDepot(front) < 0) { |
1639 return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); |
1631 return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); |
1640 } |
1632 } |
1641 |
1633 |
1775 } while ((v = v->Next()) != NULL && !only_this); |
1767 } while ((v = v->Next()) != NULL && !only_this); |
1776 |
1768 |
1777 _returned_refit_capacity = num; |
1769 _returned_refit_capacity = num; |
1778 |
1770 |
1779 /* Update the train's cached variables */ |
1771 /* Update the train's cached variables */ |
1780 if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1))); |
1772 if (flags & DC_EXEC) TrainConsistChanged(GetVehicle(p1)->First()); |
1781 |
1773 |
1782 return cost; |
1774 return cost; |
1783 } |
1775 } |
1784 |
1776 |
1785 struct TrainFindDepotData { |
1777 struct TrainFindDepotData { |
2716 v->u.rail.track != TRACK_BIT_DEPOT && |
2708 v->u.rail.track != TRACK_BIT_DEPOT && |
2717 myabs(v->z_pos - tcc->v->z_pos) < 6 && |
2709 myabs(v->z_pos - tcc->v->z_pos) < 6 && |
2718 myabs(v->x_pos - tcc->v->x_pos) < 6 && |
2710 myabs(v->x_pos - tcc->v->x_pos) < 6 && |
2719 myabs(v->y_pos - tcc->v->y_pos) < 6 ) { |
2711 myabs(v->y_pos - tcc->v->y_pos) < 6 ) { |
2720 |
2712 |
2721 Vehicle *coll = GetFirstVehicleInChain(v); |
2713 Vehicle *coll = v->First(); |
2722 |
2714 |
2723 /* it can't collide with its own wagons */ |
2715 /* it can't collide with its own wagons */ |
2724 if (tcc->v == coll || |
2716 if (tcc->v == coll || |
2725 (tcc->v->u.rail.track == TRACK_BIT_WORMHOLE && (tcc->v->direction & 2) != (v->direction & 2))) |
2717 (tcc->v->u.rail.track == TRACK_BIT_WORMHOLE && (tcc->v->direction & 2) != (v->direction & 2))) |
2726 return NULL; |
2718 return NULL; |
2805 static void TrainController(Vehicle *v, bool update_image) |
2797 static void TrainController(Vehicle *v, bool update_image) |
2806 { |
2798 { |
2807 Vehicle *prev; |
2799 Vehicle *prev; |
2808 |
2800 |
2809 /* For every vehicle after and including the given vehicle */ |
2801 /* For every vehicle after and including the given vehicle */ |
2810 for (prev = GetPrevVehicleInChain(v); v != NULL; prev = v, v = v->Next()) { |
2802 for (prev = v->Previous(); v != NULL; prev = v, v = v->Next()) { |
2811 DiagDirection enterdir = DIAGDIR_BEGIN; |
2803 DiagDirection enterdir = DIAGDIR_BEGIN; |
2812 bool update_signals = false; |
2804 bool update_signals = false; |
2813 BeginVehicleMove(v); |
2805 BeginVehicleMove(v); |
2814 |
2806 |
2815 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
2807 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
2943 |
2935 |
2944 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) { |
2936 if (!HASBIT(r, VETS_ENTERED_WORMHOLE)) { |
2945 v->tile = gp.new_tile; |
2937 v->tile = gp.new_tile; |
2946 |
2938 |
2947 if (GetTileRailType(gp.new_tile) != GetTileRailType(gp.old_tile)) { |
2939 if (GetTileRailType(gp.new_tile) != GetTileRailType(gp.old_tile)) { |
2948 TrainPowerChanged(GetFirstVehicleInChain(v)); |
2940 TrainPowerChanged(v->First()); |
2949 } |
2941 } |
2950 |
2942 |
2951 v->u.rail.track = chosen_track; |
2943 v->u.rail.track = chosen_track; |
2952 assert(v->u.rail.track); |
2944 assert(v->u.rail.track); |
2953 } |
2945 } |