diff --git a/README.md b/README.md
index 8b67720b..9b80a6a2 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,17 @@ A work-in-progress modification for **Cities: Skylines** to add additional traff
User manual: http://www.viathinksoft.de/tmpe
# Changelog
+1.8.4, 12/11/2016
+- New feature: "Stay on lane": By pressing Shift + S in the Lane Connector tool you can now link connected lanes such that vehicles are not allowed to change lanes at this point. Press Shift + S again to restrict "stay on lane" to either road direction.
+- U-turns are now only allowed to be performed from the innermost lane
+- TMPE now detects if the number of spawned vehicles is reaching its limit (16384). If so, spawning of service/emergency vehicles is prioritized over spawning other vehicles.
+- Bugfix: Bicycles cannot change from bicycle lanes to pedestrian lanes
+- Bugfix: Travel probabilities set in the "Citizen Lifecycle Rebalance v2.1" mod are not obeyed (thanks to @informmanuel, @shaundoddmusic for reporting this issue)
+- Bugfix: Number of tourists seems to drop when activating the mod (statistics were not updated, thanks to @hpp7117, @wjrohn for reporting this issue)
+- Bugfix: When loading a second savegame a second main menu button is displayed (thanks to @Cpt. Whitepaw for reporting this issue)
+- Bugfix: While path-finding is in progress vehicles do "bungee-jumping" on the current segment (thanks to @mxolsenx, @Howzitworld for reporting this issue)
+- Bugfix: Cims leaving the city search for parking spaces near the outside connection which is obviously not required
+
1.8.3, 12/4/2016
- Bugfix: Despite having the Parking AI activated, cims sometimes still spawn pocket cars.
- Bugfix: When the Parking AI is active, bicycle lanes are not used (thanks to @informmanuel for reporting this issue)
diff --git a/TLM/GlobalConfigGenerator/GlobalConfigGenerator.csproj b/TLM/GlobalConfigGenerator/GlobalConfigGenerator.csproj
index 1f5cb34a..cea07e3b 100644
--- a/TLM/GlobalConfigGenerator/GlobalConfigGenerator.csproj
+++ b/TLM/GlobalConfigGenerator/GlobalConfigGenerator.csproj
@@ -32,6 +32,16 @@
prompt
4
+
+ bin\QueuedStats\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
diff --git a/TLM/SpiralLoopTest/SpiralLoopTest.csproj b/TLM/SpiralLoopTest/SpiralLoopTest.csproj
index 41d34eca..a1ead434 100644
--- a/TLM/SpiralLoopTest/SpiralLoopTest.csproj
+++ b/TLM/SpiralLoopTest/SpiralLoopTest.csproj
@@ -32,6 +32,16 @@
prompt
4
+
+ bin\QueuedStats\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
diff --git a/TLM/TLM.sln b/TLM/TLM.sln
index a2833dce..82f852c2 100644
--- a/TLM/TLM.sln
+++ b/TLM/TLM.sln
@@ -23,19 +23,26 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ QueuedStats|Any CPU = QueuedStats|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7422AE58-8B0A-401C-9404-F4A438EFFE10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7422AE58-8B0A-401C-9404-F4A438EFFE10}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7422AE58-8B0A-401C-9404-F4A438EFFE10}.QueuedStats|Any CPU.ActiveCfg = QueuedStats|Any CPU
+ {7422AE58-8B0A-401C-9404-F4A438EFFE10}.QueuedStats|Any CPU.Build.0 = QueuedStats|Any CPU
{7422AE58-8B0A-401C-9404-F4A438EFFE10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7422AE58-8B0A-401C-9404-F4A438EFFE10}.Release|Any CPU.Build.0 = Release|Any CPU
{48D1868B-EE81-4339-95C9-4C5EADEB9ECA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48D1868B-EE81-4339-95C9-4C5EADEB9ECA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {48D1868B-EE81-4339-95C9-4C5EADEB9ECA}.QueuedStats|Any CPU.ActiveCfg = QueuedStats|Any CPU
+ {48D1868B-EE81-4339-95C9-4C5EADEB9ECA}.QueuedStats|Any CPU.Build.0 = QueuedStats|Any CPU
{48D1868B-EE81-4339-95C9-4C5EADEB9ECA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48D1868B-EE81-4339-95C9-4C5EADEB9ECA}.Release|Any CPU.Build.0 = Release|Any CPU
{615EF202-3E13-4A15-A82F-594D90CD0ECD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{615EF202-3E13-4A15-A82F-594D90CD0ECD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {615EF202-3E13-4A15-A82F-594D90CD0ECD}.QueuedStats|Any CPU.ActiveCfg = QueuedStats|Any CPU
+ {615EF202-3E13-4A15-A82F-594D90CD0ECD}.QueuedStats|Any CPU.Build.0 = QueuedStats|Any CPU
{615EF202-3E13-4A15-A82F-594D90CD0ECD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{615EF202-3E13-4A15-A82F-594D90CD0ECD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
diff --git a/TLM/TLM/Custom/AI/CustomCarAI.cs b/TLM/TLM/Custom/AI/CustomCarAI.cs
index 7ce0806f..5ab6e721 100644
--- a/TLM/TLM/Custom/AI/CustomCarAI.cs
+++ b/TLM/TLM/Custom/AI/CustomCarAI.cs
@@ -14,6 +14,7 @@
using TrafficManager.State;
using TrafficManager.Manager;
using TrafficManager.Traffic;
+using static TrafficManager.Traffic.ExtCitizenInstance;
namespace TrafficManager.Custom.AI {
public class CustomCarAI : CarAI { // TODO inherit from VehicleAI (in order to keep the correct references to `base`)
@@ -40,10 +41,33 @@ public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vect
}*/
#endif
- if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) {
+ // NON-STOCK CODE START
+ VehicleState state = null;
+ ExtCitizenInstance driverExtInstance = null;
+ bool prohibitPocketCars = Options.prohibitPocketCars;
+ if (prohibitPocketCars) {
+ state = VehicleStateManager.Instance._GetVehicleState(vehicleData.GetFirstVehicle(vehicleId));
+ if (state.VehicleType == ExtVehicleType.PassengerCar) {
+ driverExtInstance = state.GetDriverExtInstance();
+ if (driverExtInstance == null) {
+ prohibitPocketCars = false;
+ } else {
+ driverExtInstance.UpdateReturnPathState();
+ }
+ } else {
+ prohibitPocketCars = false;
+ }
+ }
+ // NON-STOCK CODE END
+
+ if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0 &&
+ (! prohibitPocketCars || driverExtInstance.ReturnPathState != ExtCitizenInstance.ExtPathState.Calculating)) {
PathManager pathManager = Singleton.instance;
byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags;
+ bool pathFindFailed = (pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0; // path == 0: non-stock code!
+ bool pathFindSucceeded = (pathFindFlags & PathUnit.FLAG_READY) != 0;
+
#if USEPATHWAITCOUNTER
if ((pathFindFlags & (PathUnit.FLAG_READY | PathUnit.FLAG_FAILED)) != 0) {
VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleId);
@@ -51,13 +75,32 @@ public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vect
}
#endif
- if ((pathFindFlags & PathUnit.FLAG_READY) != 0) {
+ if (prohibitPocketCars) {
+ if (driverExtInstance.ReturnPathState == ExtPathState.Failed) {
+#if DEBUG
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"CustomCarAI.CustomSimulationStep: Return path {driverExtInstance.ReturnPathId} FAILED. Forcing path-finding to fail.");
+#endif
+ pathFindSucceeded = false;
+ pathFindFailed = true;
+ }
+
+ driverExtInstance.ReleaseReturnPath();
+
+ if (pathFindSucceeded) {
+ CustomPassengerCarAI.OnPathFindSuccess(vehicleId, ref vehicleData, driverExtInstance);
+ } else if (pathFindFailed) {
+ CustomPassengerCarAI.OnPathFindFailure(driverExtInstance, vehicleId);
+ }
+ }
+
+ if (pathFindSucceeded) {
vehicleData.m_pathPositionIndex = 255;
vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
vehicleData.m_flags &= ~Vehicle.Flags.Arriving;
this.PathfindSuccess(vehicleId, ref vehicleData);
this.TrySpawn(vehicleId, ref vehicleData);
- } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { // path == 0: non-stock code!
+ } else if (pathFindFailed) {
vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath;
Singleton.instance.ReleasePath(vehicleData.m_path);
vehicleData.m_path = 0u;
@@ -106,13 +149,13 @@ public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vect
}
this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics);
if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) {
- VehicleManager instance2 = Singleton.instance;
+ VehicleManager vehManager = Singleton.instance;
ushort num = vehicleData.m_trailingVehicle;
int num2 = 0;
while (num != 0) {
- ushort trailingVehicle = instance2.m_vehicles.m_buffer[(int)num].m_trailingVehicle;
- VehicleInfo info = instance2.m_vehicles.m_buffer[(int)num].Info;
- info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics);
+ ushort trailingVehicle = vehManager.m_vehicles.m_buffer[(int)num].m_trailingVehicle;
+ VehicleInfo info = vehManager.m_vehicles.m_buffer[(int)num].Info;
+ info.m_vehicleAI.SimulationStep(num, ref vehManager.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics);
num = trailingVehicle;
if (++num2 > 16384) {
CODebugBase.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
diff --git a/TLM/TLM/Custom/AI/CustomCitizenAI.cs b/TLM/TLM/Custom/AI/CustomCitizenAI.cs
index 6c241a5a..8cc67245 100644
--- a/TLM/TLM/Custom/AI/CustomCitizenAI.cs
+++ b/TLM/TLM/Custom/AI/CustomCitizenAI.cs
@@ -224,8 +224,8 @@ public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenDa
ExtCitizenInstance extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);
ushort homeId = Singleton.instance.m_citizens.m_buffer[citizenData.m_citizen].m_homeBuilding;
- // if the citizen is a resident and is starting its journey: find a suitable parking space near the target
- if (extInstance.PathMode == ExtCitizenInstance.ExtPathMode.ParkedCarReached) {
+ // if the citizen is a resident starting its journey and the target is not an outside connection: find a suitable parking space near the target
+ if (extInstance.PathMode == ExtCitizenInstance.ExtPathMode.ParkedCarReached && (citizenData.m_targetBuilding == 0 || (Singleton.instance.m_buildings.m_buffer[citizenData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None)) {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
Log._Debug($"CustomCitizenAI.CustomStartPathFind: Finding parking space at target for citizen instance {instanceID}. CurrentDepartureMode={extInstance.PathMode} parkedVehicleId={parkedVehicleId}");
diff --git a/TLM/TLM/Custom/AI/CustomHumanAI.cs b/TLM/TLM/Custom/AI/CustomHumanAI.cs
index 5e8e08ba..b269d373 100644
--- a/TLM/TLM/Custom/AI/CustomHumanAI.cs
+++ b/TLM/TLM/Custom/AI/CustomHumanAI.cs
@@ -25,28 +25,26 @@ public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instance
}
// NON-STOCK CODE START
+ ExtCitizenInstance extInstance = null;
if (Options.prohibitPocketCars) {
- ExtCitizenInstance extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);
+ // query the state of the return path
+ extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);
extInstance.UpdateReturnPathState();
}
// NON-STOCK CODE END
- if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None) {
+ if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None
+ && (!Options.prohibitPocketCars || extInstance.ReturnPathState != ExtPathState.Calculating)) {
PathManager pathManager = Singleton.instance;
byte pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags;
// NON-STOCK CODE START
- bool pathFindFailed = (pathFindFlags & PathUnit.FLAG_FAILED) != 0;
+ bool pathFindFailed = (pathFindFlags & PathUnit.FLAG_FAILED) != 0 || instanceData.m_path == 0;
bool pathFindSucceeded = (pathFindFlags & PathUnit.FLAG_READY) != 0;
bool handleSuccess = true;
if (Options.prohibitPocketCars) {
- ExtCitizenInstance extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);
-
- if (extInstance.ReturnPathState == ExtPathState.Calculating) {
- // wait for the return path being calculated
- return;
- } else if (extInstance.ReturnPathState == ExtPathState.Failed) {
+ if (extInstance.ReturnPathState == ExtPathState.Failed) {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
Log._Debug($"CustomPassengerCarAI.CustomSimulationStep: Return path {extInstance.ReturnPathId} FAILED. Forcing path-finding to fail.");
@@ -55,8 +53,8 @@ public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instance
pathFindFailed = true;
}
- if (extInstance.ReturnPathState == ExtPathState.Ready || extInstance.ReturnPathState == ExtPathState.Failed)
- extInstance.ReleaseReturnPath();
+ //if (extInstance.ReturnPathState == ExtPathState.Ready || extInstance.ReturnPathState == ExtPathState.Failed)
+ extInstance.ReleaseReturnPath();
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[4] && (pathFindFailed || pathFindSucceeded)) {
@@ -165,7 +163,7 @@ public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instance
}
}
- public bool CustomArriveAtTarget(ushort instanceID, ref CitizenInstance citizenData) { // TODO stock code
+ /*public bool CustomArriveAtTarget(ushort instanceID, ref CitizenInstance citizenData) { // TODO stock code
if ((citizenData.m_flags & CitizenInstance.Flags.HangAround) != CitizenInstance.Flags.None) {
uint citizenId = citizenData.m_citizen;
if (citizenId != 0u) {
@@ -184,7 +182,7 @@ public bool CustomArriveAtTarget(ushort instanceID, ref CitizenInstance citizenD
this.ArriveAtDestination(instanceID, ref citizenData, true);
}
return true;
- }
+ }*/
internal static bool OnPathFindFailure(ushort instanceID, ref CitizenInstance instanceData, ExtCitizenInstance extInstance) {
#if DEBUG
@@ -315,7 +313,6 @@ internal static bool OnPathFindSuccess(ushort instanceID, ref CitizenInstance in
isAtOutsideConnection = (Singleton.instance.m_buildings.m_buffer[sourceBuildingId].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None;// Info.m_buildingAI is OutsideConnectionAI;
if (isAtOutsideConnection && (instanceData.GetLastFramePosition() - Singleton.instance.m_buildings.m_buffer[sourceBuildingId].m_position).magnitude > GlobalConfig.Instance.MaxBuildingToPedestrianLaneDistance)
isAtOutsideConnection = false;
- //isAtOutsideConnection = Singleton.instance.m_buildings.m_buffer[sourceBuildingId].Info.m_buildingAI is OutsideConnectionAI;
}
#if DEBUG
@@ -335,96 +332,57 @@ internal static bool OnPathFindSuccess(ushort instanceID, ref CitizenInstance in
// try to spawn parked vehicle in the vicinity of the starting point.
VehicleInfo vehicleInfo = null;
- Citizen.AgeGroup ageGroup = CustomCitizenAI.GetAgeGroup(instanceData.Info.m_agePhase);
- if (ageGroup > Citizen.AgeGroup.Child) {
- PrefabAI ai = Singleton.instance.m_citizens.m_buffer[instanceData.m_citizen].GetCitizenInfo(instanceData.m_citizen).GetAI();
- if (ai is ResidentAI) {
- vehicleInfo = CustomResidentAI.GetVehicleInfo(instanceID, ref instanceData, true);
- } else if (ai is TouristAI) {
- vehicleInfo = CustomTouristAI.GetVehicleInfo(instanceID, ref instanceData, true);
- }
+ if (instanceData.Info.m_agePhase > Citizen.AgePhase.Child) {
+ // get a random car info (due to the fact we are using a different randomizer, car assignment differs from the selection in ResidentAI.GetVehicleInfo/TouristAI.GetVehicleInfo method, but this should not matter since we are reusing parked vehicle infos there)
+ vehicleInfo = Singleton.instance.GetRandomVehicleInfo(ref Singleton.instance.m_randomizer, ItemClass.Service.Residential, ItemClass.SubService.ResidentialLow, ItemClass.Level.Level1);
}
if (vehicleInfo != null) {
- /*switch (vehicleInfo.GetService()) {
- case ItemClass.Service.PublicTransport:
- if (usesPublicTransport) {
- extInstance.PathMode = ExtCitizenInstance.ExtPathMode.PublicTransportToTarget;
- if (instanceData.m_sourceBuilding != 0)
- ExtBuildingManager.Instance.GetExtBuilding(instanceData.m_sourceBuilding).RemovePublicTransportDemand((uint)GlobalConfig.Instance.PublicTransportDemandUsageDecrement, true);
- if (instanceData.m_targetBuilding != 0)
- ExtBuildingManager.Instance.GetExtBuilding(instanceData.m_targetBuilding).RemovePublicTransportDemand((uint)GlobalConfig.Instance.PublicTransportDemandUsageDecrement, false);
- } else {
- extInstance.PathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToTarget;
- handleSoftPathFindFailure = true;
- return false;
- }
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomHumanAI.OnPathFindSuccess: Citizen {instanceData.m_citizen} (citizen instance {instanceID}), source building {sourceBuildingId} is using public transport/is walking. CurrentPathMode={extInstance.PathMode}");
-#endif
- return true;
- case ItemClass.Service.Residential:*/
-#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomHumanAI.OnPathFindSuccess: Citizen {instanceData.m_citizen} (citizen instance {instanceID}), source building {sourceBuildingId} is using their own passenger car. CurrentPathMode={extInstance.PathMode}");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"CustomHumanAI.OnPathFindSuccess: Citizen {instanceData.m_citizen} (citizen instance {instanceID}), source building {sourceBuildingId} is using their own passenger car. CurrentPathMode={extInstance.PathMode}");
#endif
- Vector3 currentPos;
- if (sourceBuildingId != 0) {
- currentPos = Singleton.instance.m_buildings.m_buffer[sourceBuildingId].m_position;
-#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomHumanAI.OnPathFindSuccess: Taking current position from source building {sourceBuildingId} for citizen {instanceData.m_citizen} (citizen instance {instanceID}): {currentPos} CurrentPathMode={extInstance.PathMode}");
-#endif
- } else {
- ushort currentBuildingId = Singleton.instance.m_citizens.m_buffer[instanceData.m_citizen].GetBuildingByLocation();
- if (currentBuildingId != 0) {
- currentPos = Singleton.instance.m_buildings.m_buffer[currentBuildingId].m_position;
+ // determine current position vector
+ Vector3 currentPos;
+ ushort currentBuildingId = Singleton.instance.m_citizens.m_buffer[instanceData.m_citizen].GetBuildingByLocation();
+ if (currentBuildingId != 0) {
+ currentPos = Singleton.instance.m_buildings.m_buffer[sourceBuildingId].m_position;
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomHumanAI.OnPathFindSuccess: Taking current position from current building {currentBuildingId} for citizen {instanceData.m_citizen} (citizen instance {instanceID}): {currentPos}. CurrentPathMode={extInstance.PathMode}");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"CustomHumanAI.OnPathFindSuccess: Taking current position from source building {sourceBuildingId} for citizen {instanceData.m_citizen} (citizen instance {instanceID}): {currentPos} CurrentPathMode={extInstance.PathMode}");
#endif
- } else {
- currentPos = instanceData.GetLastFramePosition();
+ } else {
+ currentPos = instanceData.GetLastFramePosition();
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomHumanAI.OnPathFindSuccess: Taking current position from last frame position for citizen {instanceData.m_citizen} (citizen instance {instanceID}): {currentPos}. Home {homeId} pos: {Singleton.instance.m_buildings.m_buffer[homeId].m_position} CurrentPathMode={extInstance.PathMode}");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"CustomHumanAI.OnPathFindSuccess: Taking current position from last frame position for citizen {instanceData.m_citizen} (citizen instance {instanceID}): {currentPos}. Home {homeId} pos: {Singleton.instance.m_buildings.m_buffer[homeId].m_position} CurrentPathMode={extInstance.PathMode}");
#endif
- }
- }
+ }
- Vector3 parkPos;
- if (CustomCitizenAI.TrySpawnParkedPassengerCar(instanceData.m_citizen, homeId, currentPos, vehicleInfo, out parkPos)) {
- parkedVehicleId = Singleton.instance.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
+ // spawn a passenger car near the current position
+ Vector3 parkPos;
+ if (CustomCitizenAI.TrySpawnParkedPassengerCar(instanceData.m_citizen, homeId, currentPos, vehicleInfo, out parkPos)) {
+ parkedVehicleId = Singleton.instance.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2] && sourceBuildingId != 0)
- Log._Debug($"Parked vehicle for citizen {instanceData.m_citizen} (instance {instanceID}) is {parkedVehicleId} now.");
+ if (GlobalConfig.Instance.DebugSwitches[2] && sourceBuildingId != 0)
+ Log._Debug($"Parked vehicle for citizen {instanceData.m_citizen} (instance {instanceID}) is {parkedVehicleId} now.");
#endif
- if (sourceBuildingId != 0) {
- ExtBuildingManager.Instance.GetExtBuilding(sourceBuildingId).ModifyParkingSpaceDemand(parkPos, GlobalConfig.Instance.MinSpawnedCarParkingSpaceDemandDelta, GlobalConfig.Instance.MaxSpawnedCarParkingSpaceDemandDelta);
- }
- } else {
+ if (sourceBuildingId != 0) {
+ ExtBuildingManager.Instance.GetExtBuilding(sourceBuildingId).ModifyParkingSpaceDemand(parkPos, GlobalConfig.Instance.MinSpawnedCarParkingSpaceDemandDelta, GlobalConfig.Instance.MaxSpawnedCarParkingSpaceDemandDelta);
+ }
+ } else {
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2]) {
- Log._Debug($">> Failed to spawn parked vehicle for citizen {instanceData.m_citizen} (citizen instance {instanceID}). homePos: {Singleton.instance.m_buildings.m_buffer[homeId].m_position}");
- }
+ if (GlobalConfig.Instance.DebugSwitches[2]) {
+ Log._Debug($">> Failed to spawn parked vehicle for citizen {instanceData.m_citizen} (citizen instance {instanceID}). homePos: {Singleton.instance.m_buildings.m_buffer[homeId].m_position}");
+ }
#endif
- if (sourceBuildingId != 0) {
- ExtBuildingManager.Instance.GetExtBuilding(sourceBuildingId).AddParkingSpaceDemand(GlobalConfig.Instance.FailedSpawnParkingSpaceDemandIncrement);
- }
- }
- /*break;
- default:
- extInstance.PathMode = ExtCitizenInstance.ExtPathMode.WalkingToTarget;
-#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomHumanAI.OnPathFindSuccess: Citizen {instanceData.m_citizen} (citizen instance {instanceID}), source building {sourceBuildingId} is using an UNHANDLED {vehicleInfo.GetService()} vehicle. CurrentPathMode={extInstance.PathMode}");
-#endif
- return true;
- }*/
+ if (sourceBuildingId != 0) {
+ ExtBuildingManager.Instance.GetExtBuilding(sourceBuildingId).AddParkingSpaceDemand(GlobalConfig.Instance.FailedSpawnParkingSpaceDemandIncrement);
+ }
+ }
} else {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2]) {
diff --git a/TLM/TLM/Custom/AI/CustomPassengerCarAI.cs b/TLM/TLM/Custom/AI/CustomPassengerCarAI.cs
index 831b1a61..2d6368ae 100644
--- a/TLM/TLM/Custom/AI/CustomPassengerCarAI.cs
+++ b/TLM/TLM/Custom/AI/CustomPassengerCarAI.cs
@@ -20,64 +20,14 @@
namespace TrafficManager.Custom.AI {
public class CustomPassengerCarAI : CarAI {
public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) {
- try {
- // NON-STOCK CODE START
- VehicleState state = null;
- ExtCitizenInstance driverExtInstance = null;
- if (Options.prohibitPocketCars) {
- state = VehicleStateManager.Instance._GetVehicleState(vehicleData.GetFirstVehicle(vehicleId));
- driverExtInstance = state.GetDriverExtInstance();
- /*if (driverExtInstance != null) {
- driverExtInstance.UpdateReturnPathState();
- }*/
- }
- // NON-STOCK CODE END
-
- if ((vehicleData.m_flags & Vehicle.Flags.Congestion) != 0 && Options.enableDespawning) {
- Singleton.instance.ReleaseVehicle(vehicleId);
- } else {
- // NON-STOCK CODE START
- if (Options.prohibitPocketCars) {
- if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) {
- if (driverExtInstance != null) {
- PathManager pathManager = Singleton.instance;
- byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags;
-
- bool pathFindFailed = (pathFindFlags & PathUnit.FLAG_FAILED) != 0;
- bool pathFindSucceeded = (pathFindFlags & PathUnit.FLAG_READY) != 0;
-
- if (driverExtInstance.ReturnPathState == ExtPathState.Calculating) {
- // wait for the return path being calculated
- return;
- } else if (driverExtInstance.ReturnPathState == ExtPathState.Failed) {
-#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomPassengerCarAI.CustomSimulationStep: Return path {driverExtInstance.ReturnPathId} FAILED. Forcing path-finding to fail.");
-#endif
- pathFindSucceeded = false;
- pathFindFailed = true;
- }
-
- if (driverExtInstance.ReturnPathState == ExtPathState.Ready || driverExtInstance.ReturnPathState == ExtPathState.Failed)
- driverExtInstance.ReleaseReturnPath();
-
- if (pathFindSucceeded) {
- OnPathFindSuccess(vehicleId, ref vehicleData, driverExtInstance);
- } else if (pathFindFailed) {
- OnPathFindFailure(driverExtInstance, vehicleId);
- }
- }
- }
- }
- // NON-STOCK CODE END
- base.SimulationStep(vehicleId, ref vehicleData, physicsLodRefPos);
- }
- } catch (Exception ex) {
- Log.Error("Error in CustomPassengerCarAI.SimulationStep: " + ex.ToString());
+ if ((vehicleData.m_flags & Vehicle.Flags.Congestion) != 0 && Options.enableDespawning) {
+ Singleton.instance.ReleaseVehicle(vehicleId);
+ } else {
+ base.SimulationStep(vehicleId, ref vehicleData, physicsLodRefPos);
}
}
- protected static void OnPathFindFailure(ExtCitizenInstance extInstance, ushort vehicleId) {
+ internal static void OnPathFindFailure(ExtCitizenInstance extInstance, ushort vehicleId) {
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
Log._Debug($"CustomHumanAI.OnPathFindFailure: Path-finding failed for vehicle {vehicleId}, citizen instance {extInstance.InstanceId}. CurrentPathMode={extInstance.PathMode}");
@@ -220,11 +170,19 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
float sqrDistA = 0f;
float sqrDistB;
+ ushort driverInstanceId = CustomPassengerCarAI.GetDriverInstance(vehicleID, ref vehicleData);
+ if (driverInstanceId == 0) {
+ return false;
+ }
+ CitizenManager citizenManager = Singleton.instance;
+ ushort targetBuildingId = citizenManager.m_instances.m_buffer[(int)driverInstanceId].m_targetBuilding;
+
// NON-STOCK CODE START
bool calculateEndPos = true;
bool allowRandomParking = true;
bool movingToParkingPos = false;
bool foundStartingPos = false;
+ bool skipQueue = false;
ExtPathType extPathType = ExtPathType.None;
if (Options.prohibitPocketCars) {
VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleData.GetFirstVehicle(vehicleID));
@@ -241,75 +199,83 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
case ExtPathMode.DrivingToTarget:
case ExtPathMode.DrivingToKnownParkPos:
case ExtPathMode.ParkingFailed:
- bool allowTourists = false;
- if (driverExtInstance.PathMode == ExtPathMode.ParkingFailed) {
- // previous parking attempt failed
- driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToAltParkPos;
- allowTourists = true;
+ if (targetBuildingId != 0 && (Singleton.instance.m_buildings.m_buffer[targetBuildingId].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None) {
+ // target is outside connection
+ driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToTarget;
+ } else {
+ if (driverExtInstance.PathMode == ExtPathMode.DrivingToTarget || driverExtInstance.PathMode == ExtPathMode.DrivingToKnownParkPos || driverExtInstance.PathMode == ExtPathMode.ParkingFailed)
+ skipQueue = true;
+
+ bool allowTourists = false;
+ if (driverExtInstance.PathMode == ExtPathMode.ParkingFailed) {
+ // previous parking attempt failed
+ driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToAltParkPos;
+ allowTourists = true;
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"Vehicle {vehicleID} shall move to an alternative parking position! CurrentPathMode={driverExtInstance.PathMode}");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"Vehicle {vehicleID} shall move to an alternative parking position! CurrentPathMode={driverExtInstance.PathMode}");
#endif
- if (driverExtInstance.ParkingPathStartPosition != null) {
- startPosA = (PathUnit.Position)driverExtInstance.ParkingPathStartPosition;
- foundStartingPos = true;
+ if (driverExtInstance.ParkingPathStartPosition != null) {
+ startPosA = (PathUnit.Position)driverExtInstance.ParkingPathStartPosition;
+ foundStartingPos = true;
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"Setting starting pos for {vehicleID} to segment={startPosA.m_segment}, laneIndex={startPosA.m_lane}, offset={startPosA.m_offset}");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"Setting starting pos for {vehicleID} to segment={startPosA.m_segment}, laneIndex={startPosA.m_lane}, offset={startPosA.m_offset}");
#endif
- }
- startBothWays = false;
+ }
+ startBothWays = false;
- if (driverExtInstance.FailedParkingAttempts > GlobalConfig.Instance.MaxParkingAttempts) {
- // maximum number of parking attempts reached
+ if (driverExtInstance.FailedParkingAttempts > GlobalConfig.Instance.MaxParkingAttempts) {
+ // maximum number of parking attempts reached
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"Reached maximum number of parking attempts for vehicle {vehicleID}! GIVING UP.");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"Reached maximum number of parking attempts for vehicle {vehicleID}! GIVING UP.");
#endif
- driverExtInstance.Reset();
+ driverExtInstance.Reset();
- // pocket car fallback
- vehicleData.m_flags |= Vehicle.Flags.Parking;
- return true;
+ // pocket car fallback
+ vehicleData.m_flags |= Vehicle.Flags.Parking;
+ return true;
+ }
+ } else {
+ driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToKnownParkPos;
}
- } else {
- driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToKnownParkPos;
- }
- ushort homeId = Singleton.instance.m_citizens.m_buffer[driverExtInstance.GetCitizenId()].m_homeBuilding;
- bool calcEndPos;
- Vector3 parkPos;
+ ushort homeId = Singleton.instance.m_citizens.m_buffer[driverExtInstance.GetCitizenId()].m_homeBuilding;
+ bool calcEndPos;
+ Vector3 parkPos;
- if (CustomCitizenAI.FindParkingSpaceForExtInstance(endPos, vehicleData.Info, driverExtInstance, homeId, vehicleID, allowTourists, out parkPos, ref endPosA, out calcEndPos)) {
- calculateEndPos = calcEndPos;
- allowRandomParking = false;
- movingToParkingPos = true;
+ if (CustomCitizenAI.FindParkingSpaceForExtInstance(endPos, vehicleData.Info, driverExtInstance, homeId, vehicleID, allowTourists, out parkPos, ref endPosA, out calcEndPos)) {
+ calculateEndPos = calcEndPos;
+ allowRandomParking = false;
+ movingToParkingPos = true;
- if (!driverExtInstance.CalculateReturnPath(parkPos, endPos)) {
+ if (!driverExtInstance.CalculateReturnPath(parkPos, endPos)) {
+#if DEBUG
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"Could not calculate return path for citizen instance {driverExtInstance.InstanceId}, vehicle {vehicleID}. Resetting instance.");
+#endif
+ driverExtInstance.Reset();
+ return false;
+ }
+ } else if (driverExtInstance.PathMode == ExtPathMode.CalculatingCarPathToAltParkPos) {
+ // no alternative parking spot found: abort
#if DEBUG
if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"Could not calculate return path for citizen instance {driverExtInstance.InstanceId}, vehicle {vehicleID}. Resetting instance.");
+ Log._Debug($"No alternative parking spot found for vehicle {vehicleID}, citizen instance {driverExtInstance.InstanceId} with CurrentPathMode={driverExtInstance.PathMode}! GIVING UP.");
#endif
driverExtInstance.Reset();
return false;
- }
- } else if (driverExtInstance.PathMode == ExtPathMode.CalculatingCarPathToAltParkPos) {
- // no alternative parking spot found: abort
-#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"No alternative parking spot found for vehicle {vehicleID}, citizen instance {driverExtInstance.InstanceId} with CurrentPathMode={driverExtInstance.PathMode}! GIVING UP.");
-#endif
- driverExtInstance.Reset();
- return false;
- } else {
- // calculate a direct path to target
+ } else {
+ // calculate a direct path to target
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"No alternative parking spot found for vehicle {vehicleID}, citizen instance {driverExtInstance.InstanceId} with CurrentPathMode={driverExtInstance.PathMode}! Setting CurrentPathMode to 'CalculatingCarPath'.");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"No alternative parking spot found for vehicle {vehicleID}, citizen instance {driverExtInstance.InstanceId} with CurrentPathMode={driverExtInstance.PathMode}! Setting CurrentPathMode to 'CalculatingCarPath'.");
#endif
- driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToTarget;
+ driverExtInstance.PathMode = ExtPathMode.CalculatingCarPathToTarget;
+ }
}
break;
}
@@ -322,17 +288,8 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
#endif
}
}
- // NON-STOCK CODE END
- VehicleInfo info = this.m_info;
- ushort driverInstance = CustomPassengerCarAI.GetDriverInstance(vehicleID, ref vehicleData);
- if (driverInstance == 0) {
- return false;
- }
- CitizenManager instance = Singleton.instance;
- CitizenInfo citizenInfo = instance.m_instances.m_buffer[(int)driverInstance].Info;
- NetInfo.LaneType laneTypes = NetInfo.LaneType.Vehicle; // NON-STOCK CODE
- // NON-STOCK CODE START
+ NetInfo.LaneType laneTypes = NetInfo.LaneType.Vehicle;
if (!movingToParkingPos) {
laneTypes |= NetInfo.LaneType.Pedestrian;
}
@@ -341,11 +298,10 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType;
bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
bool randomParking = false;
- ushort targetBuilding = instance.m_instances.m_buffer[(int)driverInstance].m_targetBuilding;
if (allowRandomParking && // NON-STOCK CODE
!movingToParkingPos &&
- targetBuilding != 0 &&
- Singleton.instance.m_buildings.m_buffer[(int)targetBuilding].Info.m_class.m_service > ItemClass.Service.Office) {
+ targetBuildingId != 0 &&
+ Singleton.instance.m_buildings.m_buffer[(int)targetBuildingId].Info.m_class.m_service > ItemClass.Service.Office) {
randomParking = true;
}
@@ -356,10 +312,10 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
// NON-STOCK CODE START
if (! foundStartingPos) {
- foundStartingPos = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out sqrDistA, out sqrDistB);
+ foundStartingPos = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out sqrDistA, out sqrDistB);
}
- bool foundEndPos = !calculateEndPos || citizenInfo.m_citizenAI.FindPathPosition(driverInstance, ref instance.m_instances.m_buffer[(int)driverInstance], endPos, Options.prohibitPocketCars ? NetInfo.LaneType.Pedestrian : (laneTypes | NetInfo.LaneType.Pedestrian), vehicleType, undergroundTarget, out endPosA);
+ bool foundEndPos = !calculateEndPos || citizenManager.m_instances.m_buffer[(int)driverInstanceId].Info.m_citizenAI.FindPathPosition(driverInstanceId, ref citizenManager.m_instances.m_buffer[(int)driverInstanceId], endPos, Options.prohibitPocketCars ? NetInfo.LaneType.Pedestrian : (laneTypes | NetInfo.LaneType.Pedestrian), vehicleType, undergroundTarget, out endPosA);
// NON-STOCK CODE END
if (foundStartingPos &&
@@ -368,8 +324,8 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
// NON-STOCK CODE START
bool allowEscapeTransport = true;
if (Options.restrictEvacBussesToShelter) {
- if (targetBuilding != 0) {
- BuildingInfo targetBuildingInfo = Singleton.instance.m_buildings.m_buffer[targetBuilding].Info;
+ if (targetBuildingId != 0) {
+ BuildingInfo targetBuildingInfo = Singleton.instance.m_buildings.m_buffer[targetBuildingId].Info;
allowEscapeTransport = targetBuildingInfo.GetService() == ItemClass.Service.Disaster && targetBuildingInfo.GetClassLevel() == ItemClass.Level.Level4;
} else {
allowEscapeTransport = false;
@@ -390,7 +346,7 @@ public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vecto
#else
false
#endif
- , ExtVehicleType.PassengerCar, vehicleID, extPathType, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, def, laneTypes, vehicleType, 20000f, false, false, false, false, randomParking, false, allowEscapeTransport)) {
+ , ExtVehicleType.PassengerCar, vehicleID, extPathType, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, def, laneTypes, vehicleType, 20000f, false, false, false, skipQueue, randomParking, false, allowEscapeTransport)) {
#if USEPATHWAITCOUNTER
VehicleState state = VehicleStateManager.Instance._GetVehicleState(vehicleID);
state.PathWaitCounter = 0;
@@ -769,7 +725,7 @@ public static bool FindParkingSpaceBuilding(VehicleInfo vehicleInfo, ushort home
Vector3 position = transformMatrix.MultiplyPoint(prop.m_position);
if (FindParkingSpaceProp(ignoreParked, propInfo, position, building.m_angle + prop.m_radAngle, prop.m_fixedHeight, refPos, vehicleInfo.m_generatedInfo.m_size.x, vehicleInfo.m_generatedInfo.m_size.z, ref propMinDistance, ref parkPos, ref parkRot)) { // NON-STOCK CODE
result = true;
- if (randomize && propMinDistance <= maxDistance && rng.Int32(GlobalConfig.Instance.VicinityParkingSpaceSelectionRand) != 0)
+ if (randomize && propMinDistance <= maxDistance && rng.Int32(GlobalConfig.Instance.VicinityParkingSpaceSelectionRand) == 0)
break;
}
}
@@ -913,8 +869,10 @@ public bool CustomParkVehicle(ushort vehicleID, ref Vehicle vehicleData, PathUni
if (driverCitizenId != 0u) {
if (Options.prohibitPocketCars) {
state = VehicleStateManager.Instance._GetVehicleState(vehicleData.GetFirstVehicle(vehicleID));
- driverExtInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(driverCitizenInstanceId);
- prohibitPocketCars = driverExtInstance != null; // TODO why would this be null??
+ if (driverCitizenInstanceId != 0) {
+ driverExtInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(driverCitizenInstanceId);
+ prohibitPocketCars = true;
+ }
}
uint laneID = PathManager.GetLaneID(pathPos);
@@ -1196,9 +1154,5 @@ private static bool CustomFindParkingSpace(VehicleInfo vehicleInfo, ushort homeI
}
return false;
}
-
- internal static void OnLevelLoaded() {
-
- }
}
}
diff --git a/TLM/TLM/Custom/AI/CustomResidentAI.cs b/TLM/TLM/Custom/AI/CustomResidentAI.cs
index d041c8d9..1a488ccf 100644
--- a/TLM/TLM/Custom/AI/CustomResidentAI.cs
+++ b/TLM/TLM/Custom/AI/CustomResidentAI.cs
@@ -13,7 +13,7 @@
using static TrafficManager.Traffic.ExtCitizenInstance;
namespace TrafficManager.Custom.AI {
- public class CustomResidentAI : HumanAI {
+ public class CustomResidentAI : ResidentAI {
public string CustomGetLocalizedStatus(ushort instanceID, ref CitizenInstance data, out InstanceID target) {
if ((data.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None) {
target = InstanceID.Empty;
@@ -123,10 +123,6 @@ public string CustomGetLocalizedStatus(ushort instanceID, ref CitizenInstance da
}
public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceProbability) {
- return CustomResidentAI.GetVehicleInfo(instanceID, ref citizenData, forceProbability);
- }
-
- public static new VehicleInfo GetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceProbability) {
if (citizenData.m_citizen == 0u) {
return null;
}
@@ -137,15 +133,15 @@ public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance c
ExtCitizenInstance extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);
if (extInstance.PathMode == ExtPathMode.TaxiToTarget) {
forceTaxi = true;
- }
-
- ushort parkedVehicleId = Singleton.instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
- if (parkedVehicleId != 0) {
+ } else {
+ ushort parkedVehicleId = Singleton.instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
+ if (parkedVehicleId != 0) {
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomResidentAI.GetVehicleInfo: Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info.");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"CustomResidentAI.GetVehicleInfo: Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info.");
#endif
- return Singleton.instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
+ return Singleton.instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
+ }
}
}
// NON-STOCK CODE END
@@ -155,18 +151,21 @@ public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance c
int carProb;
int bikeProb;
int taxiProb;
+ // NON-STOCK CODE START
if (forceTaxi) {
carProb = 0;
bikeProb = 0;
taxiProb = 100;
- } else if (forceProbability || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None) {
+ } else
+ // NON-STOCK CODE END
+ if (forceProbability || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None) {
carProb = 100;
bikeProb = 0;
taxiProb = 0;
} else {
- carProb = CustomResidentAI.GetCarProbability(instanceID, ref citizenData, ageGroup);
- bikeProb = CustomResidentAI.GetBikeProbability(instanceID, ref citizenData, ageGroup);
- taxiProb = CustomResidentAI.GetTaxiProbability(instanceID, ref citizenData, ageGroup);
+ carProb = GetCarProbability(instanceID, ref citizenData, ageGroup);
+ bikeProb = GetBikeProbability(instanceID, ref citizenData, ageGroup);
+ taxiProb = GetTaxiProbability(instanceID, ref citizenData, ageGroup);
}
Randomizer randomizer = new Randomizer(citizenData.m_citizen);
bool useCar = randomizer.Int32(100u) < carProb;
@@ -189,7 +188,8 @@ public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance c
return null;
}
- private static int GetTaxiProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup) {
+ private int GetTaxiProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup) {
+ Log.Error("CustomResidentAI.GetTaxiProbability called!");
switch (ageGroup) {
case Citizen.AgeGroup.Child:
return 0;
@@ -206,7 +206,8 @@ private static int GetTaxiProbability(ushort instanceID, ref CitizenInstance cit
}
}
- private static int GetBikeProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup) {
+ private int GetBikeProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup) {
+ Log.Error("CustomResidentAI.GetBikeProbability called!");
CitizenManager citizenManager = Singleton.instance;
uint citizenId = citizenData.m_citizen;
ushort homeId = citizenManager.m_citizens.m_buffer[(int)((UIntPtr)citizenId)].m_homeBuilding;
@@ -236,18 +237,19 @@ private static int GetBikeProbability(ushort instanceID, ref CitizenInstance cit
}
}
- private static int GetCarProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup) {
+ private int GetCarProbability(ushort instanceID, ref CitizenInstance citizenData, Citizen.AgeGroup ageGroup) {
+ Log.Error("CustomResidentAI.GetCarProbability called!");
switch (ageGroup) {
case Citizen.AgeGroup.Child:
- return ResidentAI.CAR_PROBABILITY_CHILD;
+ return 0;
case Citizen.AgeGroup.Teen:
- return ResidentAI.CAR_PROBABILITY_TEEN;
+ return 5;
case Citizen.AgeGroup.Young:
- return ResidentAI.CAR_PROBABILITY_YOUNG;
+ return 15;
case Citizen.AgeGroup.Adult:
- return ResidentAI.CAR_PROBABILITY_ADULT;
+ return 20;
case Citizen.AgeGroup.Senior:
- return ResidentAI.CAR_PROBABILITY_SENIOR;
+ return 10;
default:
return 0;
}
diff --git a/TLM/TLM/Custom/AI/CustomTouristAI.cs b/TLM/TLM/Custom/AI/CustomTouristAI.cs
index 33b7fbc7..3d20bcd1 100644
--- a/TLM/TLM/Custom/AI/CustomTouristAI.cs
+++ b/TLM/TLM/Custom/AI/CustomTouristAI.cs
@@ -8,6 +8,7 @@
using TrafficManager.Manager;
using TrafficManager.State;
using TrafficManager.Traffic;
+using static TrafficManager.Traffic.ExtCitizenInstance;
namespace TrafficManager.Custom.AI {
public class CustomTouristAI : TouristAI {
@@ -77,23 +78,25 @@ public string CustomGetLocalizedStatus(ushort instanceID, ref CitizenInstance da
}
public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceProbability) {
- return CustomTouristAI.GetVehicleInfo(instanceID, ref citizenData, forceProbability);
- }
-
- public static new VehicleInfo GetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceProbability) {
if (citizenData.m_citizen == 0u) {
return null;
}
// NON-STOCK CODE START
+ bool forceTaxi = false;
if (Options.prohibitPocketCars) {
- ushort parkedVehicleId = Singleton.instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
- if (parkedVehicleId != 0) {
+ ExtCitizenInstance extInstance = ExtCitizenInstanceManager.Instance.GetExtInstance(instanceID);
+ if (extInstance.PathMode == ExtPathMode.TaxiToTarget) {
+ forceTaxi = true;
+ } else {
+ ushort parkedVehicleId = Singleton.instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle;
+ if (parkedVehicleId != 0) {
#if DEBUG
- if (GlobalConfig.Instance.DebugSwitches[2])
- Log._Debug($"CustomTouristAI.GetVehicleInfo: Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info.");
+ if (GlobalConfig.Instance.DebugSwitches[2])
+ Log._Debug($"CustomTouristAI.GetVehicleInfo: Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info.");
#endif
- return Singleton.instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
+ return Singleton.instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;
+ }
}
}
// NON-STOCK CODE END
@@ -101,14 +104,21 @@ public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance c
int carProb;
int bikeProb;
int taxiProb;
+ // NON-STOCK CODE START
+ if (forceTaxi) {
+ carProb = 0;
+ bikeProb = 0;
+ taxiProb = 100;
+ } else
+ // NON-STOCK CODE END
if (forceProbability || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None) {
carProb = 100;
bikeProb = 0;
taxiProb = 0;
} else {
- carProb = CustomTouristAI.GetCarProbability();
- bikeProb = CustomTouristAI.GetBikeProbability();
- taxiProb = CustomTouristAI.GetTaxiProbability();
+ carProb = GetCarProbability();
+ bikeProb = GetBikeProbability();
+ taxiProb = GetTaxiProbability();
}
Randomizer randomizer = new Randomizer(citizenData.m_citizen);
bool useCar = randomizer.Int32(100u) < carProb;
@@ -131,15 +141,18 @@ public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance c
return null;
}
- private static int GetTaxiProbability() {
+ private int GetTaxiProbability() {
+ Log.Error("CustomTouristAI.GetTaxiProbability called!");
return 20;
}
- private static int GetBikeProbability() {
+ private int GetBikeProbability() {
+ Log.Error("CustomTouristAI.GetBikeProbability called!");
return 20;
}
- private static int GetCarProbability() {
+ private int GetCarProbability() {
+ Log.Error("CustomTouristAI.GetCarProbability called!");
return 20;
}
}
diff --git a/TLM/TLM/Custom/Manager/CustomVehicleManager.cs b/TLM/TLM/Custom/Manager/CustomVehicleManager.cs
index 61a51b6e..16158eba 100644
--- a/TLM/TLM/Custom/Manager/CustomVehicleManager.cs
+++ b/TLM/TLM/Custom/Manager/CustomVehicleManager.cs
@@ -21,6 +21,17 @@ private void ReleaseVehicleImplementation(ushort vehicleId, ref Vehicle vehicleD
}
public bool CustomCreateVehicle(out ushort vehicleId, ref Randomizer r, VehicleInfo info, Vector3 position, TransferManager.TransferReason type, bool transferToSource, bool transferToTarget) {
+ // NON-STOCK CODE START
+ if (this.m_vehicleCount > VehicleManager.MAX_VEHICLE_COUNT - 5) {
+ // prioritize service vehicles and public transport when hitting the vehicle limit
+ ItemClass.Service service = info.GetService();
+ if (service == ItemClass.Service.Residential || service == ItemClass.Service.Industrial || service == ItemClass.Service.Commercial || service == ItemClass.Service.Office) {
+ vehicleId = 0;
+ return false;
+ }
+ }
+ // NON-STOCK CODE END
+
ushort vehId;
if (this.m_vehicles.CreateItem(out vehId, ref r)) {
vehicleId = vehId;
diff --git a/TLM/TLM/Custom/PathFinding/CustomPathFind.cs b/TLM/TLM/Custom/PathFinding/CustomPathFind.cs
index d382bf01..459942a1 100644
--- a/TLM/TLM/Custom/PathFinding/CustomPathFind.cs
+++ b/TLM/TLM/Custom/PathFinding/CustomPathFind.cs
@@ -906,6 +906,7 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe
} else {
// pocket car spawning
if (Options.prohibitPocketCars &&
+ _extVehicleType == ExtVehicleType.PassengerCar &&
(_extPathType == ExtCitizenInstance.ExtPathType.WalkingOnly || (_extPathType == ExtCitizenInstance.ExtPathType.DrivingOnly && item.m_position.m_segment != _startSegmentA && item.m_position.m_segment != _startSegmentB))) {
allowPedSwitch = false;
} else {
@@ -1453,7 +1454,10 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe
// min/max compatible outer similar lane indices
short minNextOuterSimilarIndex = -1;
short maxNextOuterSimilarIndex = -1;
- if (nextIsRealJunction) {
+ if (uturn) {
+ // force u-turns to happen on the most inner lane
+ minNextOuterSimilarIndex = maxNextOuterSimilarIndex = (short)((short)nextCompatibleLaneCount - 1);
+ } else if (nextIsRealJunction) {
// at junctions: try to match distinct lanes
/*if (prevOuterSimilarLaneIndex >= nextCompatibleLaneCount-1) {
@@ -1463,7 +1467,10 @@ private void ProcessItemMain(uint unitId, BufferItem item, ref NetSegment prevSe
if (debug)
logBuf.Add($"City rules: Splitting inner lane. minNextOuterSimilarLaneIndex={minNextOuterSimilarIndex} maxNextOuterSimilarLaneIndex={maxNextOuterSimilarIndex}");
#endif
- } else */if (nextCompatibleLaneCount > prevSimilarLaneCount && prevOuterSimilarLaneIndex == prevSimilarLaneCount-1) {
+ } else */
+
+
+ if (nextCompatibleLaneCount > prevSimilarLaneCount && prevOuterSimilarLaneIndex == prevSimilarLaneCount-1) {
// merge inner lanes
minNextOuterSimilarIndex = prevOuterSimilarLaneIndex;
maxNextOuterSimilarIndex = (short)((short)nextCompatibleLaneCount - 1);
@@ -1793,11 +1800,12 @@ private static short FindValue(ref byte[] values, int value, short length) {
}
///
- /// xxx Finds the value in `values` having the (n+1)th lowest index, or, if (n+1) > number of valid elements in `values` finds the value in `values` with the highest index.
+ /// Finds the element in with the highest associated index i
satisfying i
<= .
+ /// If no such element is found, the element with the highest index is returned.
///
/// array to be queried
- /// a bitmask holding all valid indices of `values`
- /// query
+ /// a bitmask holding all valid indices of
+ /// query index
///
private static short FindCompatibleLane(ref byte[] values, ushort validMask, short n) {
short nextLaneI = -1;
@@ -2335,7 +2343,7 @@ private bool ProcessItemCosts(bool allowAdvancedAI, bool ignoreLaneArrows, bool
if (debug)
logBuf.Add($"ProcessItemCosts: applying u-turn cost factor on deactivated advaned AI");
#endif
- prevCost *= _conf.UturnLaneDistance;
+ prevCost *= (float)_conf.UturnLaneDistance;
}
}
diff --git a/TLM/TLM/LoadingExtension.cs b/TLM/TLM/LoadingExtension.cs
index 28c16d8a..1f5ea458 100644
--- a/TLM/TLM/LoadingExtension.cs
+++ b/TLM/TLM/LoadingExtension.cs
@@ -18,7 +18,7 @@
using TrafficManager.Manager;
namespace TrafficManager {
- public class LoadingExtension : LoadingExtensionBase {
+ public class LoadingExtension : LoadingExtensionBase {
public class Detour {
public MethodInfo OriginalMethod;
public MethodInfo CustomMethod;
@@ -31,7 +31,7 @@ public Detour(MethodInfo originalMethod, MethodInfo customMethod) {
}
}
- public static LoadingExtension Instance;
+ //public static LoadingExtension Instance;
public static bool IsPathManagerReplaced {
get; private set;
@@ -45,21 +45,21 @@ public static bool IsRushHourLoaded {
get; private set;
} = false;
- public CustomPathManager CustomPathManager { get; set; }
- public static bool DetourInited { get; set; }
+ public static CustomPathManager CustomPathManager { get; set; }
+ public static bool DetourInited { get; set; }
public static List Detours { get; set; }
- public TrafficManagerMode ToolMode { get; set; }
- public TrafficManagerTool TrafficManagerTool { get; set; }
+ public static TrafficManagerMode ToolMode { get; set; }
+ public static TrafficManagerTool TrafficManagerTool { get; set; }
#if !TAM
- public UIBase BaseUI { get; private set; }
+ public static UIBase BaseUI { get; private set; }
#endif
- public UITransportDemand TransportDemandUI { get; private set; }
+ public static UITransportDemand TransportDemandUI { get; private set; }
- private static bool gameLoaded = false;
+ private static bool gameLoaded = false;
- public LoadingExtension() {
- }
+ public LoadingExtension() {
+ }
public void revertDetours() {
if (DetourInited) {
@@ -220,6 +220,117 @@ public void initDetours() {
detourFailed = true;
}*/
+ Log.Info("Reverse-Redirection ResidentAI::GetTaxiProbability calls");
+ try {
+ Detours.Add(new Detour(typeof(CustomResidentAI).GetMethod("GetTaxiProbability",
+ BindingFlags.NonPublic | BindingFlags.Instance,
+ null,
+ new[]
+ {
+ typeof (ushort),
+ typeof (CitizenInstance).MakeByRefType(),
+ typeof (Citizen.AgeGroup)
+ },
+ null),
+ typeof(ResidentAI).GetMethod("GetTaxiProbability",
+ BindingFlags.NonPublic | BindingFlags.Instance,
+ null,
+ new[]
+ {
+ typeof (ushort),
+ typeof (CitizenInstance).MakeByRefType(),
+ typeof (Citizen.AgeGroup)
+ },
+ null)));
+ } catch (Exception) {
+ Log.Error("Could not reverse-redirect ResidentAI::GetTaxiProbability");
+ detourFailed = true;
+ }
+
+ Log.Info("Reverse-Redirection ResidentAI::GetBikeProbability calls");
+ try {
+ Detours.Add(new Detour(typeof(CustomResidentAI).GetMethod("GetBikeProbability",
+ BindingFlags.NonPublic | BindingFlags.Instance,
+ null,
+ new[]
+ {
+ typeof (ushort),
+ typeof (CitizenInstance).MakeByRefType(),
+ typeof (Citizen.AgeGroup)
+ },
+ null),
+ typeof(ResidentAI).GetMethod("GetBikeProbability",
+ BindingFlags.NonPublic | BindingFlags.Instance,
+ null,
+ new[]
+ {
+ typeof (ushort),
+ typeof (CitizenInstance).MakeByRefType(),
+ typeof (Citizen.AgeGroup)
+ },
+ null)));
+ } catch (Exception) {
+ Log.Error("Could not reverse-redirect ResidentAI::GetBikeProbability");
+ detourFailed = true;
+ }
+
+ Log.Info("Reverse-Redirection ResidentAI::GetCarProbability calls");
+ try {
+ Detours.Add(new Detour(typeof(CustomResidentAI).GetMethod("GetCarProbability",
+ BindingFlags.NonPublic | BindingFlags.Instance,
+ null,
+ new[]
+ {
+ typeof (ushort),
+ typeof (CitizenInstance).MakeByRefType(),
+ typeof (Citizen.AgeGroup)
+ },
+ null),
+ typeof(ResidentAI).GetMethod("GetCarProbability",
+ BindingFlags.NonPublic | BindingFlags.Instance,
+ null,
+ new[]
+ {
+ typeof (ushort),
+ typeof (CitizenInstance).MakeByRefType(),
+ typeof (Citizen.AgeGroup)
+ },
+ null)));
+ } catch (Exception) {
+ Log.Error("Could not reverse-redirect ResidentAI::GetCarProbability");
+ detourFailed = true;
+ }
+
+ Log.Info("Reverse-Redirection TouristAI::GetTaxiProbability calls");
+ try {
+ Detours.Add(new Detour(
+ typeof(CustomTouristAI).GetMethod("GetTaxiProbability", BindingFlags.NonPublic | BindingFlags.Instance),
+ typeof(TouristAI).GetMethod("GetTaxiProbability", BindingFlags.NonPublic | BindingFlags.Instance)));
+ } catch (Exception) {
+ Log.Error("Could not reverse-redirect TouristAI::GetTaxiProbability");
+ detourFailed = true;
+ }
+
+ Log.Info("Reverse-Redirection TouristAI::GetBikeProbability calls");
+ try {
+ Detours.Add(new Detour(
+ typeof(CustomTouristAI).GetMethod("GetBikeProbability", BindingFlags.NonPublic | BindingFlags.Instance),
+ typeof(TouristAI).GetMethod("GetBikeProbability", BindingFlags.NonPublic | BindingFlags.Instance)));
+ } catch (Exception) {
+ Log.Error("Could not reverse-redirect TouristAI::GetBikeProbability");
+ detourFailed = true;
+ }
+
+ Log.Info("Reverse-Redirection TouristAI::GetCarProbability calls");
+ try {
+ Detours.Add(new Detour(
+ typeof(CustomTouristAI).GetMethod("GetCarProbability", BindingFlags.NonPublic | BindingFlags.Instance),
+ typeof(TouristAI).GetMethod("GetCarProbability", BindingFlags.NonPublic | BindingFlags.Instance)));
+ } catch (Exception) {
+ Log.Error("Could not reverse-redirect TouristAI::GetCarProbability");
+ detourFailed = true;
+ }
+
Log.Info("Reverse-Redirection HumanAI::ArriveAtDestination calls");
try {
Detours.Add(new Detour(typeof(CustomHumanAI).GetMethod("ArriveAtDestination",
@@ -345,7 +456,7 @@ public void initDetours() {
},
null)));
} catch (Exception) {
- Log.Error("Could not reverse-redirect HumanAI::ArriveAtDestination");
+ Log.Error("Could not reverse-redirect HumanAI::Spawn");
detourFailed = true;
}
@@ -785,7 +896,7 @@ public void initDetours() {
Log.Error("Could not redirect VehicleManager::CreateVehicle calls");
detourFailed = true;
}
-
+
Log.Info("Redirecting TramBaseAI Calculate Segment Calls (2)");
try {
Detours.Add(new Detour(typeof(TramBaseAI).GetMethod("CalculateSegmentPosition",
@@ -951,7 +1062,7 @@ public void initDetours() {
detourFailed = true;
}
- Log.Info("Redirecting HumanAI::ArriveAtTarget Calls");
+ /*Log.Info("Redirecting HumanAI::ArriveAtTarget Calls");
try {
Detours.Add(new Detour(typeof(HumanAI).GetMethod("ArriveAtTarget",
BindingFlags.NonPublic | BindingFlags.Instance,
@@ -965,7 +1076,7 @@ public void initDetours() {
} catch (Exception) {
Log.Error("Could not redirect HumanAI::ArriveAtTarget.");
detourFailed = true;
- }
+ }*/
Log.Info("Redirection ResidentAI::GetVehicleInfo calls");
try {
@@ -1205,7 +1316,7 @@ public void initDetours() {
detourFailed = true;
}
-
+
Log.Info("Redirection PathFind::CalculatePath calls for non-Traffic++");
try {
Detours.Add(new Detour(typeof(PathFind).GetMethod("CalculatePath",
@@ -1687,7 +1798,7 @@ public void initDetours() {
Log.Error("Could not redirect RoadBaseAI::UpdateLanes");
detourFailed = true;
}
-
+
Log.Info("Redirection TrainAI::CheckNextLane calls");
try {
Detours.Add(new Detour(typeof(TrainAI).GetMethod("CheckNextLane",
@@ -1781,41 +1892,38 @@ internal static bool IsGameLoaded() {
}
public override void OnCreated(ILoading loading) {
- //SelfDestruct.DestructOldInstances(this);
+ //SelfDestruct.DestructOldInstances(this);
- base.OnCreated(loading);
+ base.OnCreated(loading);
- ToolMode = TrafficManagerMode.None;
+ ToolMode = TrafficManagerMode.None;
Detours = new List();
- DetourInited = false;
- CustomPathManager = new CustomPathManager();
- }
+ DetourInited = false;
+ CustomPathManager = new CustomPathManager();
+ }
- public override void OnReleased() {
- base.OnReleased();
+ public override void OnReleased() {
+ base.OnReleased();
- if (ToolMode != TrafficManagerMode.None) {
- ToolMode = TrafficManagerMode.None;
- DestroyTool();
- }
- }
+ if (ToolMode != TrafficManagerMode.None) {
+ ToolMode = TrafficManagerMode.None;
+ DestroyTool();
+ }
+ }
public override void OnLevelUnloading() {
Log.Info("OnLevelUnloading");
base.OnLevelUnloading();
- Instance = this;
if (IsPathManagerReplaced) {
Singleton.instance.WaitForAllPaths();
}
- revertDetours();
- gameLoaded = false;
- Object.Destroy(BaseUI);
- BaseUI = null;
- Object.Destroy(TransportDemandUI);
- TransportDemandUI = null;
+ /*Object.Destroy(BaseUI);
+ BaseUI = null;
+ Object.Destroy(TransportDemandUI);
+ TransportDemandUI = null;*/
- try {
+ try {
TrafficPriorityManager.Instance.OnLevelUnloading();
CustomCarAI.OnLevelUnloading();
CustomRoadAI.OnLevelUnloading();
@@ -1834,18 +1942,20 @@ public override void OnLevelUnloading() {
Log.Error("Exception unloading mod. " + e.Message);
// ignored - prevents collision with other mods
}
+
+ revertDetours();
+ gameLoaded = false;
}
public override void OnLevelLoaded(LoadMode mode) {
SimulationManager.UpdateMode updateMode = SimulationManager.instance.m_metaData.m_updateMode;
Log.Info($"OnLevelLoaded({mode}) called. updateMode={updateMode}");
- base.OnLevelLoaded(mode);
+ base.OnLevelLoaded(mode);
- Log._Debug("OnLevelLoaded Returned from base, calling custom code.");
- Instance = this;
+ Log._Debug("OnLevelLoaded Returned from base, calling custom code.");
gameLoaded = false;
- switch (updateMode) {
+ switch (updateMode) {
case SimulationManager.UpdateMode.NewGameFromMap:
case SimulationManager.UpdateMode.NewGameFromScenario:
case SimulationManager.UpdateMode.LoadGame:
@@ -1875,12 +1985,12 @@ public override void OnLevelLoaded(LoadMode mode) {
default:
Log.Info($"OnLevelLoaded: Unsupported game mode {mode}");
return;
- }
+ }
IsRainfallLoaded = CheckRainfallIsLoaded();
IsRushHourLoaded = CheckRushHourIsLoaded();
- if (! IsPathManagerReplaced) {
+ if (!IsPathManagerReplaced) {
try {
Log.Info("Pathfinder Compatible. Setting up CustomPathManager and SimManager.");
var pathManagerInstance = typeof(Singleton).GetField("sInstance", BindingFlags.Static | BindingFlags.NonPublic);
@@ -1924,16 +2034,18 @@ public override void OnLevelLoaded(LoadMode mode) {
}
Log.Info("Adding Controls to UI.");
- BaseUI = ToolsModifierControl.toolController.gameObject.AddComponent();
-
- // Init transport demand UI
- var uiView = UIView.GetAView();
- TransportDemandUI = (UITransportDemand)uiView.AddUIComponent(typeof(UITransportDemand));
+ if (BaseUI == null) {
+ Log._Debug("Adding UIBase instance.");
+ BaseUI = ToolsModifierControl.toolController.gameObject.AddComponent();
+ }
- initDetours();
+ // Init transport demand UI
+ if (TransportDemandUI == null) {
+ var uiView = UIView.GetAView();
+ TransportDemandUI = (UITransportDemand)uiView.AddUIComponent(typeof(UITransportDemand));
+ }
- Log.Info("Calling OnLevelLoaded.");
- CustomPassengerCarAI.OnLevelLoaded();
+ initDetours();
Log.Info("OnLevelLoaded complete.");
}
@@ -1976,34 +2088,34 @@ private bool Check3rdPartyModLoaded(string namespaceStr) {
return thirPartyModLoaded;
}
- public void SetToolMode(TrafficManagerMode mode) {
- if (mode == ToolMode) return;
+ public static void SetToolMode(TrafficManagerMode mode) {
+ if (mode == ToolMode) return;
- ToolMode = mode;
+ ToolMode = mode;
- if (mode != TrafficManagerMode.None) {
- EnableTool();
- } else {
+ if (mode != TrafficManagerMode.None) {
+ EnableTool();
+ } else {
DisableTool();
- }
- }
+ }
+ }
- public void EnableTool() {
- if (TrafficManagerTool == null) {
- TrafficManagerTool = ToolsModifierControl.toolController.gameObject.GetComponent() ??
- ToolsModifierControl.toolController.gameObject.AddComponent();
- }
+ public static void EnableTool() {
+ if (TrafficManagerTool == null) {
+ TrafficManagerTool = ToolsModifierControl.toolController.gameObject.GetComponent() ??
+ ToolsModifierControl.toolController.gameObject.AddComponent();
+ }
- ToolsModifierControl.toolController.CurrentTool = TrafficManagerTool;
- ToolsModifierControl.SetTool();
- }
+ ToolsModifierControl.toolController.CurrentTool = TrafficManagerTool;
+ ToolsModifierControl.SetTool();
+ }
- public void DisableTool() {
+ public static void DisableTool() {
ToolsModifierControl.toolController.CurrentTool = ToolsModifierControl.GetTool();
ToolsModifierControl.SetTool();
}
- private void DestroyTool() {
+ private static void DestroyTool() {
if (ToolsModifierControl.toolController != null) {
ToolsModifierControl.toolController.CurrentTool = ToolsModifierControl.GetTool();
ToolsModifierControl.SetTool();
@@ -2014,6 +2126,6 @@ private void DestroyTool() {
}
} else
Log.Warning("LoadingExtensions.DestroyTool: ToolsModifierControl.toolController is null!");
- }
+ }
}
}
diff --git a/TLM/TLM/State/GlobalConfig.cs b/TLM/TLM/State/GlobalConfig.cs
index 978a3782..8ff7a29b 100644
--- a/TLM/TLM/State/GlobalConfig.cs
+++ b/TLM/TLM/State/GlobalConfig.cs
@@ -14,7 +14,7 @@ namespace TrafficManager.State {
public class GlobalConfig {
public const string FILENAME = "TMPE_GlobalConfig.xml";
public const string BACKUP_FILENAME = FILENAME + ".bak";
- private static int LATEST_VERSION = 2;
+ private static int LATEST_VERSION = 3;
#if DEBUG
private static uint lastModificationCheckFrame = 0;
#endif
@@ -42,16 +42,16 @@ internal static void OnLevelUnloading() {
}
//public static GlobalConfig Instance() {
-//#if DEBUG
-// uint curDebugFrame = Singleton.instance.m_currentFrameIndex >> 10;
-// if (lastModificationCheckFrame == 0) {
-// lastModificationCheckFrame = curDebugFrame;
-// } else if (lastModificationCheckFrame < curDebugFrame) {
-// lastModificationCheckFrame = curDebugFrame;
-// ReloadIfNewer();
-// }
-//#endif
- //return Instance;
+ //#if DEBUG
+ // uint curDebugFrame = Singleton.instance.m_currentFrameIndex >> 10;
+ // if (lastModificationCheckFrame == 0) {
+ // lastModificationCheckFrame = curDebugFrame;
+ // } else if (lastModificationCheckFrame < curDebugFrame) {
+ // lastModificationCheckFrame = curDebugFrame;
+ // ReloadIfNewer();
+ // }
+ //#endif
+ //return Instance;
//}
private static DateTime ModifiedTime = DateTime.MinValue;
@@ -82,7 +82,7 @@ internal static void OnLevelUnloading() {
///
/// base lane changing cost factor on city streets
///
- public float CityRoadLaneChangingBaseCost = 0.1f;
+ public float CityRoadLaneChangingBaseCost = 0.15f;
///
/// lane changing cost base before junctions
diff --git a/TLM/TLM/State/Options.cs b/TLM/TLM/State/Options.cs
index e4ec7794..25fd6c64 100644
--- a/TLM/TLM/State/Options.cs
+++ b/TLM/TLM/State/Options.cs
@@ -122,8 +122,8 @@ public static bool MenuRebuildRequired {
get { return menuRebuildRequired; }
private set {
menuRebuildRequired = value;
- if (LoadingExtension.Instance != null && LoadingExtension.Instance.BaseUI != null)
- LoadingExtension.Instance.BaseUI.Close();
+ if (LoadingExtension.BaseUI != null)
+ LoadingExtension.BaseUI.Close();
}
}
diff --git a/TLM/TLM/TLM.csproj b/TLM/TLM/TLM.csproj
index 8182e122..77f00467 100644
--- a/TLM/TLM/TLM.csproj
+++ b/TLM/TLM/TLM.csproj
@@ -18,7 +18,7 @@
full
false
bin\Debug\
- DEBUG
+ DEBUG;QUEUEDSTATS
prompt
0
true
@@ -33,6 +33,16 @@
4
true
+
+ bin\QueuedStats\
+ QUEUEDSTATS
+ true
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
D:\Games\Steam\steamapps\common\Cities_Skylines\Cities_Data\Managed\Assembly-CSharp.dll
diff --git a/TLM/TLM/ThreadingExtension.cs b/TLM/TLM/ThreadingExtension.cs
index 5051b101..73503c5c 100644
--- a/TLM/TLM/ThreadingExtension.cs
+++ b/TLM/TLM/ThreadingExtension.cs
@@ -42,16 +42,16 @@ public override void OnAfterSimulationFrame() {
public override void OnUpdate(float realTimeDelta, float simulationTimeDelta) {
base.OnUpdate(realTimeDelta, simulationTimeDelta);
#if !TAM
- if (LoadingExtension.Instance == null || ToolsModifierControl.toolController == null || ToolsModifierControl.toolController == null || LoadingExtension.Instance.BaseUI == null) {
+ if (ToolsModifierControl.toolController == null || ToolsModifierControl.toolController == null || LoadingExtension.BaseUI == null) {
return;
}
- if (ToolsModifierControl.toolController.CurrentTool != LoadingExtension.Instance.TrafficManagerTool && LoadingExtension.Instance.BaseUI.IsVisible()) {
- LoadingExtension.Instance.BaseUI.Close();
+ if (ToolsModifierControl.toolController.CurrentTool != LoadingExtension.TrafficManagerTool && LoadingExtension.BaseUI.IsVisible()) {
+ LoadingExtension.BaseUI.Close();
}
if (Input.GetKeyDown(KeyCode.Escape)) {
- LoadingExtension.Instance.BaseUI.Close();
+ LoadingExtension.BaseUI.Close();
}
#endif
}
diff --git a/TLM/TLM/TrafficManagerMod.cs b/TLM/TLM/TrafficManagerMod.cs
index d9494023..f0649a1a 100644
--- a/TLM/TLM/TrafficManagerMod.cs
+++ b/TLM/TLM/TrafficManagerMod.cs
@@ -5,7 +5,7 @@
namespace TrafficManager {
public class TrafficManagerMod : IUserMod {
- public static readonly string Version = "1.8.3";
+ public static readonly string Version = "1.8.4";
public static readonly uint GameVersion = 159507472u;
public static readonly uint GameVersionA = 1u;
diff --git a/TLM/TLM/UI/SubTools/LaneConnectorTool.cs b/TLM/TLM/UI/SubTools/LaneConnectorTool.cs
index 65c5d74a..40d23165 100644
--- a/TLM/TLM/UI/SubTools/LaneConnectorTool.cs
+++ b/TLM/TLM/UI/SubTools/LaneConnectorTool.cs
@@ -22,10 +22,18 @@ enum MarkerSelectionMode {
SelectTarget
}
+ enum StayInLaneMode {
+ None,
+ Both,
+ Forward,
+ Backward
+ }
+
private Dictionary nodeGeometryUnsubscribers;
private NodeLaneMarker selectedMarker = null;
private NodeLaneMarker hoveredMarker = null;
private Dictionary> currentNodeMarkers;
+ private StayInLaneMode stayInLaneMode = StayInLaneMode.None;
//private bool initDone = false;
class NodeLaneMarker {
@@ -35,6 +43,8 @@ class NodeLaneMarker {
internal Vector3 position;
internal bool isSource;
internal uint laneId;
+ internal int innerSimilarLaneIndex;
+ internal NetInfo.Direction finalDirection;
internal float radius = 1f;
internal Color color;
internal List connectedMarkers = new List();
@@ -138,7 +148,12 @@ public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) {
}
}
- if (Input.GetKey(KeyCode.Delete)) {
+ bool deleteAll = Input.GetKeyDown(KeyCode.Delete);
+ bool stayInLane = Input.GetKeyDown(KeyCode.S) && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) && Singleton.instance.m_nodes.m_buffer[SelectedNodeId].CountSegments() == 2;
+ if (stayInLane)
+ deleteAll = true;
+
+ if (deleteAll) {
// remove all connections at selected node
List nodeMarkers = GetNodeMarkers(SelectedNodeId);
@@ -152,6 +167,52 @@ public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) {
}
RefreshCurrentNodeMarkers();
}
+
+ if (stayInLane) {
+ // "stay in lane"
+ switch (stayInLaneMode) {
+ case StayInLaneMode.None:
+ stayInLaneMode = StayInLaneMode.Both;
+ break;
+ case StayInLaneMode.Both:
+ stayInLaneMode = StayInLaneMode.Forward;
+ break;
+ case StayInLaneMode.Forward:
+ stayInLaneMode = StayInLaneMode.Backward;
+ break;
+ case StayInLaneMode.Backward:
+ stayInLaneMode = StayInLaneMode.None;
+ break;
+ }
+
+ if (stayInLaneMode != StayInLaneMode.None) {
+ List nodeMarkers = GetNodeMarkers(SelectedNodeId);
+ if (nodeMarkers != null) {
+ selectedMarker = null;
+ foreach (NodeLaneMarker sourceLaneMarker in nodeMarkers) {
+ if (!sourceLaneMarker.isSource)
+ continue;
+
+ if (stayInLaneMode == StayInLaneMode.Forward || stayInLaneMode == StayInLaneMode.Backward) {
+ if (sourceLaneMarker.finalDirection == NetInfo.Direction.Backward ^ stayInLaneMode == StayInLaneMode.Backward) {
+ continue;
+ }
+ }
+
+ foreach (NodeLaneMarker targetLaneMarker in nodeMarkers) {
+ if (targetLaneMarker.isSource || targetLaneMarker.segmentId == sourceLaneMarker.segmentId)
+ continue;
+
+ if (targetLaneMarker.innerSimilarLaneIndex == sourceLaneMarker.innerSimilarLaneIndex) {
+ Log._Debug($"Adding lane connection {sourceLaneMarker.laneId} -> {targetLaneMarker.laneId}");
+ LaneConnectionManager.Instance.AddLaneConnection(sourceLaneMarker.laneId, targetLaneMarker.laneId, sourceLaneMarker.startNode);
+ }
+ }
+ }
+ }
+ RefreshCurrentNodeMarkers();
+ }
+ }
}
if (GetMarkerSelectionMode() == MarkerSelectionMode.None && HoveredNodeId != 0) {
@@ -178,6 +239,7 @@ public override void OnPrimaryClickOverlay() {
#endif
SelectedNodeId = 0;
selectedMarker = null;
+ stayInLaneMode = StayInLaneMode.None;
return;
}
@@ -191,6 +253,7 @@ public override void OnPrimaryClickOverlay() {
if (markers != null) {
SelectedNodeId = HoveredNodeId;
selectedMarker = null;
+ stayInLaneMode = StayInLaneMode.None;
currentNodeMarkers[SelectedNodeId] = markers;
}
@@ -204,11 +267,14 @@ public override void OnPrimaryClickOverlay() {
// click on free spot. deselect node
SelectedNodeId = 0;
selectedMarker = null;
+ stayInLaneMode = StayInLaneMode.None;
return;
}
}
if (hoveredMarker != null) {
+ stayInLaneMode = StayInLaneMode.None;
+
#if DEBUGCONN
Log._Debug($"TppLaneConnectorTool: hoveredMarker != null. selMode={GetMarkerSelectionMode()}");
#endif
@@ -254,6 +320,7 @@ public override void OnSecondaryClickOverlay() {
#if DEBUGCONN
Log._Debug($"TppLaneConnectorTool: OnSecondaryClickOverlay: nothing to do");
#endif
+ stayInLaneMode = StayInLaneMode.None;
break;
case MarkerSelectionMode.SelectSource:
// deselect node
@@ -279,6 +346,7 @@ public override void OnActivate() {
SelectedNodeId = 0;
selectedMarker = null;
hoveredMarker = null;
+ stayInLaneMode = StayInLaneMode.None;
RefreshCurrentNodeMarkers();
}
@@ -338,12 +406,13 @@ private List GetNodeMarkers(ushort nodeId) {
NetInfo.Lane[] lanes = NetManager.instance.m_segments.m_buffer[segmentId].Info.m_lanes;
uint laneId = NetManager.instance.m_segments.m_buffer[segmentId].m_lanes;
for (byte laneIndex = 0; laneIndex < lanes.Length && laneId != 0; laneIndex++) {
- if ((lanes[laneIndex].m_laneType & (NetInfo.LaneType.TransportVehicle | NetInfo.LaneType.Vehicle)) != NetInfo.LaneType.None &&
- (lanes[laneIndex].m_vehicleType & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train)) != VehicleInfo.VehicleType.None) {
+ NetInfo.Lane laneInfo = lanes[laneIndex];
+ if ((laneInfo.m_laneType & (NetInfo.LaneType.TransportVehicle | NetInfo.LaneType.Vehicle)) != NetInfo.LaneType.None &&
+ (laneInfo.m_vehicleType & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train)) != VehicleInfo.VehicleType.None) {
Vector3? pos = null;
bool isSource = false;
- if (connManager.GetLaneEndPoint(segmentId, !isEndNode, laneIndex, laneId, lanes[laneIndex], out isSource, out pos)) {
+ if (connManager.GetLaneEndPoint(segmentId, !isEndNode, laneIndex, laneId, laneInfo, out isSource, out pos)) {
nodeMarkers.Add(new NodeLaneMarker() {
segmentId = segmentId,
laneId = laneId,
@@ -352,8 +421,10 @@ private List GetNodeMarkers(ushort nodeId) {
position = (Vector3)pos + offset,
color = colors[nodeMarkers.Count],
isSource = isSource,
- laneType = lanes[laneIndex].m_laneType,
- vehicleType = lanes[laneIndex].m_vehicleType
+ laneType = laneInfo.m_laneType,
+ vehicleType = laneInfo.m_vehicleType,
+ innerSimilarLaneIndex = ((byte)(laneInfo.m_finalDirection & NetInfo.Direction.Forward) != 0) ? laneInfo.m_similarLaneIndex : laneInfo.m_similarLaneCount - laneInfo.m_similarLaneIndex - 1,
+ finalDirection = laneInfo.m_finalDirection
});
}
}
@@ -400,7 +471,7 @@ private bool CheckSegmentsTurningAngle(ushort sourceSegmentId, ref NetSegment so
NetInfo sourceSegmentInfo = netManager.m_segments.m_buffer[sourceSegmentId].Info;
NetInfo targetSegmentInfo = netManager.m_segments.m_buffer[targetSegmentId].Info;
-
+
float turningAngle = 0.01f - Mathf.Min(sourceSegmentInfo.m_maxTurnAngleCos, targetSegmentInfo.m_maxTurnAngleCos);
if (turningAngle < 1f) {
Vector3 sourceDirection;
diff --git a/TLM/TLM/UI/UIBase.cs b/TLM/TLM/UI/UIBase.cs
index ad3fd0cc..5b87c95e 100644
--- a/TLM/TLM/UI/UIBase.cs
+++ b/TLM/TLM/UI/UIBase.cs
@@ -8,7 +8,7 @@
namespace TrafficManager.UI {
#if !TAM
public class UIBase : UICustomControl {
-
+
private UIMainMenuButton button;
private bool _uiShown = false;
@@ -23,6 +23,10 @@ public UIBase() {
button = (UIMainMenuButton)uiView.AddUIComponent(typeof(UIMainMenuButton));
}
+ ~UIBase() {
+ UnityEngine.Object.Destroy(button);
+ }
+
public bool IsVisible() {
return _uiShown;
}
@@ -35,41 +39,33 @@ public void ToggleMainMenu() {
}
public void Show() {
- if (LoadingExtension.Instance != null) {
- try {
- ToolsModifierControl.mainToolbar.CloseEverything();
- } catch (Exception e) {
- Log.Error("Error on Show(): " + e.ToString());
- }
- GetMenu().Show();
- LoadingExtension.Instance.SetToolMode(TrafficManagerMode.Activated);
- _uiShown = true;
- button.UpdateSprites();
- } else {
- Log._Debug("TM UI Show: LoadingExtension.Instance is null!");
+ try {
+ ToolsModifierControl.mainToolbar.CloseEverything();
+ } catch (Exception e) {
+ Log.Error("Error on Show(): " + e.ToString());
}
+ GetMenu().Show();
+ LoadingExtension.SetToolMode(TrafficManagerMode.Activated);
+ _uiShown = true;
+ button.UpdateSprites();
}
public void Close() {
- if (LoadingExtension.Instance != null) {
- var uiView = UIView.GetAView();
- var trafficManager = uiView.FindUIComponent("UITrafficManager");
- if (trafficManager != null) {
- Log._Debug("Hiding TM UI");
- Destroy(trafficManager);
- //trafficManager.Hide();
- } else {
- Log._Debug("Hiding TM UI: null!");
- }
-
- UITrafficManager.deactivateButtons();
- TrafficManagerTool.SetToolMode(ToolMode.None);
- LoadingExtension.Instance.SetToolMode(TrafficManagerMode.None);
- _uiShown = false;
- button.UpdateSprites();
+ var uiView = UIView.GetAView();
+ var trafficManager = uiView.FindUIComponent("UITrafficManager");
+ if (trafficManager != null) {
+ Log._Debug("Hiding TM UI");
+ Destroy(trafficManager);
+ //trafficManager.Hide();
} else {
- Log._Debug("TM UI Close: LoadingExtension.Instance is null!");
+ Log._Debug("Hiding TM UI: null!");
}
+
+ UITrafficManager.deactivateButtons();
+ TrafficManagerTool.SetToolMode(ToolMode.None);
+ LoadingExtension.SetToolMode(TrafficManagerMode.None);
+ _uiShown = false;
+ button.UpdateSprites();
}
internal static UITrafficManager GetMenu() {
diff --git a/TLM/TLM/UI/UIMainMenuButton.cs b/TLM/TLM/UI/UIMainMenuButton.cs
index 5de1bc08..b8649320 100644
--- a/TLM/TLM/UI/UIMainMenuButton.cs
+++ b/TLM/TLM/UI/UIMainMenuButton.cs
@@ -50,7 +50,7 @@ public override void Start() {
}
protected override void OnClick(UIMouseEventParameter p) {
- LoadingExtension.Instance.BaseUI.ToggleMainMenu();
+ LoadingExtension.BaseUI.ToggleMainMenu();
UpdateSprites();
}
@@ -67,7 +67,7 @@ protected override void OnPositionChanged() {
}
internal void UpdateSprites() {
- if (! LoadingExtension.Instance.BaseUI.IsVisible()) {
+ if (! LoadingExtension.BaseUI.IsVisible()) {
normalBgSprite = disabledBgSprite = focusedBgSprite = MAIN_MENU_BUTTON_BG_BASE;
hoveredBgSprite = MAIN_MENU_BUTTON_BG_HOVERED;
pressedBgSprite = MAIN_MENU_BUTTON_BG_ACTIVE;
diff --git a/TLM/TLM/UI/UITrafficManager.cs b/TLM/TLM/UI/UITrafficManager.cs
index 43db4125..96486426 100644
--- a/TLM/TLM/UI/UITrafficManager.cs
+++ b/TLM/TLM/UI/UITrafficManager.cs
@@ -18,7 +18,7 @@ namespace TrafficManager.UI {
public class UITrafficManager : UIPanel {
//private static UIState _uiState = UIState.None;
-#if DEBUG
+#if QUEUEDSTATS
private static bool showPathFindStats = false;
#endif
@@ -43,19 +43,18 @@ public class UITrafficManager : UIPanel {
private static UIButton _printDebugInfoButton = null;
private static UIButton _noneToVehicleButton = null;
private static UIButton _vehicleToNoneButton = null;
- private static UIButton _togglePathFindStatsButton = null;
private static UIButton _removeStuckEntitiesButton = null;
#endif
+#if QUEUEDSTATS
+ private static UIButton _togglePathFindStatsButton = null;
+#endif
+
public static TrafficManagerTool TrafficLightTool;
public static UILabel title;
public override void Start() {
- if (LoadingExtension.Instance == null) {
- Log.Error("UITrafficManager.Start(): LoadingExtension is null.");
- return;
- }
- TrafficLightTool = LoadingExtension.Instance.TrafficManagerTool;
+ TrafficLightTool = LoadingExtension.TrafficManagerTool;
backgroundSprite = "GenericPanel";
color = new Color32(75, 75, 135, 255);
@@ -157,9 +156,13 @@ public override void Start() {
_vehicleToNoneButton = _createButton("Vehicle -> None", y, clickVehicleToNone);
y += 40;
height += 40;
+#endif
+#if QUEUEDSTATS
_togglePathFindStatsButton = _createButton("Toggle PathFind stats", y, clickTogglePathFindStats);
y += 40;
height += 40;
+#endif
+#if DEBUG
_removeStuckEntitiesButton = _createButton("Remove stuck entities", y, clickRemoveStuckEntities);
y += 40;
height += 40;
@@ -263,10 +266,15 @@ private void clickNoneToVehicle(UIComponent component, UIMouseEventParameter eve
}
}
}
+#endif
+#if QUEUEDSTATS
private void clickTogglePathFindStats(UIComponent component, UIMouseEventParameter eventParam) {
showPathFindStats = !showPathFindStats;
}
+#endif
+
+#if DEBUG
private void clickRemoveStuckEntities(UIComponent component, UIMouseEventParameter eventParam) {
TrafficManagerTool.SetToolMode(ToolMode.None);
@@ -471,7 +479,7 @@ private void clickLaneConnector(UIComponent component, UIMouseEventParameter eve
}
public override void Update() {
-#if DEBUG && QUEUEDSTATS
+#if QUEUEDSTATS
if (showPathFindStats && title != null) {
title.text = CustomPathManager.TotalQueuedPathFinds.ToString();
#if EXTRAPF
diff --git a/TLM/TLM/UI/UITransportDemand.cs b/TLM/TLM/UI/UITransportDemand.cs
index 2d1783d0..0f9366b4 100644
--- a/TLM/TLM/UI/UITransportDemand.cs
+++ b/TLM/TLM/UI/UITransportDemand.cs
@@ -18,11 +18,6 @@ public class UITransportDemand : UIPanel {
private static UILabel viewModeLabel;
public override void Start() {
- if (LoadingExtension.Instance == null) {
- Log.Error("UITrafficManager.Start(): LoadingExtension is null.");
- return;
- }
-
var transportInfoViewPanel = GameObject.Find("(Library) PublicTransportInfoViewPanel").GetComponent();
if (transportInfoViewPanel != null) {
Log._Debug($"Public transport info view panel found.");
@@ -49,7 +44,6 @@ public override void Start() {
switchViewModeButton = _createButton(Translation.GetString("Switch_view"), 3, 3, clickSwitchViewMode);
}
-
private UIButton _createButton(string text, int x, int y, MouseEventHandler eventClick) {
var button = AddUIComponent();
button.textScale = 0.8f;