Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vehicle type exclusion list for "Disable despawning" feature #1441

Merged
merged 12 commits into from
Mar 6, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions TLM/TLM/Manager/Impl/VehicleBehaviorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ bool citizenDebug
if (citizenInstanceId == 0) {
continue;
}

ref CitizenInstance citizenInstance = ref citizenInstanceId.ToCitizenInstance();

// NON-STOCK CODE START
Expand Down Expand Up @@ -1165,7 +1165,7 @@ protected VehicleJunctionTransitState MayChangeSegment(
maxSpeed = 0;
if (prevTargetNodeId != targetNodeId
|| (vehicleData.m_blockCounter == 255
&& !Instance.MayDespawn(ref vehicleData)) // NON-STOCK CODE
&& !Instance.MayDespawn(frontVehicleId, ref vehicleData)) // NON-STOCK CODE
) {
// method should only be called if targetNodeId == prevTargetNode
return VehicleJunctionTransitState.Leave;
Expand Down Expand Up @@ -1714,11 +1714,12 @@ protected bool MustCheckSpace(ushort segmentId,
return checkSpace;
}

public bool MayDespawn(ref Vehicle vehicleData) {
public bool MayDespawn(ushort vehicleId, ref Vehicle vehicleData) {
return !Options.disableDespawning
|| ((vehicleData.m_flags2 & (Vehicle.Flags2.Blown
| Vehicle.Flags2.Floating)) != 0)
|| (vehicleData.m_flags & Vehicle.Flags.Parking) != 0;
|| (vehicleData.m_flags & Vehicle.Flags.Parking) != 0
|| GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleManager.Instance.ExtVehicles[vehicleId].vehicleType);
krzychu124 marked this conversation as resolved.
Show resolved Hide resolved
}

public float CalcMaxSpeed(ushort vehicleId,
Expand Down
4 changes: 4 additions & 0 deletions TLM/TLM/Patch/PatchCommons.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static IEnumerable<CodeInstruction> ReplaceSimulationStepIsCongestedCheck
found = true;
yield return instruction; // return found instruction
yield return new CodeInstruction(OpCodes.Ldsfld, _vehicleBehaviourManagerInstanceField); // loadInstFiled
yield return new CodeInstruction(OpCodes.Ldarg_1); // vehicleID
yield return new CodeInstruction(OpCodes.Ldarg_2); // loadVehicleData
yield return new CodeInstruction(OpCodes.Callvirt, _mayDespawnMethod); // callMayDespawn
yield return instruction.Clone(); //brfalse_s || brfalse - clone including label!
Expand All @@ -49,6 +50,7 @@ public static IEnumerable<CodeInstruction> ReplaceSimulationStepIsCongestedCheck

// NON-STOCK CODE START
IL_000e: ldsfld class TrafficManager.Manager.Impl.VehicleBehaviorManager TrafficManager.Manager.Impl.VehicleBehaviorManager::Instance
IL_0013: ldarg.1 // vehicleID
IL_0013: ldarg.2 // vehicleData
IL_0014: callvirt instance bool TrafficManager.Manager.Impl.VehicleBehaviorManager::MayDespawn(valuetype ['Assembly-CSharp']Vehicle&)
IL_0019: brfalse.s IL_0027
Expand Down Expand Up @@ -168,6 +170,7 @@ private static List<CodeInstruction> GetModifiedBlockCounterInstructions(Label r

return new List<CodeInstruction> {
new CodeInstruction(OpCodes.Ldsfld, instance),
new CodeInstruction(OpCodes.Ldarg_1),
new CodeInstruction(OpCodes.Ldarg_2),
new CodeInstruction(OpCodes.Callvirt, mayDespawn),
new CodeInstruction(OpCodes.Brfalse_S, retLabel)
Expand All @@ -180,6 +183,7 @@ private static List<CodeInstruction> GetModifiedBlockCounterInstructions(Label r
------------------------------

ldsfld class TrafficManager.Manager.Impl.VehicleBehaviorManager TrafficManager.Manager.Impl.VehicleBehaviorManager::Instance
ldarg.1 // vehicleID
ldarg.2 // vehicleData
callvirt instance bool TrafficManager.Manager.Impl.VehicleBehaviorManager::MayDespawn(valuetype ['Assembly-CSharp']Vehicle&)
brfalse.s IL_0248
Expand Down
1 change: 1 addition & 0 deletions TLM/TLM/Patch/_External/RTramAIModPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ private static List<CodeInstruction> GetModifiedBlockCounterInstructions(Label r

return new List<CodeInstruction> {
new CodeInstruction(OpCodes.Ldsfld, instance),
new CodeInstruction(OpCodes.Ldarg_1),
new CodeInstruction(OpCodes.Ldarg_2),
new CodeInstruction(OpCodes.Callvirt, mayDespawn),
new CodeInstruction(OpCodes.Brfalse_S, retLabel)
Expand Down
2 changes: 1 addition & 1 deletion TLM/TLM/Patch/_VehicleAI/_CarAI/SimulationStepPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ ref driverInstanceId.ToCitizenInstance(),
Singleton<VehicleManager>.instance.ReleaseVehicle(vehicleID);
} else if (data.m_blockCounter >= maxBlockCounter) {
// NON-STOCK CODE START
if (VehicleBehaviorManager.Instance.MayDespawn(ref data)) {
if (VehicleBehaviorManager.Instance.MayDespawn(vehicleID, ref data)) {
// NON-STOCK CODE END
Singleton<VehicleManager>.instance.ReleaseVehicle(vehicleID);
} // NON-STOCK CODE
Expand Down
7 changes: 7 additions & 0 deletions TLM/TLM/State/ConfigData/Gameplay.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
namespace TrafficManager.State.ConfigData {
using API.Traffic.Enums;

public class Gameplay {
/// <summary>
/// Modulo value for time-varying vehicle behavior randomization
/// </summary>
public uint VehicleTimedRandModulo = 10;

/// <summary>
/// Flags holding types allowed for despawning if "No Vehicle Despawning" option is enabled
/// </summary>
public ExtVehicleType AllowedDespawnVehicleTypes = ExtVehicleType.None;
originalfoo marked this conversation as resolved.
Show resolved Hide resolved
}
}
1 change: 1 addition & 0 deletions TLM/TLM/State/OptionsTabs/MaintenanceTab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ internal static void MakeSettings_Maintenance(ExtUITabstrip tabStrip) {
CheckboxOption.ApplyIndent(_turnOnRedEnabledToggle);

MaintenanceTab_DespawnGroup.AddUI(panelHelper);
MaintenanceTab_AllowDespawnGroup.AddUI(panelHelper);

// TODO [issue ##959] remove when TTL is implemented in asset editor.
bool inEditor = TMPELifecycle.InGameOrEditor()
Expand Down
159 changes: 159 additions & 0 deletions TLM/TLM/State/OptionsTabs/MaintenanceTab_AllowDespawnGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
namespace TrafficManager.State {
using ColossalFramework;
using ICities;
using System.Collections.Generic;
using ColossalFramework.UI;
using ConfigData;
using CSUtil.Commons;
using TrafficManager.API.Traffic.Enums;
using TrafficManager.Lifecycle;
using TrafficManager.Manager.Impl;
using TrafficManager.UI;
using TrafficManager.UI.Helpers;
using Util;

/// <summary>Exclusions list for "Force No Despawning" feature</summary>
public static class MaintenanceTab_AllowDespawnGroup {

public static CheckboxOption AllowDespawnPassengerCars =
new ("AllowDespawnPassengerCar", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Passenger Car",
Handler = (bool newValue) => OnChange(ExtVehicleType.PassengerCar, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.PassengerCar)
krzychu124 marked this conversation as resolved.
Show resolved Hide resolved
};

public static CheckboxOption AllowDespawnBuses =
new ("AllowDespawnBus", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Buses",
Handler = (bool newValue) => OnChange(ExtVehicleType.Bus, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.Bus)
};

public static CheckboxOption AllowDespawnTaxis =
new ("AllowDespawnTaxi", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Taxis",
Handler = (bool newValue) => OnChange(ExtVehicleType.Taxi, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.Taxi)
};

public static CheckboxOption AllowDespawnTrams =
new ("AllowDespawnTram", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Trams",
Handler = (bool newValue) => OnChange(ExtVehicleType.Tram, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.Tram)
};

public static CheckboxOption AllowDespawnTrolleybuses =
new ("AllowDespawnTrolleybus", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Trolleybuses",
Handler = (bool newValue) => OnChange(ExtVehicleType.Trolleybus, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.Trolleybus)
};

/* TODO #1368 - not supported yet
public static CheckboxOption AllowDespawnPassengerPlanes =
new ("AllowDespawnPassengerPlane", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Passenger Planes",
Handler = (bool newValue) => OnChange(ExtVehicleType.PassengerPlane, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.PassengerPlane)
};
*/

public static CheckboxOption AllowDespawnPassengerTrains =
new ("AllowDespawnPassengerTrain", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Passenger Trains",
Handler = (bool newValue) => OnChange(ExtVehicleType.PassengerTrain, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.PassengerTrain)
};

/* TODO #1368 - not supported yet
public static CheckboxOption AllowDespawnCargoPlanes =
new ("AllowDespawnCargoPlane", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Cargo Planes",
Handler = (bool newValue) => OnChange(ExtVehicleType.CargoPlane, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.CargoPlane)
};
*/

public static CheckboxOption AllowDespawnCargoTrains =
new ("AllowDespawnCargoTrain", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Cargo Trains",
Handler = (bool newValue) => OnChange(ExtVehicleType.CargoTrain, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.CargoTrain)
};
public static CheckboxOption AllowDespawnCargoTrucks =
new ("AllowDespawnPassengerTruck", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Cargo Trucks",
Handler = (bool newValue) => OnChange(ExtVehicleType.CargoTruck, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.CargoTruck)
};
public static CheckboxOption AllowDespawnService =
new ("AllowDespawnService", Options.PersistTo.Global) {
Label = "AllowDespawn.Checkbox:Service vehicles",
Handler = (bool newValue) => OnChange(ExtVehicleType.Service, newValue),
Value = GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(ExtVehicleType.Service)
};

private static readonly Dictionary<CheckboxOption, ExtVehicleType> AllowDespawns = new ()
{
{ AllowDespawnPassengerCars, ExtVehicleType.PassengerCar },
{ AllowDespawnBuses, ExtVehicleType.Bus },
{ AllowDespawnTaxis, ExtVehicleType.Taxi },
{ AllowDespawnTrams, ExtVehicleType.Tram },
{ AllowDespawnTrolleybuses, ExtVehicleType.Trolleybus },
/*TODO #1368 - not supported yet
{ AllowDespawnPassengerPlanes, ExtVehicleType.PassengerPlane },
*/
{ AllowDespawnPassengerTrains, ExtVehicleType.PassengerTrain },
/*TODO #1368 - not supported yet
{ AllowDespawnCargoPlanes, ExtVehicleType.CargoPlane },
*/
{ AllowDespawnCargoTrains, ExtVehicleType.CargoTrain },
{ AllowDespawnCargoTrucks, ExtVehicleType.CargoTruck },
{ AllowDespawnService, ExtVehicleType.Service },
};

static MaintenanceTab_AllowDespawnGroup() {
// attach observer, update checkboxes with new values
GlobalConfigObserver configObserver = TMPELifecycle.Instance.gameObject.AddComponent<GlobalConfigObserver>();
configObserver.OnUpdateObservers += (config) => OnUpdateCheckboxes(config);
krzychu124 marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
/// Handles update of GlobalConfig in case of reload or reset
/// </summary>
/// <param name="config">New config instance after reload</param>
private static void OnUpdateCheckboxes(GlobalConfig config) {
Log._Debug("Updating Allow Despawn checkboxes with updated global config value");
foreach (KeyValuePair<CheckboxOption,ExtVehicleType> keyValuePair in AllowDespawns) {
keyValuePair.Key.Value = config.Gameplay.AllowedDespawnVehicleTypes.IsFlagSet(keyValuePair.Value);
}
krzychu124 marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
/// Adds "Allow Despawn" group to the specified <paramref name="tab"/>.
/// </summary>
/// <param name="tab">The parent UI panel.</param>
internal static void AddUI(UIHelperBase tab) {
var group = tab.AddGroup(T("Maintenance.Group:Allow Despawn"));

foreach (var allowed in AllowDespawns) {
allowed.Key.AddUI(group);
}
}

private static string T(string text) {
return Translation.Options.Get(text);
}

private static void OnChange(ExtVehicleType vehicleType, bool newVal) {
if (newVal) {
GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes |= vehicleType;
} else {
GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes &= ~vehicleType;
}
GlobalConfig.WriteConfig();
Log._Debug($"Updated GlobalConfig AllowedDespawnVehicleTypes: {GlobalConfig.Instance.Gameplay.AllowedDespawnVehicleTypes}");
}
}
}
2 changes: 2 additions & 0 deletions TLM/TLM/TLM.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,11 @@
<Compile Include="State\OptionsTabs\GameplayTab_VehicleBehaviourGroup.cs" />
<Compile Include="State\OptionsTabs\GeneralTab_InterfaceGroup.cs" />
<Compile Include="State\OptionsTabs\GeneralTab_SimulationGroup.cs" />
<Compile Include="State\OptionsTabs\MaintenanceTab_AllowDespawnGroup.cs" />
<Compile Include="State\OptionsTabs\MaintenanceTab_DespawnGroup.cs" />
<Compile Include="State\VersionInfo.cs" />
<Compile Include="UI\Helpers\ActionButton.cs" />
<Compile Include="UI\Helpers\GlobalConfigObserver.cs" />
<Compile Include="UI\Helpers\SliderOption.cs" />
<Compile Include="UI\Helpers\OptionButtonBase.cs" />
<Compile Include="UI\Helpers\UrlButton.cs" />
Expand Down
33 changes: 33 additions & 0 deletions TLM/TLM/UI/Helpers/GlobalConfigObserver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace TrafficManager.UI.Helpers {
using System;
using API.Util;
using CSUtil.Commons;
using State;
using UnityEngine;

/// <summary>
/// GlobalConfig observer implementation, can be attached to gameObject,
/// it will destroy itself before GameObject is going to be destroyed
/// </summary>
public class GlobalConfigObserver : MonoBehaviour, IObserver<GlobalConfig> {
private IDisposable _configSubscription;

public event Action<GlobalConfig> OnUpdateObservers = delegate {};

public void Awake() {
_configSubscription = GlobalConfig.Instance.Subscribe(this);
}

private void OnDestroy() {
Log._Debug("Destroying GlobalConfigObserver");
_configSubscription.Dispose();
_configSubscription = null;
OnUpdateObservers = null;
}

public void OnUpdate(GlobalConfig newConfig) {
Log._Debug("GlobalConfigObserver.OnUpdate() called!");
OnUpdateObservers(newConfig);
}
}
}
2 changes: 1 addition & 1 deletion TLM/TLM/UI/TrafficManagerTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1423,7 +1423,7 @@ private void DebugGuiDisplayCitizens() {

for (uint citizenInstanceId = 1; citizenInstanceId < CitizenManager.MAX_INSTANCE_COUNT; ++citizenInstanceId) {
ref CitizenInstance citizenInstance = ref citizenInstanceId.ToCitizenInstance();

if (!citizenInstance.IsCreated()) {
continue;
}
Expand Down