102 } |
105 } |
103 |
106 |
104 bool VehicleNeedsService(const Vehicle *v) |
107 bool VehicleNeedsService(const Vehicle *v) |
105 { |
108 { |
106 if (v->vehstatus & VS_CRASHED) |
109 if (v->vehstatus & VS_CRASHED) |
107 return false; /* Crashed vehicles don't need service anymore */ |
110 return false; // Crashed vehicles don't need service anymore |
108 |
111 |
109 if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) { |
112 if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) { |
110 return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type); /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */ |
113 return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type); /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */ |
111 } |
114 } |
112 |
115 |
309 } |
312 } |
310 |
313 |
311 return NULL; |
314 return NULL; |
312 } |
315 } |
313 |
316 |
314 /* |
317 /** |
315 * finds a free vehicle in the memory or allocates a new one |
318 * finds a free vehicle in the memory or allocates a new one |
316 * returns a pointer to the first free vehicle or NULL if all vehicles are in use |
319 * returns a pointer to the first free vehicle or NULL if all vehicles are in use |
317 * *skip_vehicles is an offset to where in the array we should begin looking |
320 * *skip_vehicles is an offset to where in the array we should begin looking |
318 * this is to avoid looping though the same vehicles more than once after we learned that they are not free |
321 * this is to avoid looping though the same vehicles more than once after we learned that they are not free |
319 * this feature is used by AllocateVehicles() since it need to allocate more than one and when |
322 * this feature is used by AllocateVehicles() since it need to allocate more than one and when |
325 * first blocks */ |
328 * first blocks */ |
326 Vehicle *v; |
329 Vehicle *v; |
327 const int offset = (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES; |
330 const int offset = (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES; |
328 |
331 |
329 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
332 /* We don't use FOR_ALL here, because FOR_ALL skips invalid items. |
330 * TODO - This is just a temporary stage, this will be removed. */ |
333 * @todo - This is just a temporary stage, this will be removed. */ |
331 if (*skip_vehicles < (_Vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself |
334 if (*skip_vehicles < (_Vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself |
332 for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) { |
335 for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) { |
333 (*skip_vehicles)++; |
336 (*skip_vehicles)++; |
334 if (!IsValidVehicle(v)) return InitializeVehicle(v); |
337 if (!IsValidVehicle(v)) return InitializeVehicle(v); |
335 } |
338 } |
379 |
382 |
380 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc) |
383 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc) |
381 { |
384 { |
382 Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, 0); |
385 Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, 0); |
383 |
386 |
384 // The hash area to scan |
387 /* The hash area to scan */ |
385 const int xl = GB(pt.x - 174, 7, 6); |
388 const int xl = GB(pt.x - 174, 7, 6); |
386 const int xu = GB(pt.x + 104, 7, 6); |
389 const int xu = GB(pt.x + 104, 7, 6); |
387 const int yl = GB(pt.y - 294, 6, 6) << 6; |
390 const int yl = GB(pt.y - 294, 6, 6) << 6; |
388 const int yu = GB(pt.y + 56, 6, 6) << 6; |
391 const int yu = GB(pt.y + 56, 6, 6) << 6; |
389 |
392 |
604 void Ship_Tick(Vehicle *v); |
607 void Ship_Tick(Vehicle *v); |
605 void Train_Tick(Vehicle *v); |
608 void Train_Tick(Vehicle *v); |
606 static void EffectVehicle_Tick(Vehicle *v); |
609 static void EffectVehicle_Tick(Vehicle *v); |
607 void DisasterVehicle_Tick(Vehicle *v); |
610 void DisasterVehicle_Tick(Vehicle *v); |
608 |
611 |
609 // head of the linked list to tell what vehicles that visited a depot in a tick |
612 /** head of the linked list to tell what vehicles that visited a depot in a tick */ |
610 static Vehicle* _first_veh_in_depot_list; |
613 static Vehicle* _first_veh_in_depot_list; |
611 |
614 |
612 /** Adds a vehicle to the list of vehicles, that visited a depot this tick |
615 /** Adds a vehicle to the list of vehicles, that visited a depot this tick |
613 * @param *v vehicle to add |
616 * @param *v vehicle to add |
614 */ |
617 */ |
615 void VehicleEnteredDepotThisTick(Vehicle *v) |
618 void VehicleEnteredDepotThisTick(Vehicle *v) |
616 { |
619 { |
617 // we need to set v->leave_depot_instantly as we have no control of it's contents at this time |
620 /* we need to set v->leave_depot_instantly as we have no control of it's contents at this time */ |
618 if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) { |
621 if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) { |
619 // we keep the vehicle in the depot since the user ordered it to stay |
622 /* we keep the vehicle in the depot since the user ordered it to stay */ |
620 v->leave_depot_instantly = false; |
623 v->leave_depot_instantly = false; |
621 } else { |
624 } else { |
622 // the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path |
625 /* the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path |
623 // out of the depot before we might autoreplace it to a different engine. The new engine would not own the reserved path |
626 * out of the depot before we might autoreplace it to a different engine. The new engine would not own the reserved path |
624 // we store that we stopped the vehicle, so autoreplace can start it again |
627 * we store that we stopped the vehicle, so autoreplace can start it again */ |
625 v->vehstatus |= VS_STOPPED; |
628 v->vehstatus |= VS_STOPPED; |
626 v->leave_depot_instantly = true; |
629 v->leave_depot_instantly = true; |
627 } |
630 } |
628 |
631 |
629 if (_first_veh_in_depot_list == NULL) { |
632 if (_first_veh_in_depot_list == NULL) { |
648 void CallVehicleTicks() |
651 void CallVehicleTicks() |
649 { |
652 { |
650 Vehicle *v; |
653 Vehicle *v; |
651 |
654 |
652 #ifdef ENABLE_NETWORK |
655 #ifdef ENABLE_NETWORK |
653 // hotfix for desync problem: |
656 /* hotfix for desync problem: |
654 // for MP games invalidate the YAPF cache every tick to keep it exactly the same on the server and all clients |
657 * for MP games invalidate the YAPF cache every tick to keep it exactly the same on the server and all clients */ |
655 if (_networking) { |
658 if (_networking) { |
656 YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK); |
659 YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK); |
657 } |
660 } |
658 #endif //ENABLE_NETWORK |
661 #endif //ENABLE_NETWORK |
659 |
662 |
677 /* Play an alterate running sound every 16 ticks */ |
680 /* Play an alterate running sound every 16 ticks */ |
678 if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16); |
681 if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16); |
679 } |
682 } |
680 } |
683 } |
681 |
684 |
682 // now we handle all the vehicles that entered a depot this tick |
685 /* now we handle all the vehicles that entered a depot this tick */ |
683 v = _first_veh_in_depot_list; |
686 v = _first_veh_in_depot_list; |
684 while (v != NULL) { |
687 while (v != NULL) { |
685 Vehicle *w = v->depot_list; |
688 Vehicle *w = v->depot_list; |
686 v->depot_list = NULL; // it should always be NULL at the end of each tick |
689 v->depot_list = NULL; // it should always be NULL at the end of each tick |
687 MaybeReplaceVehicle(v, false, true); |
690 MaybeReplaceVehicle(v, false, true); |
693 { |
696 { |
694 uint32 full = 0, not_full = 0; |
697 uint32 full = 0, not_full = 0; |
695 bool keep_loading = false; |
698 bool keep_loading = false; |
696 const GoodsEntry *ge = GetStation(v->last_station_visited)->goods; |
699 const GoodsEntry *ge = GetStation(v->last_station_visited)->goods; |
697 |
700 |
698 //special handling of aircraft |
701 /* special handling of aircraft */ |
699 |
702 |
700 //if the aircraft carries passengers and is NOT full, then |
703 /* if the aircraft carries passengers and is NOT full, then |
701 //continue loading, no matter how much mail is in |
704 *continue loading, no matter how much mail is in */ |
702 if (v->type == VEH_AIRCRAFT && |
705 if (v->type == VEH_AIRCRAFT && |
703 IsCargoInClass(v->cargo_type, CC_PASSENGERS) && |
706 IsCargoInClass(v->cargo_type, CC_PASSENGERS) && |
704 v->cargo_cap != v->cargo_count) { |
707 v->cargo_cap != v->cargo_count) { |
705 return true; |
708 return true; |
706 } |
709 } |
707 |
710 |
708 // patch should return "true" to continue loading, i.e. when there is no cargo type that is fully loaded. |
711 /* patch should return "true" to continue loading, i.e. when there is no cargo type that is fully loaded. */ |
709 do { |
712 do { |
710 //Should never happen, but just in case future additions change this |
713 /* Should never happen, but just in case future additions change this */ |
711 assert(v->cargo_type<32); |
714 assert(v->cargo_type<32); |
712 |
715 |
713 if (v->cargo_cap != 0) { |
716 if (v->cargo_cap != 0) { |
714 uint32 mask = 1 << v->cargo_type; |
717 uint32 mask = 1 << v->cargo_type; |
715 |
718 |
741 IsTileType(TILE_ADDXY(tile, 0, 1), MP_STATION) || |
744 IsTileType(TILE_ADDXY(tile, 0, 1), MP_STATION) || |
742 IsTileType(TILE_ADDXY(tile, 0, -1), MP_STATION) || |
745 IsTileType(TILE_ADDXY(tile, 0, -1), MP_STATION) || |
743 IsTileType(TILE_ADDXY(tile, -2, 0), MP_STATION) |
746 IsTileType(TILE_ADDXY(tile, -2, 0), MP_STATION) |
744 ))) { |
747 ))) { |
745 |
748 |
746 // If patch is active, use alternative CanFillVehicle-function |
749 /* If patch is active, use alternative CanFillVehicle-function */ |
747 if (_patches.full_load_any && v->current_order.flags & OF_FULL_LOAD) return CanFillVehicle_FullLoadAny(v); |
750 if (_patches.full_load_any && v->current_order.flags & OF_FULL_LOAD) return CanFillVehicle_FullLoadAny(v); |
748 |
751 |
749 do { |
752 do { |
750 if (v->cargo_count != v->cargo_cap) return true; |
753 if (v->cargo_count != v->cargo_cap) return true; |
751 } while ((v = v->next) != NULL); |
754 } while ((v = v->next) != NULL); |
819 v->sprite_width, v->sprite_height, v->z_height, v->z_pos); |
822 v->sprite_width, v->sprite_height, v->z_height, v->z_pos); |
820 } |
823 } |
821 |
824 |
822 void ViewportAddVehicles(DrawPixelInfo *dpi) |
825 void ViewportAddVehicles(DrawPixelInfo *dpi) |
823 { |
826 { |
824 // The bounding rectangle |
827 /* The bounding rectangle */ |
825 const int l = dpi->left; |
828 const int l = dpi->left; |
826 const int r = dpi->left + dpi->width; |
829 const int r = dpi->left + dpi->width; |
827 const int t = dpi->top; |
830 const int t = dpi->top; |
828 const int b = dpi->top + dpi->height; |
831 const int b = dpi->top + dpi->height; |
829 |
832 |
830 // The hash area to scan |
833 /* The hash area to scan */ |
831 const int xl = GB(l - 70, 7, 6); |
834 const int xl = GB(l - 70, 7, 6); |
832 const int xu = GB(r, 7, 6); |
835 const int xu = GB(r, 7, 6); |
833 const int yl = GB(t - 70, 6, 6) << 6; |
836 const int yl = GB(t - 70, 6, 6) << 6; |
834 const int yu = GB(b, 6, 6) << 6; |
837 const int yu = GB(b, 6, 6) << 6; |
835 |
838 |
1565 |
1568 |
1566 static void ShowVehicleGettingOld(Vehicle *v, StringID msg) |
1569 static void ShowVehicleGettingOld(Vehicle *v, StringID msg) |
1567 { |
1570 { |
1568 if (v->owner != _local_player) return; |
1571 if (v->owner != _local_player) return; |
1569 |
1572 |
1570 // Do not show getting-old message if autorenew is active |
1573 /* Do not show getting-old message if autorenew is active */ |
1571 if (GetPlayer(v->owner)->engine_renew) return; |
1574 if (GetPlayer(v->owner)->engine_renew) return; |
1572 |
1575 |
1573 SetDParam(0, _vehicle_type_names[v->type]); |
1576 SetDParam(0, _vehicle_type_names[v->type]); |
1574 SetDParam(1, v->unitnumber); |
1577 SetDParam(1, v->unitnumber); |
1575 AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0); |
1578 AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0); |
1597 } |
1600 } |
1598 } |
1601 } |
1599 |
1602 |
1600 /** Starts or stops a lot of vehicles |
1603 /** Starts or stops a lot of vehicles |
1601 * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots) |
1604 * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots) |
|
1605 * @param flags type of operation |
1602 * @param p1 Station/Order/Depot ID (only used for vehicle list windows) |
1606 * @param p1 Station/Order/Depot ID (only used for vehicle list windows) |
1603 * @param p2 bitmask |
1607 * @param p2 bitmask |
1604 * - bit 0-4 Vehicle type |
1608 * - bit 0-4 Vehicle type |
1605 * - bit 5 false = start vehicles, true = stop vehicles |
1609 * - bit 5 false = start vehicles, true = stop vehicles |
1606 * - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case |
1610 * - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case |
1663 free(vl); |
1667 free(vl); |
1664 return return_value; |
1668 return return_value; |
1665 } |
1669 } |
1666 |
1670 |
1667 /** Sells all vehicles in a depot |
1671 /** Sells all vehicles in a depot |
1668 * @param tile Tile of the depot where the depot is |
1672 * @param tile Tile of the depot where the depot is |
1669 * @param p1 Vehicle type |
1673 * @param flags type of operation |
1670 * @param p2 unused |
1674 * @param p1 Vehicle type |
1671 */ |
1675 * @param p2 unused |
|
1676 */ |
1672 int32 CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1677 int32 CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1673 { |
1678 { |
1674 Vehicle **engines = NULL; |
1679 Vehicle **engines = NULL; |
1675 Vehicle **wagons = NULL; |
1680 Vehicle **wagons = NULL; |
1676 uint16 engine_list_length = 0; |
1681 uint16 engine_list_length = 0; |
1715 if (cost == 0) return CMD_ERROR; // no vehicles to sell |
1720 if (cost == 0) return CMD_ERROR; // no vehicles to sell |
1716 return cost; |
1721 return cost; |
1717 } |
1722 } |
1718 |
1723 |
1719 /** Autoreplace all vehicles in the depot |
1724 /** Autoreplace all vehicles in the depot |
1720 * @param tile Tile of the depot where the vehicles are |
1725 * @param tile Tile of the depot where the vehicles are |
1721 * @param p1 Type of vehicle |
1726 * @param flags type of operation |
1722 * @param p2 Unused |
1727 * @param p1 Type of vehicle |
1723 */ |
1728 * @param p2 Unused |
|
1729 */ |
1724 int32 CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1730 int32 CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1725 { |
1731 { |
1726 Vehicle **vl = NULL; |
1732 Vehicle **vl = NULL; |
1727 uint16 engine_list_length = 0; |
1733 uint16 engine_list_length = 0; |
1728 uint16 engine_count = 0; |
1734 uint16 engine_count = 0; |
1782 return cost; |
1788 return cost; |
1783 } |
1789 } |
1784 |
1790 |
1785 /** Clone a vehicle. If it is a train, it will clone all the cars too |
1791 /** Clone a vehicle. If it is a train, it will clone all the cars too |
1786 * @param tile tile of the depot where the cloned vehicle is build |
1792 * @param tile tile of the depot where the cloned vehicle is build |
|
1793 * @param flags type of operation |
1787 * @param p1 the original vehicle's index |
1794 * @param p1 the original vehicle's index |
1788 * @param p2 1 = shared orders, else copied orders |
1795 * @param p2 1 = shared orders, else copied orders |
1789 */ |
1796 */ |
1790 int32 CmdCloneVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1797 int32 CmdCloneVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1791 { |
1798 { |
1812 |
1819 |
1813 if (!CheckOwnership(v->owner)) return CMD_ERROR; |
1820 if (!CheckOwnership(v->owner)) return CMD_ERROR; |
1814 |
1821 |
1815 if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR; |
1822 if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR; |
1816 |
1823 |
1817 // check that we can allocate enough vehicles |
1824 /* check that we can allocate enough vehicles */ |
1818 if (!(flags & DC_EXEC)) { |
1825 if (!(flags & DC_EXEC)) { |
1819 int veh_counter = 0; |
1826 int veh_counter = 0; |
1820 do { |
1827 do { |
1821 veh_counter++; |
1828 veh_counter++; |
1822 } while ((v = v->next) != NULL); |
1829 } while ((v = v->next) != NULL); |
1860 if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) { |
1867 if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) { |
1861 SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION); |
1868 SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION); |
1862 } |
1869 } |
1863 |
1870 |
1864 if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { |
1871 if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { |
1865 // this s a train car |
1872 /* this s a train car |
1866 // add this unit to the end of the train |
1873 * add this unit to the end of the train */ |
1867 DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE); |
1874 DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE); |
1868 } else { |
1875 } else { |
1869 // this is a front engine or not a train. It need orders |
1876 /* this is a front engine or not a train. It need orders */ |
1870 w_front = w; |
1877 w_front = w; |
1871 w->service_interval = v->service_interval; |
1878 w->service_interval = v->service_interval; |
1872 DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER); |
1879 DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER); |
1873 } |
1880 } |
1874 w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop |
1881 w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop |
1875 } |
1882 } |
1876 } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL); |
1883 } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL); |
1877 |
1884 |
1878 if (flags & DC_EXEC && v_front->type == VEH_TRAIN) { |
1885 if (flags & DC_EXEC && v_front->type == VEH_TRAIN) { |
1879 // for trains this needs to be the front engine due to the callback function |
1886 /* for trains this needs to be the front engine due to the callback function */ |
1880 _new_vehicle_id = w_front->index; |
1887 _new_vehicle_id = w_front->index; |
1881 } |
1888 } |
1882 |
1889 |
1883 /* Set the expense type last as refitting will make the cost go towards |
1890 /* Set the expense type last as refitting will make the cost go towards |
1884 * running costs... */ |
1891 * running costs... */ |
2251 } |
2259 } |
2252 |
2260 |
2253 |
2261 |
2254 /** Change the service interval of a vehicle |
2262 /** Change the service interval of a vehicle |
2255 * @param tile unused |
2263 * @param tile unused |
|
2264 * @param flags type of operation |
2256 * @param p1 vehicle ID that is being service-interval-changed |
2265 * @param p1 vehicle ID that is being service-interval-changed |
2257 * @param p2 new service interval |
2266 * @param p2 new service interval |
2258 */ |
2267 */ |
2259 int32 CmdChangeServiceInt(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
2268 int32 CmdChangeServiceInt(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
2260 { |
2269 { |
2347 { |
2356 { |
2348 if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR; |
2357 if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR; |
2349 |
2358 |
2350 switch (v->type) { |
2359 switch (v->type) { |
2351 case VEH_TRAIN: |
2360 case VEH_TRAIN: |
2352 if (v->u.rail.track == TRACK_BIT_DEPOT) /* We'll assume the train is facing outwards */ |
2361 if (v->u.rail.track == TRACK_BIT_DEPOT) // We'll assume the train is facing outwards |
2353 return DiagdirToDiagTrackdir(GetRailDepotDirection(v->tile)); /* Train in depot */ |
2362 return DiagdirToDiagTrackdir(GetRailDepotDirection(v->tile)); // Train in depot |
2354 |
2363 |
2355 if (v->u.rail.track == TRACK_BIT_WORMHOLE) /* train in tunnel, so just use his direction and assume a diagonal track */ |
2364 if (v->u.rail.track == TRACK_BIT_WORMHOLE) // train in tunnel, so just use his direction and assume a diagonal track |
2356 return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
2365 return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
2357 |
2366 |
2358 return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction); |
2367 return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction); |
2359 |
2368 |
2360 case VEH_SHIP: |
2369 case VEH_SHIP: |
2361 if (IsShipInDepot(v)) |
2370 if (IsShipInDepot(v)) |
2362 /* We'll assume the ship is facing outwards */ |
2371 // We'll assume the ship is facing outwards |
2363 return DiagdirToDiagTrackdir(GetShipDepotDirection(v->tile)); |
2372 return DiagdirToDiagTrackdir(GetShipDepotDirection(v->tile)); |
2364 |
2373 |
2365 return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction); |
2374 return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction); |
2366 |
2375 |
2367 case VEH_ROAD: |
2376 case VEH_ROAD: |
2368 if (IsRoadVehInDepot(v)) /* We'll assume the road vehicle is facing outwards */ |
2377 if (IsRoadVehInDepot(v)) // We'll assume the road vehicle is facing outwards |
2369 return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile)); |
2378 return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile)); |
2370 |
2379 |
2371 if (IsStandardRoadStopTile(v->tile)) /* We'll assume the road vehicle is facing outwards */ |
2380 if (IsStandardRoadStopTile(v->tile)) // We'll assume the road vehicle is facing outwards |
2372 return DiagdirToDiagTrackdir(GetRoadStopDir(v->tile)); /* Road vehicle in a station */ |
2381 return DiagdirToDiagTrackdir(GetRoadStopDir(v->tile)); // Road vehicle in a station |
2373 |
2382 |
2374 if (IsDriveThroughStopTile(v->tile)) return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
2383 if (IsDriveThroughStopTile(v->tile)) return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
2375 |
2384 |
2376 /* If vehicle's state is a valid track direction (vehicle is not turning around) return it */ |
2385 /* If vehicle's state is a valid track direction (vehicle is not turning around) return it */ |
2377 if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state; |
2386 if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state; |
2420 gmax = max; |
2429 gmax = max; |
2421 free(cache); |
2430 free(cache); |
2422 cache = MallocT<bool>(max + 1); |
2431 cache = MallocT<bool>(max + 1); |
2423 } |
2432 } |
2424 |
2433 |
2425 // Clear the cache |
2434 /* Clear the cache */ |
2426 memset(cache, 0, (max + 1) * sizeof(*cache)); |
2435 memset(cache, 0, (max + 1) * sizeof(*cache)); |
2427 |
2436 |
2428 // Fill the cache |
2437 /* Fill the cache */ |
2429 FOR_ALL_VEHICLES(u) { |
2438 FOR_ALL_VEHICLES(u) { |
2430 if (u->type == type && u->owner == _current_player && u->unitnumber != 0 && u->unitnumber <= max) |
2439 if (u->type == type && u->owner == _current_player && u->unitnumber != 0 && u->unitnumber <= max) |
2431 cache[u->unitnumber] = true; |
2440 cache[u->unitnumber] = true; |
2432 } |
2441 } |
2433 |
2442 |
2434 // Find the first unused unit number |
2443 /* Find the first unused unit number */ |
2435 for (unit = 1; unit <= max; unit++) { |
2444 for (unit = 1; unit <= max; unit++) { |
2436 if (!cache[unit]) break; |
2445 if (!cache[unit]) break; |
2437 } |
2446 } |
2438 |
2447 |
2439 return unit; |
2448 return unit; |
2560 } |
2569 } |
2561 |
2570 |
2562 return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v); |
2571 return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v); |
2563 } |
2572 } |
2564 |
2573 |
2565 // Save and load of vehicles |
2574 /** Save and load of vehicles */ |
2566 extern const SaveLoad _common_veh_desc[] = { |
2575 extern const SaveLoad _common_veh_desc[] = { |
2567 SLE_VAR(Vehicle, subtype, SLE_UINT8), |
2576 SLE_VAR(Vehicle, subtype, SLE_UINT8), |
2568 |
2577 |
2569 SLE_REF(Vehicle, next, REF_VEHICLE_OLD), |
2578 SLE_REF(Vehicle, next, REF_VEHICLE_OLD), |
2570 SLE_VAR(Vehicle, string_id, SLE_STRINGID), |
2579 SLE_VAR(Vehicle, string_id, SLE_STRINGID), |
2665 SLE_VAR(Vehicle, waiting_triggers, SLE_UINT8), |
2674 SLE_VAR(Vehicle, waiting_triggers, SLE_UINT8), |
2666 |
2675 |
2667 SLE_REF(Vehicle, next_shared, REF_VEHICLE), |
2676 SLE_REF(Vehicle, next_shared, REF_VEHICLE), |
2668 SLE_REF(Vehicle, prev_shared, REF_VEHICLE), |
2677 SLE_REF(Vehicle, prev_shared, REF_VEHICLE), |
2669 |
2678 |
2670 // reserve extra space in savegame here. (currently 10 bytes) |
2679 /* reserve extra space in savegame here. (currently 10 bytes) */ |
2671 SLE_CONDNULL(10, 2, SL_MAX_VERSION), |
2680 SLE_CONDNULL(10, 2, SL_MAX_VERSION), |
2672 |
2681 |
2673 SLE_END() |
2682 SLE_END() |
2674 }; |
2683 }; |
2675 |
2684 |
2684 |
2693 |
2685 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, flags), SLE_UINT8, 2, SL_MAX_VERSION), |
2694 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, flags), SLE_UINT8, 2, SL_MAX_VERSION), |
2686 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, days_since_order_progr), SLE_UINT16, 2, SL_MAX_VERSION), |
2695 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, days_since_order_progr), SLE_UINT16, 2, SL_MAX_VERSION), |
2687 |
2696 |
2688 SLE_CONDNULL(2, 2, 19), |
2697 SLE_CONDNULL(2, 2, 19), |
2689 // reserve extra space in savegame here. (currently 11 bytes) |
2698 /* reserve extra space in savegame here. (currently 11 bytes) */ |
2690 SLE_CONDNULL(11, 2, SL_MAX_VERSION), |
2699 SLE_CONDNULL(11, 2, SL_MAX_VERSION), |
2691 |
2700 |
2692 SLE_END() |
2701 SLE_END() |
2693 }; |
2702 }; |
2694 |
2703 |
2704 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, reverse_ctr), SLE_UINT8), |
2713 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, reverse_ctr), SLE_UINT8), |
2705 |
2714 |
2706 SLE_CONDREFX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot), REF_ROADSTOPS, 6, SL_MAX_VERSION), |
2715 SLE_CONDREFX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot), REF_ROADSTOPS, 6, SL_MAX_VERSION), |
2707 SLE_CONDNULL(1, 6, SL_MAX_VERSION), |
2716 SLE_CONDNULL(1, 6, SL_MAX_VERSION), |
2708 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot_age), SLE_UINT8, 6, SL_MAX_VERSION), |
2717 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot_age), SLE_UINT8, 6, SL_MAX_VERSION), |
2709 // reserve extra space in savegame here. (currently 16 bytes) |
2718 /* reserve extra space in savegame here. (currently 16 bytes) */ |
2710 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2719 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2711 |
2720 |
2712 SLE_END() |
2721 SLE_END() |
2713 }; |
2722 }; |
2714 |
2723 |
2715 static const SaveLoad _ship_desc[] = { |
2724 static const SaveLoad _ship_desc[] = { |
2716 SLE_WRITEBYTE(Vehicle, type, VEH_SHIP, 2), // Ship type. VEH_SHIP in mem, 2 in file. |
2725 SLE_WRITEBYTE(Vehicle, type, VEH_SHIP, 2), // Ship type. VEH_SHIP in mem, 2 in file. |
2717 SLE_INCLUDEX(0, INC_VEHICLE_COMMON), |
2726 SLE_INCLUDEX(0, INC_VEHICLE_COMMON), |
2718 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleShip, state), SLE_UINT8), |
2727 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleShip, state), SLE_UINT8), |
2719 |
2728 |
2720 // reserve extra space in savegame here. (currently 16 bytes) |
2729 /* reserve extra space in savegame here. (currently 16 bytes) */ |
2721 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2730 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2722 |
2731 |
2723 SLE_END() |
2732 SLE_END() |
2724 }; |
2733 }; |
2725 |
2734 |
2734 |
2743 |
2735 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, state), SLE_UINT8), |
2744 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, state), SLE_UINT8), |
2736 |
2745 |
2737 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, previous_pos), SLE_UINT8, 2, SL_MAX_VERSION), |
2746 SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, previous_pos), SLE_UINT8, 2, SL_MAX_VERSION), |
2738 |
2747 |
2739 // reserve extra space in savegame here. (currently 15 bytes) |
2748 /* reserve extra space in savegame here. (currently 15 bytes) */ |
2740 SLE_CONDNULL(15, 2, SL_MAX_VERSION), |
2749 SLE_CONDNULL(15, 2, SL_MAX_VERSION), |
2741 |
2750 |
2742 SLE_END() |
2751 SLE_END() |
2743 }; |
2752 }; |
2744 |
2753 |
2766 SLE_VAR(Vehicle, vehstatus, SLE_UINT8), |
2775 SLE_VAR(Vehicle, vehstatus, SLE_UINT8), |
2767 |
2776 |
2768 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk0), SLE_UINT16), |
2777 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk0), SLE_UINT16), |
2769 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk2), SLE_UINT8), |
2778 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk2), SLE_UINT8), |
2770 |
2779 |
2771 // reserve extra space in savegame here. (currently 16 bytes) |
2780 /* reserve extra space in savegame here. (currently 16 bytes) */ |
2772 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2781 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2773 |
2782 |
2774 SLE_END() |
2783 SLE_END() |
2775 }; |
2784 }; |
2776 |
2785 |
2808 SLE_VAR(Vehicle, tick_counter, SLE_UINT8), |
2817 SLE_VAR(Vehicle, tick_counter, SLE_UINT8), |
2809 |
2818 |
2810 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, image_override), SLE_UINT16), |
2819 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, image_override), SLE_UINT16), |
2811 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, unk2), SLE_UINT16), |
2820 SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, unk2), SLE_UINT16), |
2812 |
2821 |
2813 // reserve extra space in savegame here. (currently 16 bytes) |
2822 /* reserve extra space in savegame here. (currently 16 bytes) */ |
2814 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2823 SLE_CONDNULL(16, 2, SL_MAX_VERSION), |
2815 |
2824 |
2816 SLE_END() |
2825 SLE_END() |
2817 }; |
2826 }; |
2818 |
2827 |
2824 _aircraft_desc, |
2833 _aircraft_desc, |
2825 _special_desc, |
2834 _special_desc, |
2826 _disaster_desc, |
2835 _disaster_desc, |
2827 }; |
2836 }; |
2828 |
2837 |
2829 // Will be called when the vehicles need to be saved. |
2838 /** Will be called when the vehicles need to be saved. */ |
2830 static void Save_VEHS() |
2839 static void Save_VEHS() |
2831 { |
2840 { |
2832 Vehicle *v; |
2841 Vehicle *v; |
2833 // Write the vehicles |
2842 /* Write the vehicles */ |
2834 FOR_ALL_VEHICLES(v) { |
2843 FOR_ALL_VEHICLES(v) { |
2835 SlSetArrayIndex(v->index); |
2844 SlSetArrayIndex(v->index); |
2836 SlObject(v, (SaveLoad*)_veh_descs[v->type]); |
2845 SlObject(v, (SaveLoad*)_veh_descs[v->type]); |
2837 } |
2846 } |
2838 } |
2847 } |
2839 |
2848 |
2840 // Will be called when vehicles need to be loaded. |
2849 /** Will be called when vehicles need to be loaded. */ |
2841 static void Load_VEHS() |
2850 static void Load_VEHS() |
2842 { |
2851 { |
2843 int index; |
2852 int index; |
2844 Vehicle *v; |
2853 Vehicle *v; |
2845 |
2854 |