diff --git a/TLM/TLM/Custom/AI/CustomPostVanAI.cs b/TLM/TLM/Custom/AI/CustomPostVanAI.cs new file mode 100644 index 000000000..86ee385b8 --- /dev/null +++ b/TLM/TLM/Custom/AI/CustomPostVanAI.cs @@ -0,0 +1,115 @@ +using ColossalFramework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TrafficManager.Custom.PathFinding; +using TrafficManager.Traffic; +using TrafficManager.Traffic.Data; +using UnityEngine; +using static TrafficManager.Custom.PathFinding.CustomPathManager; + +namespace TrafficManager.Custom.AI { + public class CustomPostVanAI : CarAI { + public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { + if (vehicleData.m_transferType == (byte)TransferManager.TransferReason.Mail) { + return base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget); + } + + if ((vehicleData.m_flags & (Vehicle.Flags.TransferToSource | Vehicle.Flags.GoingBack)) != 0) { + return base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget); + } + + bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != (Vehicle.Flags)0; + PathUnit.Position startPosA = default(PathUnit.Position); + PathUnit.Position startPosB = default(PathUnit.Position); + float startDistSqrA = default(float); + float startDistSqrB = default(float); + + // try to find road start position + bool startPosFound = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, allowUnderground, false, 32f, out startPosA, out startPosB, out startDistSqrA, out startDistSqrB); + + // try to find other start position (plane, train, ship) + PathUnit.Position altStartPosA = default(PathUnit.Position); + PathUnit.Position altStartPosB = default(PathUnit.Position); + float altStartDistSqrA = default(float); + float altStartDistSqrB = default(float); + if (PathManager.FindPathPosition(startPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship | VehicleInfo.VehicleType.Plane, allowUnderground, false, 32f, out altStartPosA, out altStartPosB, out altStartDistSqrA, out altStartDistSqrB)) { + if (!startPosFound || (altStartDistSqrA < startDistSqrA && (Mathf.Abs(startPos.x) > 4800f || Mathf.Abs(startPos.z) > 4800f))) { + startPosA = altStartPosA; + startPosB = altStartPosB; + startDistSqrA = altStartDistSqrA; + startDistSqrB = altStartDistSqrB; + } + startPosFound = true; + } + + PathUnit.Position endPosA = default(PathUnit.Position); + PathUnit.Position endPosB = default(PathUnit.Position); + float endDistSqrA = default(float); + float endDistSqrB = default(float); + + // try to find road end position + bool endPosFound = PathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, undergroundTarget, false, 32f, out endPosA, out endPosB, out endDistSqrA, out endDistSqrB); + + // try to find other end position (plane, train, ship) + PathUnit.Position altEndPosA = default(PathUnit.Position); + PathUnit.Position altEndPosB = default(PathUnit.Position); + float altEndDistSqrA = default(float); + float altEndDistSqrB = default(float); + if (PathManager.FindPathPosition(endPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship | VehicleInfo.VehicleType.Plane, undergroundTarget, false, 32f, out altEndPosA, out altEndPosB, out altEndDistSqrA, out altEndDistSqrB)) { + if (!endPosFound || (altEndDistSqrA < endDistSqrA && (Mathf.Abs(endPos.x) > 4800f || Mathf.Abs(endPos.z) > 4800f))) { + endPosA = altEndPosA; + endPosB = altEndPosB; + endDistSqrA = altEndDistSqrA; + endDistSqrB = altEndDistSqrB; + } + endPosFound = true; + } + + if (startPosFound && endPosFound) { + CustomPathManager pathManager = CustomPathManager._instance; + if (!startBothWays || startDistSqrA < 10f) { + startPosB = default(PathUnit.Position); + } + if (!endBothWays || endDistSqrA < 10f) { + endPosB = default(PathUnit.Position); + } + uint path; + + PathCreationArgs args; + args.extPathType = ExtCitizenInstance.ExtPathType.None; + args.extVehicleType = ExtVehicleType.Service; + args.vehicleId = vehicleID; + args.spawned = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; + args.buildIndex = Singleton.instance.m_currentBuildIndex; + args.startPosA = startPosA; + args.startPosB = startPosB; + args.endPosA = endPosA; + args.endPosB = endPosB; + args.vehiclePosition = default(PathUnit.Position); + args.laneTypes = NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle; + args.vehicleTypes = VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Ship | VehicleInfo.VehicleType.Plane; + args.maxLength = 20000f; + args.isHeavyVehicle = this.IsHeavyVehicle(); + args.hasCombustionEngine = this.CombustionEngine(); + args.ignoreBlocked = this.IgnoreBlocked(vehicleID, ref vehicleData); + args.ignoreFlooded = false; + args.ignoreCosts = false; + args.randomParking = false; + args.stablePath = false; + args.skipQueue = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; + + if (pathManager.CreatePath(out path, ref Singleton.instance.m_randomizer, args)) { + if (vehicleData.m_path != 0) { + pathManager.ReleasePath(vehicleData.m_path); + } + vehicleData.m_path = path; + vehicleData.m_flags |= Vehicle.Flags.WaitingPath; + return true; + } + } + return false; + } + } +} diff --git a/TLM/TLM/Custom/PathFinding/CustomPathFind2.cs b/TLM/TLM/Custom/PathFinding/CustomPathFind2.cs index ccc859e57..fbcff6bef 100644 --- a/TLM/TLM/Custom/PathFinding/CustomPathFind2.cs +++ b/TLM/TLM/Custom/PathFinding/CustomPathFind2.cs @@ -414,7 +414,12 @@ private void PathFindImplementation(uint unit, ref PathUnit data) { } #if DEBUG - if (m_debug) { + bool detourMissing = (m_vehicleTypes & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Tram | VehicleInfo.VehicleType.Monorail | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None && !m_queueItem.queued; + if (detourMissing) { + Log.Warning($"Path-finding for unhandled vehicle requested!"); + } + + if (m_debug || detourMissing) { Debug(unit, $"PathFindImplementation: Preparing calculation:\n" + $"\tbufferItemStartA: segment={bufferItemStartA.m_position.m_segment} lane={bufferItemStartA.m_position.m_lane} off={bufferItemStartA.m_position.m_offset} laneId={bufferItemStartA.m_laneID}\n" + $"\tbufferItemStartB: segment={bufferItemStartB.m_position.m_segment} lane={bufferItemStartB.m_position.m_lane} off={bufferItemStartB.m_position.m_offset} laneId={bufferItemStartB.m_laneID}\n" + diff --git a/TLM/TLM/LoadingExtension.cs b/TLM/TLM/LoadingExtension.cs index 717cd5c51..3d2f5fd1c 100644 --- a/TLM/TLM/LoadingExtension.cs +++ b/TLM/TLM/LoadingExtension.cs @@ -2266,6 +2266,28 @@ public void initDetours() { detourFailed = true; } + Log.Info("Redirection PostVanAI::StartPathFind calls"); + try { + Detours.Add(new Detour(typeof(PostVanAI).GetMethod("StartPathFind", + BindingFlags.NonPublic | BindingFlags.Instance, + null, + new[] + { + typeof (ushort), + typeof (Vehicle).MakeByRefType(), + typeof (Vector3), + typeof (Vector3), + typeof (bool), + typeof (bool), + typeof (bool) + }, + null), + typeof(CustomPostVanAI).GetMethod("CustomStartPathFind"))); + } catch (Exception) { + Log.Error("Could not redirect PostVanAI::StartPathFind"); + detourFailed = true; + } + Log.Info("Redirection RoadBaseAI::SetTrafficLightState calls"); try { Detours.Add(new Detour(typeof(RoadBaseAI).GetMethod("SetTrafficLightState", diff --git a/TLM/TLM/TLM.csproj b/TLM/TLM/TLM.csproj index 7cb327aa8..c154daa11 100644 --- a/TLM/TLM/TLM.csproj +++ b/TLM/TLM/TLM.csproj @@ -103,6 +103,7 @@ +