35 #include "newgrf_text.h" |
35 #include "newgrf_text.h" |
36 #include "direction.h" |
36 #include "direction.h" |
37 #include "yapf/yapf.h" |
37 #include "yapf/yapf.h" |
38 #include "date.h" |
38 #include "date.h" |
39 #include "cargotype.h" |
39 #include "cargotype.h" |
|
40 #include "group.h" |
40 |
41 |
41 static bool TrainCheckIfLineEnds(Vehicle *v); |
42 static bool TrainCheckIfLineEnds(Vehicle *v); |
42 static void TrainController(Vehicle *v, bool update_image); |
43 static void TrainController(Vehicle *v, bool update_image); |
43 |
44 |
44 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8}; |
45 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8}; |
112 uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo_count * FreightWagonMult(u->cargo_type) / 16; |
113 uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo_count * FreightWagonMult(u->cargo_type) / 16; |
113 |
114 |
114 /* Vehicle weight is not added for articulated parts. */ |
115 /* Vehicle weight is not added for articulated parts. */ |
115 if (!IsArticulatedPart(u)) { |
116 if (!IsArticulatedPart(u)) { |
116 /* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */ |
117 /* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */ |
117 vweight += RailVehInfo(u->engine_type)->weight; |
118 vweight += GetVehicleProperty(u, 0x16, RailVehInfo(u->engine_type)->weight); |
118 |
119 |
119 /* powered wagons have extra weight added */ |
120 /* powered wagons have extra weight added */ |
120 if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON)) |
121 if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON)) |
121 vweight += RailVehInfo(u->u.rail.first_engine)->pow_wag_weight; |
122 vweight += RailVehInfo(u->u.rail.first_engine)->pow_wag_weight; |
122 } |
123 } |
163 /* update the 'first engine' */ |
164 /* update the 'first engine' */ |
164 u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine; |
165 u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine; |
165 u->u.rail.railtype = rvi_u->railtype; |
166 u->u.rail.railtype = rvi_u->railtype; |
166 |
167 |
167 if (IsTrainEngine(u)) first_engine = u->engine_type; |
168 if (IsTrainEngine(u)) first_engine = u->engine_type; |
|
169 |
|
170 /* Cache wagon override sprite group. NULL is returned if there is none */ |
|
171 u->u.rail.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->u.rail.first_engine); |
168 |
172 |
169 if (rvi_u->visual_effect != 0) { |
173 if (rvi_u->visual_effect != 0) { |
170 u->u.rail.cached_vis_effect = rvi_u->visual_effect; |
174 u->u.rail.cached_vis_effect = rvi_u->visual_effect; |
171 } else { |
175 } else { |
172 if (IsTrainWagon(u) || IsArticulatedPart(u)) { |
176 if (IsTrainWagon(u) || IsArticulatedPart(u)) { |
188 |
192 |
189 if (callback != CALLBACK_FAILED) u->u.rail.cached_vis_effect = callback; |
193 if (callback != CALLBACK_FAILED) u->u.rail.cached_vis_effect = callback; |
190 } |
194 } |
191 |
195 |
192 if (rvi_v->pow_wag_power != 0 && rvi_u->railveh_type == RAILVEH_WAGON && |
196 if (rvi_v->pow_wag_power != 0 && rvi_u->railveh_type == RAILVEH_WAGON && |
193 UsesWagonOverride(u) && (u->u.rail.cached_vis_effect < 0x40)) { |
197 UsesWagonOverride(u) && !HASBIT(u->u.rail.cached_vis_effect, 7)) { |
194 /* wagon is powered */ |
198 /* wagon is powered */ |
195 SETBIT(u->u.rail.flags, VRF_POWEREDWAGON); // cache 'powered' status |
199 SETBIT(u->u.rail.flags, VRF_POWEREDWAGON); // cache 'powered' status |
196 } else { |
200 } else { |
197 CLRBIT(u->u.rail.flags, VRF_POWEREDWAGON); |
201 CLRBIT(u->u.rail.flags, VRF_POWEREDWAGON); |
198 } |
202 } |
213 /* max speed is the minimum of the speed limits of all vehicles in the consist */ |
217 /* max speed is the minimum of the speed limits of all vehicles in the consist */ |
214 if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) { |
218 if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) { |
215 uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed); |
219 uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed); |
216 if (speed != 0) max_speed = min(speed, max_speed); |
220 if (speed != 0) max_speed = min(speed, max_speed); |
217 } |
221 } |
|
222 } |
|
223 |
|
224 if (u->cargo_type == rvi_u->cargo_type && u->cargo_subtype == 0) { |
|
225 /* Set cargo capacity if we've not been refitted */ |
|
226 u->cargo_cap = GetVehicleProperty(u, 0x14, rvi_u->capacity); |
218 } |
227 } |
219 |
228 |
220 /* check the vehicle length (callback) */ |
229 /* check the vehicle length (callback) */ |
221 uint16 veh_len = CALLBACK_FAILED; |
230 uint16 veh_len = CALLBACK_FAILED; |
222 if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) { |
231 if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) { |
533 u->owner = v->owner; |
542 u->owner = v->owner; |
534 u->tile = v->tile; |
543 u->tile = v->tile; |
535 u->x_pos = v->x_pos; |
544 u->x_pos = v->x_pos; |
536 u->y_pos = v->y_pos; |
545 u->y_pos = v->y_pos; |
537 u->z_pos = v->z_pos; |
546 u->z_pos = v->z_pos; |
538 u->z_height = v->z_height; |
|
539 u->u.rail.track = v->u.rail.track; |
547 u->u.rail.track = v->u.rail.track; |
540 u->u.rail.railtype = v->u.rail.railtype; |
548 u->u.rail.railtype = v->u.rail.railtype; |
541 u->build_year = v->build_year; |
549 u->build_year = v->build_year; |
542 u->vehstatus = v->vehstatus & ~VS_STOPPED; |
550 u->vehstatus = v->vehstatus & ~VS_STOPPED; |
543 u->u.rail.first_engine = v->engine_type; |
551 u->u.rail.first_engine = v->engine_type; |
550 u->cargo_cap = rvi_artic->capacity; |
558 u->cargo_cap = rvi_artic->capacity; |
551 u->max_speed = 0; |
559 u->max_speed = 0; |
552 u->max_age = 0; |
560 u->max_age = 0; |
553 u->engine_type = engine_type; |
561 u->engine_type = engine_type; |
554 u->value = 0; |
562 u->value = 0; |
555 u->type = VEH_TRAIN; |
563 u = new (u) Train(); |
556 u->subtype = 0; |
564 u->subtype = 0; |
557 SetArticulatedPart(u); |
565 SetArticulatedPart(u); |
558 u->cur_image = 0xAC2; |
566 u->cur_image = 0xAC2; |
559 u->random_bits = VehicleRandomBits(); |
567 u->random_bits = VehicleRandomBits(); |
560 |
568 |
565 static int32 CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags) |
573 static int32 CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags) |
566 { |
574 { |
567 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
575 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
568 |
576 |
569 const RailVehicleInfo *rvi = RailVehInfo(engine); |
577 const RailVehicleInfo *rvi = RailVehInfo(engine); |
570 int32 value = (rvi->base_cost * _eco->GetPrice(CEconomy::BUILD_RAILWAGON)) >> 8; |
578 int32 value = (GetEngineProperty(engine, 0x17, rvi->base_cost) * _eco->GetPrice(CEconomy::BUILD_RAILWAGON)) >> 8; |
571 |
579 |
572 uint num_vehicles = 1 + CountArticulatedParts(engine); |
580 uint num_vehicles = 1 + CountArticulatedParts(engine); |
573 |
581 |
574 if (!(flags & DC_QUERY_COST)) { |
582 if (!(flags & DC_QUERY_COST)) { |
575 Vehicle *vl[11]; // Allow for wagon and upto 10 artic parts. |
583 Vehicle *vl[11]; // Allow for wagon and upto 10 artic parts. |
628 // v->day_counter = 0; |
635 // v->day_counter = 0; |
629 |
636 |
630 v->u.rail.railtype = rvi->railtype; |
637 v->u.rail.railtype = rvi->railtype; |
631 |
638 |
632 v->build_year = _cur_year; |
639 v->build_year = _cur_year; |
633 v->type = VEH_TRAIN; |
640 v = new (v) Train(); |
634 v->cur_image = 0xAC2; |
641 v->cur_image = 0xAC2; |
635 v->random_bits = VehicleRandomBits(); |
642 v->random_bits = VehicleRandomBits(); |
636 |
643 |
|
644 v->group_id = DEFAULT_GROUP; |
|
645 |
637 AddArticulatedParts(vl); |
646 AddArticulatedParts(vl); |
638 |
647 |
639 _new_vehicle_id = v->index; |
648 _new_vehicle_id = v->index; |
640 |
649 |
641 VehiclePositionChanged(v); |
650 VehiclePositionChanged(v); |
642 TrainConsistChanged(GetFirstVehicleInChain(v)); |
651 TrainConsistChanged(GetFirstVehicleInChain(v)); |
|
652 UpdateTrainGroupID(GetFirstVehicleInChain(v)); |
643 |
653 |
644 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
654 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
645 if (IsLocalPlayer()) { |
655 if (IsLocalPlayer()) { |
646 InvalidateAutoreplaceWindow(VEH_TRAIN); // updates the replace Train window |
656 InvalidateAutoreplaceWindow(VEH_TRAIN); // updates the replace Train window |
647 } |
657 } |
666 break; |
676 break; |
667 } |
677 } |
668 } |
678 } |
669 } |
679 } |
670 |
680 |
671 static int32 EstimateTrainCost(const RailVehicleInfo* rvi) |
681 static int32 EstimateTrainCost(EngineID engine, const RailVehicleInfo* rvi) |
672 { |
682 { |
673 return rvi->base_cost * (_eco->GetPrice(CEconomy::BUILD_RAILVEHICLE) >> 3) >> 5; |
683 return GetEngineProperty(engine, 0x17, rvi->base_cost) * (_eco->GetPrice(CEconomy::BUILD_RAILVEHICLE) >> 3) >> 5; |
674 } |
684 } |
675 |
685 |
676 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building) |
686 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building) |
677 { |
687 { |
678 u->direction = v->direction; |
688 u->direction = v->direction; |
679 u->owner = v->owner; |
689 u->owner = v->owner; |
680 u->tile = v->tile; |
690 u->tile = v->tile; |
681 u->x_pos = v->x_pos; |
691 u->x_pos = v->x_pos; |
682 u->y_pos = v->y_pos; |
692 u->y_pos = v->y_pos; |
683 u->z_pos = v->z_pos; |
693 u->z_pos = v->z_pos; |
684 u->z_height = 6; |
|
685 u->u.rail.track = TRACK_BIT_DEPOT; |
694 u->u.rail.track = TRACK_BIT_DEPOT; |
686 u->vehstatus = v->vehstatus & ~VS_STOPPED; |
695 u->vehstatus = v->vehstatus & ~VS_STOPPED; |
687 u->subtype = 0; |
696 u->subtype = 0; |
688 SetMultiheaded(u); |
697 SetMultiheaded(u); |
689 u->spritenum = v->spritenum + 1; |
698 u->spritenum = v->spritenum + 1; |
694 if (building) v->next = u; |
703 if (building) v->next = u; |
695 u->engine_type = v->engine_type; |
704 u->engine_type = v->engine_type; |
696 u->build_year = v->build_year; |
705 u->build_year = v->build_year; |
697 if (building) v->value >>= 1; |
706 if (building) v->value >>= 1; |
698 u->value = v->value; |
707 u->value = v->value; |
699 u->type = VEH_TRAIN; |
708 u = new (u) Train(); |
700 u->cur_image = 0xAC2; |
709 u->cur_image = 0xAC2; |
701 u->random_bits = VehicleRandomBits(); |
710 u->random_bits = VehicleRandomBits(); |
702 VehiclePositionChanged(u); |
711 VehiclePositionChanged(u); |
703 } |
712 } |
704 |
713 |
729 /* We need to see if the engine got power on the tile to avoid eletric engines in non-electric depots */ |
738 /* We need to see if the engine got power on the tile to avoid eletric engines in non-electric depots */ |
730 if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR; |
739 if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR; |
731 |
740 |
732 if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags); |
741 if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags); |
733 |
742 |
734 int32 value = EstimateTrainCost(rvi); |
743 int32 value = EstimateTrainCost(p1, rvi); |
735 |
744 |
736 uint num_vehicles = |
745 uint num_vehicles = |
737 (rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + |
746 (rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + |
738 CountArticulatedParts(p1); |
747 CountArticulatedParts(p1); |
739 |
748 |
761 v->tile = tile; |
770 v->tile = tile; |
762 v->owner = _current_player; |
771 v->owner = _current_player; |
763 v->x_pos = x; |
772 v->x_pos = x; |
764 v->y_pos = y; |
773 v->y_pos = y; |
765 v->z_pos = GetSlopeZ(x, y); |
774 v->z_pos = GetSlopeZ(x, y); |
766 v->z_height = 6; |
|
767 v->u.rail.track = TRACK_BIT_DEPOT; |
775 v->u.rail.track = TRACK_BIT_DEPOT; |
768 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
776 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; |
769 v->spritenum = rvi->image_index; |
777 v->spritenum = rvi->image_index; |
770 v->cargo_type = rvi->cargo_type; |
778 v->cargo_type = rvi->cargo_type; |
771 v->cargo_subtype = 0; |
779 v->cargo_subtype = 0; |
787 _new_vehicle_id = v->index; |
795 _new_vehicle_id = v->index; |
788 |
796 |
789 v->service_interval = _patches.servint_trains; |
797 v->service_interval = _patches.servint_trains; |
790 v->date_of_last_service = _date; |
798 v->date_of_last_service = _date; |
791 v->build_year = _cur_year; |
799 v->build_year = _cur_year; |
792 v->type = VEH_TRAIN; |
800 v = new (v) Train(); |
793 v->cur_image = 0xAC2; |
801 v->cur_image = 0xAC2; |
794 v->random_bits = VehicleRandomBits(); |
802 v->random_bits = VehicleRandomBits(); |
795 |
803 |
796 v->vehicle_flags = 0; |
804 v->vehicle_flags = 0; |
797 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
805 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
|
806 |
|
807 v->group_id = DEFAULT_GROUP; |
798 |
808 |
799 v->subtype = 0; |
809 v->subtype = 0; |
800 SetFrontEngine(v); |
810 SetFrontEngine(v); |
801 SetTrainEngine(v); |
811 SetTrainEngine(v); |
802 |
812 |
815 AddArticulatedParts(vl); |
825 AddArticulatedParts(vl); |
816 } |
826 } |
817 |
827 |
818 TrainConsistChanged(v); |
828 TrainConsistChanged(v); |
819 UpdateTrainAcceleration(v); |
829 UpdateTrainAcceleration(v); |
|
830 UpdateTrainGroupID(v); |
820 |
831 |
821 if (!HASBIT(p2, 1)) { // check if the cars should be added to the new vehicle |
832 if (!HASBIT(p2, 1)) { // check if the cars should be added to the new vehicle |
822 NormalizeTrainVehInDepot(v); |
833 NormalizeTrainVehInDepot(v); |
823 } |
834 } |
824 |
835 |
1110 if (flags & DC_EXEC) { |
1121 if (flags & DC_EXEC) { |
1111 /* clear the ->first cache */ |
1122 /* clear the ->first cache */ |
1112 for (Vehicle *u = src_head; u != NULL; u = u->next) u->first = NULL; |
1123 for (Vehicle *u = src_head; u != NULL; u = u->next) u->first = NULL; |
1113 for (Vehicle *u = dst_head; u != NULL; u = u->next) u->first = NULL; |
1124 for (Vehicle *u = dst_head; u != NULL; u = u->next) u->first = NULL; |
1114 |
1125 |
|
1126 /* If we move the front Engine and if the second vehicle is not an engine |
|
1127 add the whole vehicle to the DEFAULT_GROUP */ |
|
1128 if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) { |
|
1129 const Vehicle *v = GetNextVehicle(src); |
|
1130 |
|
1131 if (v != NULL && !IsTrainEngine(v)) { |
|
1132 DoCommand(tile, DEFAULT_GROUP, v->index, flags, CMD_ADD_VEHICLE_GROUP); |
|
1133 } |
|
1134 } |
|
1135 |
1115 if (HASBIT(p2, 0)) { |
1136 if (HASBIT(p2, 0)) { |
1116 /* unlink ALL wagons */ |
1137 /* unlink ALL wagons */ |
1117 if (src != src_head) { |
1138 if (src != src_head) { |
1118 Vehicle *v = src_head; |
1139 Vehicle *v = src_head; |
1119 while (GetNextVehicle(v) != src) v = GetNextVehicle(v); |
1140 while (GetNextVehicle(v) != src) v = GetNextVehicle(v); |
1139 if (!IsFrontEngine(src)) { |
1160 if (!IsFrontEngine(src)) { |
1140 /* setting the type to 0 also involves setting up the orders field. */ |
1161 /* setting the type to 0 also involves setting up the orders field. */ |
1141 SetFrontEngine(src); |
1162 SetFrontEngine(src); |
1142 assert(src->orders == NULL); |
1163 assert(src->orders == NULL); |
1143 src->num_orders = 0; |
1164 src->num_orders = 0; |
|
1165 |
|
1166 // Decrease the engines number of the src engine_type |
|
1167 if (!IsDefaultGroupID(src->group_id) && IsValidGroupID(src->group_id)) { |
|
1168 GetGroup(src->group_id)->num_engines[src->engine_type]--; |
|
1169 } |
|
1170 |
|
1171 // If we move an engine to a new line affect it to the DEFAULT_GROUP |
|
1172 src->group_id = DEFAULT_GROUP; |
1144 } |
1173 } |
1145 } else { |
1174 } else { |
1146 SetFreeWagon(src); |
1175 SetFreeWagon(src); |
1147 } |
1176 } |
1148 dst_head = src; |
1177 dst_head = src; |
1200 |
1229 |
1201 /* If there is an engine behind first_engine we moved away, it should become new first_engine |
1230 /* If there is an engine behind first_engine we moved away, it should become new first_engine |
1202 * To do this, CmdMoveRailVehicle must be called once more |
1231 * To do this, CmdMoveRailVehicle must be called once more |
1203 * we can't loop forever here because next time we reach this line we will have a front engine */ |
1232 * we can't loop forever here because next time we reach this line we will have a front engine */ |
1204 if (src_head != NULL && !IsFrontEngine(src_head) && IsTrainEngine(src_head)) { |
1233 if (src_head != NULL && !IsFrontEngine(src_head) && IsTrainEngine(src_head)) { |
|
1234 /* As in CmdMoveRailVehicle src_head->group_id will be equal to DEFAULT_GROUP |
|
1235 * we need to save the group and reaffect it to src_head */ |
|
1236 const GroupID tmp_g = src_head->group_id; |
1205 CmdMoveRailVehicle(0, flags, src_head->index | (INVALID_VEHICLE << 16), 1); |
1237 CmdMoveRailVehicle(0, flags, src_head->index | (INVALID_VEHICLE << 16), 1); |
|
1238 SetTrainGroupID(src_head, tmp_g); |
1206 src_head = NULL; // don't do anything more to this train since the new call will do it |
1239 src_head = NULL; // don't do anything more to this train since the new call will do it |
1207 } |
1240 } |
1208 |
1241 |
1209 if (src_head != NULL) { |
1242 if (src_head != NULL) { |
1210 NormaliseTrainConsist(src_head); |
1243 NormaliseTrainConsist(src_head); |
1211 TrainConsistChanged(src_head); |
1244 TrainConsistChanged(src_head); |
|
1245 UpdateTrainGroupID(src_head); |
1212 if (IsFrontEngine(src_head)) { |
1246 if (IsFrontEngine(src_head)) { |
1213 UpdateTrainAcceleration(src_head); |
1247 UpdateTrainAcceleration(src_head); |
1214 InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index); |
1248 InvalidateWindow(WC_VEHICLE_DETAILS, src_head->index); |
1215 /* Update the refit button and window */ |
1249 /* Update the refit button and window */ |
1216 InvalidateWindow(WC_VEHICLE_REFIT, src_head->index); |
1250 InvalidateWindow(WC_VEHICLE_REFIT, src_head->index); |
1221 } |
1255 } |
1222 |
1256 |
1223 if (dst_head != NULL) { |
1257 if (dst_head != NULL) { |
1224 NormaliseTrainConsist(dst_head); |
1258 NormaliseTrainConsist(dst_head); |
1225 TrainConsistChanged(dst_head); |
1259 TrainConsistChanged(dst_head); |
|
1260 UpdateTrainGroupID(dst_head); |
1226 if (IsFrontEngine(dst_head)) { |
1261 if (IsFrontEngine(dst_head)) { |
1227 UpdateTrainAcceleration(dst_head); |
1262 UpdateTrainAcceleration(dst_head); |
1228 InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index); |
1263 InvalidateWindow(WC_VEHICLE_DETAILS, dst_head->index); |
1229 /* Update the refit button and window */ |
1264 /* Update the refit button and window */ |
1230 InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, 12); |
1265 InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, 12); |
1267 if (flags & DC_EXEC) { |
1302 if (flags & DC_EXEC) { |
1268 if (v->vehstatus & VS_STOPPED && v->u.rail.track == TRACK_BIT_DEPOT) { |
1303 if (v->vehstatus & VS_STOPPED && v->u.rail.track == TRACK_BIT_DEPOT) { |
1269 DeleteVehicleNews(p1, STR_8814_TRAIN_IS_WAITING_IN_DEPOT); |
1304 DeleteVehicleNews(p1, STR_8814_TRAIN_IS_WAITING_IN_DEPOT); |
1270 } |
1305 } |
1271 |
1306 |
1272 v->u.rail.days_since_order_progr = 0; |
|
1273 v->vehstatus ^= VS_STOPPED; |
1307 v->vehstatus ^= VS_STOPPED; |
1274 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
1308 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
1275 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1309 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1276 } |
1310 } |
1277 return 0; |
1311 return 0; |
1362 } |
1396 } |
1363 |
1397 |
1364 if (first->next_shared != NULL) { |
1398 if (first->next_shared != NULL) { |
1365 first->next_shared->prev_shared = new_f; |
1399 first->next_shared->prev_shared = new_f; |
1366 new_f->next_shared = first->next_shared; |
1400 new_f->next_shared = first->next_shared; |
|
1401 } else { |
|
1402 RemoveVehicleFromGroup(v); |
1367 } |
1403 } |
1368 |
1404 |
1369 /* |
1405 /* |
1370 * Remove all order information from the front train, to |
1406 * Remove all order information from the front train, to |
1371 * prevent the order and the shared order list to be |
1407 * prevent the order and the shared order list to be |
1392 |
1428 |
1393 /* 5. If the train still exists, update its acceleration, window, etc. */ |
1429 /* 5. If the train still exists, update its acceleration, window, etc. */ |
1394 if (first != NULL) { |
1430 if (first != NULL) { |
1395 NormaliseTrainConsist(first); |
1431 NormaliseTrainConsist(first); |
1396 TrainConsistChanged(first); |
1432 TrainConsistChanged(first); |
|
1433 UpdateTrainGroupID(first); |
1397 if (IsFrontEngine(first)) { |
1434 if (IsFrontEngine(first)) { |
1398 InvalidateWindow(WC_VEHICLE_DETAILS, first->index); |
1435 InvalidateWindow(WC_VEHICLE_DETAILS, first->index); |
1399 InvalidateWindow(WC_VEHICLE_REFIT, first->index); |
1436 InvalidateWindow(WC_VEHICLE_REFIT, first->index); |
1400 UpdateTrainAcceleration(first); |
1437 UpdateTrainAcceleration(first); |
1401 } |
1438 } |
1445 cost -= v->value; |
1482 cost -= v->value; |
1446 if (flags & DC_EXEC) { |
1483 if (flags & DC_EXEC) { |
1447 first = UnlinkWagon(v, first); |
1484 first = UnlinkWagon(v, first); |
1448 DeleteDepotHighlightOfVehicle(v); |
1485 DeleteDepotHighlightOfVehicle(v); |
1449 DeleteVehicle(v); |
1486 DeleteVehicle(v); |
|
1487 RemoveVehicleFromGroup(v); |
1450 } |
1488 } |
1451 } |
1489 } |
1452 |
1490 |
1453 /* 3. If it is still a valid train after selling, update its acceleration and cached values */ |
1491 /* 3. If it is still a valid train after selling, update its acceleration and cached values */ |
1454 if (flags & DC_EXEC && first != NULL) { |
1492 if (flags & DC_EXEC && first != NULL) { |
1455 NormaliseTrainConsist(first); |
1493 NormaliseTrainConsist(first); |
1456 TrainConsistChanged(first); |
1494 TrainConsistChanged(first); |
|
1495 UpdateTrainGroupID(first); |
1457 if (IsFrontEngine(first)) UpdateTrainAcceleration(first); |
1496 if (IsFrontEngine(first)) UpdateTrainAcceleration(first); |
1458 InvalidateWindow(WC_VEHICLE_DETAILS, first->index); |
1497 InvalidateWindow(WC_VEHICLE_DETAILS, first->index); |
1459 InvalidateWindow(WC_VEHICLE_REFIT, first->index); |
1498 InvalidateWindow(WC_VEHICLE_REFIT, first->index); |
1460 } |
1499 } |
1461 } break; |
1500 } break; |
1462 } |
1501 } |
1463 return cost; |
1502 return cost; |
1464 } |
1503 } |
1465 |
1504 |
1466 static void UpdateTrainDeltaXY(Vehicle *v, Direction direction) |
1505 void Train::UpdateDeltaXY(Direction direction) |
1467 { |
1506 { |
1468 #define MKIT(a,b,c,d) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0) |
1507 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
1469 static const uint32 _delta_xy_table[8] = { |
1508 static const uint32 _delta_xy_table[8] = { |
1470 MKIT(3, 3, -1, -1), |
1509 MKIT(3, 3, -1, -1), |
1471 MKIT(3, 7, -1, -3), |
1510 MKIT(3, 7, -1, -3), |
1472 MKIT(3, 3, -1, -1), |
1511 MKIT(3, 3, -1, -1), |
1473 MKIT(7, 3, -3, -1), |
1512 MKIT(7, 3, -3, -1), |
1477 MKIT(7, 3, -3, -1), |
1516 MKIT(7, 3, -3, -1), |
1478 }; |
1517 }; |
1479 #undef MKIT |
1518 #undef MKIT |
1480 |
1519 |
1481 uint32 x = _delta_xy_table[direction]; |
1520 uint32 x = _delta_xy_table[direction]; |
1482 |
1521 this->x_offs = GB(x, 0, 8); |
1483 v->x_offs = GB(x, 0, 8); |
1522 this->y_offs = GB(x, 8, 8); |
1484 v->y_offs = GB(x, 8, 8); |
1523 this->sprite_width = GB(x, 16, 8); |
1485 v->sprite_width = GB(x, 16, 8); |
1524 this->sprite_height = GB(x, 24, 8); |
1486 v->sprite_height = GB(x, 24, 8); |
1525 this->z_height = 6; |
1487 } |
1526 } |
1488 |
1527 |
1489 static void UpdateVarsAfterSwap(Vehicle *v) |
1528 static void UpdateVarsAfterSwap(Vehicle *v) |
1490 { |
1529 { |
1491 UpdateTrainDeltaXY(v, v->direction); |
1530 v->UpdateDeltaXY(v->direction); |
1492 v->cur_image = GetTrainImage(v, v->direction); |
1531 v->cur_image = GetTrainImage(v, v->direction); |
1493 BeginVehicleMove(v); |
1532 BeginVehicleMove(v); |
1494 VehiclePositionChanged(v); |
1533 VehiclePositionChanged(v); |
1495 EndVehicleMove(v); |
1534 EndVehicleMove(v); |
1496 } |
1535 } |
1749 * @param flags type of operation |
1788 * @param flags type of operation |
1750 * @param p1 vehicle ID of the train to refit |
1789 * @param p1 vehicle ID of the train to refit |
1751 * param p2 various bitstuffed elements |
1790 * param p2 various bitstuffed elements |
1752 * - p2 = (bit 0-7) - the new cargo type to refit to |
1791 * - p2 = (bit 0-7) - the new cargo type to refit to |
1753 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
1792 * - p2 = (bit 8-15) - the new cargo subtype to refit to |
|
1793 * - p2 = (bit 16) - refit only this vehicle |
|
1794 * @return cost of refit or error |
1754 */ |
1795 */ |
1755 int32 CmdRefitRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1796 int32 CmdRefitRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1756 { |
1797 { |
1757 CargoID new_cid = GB(p2, 0, 8); |
1798 CargoID new_cid = GB(p2, 0, 8); |
1758 byte new_subtype = GB(p2, 8, 8); |
1799 byte new_subtype = GB(p2, 8, 8); |
|
1800 bool only_this = HASBIT(p2, 16); |
1759 |
1801 |
1760 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
1802 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
1761 |
1803 |
1762 Vehicle *v = GetVehicle(p1); |
1804 Vehicle *v = GetVehicle(p1); |
1763 |
1805 |
1831 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1873 InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); |
1832 RebuildVehicleLists(); |
1874 RebuildVehicleLists(); |
1833 } |
1875 } |
1834 } |
1876 } |
1835 } |
1877 } |
1836 } while ((v = v->next) != NULL); |
1878 } while ((v = v->next) != NULL && !only_this); |
1837 |
1879 |
1838 _returned_refit_capacity = num; |
1880 _returned_refit_capacity = num; |
1839 |
1881 |
1840 /* Update the train's cached variables */ |
1882 /* Update the train's cached variables */ |
1841 if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1))); |
1883 if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1))); |
1964 } |
2006 } |
1965 |
2007 |
1966 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
2008 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
1967 if (flags & DC_EXEC) { |
2009 if (flags & DC_EXEC) { |
1968 if (HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) { |
2010 if (HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) { |
1969 v->u.rail.days_since_order_progr = 0; |
|
1970 v->cur_order_index++; |
2011 v->cur_order_index++; |
1971 } |
2012 } |
1972 |
2013 |
1973 v->current_order.type = OT_DUMMY; |
2014 v->current_order.type = OT_DUMMY; |
1974 v->current_order.flags = 0; |
2015 v->current_order.flags = 0; |
2027 bool disable_effect = HASBIT(v->u.rail.cached_vis_effect, 6); |
2068 bool disable_effect = HASBIT(v->u.rail.cached_vis_effect, 6); |
2028 |
2069 |
2029 /* no smoke? */ |
2070 /* no smoke? */ |
2030 if ((rvi->railveh_type == RAILVEH_WAGON && effect_type == 0) || |
2071 if ((rvi->railveh_type == RAILVEH_WAGON && effect_type == 0) || |
2031 disable_effect || |
2072 disable_effect || |
2032 rvi->railtype > RAILTYPE_ELECTRIC || |
|
2033 v->vehstatus & VS_HIDDEN) { |
2073 v->vehstatus & VS_HIDDEN) { |
2034 continue; |
2074 continue; |
2035 } |
2075 } |
2036 |
2076 |
2037 /* No smoke in depots or tunnels */ |
2077 /* No smoke in depots or tunnels */ |
2088 static void TrainPlayLeaveStationSound(const Vehicle* v) |
2128 static void TrainPlayLeaveStationSound(const Vehicle* v) |
2089 { |
2129 { |
2090 static const SoundFx sfx[] = { |
2130 static const SoundFx sfx[] = { |
2091 SND_04_TRAIN, |
2131 SND_04_TRAIN, |
2092 SND_0A_TRAIN_HORN, |
2132 SND_0A_TRAIN_HORN, |
2093 SND_0A_TRAIN_HORN |
2133 SND_0A_TRAIN_HORN, |
|
2134 SND_47_MAGLEV_2, |
|
2135 SND_41_MAGLEV |
2094 }; |
2136 }; |
2095 |
2137 |
2096 if (PlayVehicleSound(v, VSE_START)) return; |
2138 if (PlayVehicleSound(v, VSE_START)) return; |
2097 |
2139 |
2098 EngineID engtype = v->engine_type; |
2140 EngineID engtype = v->engine_type; |
2099 switch (RailVehInfo(engtype)->railtype) { |
2141 SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], v); |
2100 case RAILTYPE_RAIL: |
2142 } |
2101 case RAILTYPE_ELECTRIC: |
2143 |
2102 SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], v); |
2144 void Train::PlayLeaveStationSound() const |
2103 break; |
2145 { |
2104 |
2146 TrainPlayLeaveStationSound(this); |
2105 case RAILTYPE_MONO: SndPlayVehicleFx(SND_47_MAGLEV_2, v); break; |
|
2106 case RAILTYPE_MAGLEV: SndPlayVehicleFx(SND_41_MAGLEV, v); break; |
|
2107 default: NOT_REACHED(); |
|
2108 } |
|
2109 } |
2147 } |
2110 |
2148 |
2111 static bool CheckTrainStayInDepot(Vehicle *v) |
2149 static bool CheckTrainStayInDepot(Vehicle *v) |
2112 { |
2150 { |
2113 /* bail out if not all wagons are in the same depot or not in a depot at all */ |
2151 /* bail out if not all wagons are in the same depot or not in a depot at all */ |
2144 if (v->direction & 2) v->u.rail.track = TRACK_BIT_Y; |
2182 if (v->direction & 2) v->u.rail.track = TRACK_BIT_Y; |
2145 |
2183 |
2146 v->vehstatus &= ~VS_HIDDEN; |
2184 v->vehstatus &= ~VS_HIDDEN; |
2147 v->cur_speed = 0; |
2185 v->cur_speed = 0; |
2148 |
2186 |
2149 UpdateTrainDeltaXY(v, v->direction); |
2187 v->UpdateDeltaXY(v->direction); |
2150 v->cur_image = GetTrainImage(v, v->direction); |
2188 v->cur_image = GetTrainImage(v, v->direction); |
2151 VehiclePositionChanged(v); |
2189 VehiclePositionChanged(v); |
2152 UpdateSignalsOnSegment(v->tile, DirToDiagDir(v->direction)); |
2190 UpdateSignalsOnSegment(v->tile, DirToDiagDir(v->direction)); |
2153 UpdateTrainAcceleration(v); |
2191 UpdateTrainAcceleration(v); |
2154 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
2192 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
2517 } |
2555 } |
2518 |
2556 |
2519 return !at_waypoint && CheckReverseTrain(v); |
2557 return !at_waypoint && CheckReverseTrain(v); |
2520 } |
2558 } |
2521 |
2559 |
2522 static void MarkTrainDirty(Vehicle *v) |
2560 void Train::MarkDirty() |
2523 { |
2561 { |
|
2562 Vehicle *v = this; |
2524 do { |
2563 do { |
2525 v->cur_image = GetTrainImage(v, v->direction); |
2564 v->cur_image = GetTrainImage(v, v->direction); |
2526 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
2565 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
2527 } while ((v = v->next) != NULL); |
2566 } while ((v = v->next) != NULL); |
2528 } |
2567 |
2529 |
2568 /* need to update acceleration and cached values since the goods on the train changed. */ |
2530 static void HandleTrainLoading(Vehicle *v, bool mode) |
2569 TrainCargoChanged(this); |
2531 { |
2570 UpdateTrainAcceleration(this); |
2532 switch (v->current_order.type) { |
|
2533 case OT_LOADING: { |
|
2534 if (mode) return; |
|
2535 |
|
2536 /* don't mark the train as lost if we're loading on the final station. */ |
|
2537 if (v->current_order.flags & OF_NON_STOP) { |
|
2538 v->u.rail.days_since_order_progr = 0; |
|
2539 } |
|
2540 |
|
2541 if (--v->load_unload_time_rem) return; |
|
2542 |
|
2543 if (CanFillVehicle(v) && ( |
|
2544 v->current_order.flags & OF_FULL_LOAD || |
|
2545 (_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED)) |
|
2546 )) { |
|
2547 v->u.rail.days_since_order_progr = 0; // Prevent a train lost message for full loading trains |
|
2548 SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); |
|
2549 if (LoadUnloadVehicle(v, false)) { |
|
2550 InvalidateWindow(WC_TRAINS_LIST, v->owner); |
|
2551 MarkTrainDirty(v); |
|
2552 |
|
2553 /* need to update acceleration and cached values since the goods on the train changed. */ |
|
2554 TrainCargoChanged(v); |
|
2555 UpdateTrainAcceleration(v); |
|
2556 } |
|
2557 return; |
|
2558 } |
|
2559 |
|
2560 TrainPlayLeaveStationSound(v); |
|
2561 |
|
2562 Order b = v->current_order; |
|
2563 v->LeaveStation(); |
|
2564 |
|
2565 /* If this was not the final order, don't remove it from the list. */ |
|
2566 if (!(b.flags & OF_NON_STOP)) return; |
|
2567 break; |
|
2568 } |
|
2569 |
|
2570 case OT_DUMMY: break; |
|
2571 |
|
2572 default: return; |
|
2573 } |
|
2574 |
|
2575 v->u.rail.days_since_order_progr = 0; |
|
2576 v->cur_order_index++; |
|
2577 InvalidateVehicleOrder(v); |
|
2578 } |
2571 } |
2579 |
2572 |
2580 static int UpdateTrainSpeed(Vehicle *v) |
2573 static int UpdateTrainSpeed(Vehicle *v) |
2581 { |
2574 { |
2582 uint accel; |
2575 uint accel; |
2629 v->index, |
2622 v->index, |
2630 0 |
2623 0 |
2631 ); |
2624 ); |
2632 } |
2625 } |
2633 |
2626 |
2634 /* Did we reach the final destination? */ |
2627 v->BeginLoading(); |
2635 if (v->current_order.type == OT_GOTO_STATION && |
|
2636 v->current_order.dest == station) { |
|
2637 /* Yeah, keep the load/unload flags |
|
2638 * Non Stop now means if the order should be increased. */ |
|
2639 v->BeginLoading(); |
|
2640 v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER; |
|
2641 v->current_order.flags |= OF_NON_STOP; |
|
2642 } else { |
|
2643 /* No, just do a simple load */ |
|
2644 v->BeginLoading(); |
|
2645 v->current_order.flags = 0; |
|
2646 } |
|
2647 v->current_order.dest = 0; |
2628 v->current_order.dest = 0; |
2648 |
|
2649 SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC); |
|
2650 if (LoadUnloadVehicle(v, true) != 0) { |
|
2651 InvalidateWindow(WC_TRAINS_LIST, v->owner); |
|
2652 TrainCargoChanged(v); |
|
2653 UpdateTrainAcceleration(v); |
|
2654 } |
|
2655 MarkTrainDirty(v); |
|
2656 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
|
2657 } |
2629 } |
2658 |
2630 |
2659 static byte AfterSetTrainPos(Vehicle *v, bool new_tile) |
2631 static byte AfterSetTrainPos(Vehicle *v, bool new_tile) |
2660 { |
2632 { |
2661 /* need this hint so it returns the right z coordinate on bridges. */ |
2633 /* need this hint so it returns the right z coordinate on bridges. */ |
3076 } |
3048 } |
3077 } |
3049 } |
3078 |
3050 |
3079 /* update image of train, as well as delta XY */ |
3051 /* update image of train, as well as delta XY */ |
3080 Direction newdir = GetNewVehicleDirection(v, gp.x, gp.y); |
3052 Direction newdir = GetNewVehicleDirection(v, gp.x, gp.y); |
3081 UpdateTrainDeltaXY(v, newdir); |
3053 v->UpdateDeltaXY(newdir); |
3082 if (update_image) v->cur_image = GetTrainImage(v, newdir); |
3054 if (update_image) v->cur_image = GetTrainImage(v, newdir); |
3083 |
3055 |
3084 v->x_pos = gp.x; |
3056 v->x_pos = gp.x; |
3085 v->y_pos = gp.y; |
3057 v->y_pos = gp.y; |
3086 |
3058 |
3128 RebuildVehicleLists(); |
3100 RebuildVehicleLists(); |
3129 InvalidateWindow(WC_COMPANY, v->owner); |
3101 InvalidateWindow(WC_COMPANY, v->owner); |
3130 |
3102 |
3131 BeginVehicleMove(v); |
3103 BeginVehicleMove(v); |
3132 EndVehicleMove(v); |
3104 EndVehicleMove(v); |
|
3105 |
|
3106 if (IsFrontEngine(v)) RemoveVehicleFromGroup(v); |
|
3107 |
3133 DeleteVehicle(v); |
3108 DeleteVehicle(v); |
3134 |
3109 |
3135 if (v->u.rail.track != TRACK_BIT_DEPOT && v->u.rail.track != TRACK_BIT_WORMHOLE) |
3110 if (v->u.rail.track != TRACK_BIT_DEPOT && v->u.rail.track != TRACK_BIT_WORMHOLE) |
3136 SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(v->u.rail.track)); |
3111 SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(v->u.rail.track)); |
3137 |
3112 |
3172 do { |
3147 do { |
3173 /* We don't need to twist around vehicles if they're not visible */ |
3148 /* We don't need to twist around vehicles if they're not visible */ |
3174 if (!(v->vehstatus & VS_HIDDEN)) { |
3149 if (!(v->vehstatus & VS_HIDDEN)) { |
3175 v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]); |
3150 v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]); |
3176 BeginVehicleMove(v); |
3151 BeginVehicleMove(v); |
3177 UpdateTrainDeltaXY(v, v->direction); |
3152 v->UpdateDeltaXY(v->direction); |
3178 v->cur_image = GetTrainImage(v, v->direction); |
3153 v->cur_image = GetTrainImage(v, v->direction); |
3179 /* Refrain from updating the z position of the vehicle when on |
3154 /* Refrain from updating the z position of the vehicle when on |
3180 a bridge, because AfterSetTrainPos will put the vehicle under |
3155 a bridge, because AfterSetTrainPos will put the vehicle under |
3181 the bridge in that case */ |
3156 the bridge in that case */ |
3182 if (v->u.rail.track != TRACK_BIT_WORMHOLE) AfterSetTrainPos(v, false); |
3157 if (v->u.rail.track != TRACK_BIT_WORMHOLE) AfterSetTrainPos(v, false); |
3462 if (v->current_order.type == OT_GOTO_DEPOT && |
3438 if (v->current_order.type == OT_GOTO_DEPOT && |
3463 v->current_order.dest != depot->index && |
3439 v->current_order.dest != depot->index && |
3464 !CHANCE16(3, 16)) { |
3440 !CHANCE16(3, 16)) { |
3465 return; |
3441 return; |
3466 } |
3442 } |
|
3443 |
|
3444 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
3467 |
3445 |
3468 v->current_order.type = OT_GOTO_DEPOT; |
3446 v->current_order.type = OT_GOTO_DEPOT; |
3469 v->current_order.flags = OF_NON_STOP; |
3447 v->current_order.flags = OF_NON_STOP; |
3470 v->current_order.dest = depot->index; |
3448 v->current_order.dest = depot->index; |
3471 v->dest_tile = tfdd.tile; |
3449 v->dest_tile = tfdd.tile; |