589 * other artic parts. */ |
589 * other artic parts. */ |
590 if ((this->type == VEH_TRAIN && EngineHasArticPart(this)) || (this->type == VEH_ROAD && RoadVehHasArticPart(this))) { |
590 if ((this->type == VEH_TRAIN && EngineHasArticPart(this)) || (this->type == VEH_ROAD && RoadVehHasArticPart(this))) { |
591 delete this->Next(); |
591 delete this->Next(); |
592 } |
592 } |
593 |
593 |
594 Window *w = FindWindowById(WC_MAIN_WINDOW, 0); |
594 extern void StopGlobalFollowVehicle(const Vehicle *v); |
595 if (w != NULL && w->viewport->follow_vehicle == this->index) { |
595 StopGlobalFollowVehicle(this); |
596 ScrollMainWindowTo(this->x_pos, this->y_pos, true); // lock the main view on the vehicle's last position |
|
597 w->viewport->follow_vehicle = INVALID_VEHICLE; |
|
598 } |
|
599 } |
596 } |
600 |
597 |
601 Vehicle::~Vehicle() |
598 Vehicle::~Vehicle() |
602 { |
599 { |
603 free(this->name); |
600 free(this->name); |
951 /* Do not show getting-old message if autorenew is active (and it can replace the vehicle) */ |
948 /* Do not show getting-old message if autorenew is active (and it can replace the vehicle) */ |
952 if (GetPlayer(v->owner)->engine_renew && GetEngine(v->engine_type)->player_avail != 0) return; |
949 if (GetPlayer(v->owner)->engine_renew && GetEngine(v->engine_type)->player_avail != 0) return; |
953 |
950 |
954 SetDParam(0, _vehicle_type_names[v->type]); |
951 SetDParam(0, _vehicle_type_names[v->type]); |
955 SetDParam(1, v->unitnumber); |
952 SetDParam(1, v->unitnumber); |
956 AddNewsItem(msg, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0); |
953 AddNewsItem(msg, NS_ADVICE, v->index, 0); |
957 } |
954 } |
958 |
955 |
959 void AgeVehicle(Vehicle *v) |
956 void AgeVehicle(Vehicle *v) |
960 { |
957 { |
961 if (v->age < 65535) v->age++; |
958 if (v->age < 65535) v->age++; |
1551 * Calculates how full a vehicle is. |
1548 * Calculates how full a vehicle is. |
1552 * @param v The Vehicle to check. For trains, use the first engine. |
1549 * @param v The Vehicle to check. For trains, use the first engine. |
1553 * @param color The string to show depending on if we are unloading or loading |
1550 * @param color The string to show depending on if we are unloading or loading |
1554 * @return A percentage of how full the Vehicle is. |
1551 * @return A percentage of how full the Vehicle is. |
1555 */ |
1552 */ |
1556 uint8 CalcPercentVehicleFilled(Vehicle *v, StringID *color) |
1553 uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *color) |
1557 { |
1554 { |
1558 int count = 0; |
1555 int count = 0; |
1559 int max = 0; |
1556 int max = 0; |
1560 int cars = 0; |
1557 int cars = 0; |
1561 int unloading = 0; |
1558 int unloading = 0; |
1650 v->leave_depot_instantly = false; // We ensure that the vehicle stays in the depot |
1647 v->leave_depot_instantly = false; // We ensure that the vehicle stays in the depot |
1651 if (v->owner == _local_player) { |
1648 if (v->owner == _local_player) { |
1652 /* Notify the user that we stopped the vehicle */ |
1649 /* Notify the user that we stopped the vehicle */ |
1653 SetDParam(0, _vehicle_type_names[v->type]); |
1650 SetDParam(0, _vehicle_type_names[v->type]); |
1654 SetDParam(1, v->unitnumber); |
1651 SetDParam(1, v->unitnumber); |
1655 AddNewsItem(STR_ORDER_REFIT_FAILED, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0); |
1652 AddNewsItem(STR_ORDER_REFIT_FAILED, NS_ADVICE, v->index, 0); |
1656 } |
1653 } |
1657 } else if (v->owner == _local_player && cost.GetCost() != 0) { |
1654 } else if (v->owner == _local_player && cost.GetCost() != 0) { |
1658 ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost()); |
1655 ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost()); |
1659 } |
1656 } |
1660 } |
1657 } |
1676 case VEH_AIRCRAFT: string = STR_A014_AIRCRAFT_IS_WAITING_IN; break; |
1673 case VEH_AIRCRAFT: string = STR_A014_AIRCRAFT_IS_WAITING_IN; break; |
1677 default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning |
1674 default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning |
1678 } |
1675 } |
1679 |
1676 |
1680 SetDParam(0, v->unitnumber); |
1677 SetDParam(0, v->unitnumber); |
1681 AddNewsItem(string, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0); |
1678 AddNewsItem(string, NS_ADVICE, v->index, 0); |
1682 } |
1679 } |
1683 AI_Event(v->owner, new AIEventVehicleWaitingInDepot(v->index)); |
1680 AI_Event(v->owner, new AIEventVehicleWaitingInDepot(v->index)); |
1684 } |
1681 } |
1685 } |
1682 } |
1686 } |
1683 } |
1736 if (!IsUniqueVehicleName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE); |
1733 if (!IsUniqueVehicleName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE); |
1737 |
1734 |
1738 if (flags & DC_EXEC) { |
1735 if (flags & DC_EXEC) { |
1739 free(v->name); |
1736 free(v->name); |
1740 v->name = strdup(_cmd_text); |
1737 v->name = strdup(_cmd_text); |
1741 ResortVehicleLists(); |
1738 InvalidateWindowClassesData(WC_TRAINS_LIST, 1); |
1742 MarkWholeScreenDirty(); |
1739 MarkWholeScreenDirty(); |
1743 } |
1740 } |
1744 |
1741 |
1745 return CommandCost(); |
1742 return CommandCost(); |
1746 } |
1743 } |
1867 if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR; |
1864 if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR; |
1868 |
1865 |
1869 switch (v->type) { |
1866 switch (v->type) { |
1870 case VEH_TRAIN: |
1867 case VEH_TRAIN: |
1871 if (v->u.rail.track == TRACK_BIT_DEPOT) // We'll assume the train is facing outwards |
1868 if (v->u.rail.track == TRACK_BIT_DEPOT) // We'll assume the train is facing outwards |
1872 return DiagdirToDiagTrackdir(GetRailDepotDirection(v->tile)); // Train in depot |
1869 return DiagDirToDiagTrackdir(GetRailDepotDirection(v->tile)); // Train in depot |
1873 |
1870 |
1874 if (v->u.rail.track == TRACK_BIT_WORMHOLE) // train in tunnel, so just use his direction and assume a diagonal track |
1871 if (v->u.rail.track == TRACK_BIT_WORMHOLE) // train in tunnel, so just use his direction and assume a diagonal track |
1875 return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
1872 return DiagDirToDiagTrackdir(DirToDiagDir(v->direction)); |
1876 |
1873 |
1877 return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction); |
1874 return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction); |
1878 |
1875 |
1879 case VEH_SHIP: |
1876 case VEH_SHIP: |
1880 if (v->IsInDepot()) |
1877 if (v->IsInDepot()) |
1881 // We'll assume the ship is facing outwards |
1878 // We'll assume the ship is facing outwards |
1882 return DiagdirToDiagTrackdir(GetShipDepotDirection(v->tile)); |
1879 return DiagDirToDiagTrackdir(GetShipDepotDirection(v->tile)); |
1883 |
1880 |
1884 return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction); |
1881 return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction); |
1885 |
1882 |
1886 case VEH_ROAD: |
1883 case VEH_ROAD: |
1887 if (v->IsInDepot()) // We'll assume the road vehicle is facing outwards |
1884 if (v->IsInDepot()) // We'll assume the road vehicle is facing outwards |
1888 return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile)); |
1885 return DiagDirToDiagTrackdir(GetRoadDepotDirection(v->tile)); |
1889 |
1886 |
1890 if (IsStandardRoadStopTile(v->tile)) // We'll assume the road vehicle is facing outwards |
1887 if (IsStandardRoadStopTile(v->tile)) // We'll assume the road vehicle is facing outwards |
1891 return DiagdirToDiagTrackdir(GetRoadStopDir(v->tile)); // Road vehicle in a station |
1888 return DiagDirToDiagTrackdir(GetRoadStopDir(v->tile)); // Road vehicle in a station |
1892 |
1889 |
1893 if (IsDriveThroughStopTile(v->tile)) return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
1890 if (IsDriveThroughStopTile(v->tile)) return DiagDirToDiagTrackdir(DirToDiagDir(v->direction)); |
1894 |
1891 |
1895 /* If vehicle's state is a valid track direction (vehicle is not turning around) return it */ |
1892 /* If vehicle's state is a valid track direction (vehicle is not turning around) return it */ |
1896 if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state; |
1893 if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state; |
1897 |
1894 |
1898 /* Vehicle is turning around, get the direction from vehicle's direction */ |
1895 /* Vehicle is turning around, get the direction from vehicle's direction */ |
1899 return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); |
1896 return DiagDirToDiagTrackdir(DirToDiagDir(v->direction)); |
1900 |
1897 |
1901 /* case VEH_AIRCRAFT: case VEH_EFFECT: case VEH_DISASTER: */ |
1898 /* case VEH_AIRCRAFT: case VEH_EFFECT: case VEH_DISASTER: */ |
1902 default: return INVALID_TRACKDIR; |
1899 default: return INVALID_TRACKDIR; |
1903 } |
1900 } |
1904 } |
1901 } |
2757 /* The vehicle should be free since we are restoring something we just sold. */ |
2754 /* The vehicle should be free since we are restoring something we just sold. */ |
2758 assert(!dest->IsValid()); |
2755 assert(!dest->IsValid()); |
2759 memcpy(dest, backup, sizeof(Vehicle)); |
2756 memcpy(dest, backup, sizeof(Vehicle)); |
2760 |
2757 |
2761 /* We decreased the engine count when we sold the engines so we will increase it again. */ |
2758 /* We decreased the engine count when we sold the engines so we will increase it again. */ |
2762 if (IsEngineCountable(backup)) p->num_engines[backup->engine_type]++; |
2759 if (IsEngineCountable(backup)) { |
|
2760 p->num_engines[backup->engine_type]++; |
|
2761 if (IsValidGroupID(backup->group_id)) GetGroup(backup->group_id)->num_engines[backup->engine_type]++; |
|
2762 if (backup->IsPrimaryVehicle()) IncreaseGroupNumVehicle(backup->group_id); |
|
2763 } |
2763 |
2764 |
2764 /* Update hash. */ |
2765 /* Update hash. */ |
2765 Vehicle *dummy = dest; |
2766 Vehicle *dummy = dest; |
2766 dest->old_new_hash = &dummy; |
2767 dest->old_new_hash = &dummy; |
2767 dest->left_coord = INVALID_COORD; |
2768 dest->left_coord = INVALID_COORD; |
2804 */ |
2805 */ |
2805 Vehicle *BackuppedVehicle::Restore(Vehicle *v, Player *p) |
2806 Vehicle *BackuppedVehicle::Restore(Vehicle *v, Player *p) |
2806 { |
2807 { |
2807 if (!ContainsBackup()) return v; |
2808 if (!ContainsBackup()) return v; |
2808 if (v != NULL) { |
2809 if (v != NULL) { |
2809 ChangeVehicleViewWindow(v, INVALID_VEHICLE); |
2810 ChangeVehicleViewWindow(v->index, INVALID_VEHICLE); |
2810 DoCommand(0, v->index, 1, DC_EXEC, GetCmdSellVeh(v)); |
2811 DoCommand(0, v->index, 1, DC_EXEC, GetCmdSellVeh(v)); |
2811 } |
2812 } |
2812 v = RestoreBackupVehicle(this->vehicles, p); |
2813 v = RestoreBackupVehicle(this->vehicles, p); |
2813 ChangeVehicleViewWindow(INVALID_VEHICLE, v); |
2814 ChangeVehicleViewWindow(INVALID_VEHICLE, v->index); |
2814 if (orders != NULL) RestoreVehicleOrdersBruteForce(v, orders); |
2815 if (orders != NULL) RestoreVehicleOrdersBruteForce(v, orders); |
2815 if (economy != NULL) economy->Restore(); |
2816 if (economy != NULL) economy->Restore(); |
2816 /* If we stored cargo as well then we should restore it. */ |
2817 /* If we stored cargo as well then we should restore it. */ |
2817 cargo_packets->RestoreBackup(); |
2818 cargo_packets->RestoreBackup(); |
2818 return v; |
2819 return v; |