Пример #1
0
        public static bool GetLast2Positions(this PathUnit unit, out PathUnit.Position position1, out PathUnit.Position position2)
        {
            uint num = unit.m_nextPathUnit;

            if (num != 0u)
            {
                PathManager instance     = Singleton <PathManager> .instance;
                int         num2         = 0;
                uint        nextPathUnit = instance.m_pathUnits.m_buffer[(int)(num)].m_nextPathUnit;
                while (nextPathUnit != 0u)
                {
                    num          = nextPathUnit;
                    nextPathUnit = instance.m_pathUnits.m_buffer[(int)(num)].m_nextPathUnit;
                    if (++num2 >= 262144)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                        position1 = default;
                        position2 = default;
                        return(false);
                    }
                }
                if (instance.m_pathUnits.m_buffer[(int)num].m_positionCount == 1)
                {
                    return(unit.GetPosition(unit.m_positionCount - 1, out position1) & instance.m_pathUnits.m_buffer[(int)num].GetLastPosition(out position2));
                }
                return(instance.m_pathUnits.m_buffer[(int)num].GetLast2Positions(out position1, out position2));
            }
            return(unit.GetPosition(unit.m_positionCount - 2, out position1) & unit.GetPosition(unit.m_positionCount - 1, out position2));
        }
 // from CitizenAI
 public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position)
 {
     position = default(PathUnit.Position);
     float num = 1E+10f;
     PathUnit.Position position2;
     PathUnit.Position position3;
     float num2;
     float num3;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, 32f, out position2, out position3, out num2, out num3, RoadManager.VehicleType.PassengerCar) && num2 < num)
     {
         num = num2;
         position = position2;
     }
     PathUnit.Position position4;
     PathUnit.Position position5;
     float num4;
     float num5;
     if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, 32f, out position4, out position5, out num4, out num5, RoadManager.VehicleType.PassengerCar) && num4 < num)
     {
         num = num4;
         position = position4;
     }
     PathUnit.Position position6;
     PathUnit.Position position7;
     float num6;
     float num7;
     if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && CustomPathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num)
     {
         position = position6;
     }
     return position.m_segment != 0;
 }
        public void CalculateSegmentPosition2(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, uint laneId, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            var instance = Singleton<NetManager>.instance;
            instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
            var info = instance.m_segments.m_buffer[position.m_segment].Info;
            if (info.m_lanes != null && info.m_lanes.Length > position.m_lane)
            {
                var laneSpeedLimit = info.m_lanes[position.m_lane].m_speedLimit;

                if (TrafficRoadRestrictions.IsSegment(position.m_segment))
                {
                    var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment);

                    if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f)
                    {
                        laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane];
                    }
                }

                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }
        }
        public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, ItemClass.Service vehicleService)
        {
            while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
            {
            }
            uint num;
            try
            {
                if (!this.m_pathUnits.CreateItem(out num, ref randomizer))
                {
                    unit = 0u;
                    bool result = false;
                    return result;
                }
                this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u);
            }
            finally
            {
                Monitor.Exit(this.m_bufferLock);
            }
            unit = num;

            byte simulationFlags = createSimulationFlag(isHeavyVehicle, ignoreBlocked, stablePath, vehicleService);
            assignPathProperties(unit, buildIndex, startPosA, startPosB, endPosA, endPosB, vehiclePosition, laneTypes, vehicleTypes, maxLength, simulationFlags);

            return findShortestPath(unit, skipQueue);
        }
Пример #5
0
        public static float GetFullPathLength(this PathUnit unit)
        {
            uint  num  = unit.m_nextPathUnit;
            float dist = 0;

            if (num != 0u)
            {
                PathManager instance = Singleton <PathManager> .instance;
                int         num2     = 0;
                dist += unit.m_length;
                uint nextPathUnit = instance.m_pathUnits.m_buffer[(int)(num)].m_nextPathUnit;
                while (nextPathUnit != 0u)
                {
                    num          = nextPathUnit;
                    nextPathUnit = instance.m_pathUnits.m_buffer[(int)(num)].m_nextPathUnit;
                    dist        += instance.m_pathUnits.m_buffer[(int)(num)].m_length;
                    if (++num2 >= 262144)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                        return(-1);
                    }
                }
                return(dist);
            }
            else
            {
                return(unit.m_length);
            }
        }
Пример #6
0
 public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPos, RoadManager.VehicleType vehicleType)
 {
     PathUnit.Position position2;
     float num;
     float num2;
     return CustomPathManager.FindPathPosition(position, service, laneType, vehicleTypes, allowUnderground, requireConnect, maxDistance, out pathPos, out position2, out num, out num2, vehicleType);
 }
Пример #7
0
        private bool PathContainsSegment(uint pathID, ushort segmentID, NetInfo.Direction dir)
        {
            PathUnit path = this.getPath(pathID);

            while (true)
            {
                // HACK: Dont inlude last segment as it will show vechicles arriving for both directions
                for (int i = 0; i < path.m_positionCount - 1; i++)
                {
                    PathUnit.Position p       = path.GetPosition(i);
                    NetSegment        segment = netMan.m_segments.m_buffer[(int)p.m_segment];

                    // Exclude paths with deleted segments
                    if (PathManager.GetLaneID(p) == 0 || (segment.m_flags & NetSegment.Flags.Deleted) != 0)
                    {
                        return(false);
                    }

                    if (p.m_segment == segmentID)
                    {
                        if (dir == NetInfo.Direction.Both)
                        {
                            return(true);
                        }

                        NetInfo           info    = netMan.m_segments.m_buffer[(int)p.m_segment].Info;
                        NetInfo.Direction laneDir = NetInfo.Direction.None;

                        if (info.m_lanes.Length > (int)p.m_lane)
                        {
                            laneDir = info.m_lanes[(int)p.m_lane].m_finalDirection;
                            if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                            {
                                laneDir = NetInfo.InvertDirection(laneDir);
                            }
                        }
                        else
                        {
                            Log.error("bad lane count");
                        }

                        if (laneDir == dir)
                        {
                            return(true);
                        }
//						} else if ((laneDir != NetInfo.Direction.Forward) && (laneDir != NetInfo.Direction.Backward)) {
                        //					Log.debug("laneDir = " + laneDir);
                        //				}
                    }
                }

                if (path.m_nextPathUnit == 0)
                {
                    return(false);
                }

                path = this.getPath(path.m_nextPathUnit);
            }
        }
 public static uint GetLaneID(PathUnit.Position pathPos)
 {
     NetManager instance = Singleton<NetManager>.instance;
     uint num = instance.m_segments.m_buffer[(int)pathPos.m_segment].m_lanes;
     int num2 = 0;
     while (num2 < (int)pathPos.m_lane && num != 0u)
     {
         num = instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane;
         num2++;
     }
     return num;
 }
 public static new uint GetLaneID(PathUnit.Position pathPos)
 {
     var netManager = Singleton<NetManager>.instance;
     var num = netManager.m_segments.m_buffer[pathPos.m_segment].m_lanes;
     var num2 = 0;
     while (num2 < pathPos.m_lane && num != 0u)
     {
         num = netManager.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane;
         num2++;
     }
     return num;
 }
Пример #10
0
        private bool PathContainsSegment(uint pathID, ushort segmentID)
        {
            PathUnit path = this.getPath(pathID);

            while (true)
            {
                for (int i = 0; i < path.m_positionCount; i++)
                {
                    PathUnit.Position p = path.GetPosition(i);
                    if (p.m_segment == segmentID)
                    {
                        return(true);
                    }
                }

                if (path.m_nextPathUnit == 0)
                {
                    return(false);
                }
                path = this.getPath(path.m_nextPathUnit);
            }
        }
Пример #11
0
    Vector2 m_TargetPos;                        // 走路的终点

    // 建立导航网格路径
    int BuildNavMeshPath(Vector2 fvCurrent, Vector2 fvTarget, int nPassLevel)
    {
        // 先清空路径.
        m_vPosStack.Clear();
        List <Vector2> pathList = null;

        PathResCode pathResult = PathFinder.Instance.FindPath(fvCurrent, fvTarget, out pathList, 0);

        if (pathList.Count >= 2)
        {
            PathUnit pu = new PathUnit();
            pu.fvStart = pathList[0];
            for (int i = 1; i < pathList.Count; i++)
            {
                Vector2 pt = pathList[i];
                pu.fvTarget = pt;
                m_vPosStack.Add(pu);
                pu.fvStart = pu.fvTarget;
            }
        }
        return(m_vPosStack.Count);
    }
		public void CustomCalculateSegmentPositionPathFinder(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			CalculateSegPos(vehicleID, ref vehicleData, position, laneID, offset, out pos, out dir, out maxSpeed);
		}
Пример #13
0
        public void CustomSimulationStep(ushort vehicleID, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ushort leaderID, ref Vehicle leaderData, int lodPhysics)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[16] && GlobalConfig.Instance.Debug.NodeId == vehicleID;
#endif

            ushort      leadingVehicle    = vehicleData.m_leadingVehicle;
            uint        currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            VehicleInfo leaderInfo;
            if (leaderID != vehicleID)
            {
                leaderInfo = leaderData.Info;
            }
            else
            {
                leaderInfo = this.m_info;
            }
            TramBaseAI tramBaseAI = leaderInfo.m_vehicleAI as TramBaseAI;

            if (leadingVehicle != 0)
            {
                frameData.m_position += frameData.m_velocity * 0.4f;
            }
            else
            {
                frameData.m_position += frameData.m_velocity * 0.5f;
            }

            frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f;
            Vector3 wheelBaseRot      = frameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);
            Vector3 posAfterWheelRot  = frameData.m_position + wheelBaseRot;
            Vector3 posBeforeWheelRot = frameData.m_position - wheelBaseRot;

            float acceleration = this.m_info.m_acceleration;
            float braking      = this.m_info.m_braking;
            float curSpeed     = frameData.m_velocity.magnitude;

            Vector3 afterRotToTargetPos1Diff       = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot;
            float   afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude;

            Quaternion curInvRot    = Quaternion.Inverse(frameData.m_rotation);
            Vector3    curveTangent = curInvRot * frameData.m_velocity;

#if DEBUG
            if (debug)
            {
                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): ================================================");
                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): leadingVehicle={leadingVehicle} frameData.m_position={frameData.m_position} frameData.m_swayPosition={frameData.m_swayPosition} wheelBaseRot={wheelBaseRot} posAfterWheelRot={posAfterWheelRot} posBeforeWheelRot={posBeforeWheelRot} acceleration={acceleration} braking={braking} curSpeed={curSpeed} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag} curInvRot={curInvRot} curveTangent={curveTangent} this.m_info.m_generatedInfo.m_wheelBase={this.m_info.m_generatedInfo.m_wheelBase}");
            }
#endif

            Vector3 forward      = Vector3.forward;
            Vector3 targetMotion = Vector3.zero;
            float   targetSpeed  = 0f;
            float   motionFactor = 0.5f;
            float   turnAngle    = 0f;
            if (leadingVehicle != 0)
            {
                VehicleManager vehMan = Singleton <VehicleManager> .instance;
                Vehicle.Frame  leadingVehLastFrameData = vehMan.m_vehicles.m_buffer[(int)leadingVehicle].GetLastFrameData();
                VehicleInfo    leadingVehInfo          = vehMan.m_vehicles.m_buffer[(int)leadingVehicle].Info;

                float attachOffset;
                if ((vehicleData.m_flags & Vehicle.Flags.Inverted) != (Vehicle.Flags) 0)
                {
                    attachOffset = this.m_info.m_attachOffsetBack - this.m_info.m_generatedInfo.m_size.z * 0.5f;
                }
                else
                {
                    attachOffset = this.m_info.m_attachOffsetFront - this.m_info.m_generatedInfo.m_size.z * 0.5f;
                }

                float leadingAttachOffset;
                if ((vehMan.m_vehicles.m_buffer[(int)leadingVehicle].m_flags & Vehicle.Flags.Inverted) != (Vehicle.Flags) 0)
                {
                    leadingAttachOffset = leadingVehInfo.m_attachOffsetFront - leadingVehInfo.m_generatedInfo.m_size.z * 0.5f;
                }
                else
                {
                    leadingAttachOffset = leadingVehInfo.m_attachOffsetBack - leadingVehInfo.m_generatedInfo.m_size.z * 0.5f;
                }

                Vector3 curPosMinusRotAttachOffset    = frameData.m_position - frameData.m_rotation * new Vector3(0f, 0f, attachOffset);
                Vector3 leadingPosPlusRotAttachOffset = leadingVehLastFrameData.m_position + leadingVehLastFrameData.m_rotation * new Vector3(0f, 0f, leadingAttachOffset);

                wheelBaseRot = leadingVehLastFrameData.m_rotation * new Vector3(0f, 0f, leadingVehInfo.m_generatedInfo.m_wheelBase * 0.5f);
                Vector3 leadingPosBeforeWheelRot = leadingVehLastFrameData.m_position - wheelBaseRot;

                if (Vector3.Dot(vehicleData.m_targetPos1 - vehicleData.m_targetPos0, (Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) < 0f && vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                {
                    int someIndex = -1;
                    InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, 0, ref leaderData, ref someIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f);
                    afterRotToTargetPos1DiffSqrMag = 0f;
                }

                float attachRotDist = Mathf.Max(Vector3.Distance(curPosMinusRotAttachOffset, leadingPosPlusRotAttachOffset), 2f);

                float one = 1f;
                float attachRotSqrDist = attachRotDist * attachRotDist;
                float oneSqr           = one * one;
                int   i = 0;
                if (afterRotToTargetPos1DiffSqrMag < attachRotSqrDist)
                {
                    if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                    {
                        InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, posBeforeWheelRot, posAfterWheelRot, 0, ref leaderData, ref i, 1, 2, attachRotSqrDist, oneSqr);
                    }
                    while (i < 4)
                    {
                        vehicleData.SetTargetPos(i, vehicleData.GetTargetPos(i - 1));
                        i++;
                    }
                    afterRotToTargetPos1Diff       = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot;
                    afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude;
                }
                afterRotToTargetPos1Diff = curInvRot * afterRotToTargetPos1Diff;

                float negTotalAttachLen = -((this.m_info.m_generatedInfo.m_wheelBase + leadingVehInfo.m_generatedInfo.m_wheelBase) * 0.5f + attachOffset + leadingAttachOffset);
                bool  hasPath           = false;
                if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                {
                    float u1;
                    float u2;
                    if (Line3.Intersect(posAfterWheelRot, vehicleData.m_targetPos1, leadingPosBeforeWheelRot, negTotalAttachLen, out u1, out u2))
                    {
                        targetMotion = afterRotToTargetPos1Diff * Mathf.Clamp(Mathf.Min(u1, u2) / 0.6f, 0f, 2f);
                    }
                    else
                    {
                        Line3.DistanceSqr(posAfterWheelRot, vehicleData.m_targetPos1, leadingPosBeforeWheelRot, out u1);
                        targetMotion = afterRotToTargetPos1Diff * Mathf.Clamp(u1 / 0.6f, 0f, 2f);
                    }
                    hasPath = true;
                }

                if (hasPath)
                {
                    if (Vector3.Dot(leadingPosBeforeWheelRot - posAfterWheelRot, posAfterWheelRot - posBeforeWheelRot) < 0f)
                    {
                        motionFactor = 0f;
                    }
                }
                else
                {
                    float leadingPosBeforeToAfterWheelRotDist = Vector3.Distance(leadingPosBeforeWheelRot, posAfterWheelRot);
                    motionFactor = 0f;
                    targetMotion = curInvRot * ((leadingPosBeforeWheelRot - posAfterWheelRot) * (Mathf.Max(0f, leadingPosBeforeToAfterWheelRotDist - negTotalAttachLen) / Mathf.Max(1f, leadingPosBeforeToAfterWheelRotDist * 0.6f)));
                }
            }
            else
            {
                float estimatedFrameDist = (curSpeed + acceleration) * (0.5f + 0.5f * (curSpeed + acceleration) / braking) + (this.m_info.m_generatedInfo.m_size.z - this.m_info.m_generatedInfo.m_wheelBase) * 0.5f;
                float maxSpeedAdd        = Mathf.Max(curSpeed + acceleration, 2f);
                float meanSpeedAdd       = Mathf.Max((estimatedFrameDist - maxSpeedAdd) / 2f, 2f);
                float maxSpeedAddSqr     = maxSpeedAdd * maxSpeedAdd;
                float meanSpeedAddSqr    = meanSpeedAdd * meanSpeedAdd;
                if (Vector3.Dot(vehicleData.m_targetPos1 - vehicleData.m_targetPos0, (Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) < 0f && vehicleData.m_path != 0u && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == (Vehicle.Flags) 0)
                {
                    int someIndex = -1;
                    InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, leaderID, ref leaderData, ref someIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f);
                    afterRotToTargetPos1DiffSqrMag = 0f;
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): dot < 0");
                    }
#endif
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Leading vehicle is 0. vehicleData.m_targetPos0={vehicleData.m_targetPos0} vehicleData.m_targetPos1={vehicleData.m_targetPos1} posBeforeWheelRot={posBeforeWheelRot} posBeforeWheelRot={posAfterWheelRot} estimatedFrameDist={estimatedFrameDist} maxSpeedAdd={maxSpeedAdd} meanSpeedAdd={meanSpeedAdd} maxSpeedAddSqr={maxSpeedAddSqr} meanSpeedAddSqr={meanSpeedAddSqr} afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag}");
                }
#endif

                int  posIndex = 0;
                bool hasValidPathTargetPos = false;
                if ((afterRotToTargetPos1DiffSqrMag < maxSpeedAddSqr || vehicleData.m_targetPos3.w < 0.01f) && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == (Vehicle.Flags) 0)
                {
                    if (vehicleData.m_path != 0u)
                    {
                        InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, posBeforeWheelRot, posAfterWheelRot, leaderID, ref leaderData, ref posIndex, 1, 4, maxSpeedAddSqr, meanSpeedAddSqr);
                    }
                    if (posIndex < 4)
                    {
                        hasValidPathTargetPos = true;
                        while (posIndex < 4)
                        {
                            vehicleData.SetTargetPos(posIndex, vehicleData.GetTargetPos(posIndex - 1));
                            posIndex++;
                        }
                    }
                    afterRotToTargetPos1Diff       = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot;
                    afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude;
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): posIndex={posIndex} hasValidPathTargetPos={hasValidPathTargetPos}");
                }
#endif

                if (leaderData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                {
                    NetManager netMan               = Singleton <NetManager> .instance;
                    byte       leaderPathPosIndex   = leaderData.m_pathPositionIndex;
                    byte       leaderLastPathOffset = leaderData.m_lastPathOffset;
                    if (leaderPathPosIndex == 255)
                    {
                        leaderPathPosIndex = 0;
                    }
                    float leaderLen = 1f + leaderData.CalculateTotalLength(leaderID);

#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): leaderPathPosIndex={leaderPathPosIndex} leaderLastPathOffset={leaderLastPathOffset} leaderPathPosIndex={leaderPathPosIndex} leaderLen={leaderLen}");
                    }
#endif

                    // reserve space / add traffic
                    PathManager       pathMan = Singleton <PathManager> .instance;
                    PathUnit.Position pathPos;
                    if (pathMan.m_pathUnits.m_buffer[leaderData.m_path].GetPosition(leaderPathPosIndex >> 1, out pathPos))
                    {
                        netMan.m_segments.m_buffer[(int)pathPos.m_segment].AddTraffic(Mathf.RoundToInt(leaderLen * 2.5f));
                        bool reservedSpaceOnCurrentLane = false;
                        if ((leaderPathPosIndex & 1) == 0 || leaderLastPathOffset == 0)
                        {
                            uint laneId = PathManager.GetLaneID(pathPos);
                            if (laneId != 0u)
                            {
                                Vector3 curPathOffsetPos = netMan.m_lanes.m_buffer[laneId].CalculatePosition((float)pathPos.m_offset * 0.003921569f);
                                float   speedAdd         = 0.5f * curSpeed * curSpeed / this.m_info.m_braking;
                                float   afterWheelRotCurPathOffsetDist  = Vector3.Distance(posAfterWheelRot, curPathOffsetPos);
                                float   beforeWheelRotCurPathOffsetDist = Vector3.Distance(posBeforeWheelRot, curPathOffsetPos);
                                if (Mathf.Min(afterWheelRotCurPathOffsetDist, beforeWheelRotCurPathOffsetDist) >= speedAdd - 1f)
                                {
                                    netMan.m_lanes.m_buffer[laneId].ReserveSpace(leaderLen);
                                    reservedSpaceOnCurrentLane = true;
                                }
                            }
                        }

                        if (!reservedSpaceOnCurrentLane && pathMan.m_pathUnits.m_buffer[leaderData.m_path].GetNextPosition(leaderPathPosIndex >> 1, out pathPos))
                        {
                            uint nextLaneId = PathManager.GetLaneID(pathPos);
                            if (nextLaneId != 0u)
                            {
                                netMan.m_lanes.m_buffer[nextLaneId].ReserveSpace(leaderLen);
                            }
                        }
                    }

                    if ((ulong)(currentFrameIndex >> 4 & 15u) == (ulong)((long)(leaderID & 15)))
                    {
                        // check if vehicle can proceed to next path position

                        bool canProceeed           = false;
                        uint curLeaderPathId       = leaderData.m_path;
                        int  curLeaderPathPosIndex = leaderPathPosIndex >> 1;
                        int  k = 0;
                        while (k < 5)
                        {
                            bool invalidPos;
                            if (PathUnit.GetNextPosition(ref curLeaderPathId, ref curLeaderPathPosIndex, out pathPos, out invalidPos))
                            {
                                uint laneId = PathManager.GetLaneID(pathPos);
                                if (laneId != 0u && !netMan.m_lanes.m_buffer[laneId].CheckSpace(leaderLen))
                                {
                                    k++;
                                    continue;
                                }
                            }
                            if (invalidPos)
                            {
                                this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                            }
                            canProceeed = true;
                            break;
                        }
                        if (!canProceeed)
                        {
                            leaderData.m_flags |= Vehicle.Flags.Congestion;
                        }
                    }
                }

                float maxSpeed;
                if ((leaderData.m_flags & Vehicle.Flags.Stopped) != (Vehicle.Flags) 0)
                {
                    maxSpeed = 0f;
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is stopped. maxSpeed={maxSpeed}");
                    }
#endif
                }
                else
                {
                    maxSpeed = Mathf.Min(vehicleData.m_targetPos1.w, GetMaxSpeed(leaderID, ref leaderData));
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is not stopped. maxSpeed={maxSpeed}");
                    }
#endif
                }

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Start of second part. curSpeed={curSpeed} curInvRot={curInvRot}");
                }
#endif

                afterRotToTargetPos1Diff = curInvRot * afterRotToTargetPos1Diff;
#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} (old afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag})");
                }
#endif
                Vector3 zero       = Vector3.zero;
                bool    blocked    = false;
                float   forwardLen = 0f;
                if (afterRotToTargetPos1DiffSqrMag > 1f)                   // TODO why is this not recalculated?
                {
                    forward = VectorUtils.NormalizeXZ(afterRotToTargetPos1Diff, out forwardLen);
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1DiffSqrMag > 1f. forward={forward} forwardLen={forwardLen}");
                    }
#endif
                    if (forwardLen > 1f)
                    {
                        Vector3 fwd = afterRotToTargetPos1Diff;
                        maxSpeedAdd    = Mathf.Max(curSpeed, 2f);
                        maxSpeedAddSqr = maxSpeedAdd * maxSpeedAdd;
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): forwardLen > 1f. fwd={fwd} maxSpeedAdd={maxSpeedAdd} maxSpeedAddSqr={maxSpeedAddSqr}");
                        }
#endif
                        if (afterRotToTargetPos1DiffSqrMag > maxSpeedAddSqr)
                        {
                            float fwdLimiter = maxSpeedAdd / Mathf.Sqrt(afterRotToTargetPos1DiffSqrMag);
                            fwd.x *= fwdLimiter;
                            fwd.y *= fwdLimiter;

#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1DiffSqrMag > maxSpeedAddSqr. afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag} maxSpeedAddSqr={maxSpeedAddSqr} fwdLimiter={fwdLimiter} fwd={fwd}");
                            }
#endif
                        }

                        if (fwd.z < -1f)                           // !!!
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): fwd.z < -1f. fwd={fwd}");
                            }
#endif

                            if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0)
                            {
                                Vector3 targetPos0TargetPos1Diff = vehicleData.m_targetPos1 - vehicleData.m_targetPos0;
                                if ((curInvRot * targetPos0TargetPos1Diff).z < -0.01f)                                   // !!!
                                {
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): (curInvRot * targetPos0TargetPos1Diff).z < -0.01f. curInvRot={curInvRot} targetPos0TargetPos1Diff={targetPos0TargetPos1Diff}");
                                    }
#endif
                                    if (afterRotToTargetPos1Diff.z < Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f)                                       // !!!
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff.z < Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f. fwd={fwd} targetPos0TargetPos1Diff={targetPos0TargetPos1Diff} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff}");
                                        }
#endif

                                        /*fwd.z = 0f;
                                         * afterRotToTargetPos1Diff = Vector3.zero;*/
                                        maxSpeed = 0.5f;                                         // NON-STOCK CODE

#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): (1) set maxSpeed={maxSpeed}");
                                        }
#endif
                                    }
                                    else
                                    {
                                        posAfterWheelRot = posBeforeWheelRot + Vector3.Normalize(vehicleData.m_targetPos1 - vehicleData.m_targetPos0) * this.m_info.m_generatedInfo.m_wheelBase;
                                        posIndex         = -1;
                                        InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, vehicleData.m_targetPos1, leaderID, ref leaderData, ref posIndex, 0, 0, Vector3.SqrMagnitude(vehicleData.m_targetPos1 - vehicleData.m_targetPos0) + 1f, 1f);

#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff.z >= Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f. Invoked UpdatePathTargetPositions. posAfterWheelRot={posAfterWheelRot} posBeforeWheelRot={posBeforeWheelRot} this.m_info.m_generatedInfo.m_wheelBase={this.m_info.m_generatedInfo.m_wheelBase}");
                                        }
#endif
                                    }
                                }
                                else
                                {
                                    posIndex = -1;
                                    InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, leaderID, ref leaderData, ref posIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f);
                                    vehicleData.m_targetPos1 = posAfterWheelRot;
                                    fwd.z = 0f;
                                    afterRotToTargetPos1Diff = Vector3.zero;
                                    maxSpeed = 0f;

#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is waiting for a path. posIndex={posIndex} vehicleData.m_targetPos1={vehicleData.m_targetPos1} fwd={fwd} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} maxSpeed={maxSpeed}");
                                    }
#endif
                                }
                            }
                            motionFactor = 0f;
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Reset motion factor. motionFactor={motionFactor}");
                            }
#endif
                        }

                        forward = VectorUtils.NormalizeXZ(fwd, out forwardLen);
                        float curve = Mathf.PI / 2f /* 1.57079637f*/ * (1f - forward.z);                       // <- constant: a bit inaccurate PI/2
                        if (forwardLen > 1f)
                        {
                            curve /= forwardLen;
                        }
                        float targetDist = forwardLen;
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): targetDist={targetDist} fwd={fwd} curve={curve} maxSpeed={maxSpeed}");
                        }
#endif

                        if (vehicleData.m_targetPos1.w < 0.1f)
                        {
                            maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve);
                            maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos1.w, braking * 0.9f));
                        }
                        else
                        {
                            maxSpeed = Mathf.Min(maxSpeed, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve));
                        }
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [1] maxSpeed={maxSpeed}");
                        }
#endif
                        maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos2.w, braking * 0.9f));
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [2] maxSpeed={maxSpeed}");
                        }
#endif
                        targetDist += VectorUtils.LengthXZ(vehicleData.m_targetPos2 - vehicleData.m_targetPos1);
                        maxSpeed    = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos3.w, braking * 0.9f));
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [3] maxSpeed={maxSpeed}");
                        }
#endif
                        targetDist += VectorUtils.LengthXZ(vehicleData.m_targetPos3 - vehicleData.m_targetPos2);
                        if (vehicleData.m_targetPos3.w < 0.01f)
                        {
                            targetDist = Mathf.Max(0f, targetDist + (this.m_info.m_generatedInfo.m_wheelBase - this.m_info.m_generatedInfo.m_size.z) * 0.5f);
                        }
                        maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, 0f, braking * 0.9f));
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [4] maxSpeed={maxSpeed}");
                        }
#endif
                        CarAI.CheckOtherVehicles(vehicleID, ref vehicleData, ref frameData, ref maxSpeed, ref blocked, ref zero, estimatedFrameDist, braking * 0.9f, lodPhysics);
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): CheckOtherVehicles finished. blocked={blocked}");
                        }
#endif
                        if (maxSpeed < curSpeed)
                        {
                            float brake = Mathf.Max(acceleration, Mathf.Min(braking, curSpeed));
                            targetSpeed = Mathf.Max(maxSpeed, curSpeed - brake);
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): maxSpeed < curSpeed. maxSpeed={maxSpeed} curSpeed={curSpeed} brake={brake} targetSpeed={targetSpeed}");
                            }
#endif
                        }
                        else
                        {
                            float accel = Mathf.Max(acceleration, Mathf.Min(braking, -curSpeed));
                            targetSpeed = Mathf.Min(maxSpeed, curSpeed + accel);
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): maxSpeed >= curSpeed. maxSpeed={maxSpeed} curSpeed={curSpeed} accel={accel} targetSpeed={targetSpeed}");
                            }
#endif
                        }
                    }
                }
                else if (curSpeed < 0.1f && hasValidPathTargetPos && leaderInfo.m_vehicleAI.ArriveAtDestination(leaderID, ref leaderData))
                {
                    leaderData.Unspawn(leaderID);
                    return;
                }
                if ((leaderData.m_flags & Vehicle.Flags.Stopped) == (Vehicle.Flags) 0 && maxSpeed < 0.1f)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is not stopped but maxSpeed < 0.1. maxSpeed={maxSpeed}");
                    }
#endif
                    blocked = true;
                }
                if (blocked)
                {
                    leaderData.m_blockCounter = (byte)Mathf.Min((int)(leaderData.m_blockCounter + 1), 255);
                }
                else
                {
                    leaderData.m_blockCounter = 0;
                }
                if (forwardLen > 1f)
                {
                    turnAngle    = Mathf.Asin(forward.x) * Mathf.Sign(targetSpeed);
                    targetMotion = forward * targetSpeed;
                }
                else
                {
                    Vector3 vel = Vector3.ClampMagnitude(afterRotToTargetPos1Diff * 0.5f - curveTangent, braking);
                    targetMotion = curveTangent + vel;
                }
            }
            bool    mayBlink = (currentFrameIndex + (uint)leaderID & 16u) != 0u;
            Vector3 springs  = targetMotion - curveTangent;
            Vector3 targetAfterWheelRotMotion  = frameData.m_rotation * targetMotion;
            Vector3 targetBeforeWheelRotMotion = Vector3.Normalize((Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) * (targetMotion.magnitude * motionFactor);
            targetBeforeWheelRotMotion -= targetAfterWheelRotMotion * (Vector3.Dot(targetAfterWheelRotMotion, targetBeforeWheelRotMotion) / Mathf.Max(1f, targetAfterWheelRotMotion.sqrMagnitude));
            posAfterWheelRot           += targetAfterWheelRotMotion;
            posBeforeWheelRot          += targetBeforeWheelRotMotion;
            frameData.m_rotation        = Quaternion.LookRotation(posAfterWheelRot - posBeforeWheelRot);
            Vector3 targetPos = posAfterWheelRot - frameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);
            frameData.m_velocity = targetPos - frameData.m_position;
            if (leadingVehicle != 0)
            {
                frameData.m_position += frameData.m_velocity * 0.6f;
            }
            else
            {
                frameData.m_position += frameData.m_velocity * 0.5f;
            }
            frameData.m_swayVelocity    = frameData.m_swayVelocity * (1f - this.m_info.m_dampers) - springs * (1f - this.m_info.m_springs) - frameData.m_swayPosition * this.m_info.m_springs;
            frameData.m_swayPosition   += frameData.m_swayVelocity * 0.5f;
            frameData.m_steerAngle      = 0f;
            frameData.m_travelDistance += targetMotion.z;
            if (leadingVehicle != 0)
            {
                frameData.m_lightIntensity = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[(int)leaderID].GetLastFrameData().m_lightIntensity;
            }
            else
            {
                frameData.m_lightIntensity.x = 5f;
                frameData.m_lightIntensity.y = ((springs.z >= -0.1f) ? 0.5f : 5f);
                frameData.m_lightIntensity.z = ((turnAngle >= -0.1f || !mayBlink) ? 0f : 5f);
                frameData.m_lightIntensity.w = ((turnAngle <= 0.1f || !mayBlink) ? 0f : 5f);
            }
            frameData.m_underground = ((vehicleData.m_flags & Vehicle.Flags.Underground) != (Vehicle.Flags) 0);
            frameData.m_transition  = ((vehicleData.m_flags & Vehicle.Flags.Transition) != (Vehicle.Flags) 0);
            //base.SimulationStep(vehicleID, ref vehicleData, ref frameData, leaderID, ref leaderData, lodPhysics);
        }
Пример #14
0
 public new bool NeedChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID, VehicleInfo.VehicleType laneVehicleType, ref Vector4 target)
 {
     return base.NeedChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID, laneVehicleType, ref target);
 }
Пример #15
0
 public new void CalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
 {
     base.CalculateSegmentPosition(vehicleID, ref vehicleData, nextPosition, position, laneID, offset, prevPos, prevLaneID, prevOffset, out pos, out dir, out maxSpeed);
 }
        protected virtual void PathFindImplementation(uint unit, ref PathUnit data)
        {
            NetManager instance = Singleton<NetManager>.instance;
            this.m_laneTypes = (NetInfo.LaneType)this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes;
            this.m_vehicleTypes = (VehicleInfo.VehicleType)this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes;
            this.m_maxLength = this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length;
            this.m_pathFindIndex = (this.m_pathFindIndex + 1u & 32767u);
            this.m_pathRandomizer = new Randomizer(unit);
            this.m_isHeavyVehicle = ((this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 16) != 0);
            this.m_ignoreBlocked = ((this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 32) != 0);
            this.m_stablePath = ((this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags & 64) != 0);
            this.m_transportVehicle = ((byte)(this.m_laneTypes & NetInfo.LaneType.TransportVehicle) != 0);
            if ((byte)(this.m_laneTypes & NetInfo.LaneType.Vehicle) != 0)
            {
                this.m_laneTypes |= NetInfo.LaneType.TransportVehicle;
            }

            int num = (int)(this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount & 15);
            int num2 = this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount >> 4;
            BufferItem bufferItem;
            if (data.m_position00.m_segment != 0 && num >= 1)
            {
                this.m_startLaneA = PathManager.GetLaneID(data.m_position00);
                this.m_startOffsetA = data.m_position00.m_offset;
                bufferItem.m_laneID = this.m_startLaneA;
                bufferItem.m_position = data.m_position00;
                this.GetLaneDirection(data.m_position00, out bufferItem.m_direction, out bufferItem.m_lanesUsed);
                bufferItem.m_comparisonValue = 0f;
            }
            else
            {
                this.m_startLaneA = 0u;
                this.m_startOffsetA = 0;
                bufferItem = default(BufferItem);
            }
            BufferItem bufferItem2;
            if (data.m_position02.m_segment != 0 && num >= 3)
            {
                this.m_startLaneB = PathManager.GetLaneID(data.m_position02);
                this.m_startOffsetB = data.m_position02.m_offset;
                bufferItem2.m_laneID = this.m_startLaneB;
                bufferItem2.m_position = data.m_position02;
                this.GetLaneDirection(data.m_position02, out bufferItem2.m_direction, out bufferItem2.m_lanesUsed);
                bufferItem2.m_comparisonValue = 0f;
            }
            else
            {
                this.m_startLaneB = 0u;
                this.m_startOffsetB = 0;
                bufferItem2 = default(BufferItem);
            }
            BufferItem bufferItem3;
            if (data.m_position01.m_segment != 0 && num >= 2)
            {
                this.m_endLaneA = PathManager.GetLaneID(data.m_position01);
                bufferItem3.m_laneID = this.m_endLaneA;
                bufferItem3.m_position = data.m_position01;
                this.GetLaneDirection(data.m_position01, out bufferItem3.m_direction, out bufferItem3.m_lanesUsed);
                bufferItem3.m_methodDistance = 0f;
                bufferItem3.m_comparisonValue = 0f;
            }
            else
            {
                this.m_endLaneA = 0u;
                bufferItem3 = default(BufferItem);
            }
            BufferItem bufferItem4;
            if (data.m_position03.m_segment != 0 && num >= 4)
            {
                this.m_endLaneB = PathManager.GetLaneID(data.m_position03);
                bufferItem4.m_laneID = this.m_endLaneB;
                bufferItem4.m_position = data.m_position03;
                this.GetLaneDirection(data.m_position03, out bufferItem4.m_direction, out bufferItem4.m_lanesUsed);
                bufferItem4.m_methodDistance = 0f;
                bufferItem4.m_comparisonValue = 0f;
            }
            else
            {
                this.m_endLaneB = 0u;
                bufferItem4 = default(BufferItem);
            }
            if (data.m_position11.m_segment != 0 && num2 >= 1)
            {
                this.m_vehicleLane = PathManager.GetLaneID(data.m_position11);
                this.m_vehicleOffset = data.m_position11.m_offset;
            }
            else
            {
                this.m_vehicleLane = 0u;
                this.m_vehicleOffset = 0;
            }
            BufferItem bufferItem5 = default(BufferItem);
            byte b = 0;
            this.m_bufferMinPos = 0;
            this.m_bufferMaxPos = -1;
            if (this.m_pathFindIndex == 0u)
            {
                uint num3 = 4294901760u;
                for (int i = 0; i < 262144; i++)
                {
                    this.m_laneLocation[i] = num3;
                }
            }
            for (int j = 0; j < 1024; j++)
            {
                this.m_bufferMin[j] = 0;
                this.m_bufferMax[j] = -1;
            }
            if (bufferItem3.m_position.m_segment != 0)
            {
                this.m_bufferMax[0]++;
                this.m_buffer[++this.m_bufferMaxPos] = bufferItem3;
            }
            if (bufferItem4.m_position.m_segment != 0)
            {
                this.m_bufferMax[0]++;
                this.m_buffer[++this.m_bufferMaxPos] = bufferItem4;
            }
            bool flag = false;
            while (this.m_bufferMinPos <= this.m_bufferMaxPos)
            {
                int num4 = this.m_bufferMin[this.m_bufferMinPos];
                int num5 = this.m_bufferMax[this.m_bufferMinPos];
                if (num4 > num5)
                {
                    this.m_bufferMinPos++;
                }
                else
                {
                    this.m_bufferMin[this.m_bufferMinPos] = num4 + 1;
                    BufferItem bufferItem6 = this.m_buffer[(this.m_bufferMinPos << 6) + num4];
                    if (bufferItem6.m_position.m_segment == bufferItem.m_position.m_segment && bufferItem6.m_position.m_lane == bufferItem.m_position.m_lane)
                    {
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Forward) != 0 && bufferItem6.m_position.m_offset >= this.m_startOffsetA)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetA;
                            flag = true;
                            break;
                        }
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Backward) != 0 && bufferItem6.m_position.m_offset <= this.m_startOffsetA)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetA;
                            flag = true;
                            break;
                        }
                    }
                    if (bufferItem6.m_position.m_segment == bufferItem2.m_position.m_segment && bufferItem6.m_position.m_lane == bufferItem2.m_position.m_lane)
                    {
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Forward) != 0 && bufferItem6.m_position.m_offset >= this.m_startOffsetB)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetB;
                            flag = true;
                            break;
                        }
                        if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Backward) != 0 && bufferItem6.m_position.m_offset <= this.m_startOffsetB)
                        {
                            bufferItem5 = bufferItem6;
                            b = this.m_startOffsetB;
                            flag = true;
                            break;
                        }
                    }
                    if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Forward) != 0)
                    {
                        ushort startNode = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_startNode;
                        this.ProcessItem(bufferItem6, startNode, ref instance.m_nodes.m_buffer[(int)startNode], 0, false);
                    }
                    if ((byte)(bufferItem6.m_direction & NetInfo.Direction.Backward) != 0)
                    {
                        ushort endNode = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_endNode;
                        this.ProcessItem(bufferItem6, endNode, ref instance.m_nodes.m_buffer[(int)endNode], 255, false);
                    }
                    int num6 = 0;
                    ushort num7 = instance.m_lanes.m_buffer[(int)((UIntPtr)bufferItem6.m_laneID)].m_nodes;
                    if (num7 != 0)
                    {
                        ushort startNode2 = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_startNode;
                        ushort endNode2 = instance.m_segments.m_buffer[(int)bufferItem6.m_position.m_segment].m_endNode;
                        bool flag2 = ((instance.m_nodes.m_buffer[(int)startNode2].m_flags | instance.m_nodes.m_buffer[(int)endNode2].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None;
                        while (num7 != 0)
                        {
                            NetInfo.Direction direction = NetInfo.Direction.None;
                            byte laneOffset = instance.m_nodes.m_buffer[(int)num7].m_laneOffset;
                            if (laneOffset <= bufferItem6.m_position.m_offset)
                            {
                                direction |= NetInfo.Direction.Forward;
                            }
                            if (laneOffset >= bufferItem6.m_position.m_offset)
                            {
                                direction |= NetInfo.Direction.Backward;
                            }
                            if ((byte)(bufferItem6.m_direction & direction) != 0 && (!flag2 || (instance.m_nodes.m_buffer[(int)num7].m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None))
                            {
                                this.ProcessItem(bufferItem6, num7, ref instance.m_nodes.m_buffer[(int)num7], laneOffset, true);
                            }
                            num7 = instance.m_nodes.m_buffer[(int)num7].m_nextLaneNode;
                            if (++num6 == 32768)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            if (!flag)
            {
                PathUnit[] expr_909_cp_0 = this.m_pathUnits.m_buffer;
                UIntPtr expr_909_cp_1 = (UIntPtr)unit;
                expr_909_cp_0[(int)expr_909_cp_1].m_pathFindFlags = (byte)(expr_909_cp_0[(int)expr_909_cp_1].m_pathFindFlags | 8);
                return;
            }
            float num8 = bufferItem5.m_comparisonValue * this.m_maxLength;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = num8;
            uint num9 = unit;
            int num10 = 0;
            int num11 = 0;
            PathUnit.Position position = bufferItem5.m_position;
            if ((position.m_segment != bufferItem3.m_position.m_segment || position.m_lane != bufferItem3.m_position.m_lane || position.m_offset != bufferItem3.m_position.m_offset) && (position.m_segment != bufferItem4.m_position.m_segment || position.m_lane != bufferItem4.m_position.m_lane || position.m_offset != bufferItem4.m_position.m_offset))
            {
                if (b != position.m_offset)
                {
                    PathUnit.Position position2 = position;
                    position2.m_offset = b;
                    this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position2);
                }
                this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position);
                position = this.m_laneTarget[(int)((UIntPtr)bufferItem5.m_laneID)];
            }
            for (int k = 0; k < 262144; k++)
            {
                this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].SetPosition(num10++, position);
                if ((position.m_segment == bufferItem3.m_position.m_segment && position.m_lane == bufferItem3.m_position.m_lane && position.m_offset == bufferItem3.m_position.m_offset) || (position.m_segment == bufferItem4.m_position.m_segment && position.m_lane == bufferItem4.m_position.m_lane && position.m_offset == bufferItem4.m_position.m_offset))
                {
                    this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount = (byte)num10;
                    num11 += num10;
                    if (num11 != 0)
                    {
                        num9 = this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit;
                        num10 = (int)this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount;
                        int num12 = 0;
                        while (num9 != 0u)
                        {
                            this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_length = num8 * (float)(num11 - num10) / (float)num11;
                            num10 += (int)this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount;
                            num9 = this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_nextPathUnit;
                            if (++num12 >= 262144)
                            {
                                CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                                break;
                            }
                        }
                    }
                    PathUnit[] expr_C16_cp_0 = this.m_pathUnits.m_buffer;
                    UIntPtr expr_C16_cp_1 = (UIntPtr)unit;
                    expr_C16_cp_0[(int)expr_C16_cp_1].m_pathFindFlags = (byte)(expr_C16_cp_0[(int)expr_C16_cp_1].m_pathFindFlags | 4);
                    return;
                }
                if (num10 == 12)
                {
                    while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
                    {
                    }
                    uint num13;
                    try
                    {
                        if (!this.m_pathUnits.CreateItem(out num13, ref this.m_pathRandomizer))
                        {
                            PathUnit[] expr_D15_cp_0 = this.m_pathUnits.m_buffer;
                            UIntPtr expr_D15_cp_1 = (UIntPtr)unit;
                            expr_D15_cp_0[(int)expr_D15_cp_1].m_pathFindFlags = (byte)(expr_D15_cp_0[(int)expr_D15_cp_1].m_pathFindFlags | 8);
                            return;
                        }
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num13)] = this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)];
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num13)].m_referenceCount = 1;
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num13)].m_pathFindFlags = 4;
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_nextPathUnit = num13;
                        this.m_pathUnits.m_buffer[(int)((UIntPtr)num9)].m_positionCount = (byte)num10;
                        num11 += num10;
                        Singleton<PathManager>.instance.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u);
                    }
                    finally
                    {
                        Monitor.Exit(this.m_bufferLock);
                    }
                    num9 = num13;
                    num10 = 0;
                }
                uint laneID = PathManager.GetLaneID(position);
                position = this.m_laneTarget[(int)((UIntPtr)laneID)];
            }
            PathUnit[] expr_D99_cp_0 = this.m_pathUnits.m_buffer;
            UIntPtr expr_D99_cp_1 = (UIntPtr)unit;
            expr_D99_cp_0[(int)expr_D99_cp_1].m_pathFindFlags = (byte)(expr_D99_cp_0[(int)expr_D99_cp_1].m_pathFindFlags | 8);
        }
        private static void ResetTargets(ushort vehicleID, ref Vehicle vehicleData, ushort leaderID, ref Vehicle leaderData, bool pushPathPos)
        {
            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            VehicleInfo   info          = vehicleData.Info;
            TrainAI       trainAI       = info.m_vehicleAI as TrainAI;
            Vector3       vector        = lastFrameData.m_position;
            Vector3       vector2       = lastFrameData.m_position;
            Vector3       b             = lastFrameData.m_rotation * new Vector3(0f, 0f, info.m_generatedInfo.m_wheelBase * 0.5f);

            if ((leaderData.m_flags & Vehicle.Flags.Reversed) != Vehicle.Flags.None)
            {
                vector  -= b;
                vector2 += b;
            }
            else
            {
                vector  += b;
                vector2 -= b;
            }
            vehicleData.m_targetPos0   = vector2;
            vehicleData.m_targetPos0.w = 2f;
            vehicleData.m_targetPos1   = vector;
            vehicleData.m_targetPos1.w = 2f;
            vehicleData.m_targetPos2   = vehicleData.m_targetPos1;
            vehicleData.m_targetPos3   = vehicleData.m_targetPos1;
            if (vehicleData.m_path != 0u)
            {
                PathManager instance = Singleton <PathManager> .instance;
                int         num      = (vehicleData.m_pathPositionIndex >> 1) + 1;
                uint        num2     = vehicleData.m_path;
                if (num >= (int)instance.m_pathUnits.m_buffer [(int)((UIntPtr)num2)].m_positionCount)
                {
                    num  = 0;
                    num2 = instance.m_pathUnits.m_buffer [(int)((UIntPtr)num2)].m_nextPathUnit;
                }
                PathUnit.Position pathPos;
                if (instance.m_pathUnits.m_buffer [(int)((UIntPtr)vehicleData.m_path)].GetPosition(vehicleData.m_pathPositionIndex >> 1, out pathPos))
                {
                    uint laneID = PathManager.GetLaneID(pathPos);
                    PathUnit.Position pathPos2;
                    if (num2 != 0u && instance.m_pathUnits.m_buffer [(int)((UIntPtr)num2)].GetPosition(num, out pathPos2))
                    {
                        uint laneID2 = PathManager.GetLaneID(pathPos2);
                        if (laneID2 == laneID)
                        {
                            if (num2 != vehicleData.m_path)
                            {
                                instance.ReleaseFirstUnit(ref vehicleData.m_path);
                            }
                            vehicleData.m_pathPositionIndex = (byte)(num << 1);
                        }
                    }
                    PathUnit.CalculatePathPositionOffset(laneID, vector2, out vehicleData.m_lastPathOffset);
                }
            }
            if (vehicleData.m_path != 0u)
            {
                int num3 = 0;
                ((FakeTrainAI)trainAI).UpdatePathTargetPositions(vehicleID, ref vehicleData, vector2, vector, 0, ref leaderData, ref num3, 1, 4, 4f, 1f);
            }
        }
Пример #18
0
        public static void SimulationStep(CarAI carAI, ushort vehicleID, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ushort leaderID, ref Vehicle leaderData, int lodPhysics)
        {
            uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            frameData.m_position     += frameData.m_velocity * 0.5f;
            frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f;
            float   acceleration = carAI.m_info.m_acceleration;
            float   braking      = carAI.m_info.m_braking;
            float   magnitude    = frameData.m_velocity.magnitude;
            Vector3 vector       = vehicleData.m_targetPos0 - (Vector4)frameData.m_position;
            float   sqrMagnitude = vector.sqrMagnitude;
            float   num          = (magnitude + acceleration) * (0.5f + 0.5f * (magnitude + acceleration) / braking) + carAI.m_info.m_generatedInfo.m_size.z * 0.5f;
            float   num2         = Mathf.Max(magnitude + acceleration, 5f);

            if (lodPhysics >= 2 && (ulong)(currentFrameIndex >> 4 & 3u) == (ulong)((long)(vehicleID & 3)))
            {
                num2 *= 2f;
            }
            float num3 = Mathf.Max((num - num2) / 3f, 1f);
            float num4 = num2 * num2;
            float num5 = num3 * num3;
            int   i    = 0;
            bool  flag = false;

            if ((sqrMagnitude < num4 || vehicleData.m_targetPos3.w < 0.01f) && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == Vehicle.Flags.None)
            {
                if (leaderData.m_path != 0u)
                {
                    CustomVehicleAI.UpdatePathTargetPositions(carAI, vehicleID, ref vehicleData, frameData.m_position, ref i, 4, num4, num5);
                    if ((leaderData.m_flags & Vehicle.Flags.Spawned) == Vehicle.Flags.None)
                    {
                        frameData = vehicleData.m_frame0;
                        return;
                    }
                }
                if ((leaderData.m_flags & Vehicle.Flags.WaitingPath) == Vehicle.Flags.None)
                {
                    while (i < 4)
                    {
                        float   minSqrDistance;
                        Vector3 refPos;
                        if (i == 0)
                        {
                            minSqrDistance = num4;
                            refPos         = frameData.m_position;
                            flag           = true;
                        }
                        else
                        {
                            minSqrDistance = num5;
                            refPos         = vehicleData.GetTargetPos(i - 1);
                        }
                        int num6 = i;
                        carAI.UpdateBuildingTargetPositions(vehicleID, ref vehicleData, refPos, leaderID, ref leaderData, ref i, minSqrDistance);
                        if (i == num6)
                        {
                            break;
                        }
                    }
                    if (i != 0)
                    {
                        Vector4 targetPos = vehicleData.GetTargetPos(i - 1);
                        while (i < 4)
                        {
                            vehicleData.SetTargetPos(i++, targetPos);
                        }
                    }
                }
                vector       = vehicleData.m_targetPos0 - (Vector4)frameData.m_position;
                sqrMagnitude = vector.sqrMagnitude;
            }
            if (leaderData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == Vehicle.Flags.None)
            {
                NetManager instance       = Singleton <NetManager> .instance;
                byte       b              = leaderData.m_pathPositionIndex;
                byte       lastPathOffset = leaderData.m_lastPathOffset;
                if (b == 255)
                {
                    b = 0;
                }
                float             num7      = 1f + leaderData.CalculateTotalLength(leaderID);
                PathManager       instance2 = Singleton <PathManager> .instance;
                PathUnit.Position pathPos;
                if (instance2.m_pathUnits.m_buffer[(int)((UIntPtr)leaderData.m_path)].GetPosition(b >> 1, out pathPos))
                {
                    instance.m_segments.m_buffer[(int)pathPos.m_segment].AddTraffic(Mathf.RoundToInt(num7 * 2.5f));
                    bool flag2 = false;
                    if ((b & 1) == 0 || lastPathOffset == 0)
                    {
                        uint laneID = PathManager.GetLaneID(pathPos);
                        if (laneID != 0u)
                        {
                            Vector3 b2   = instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePosition((float)pathPos.m_offset * 0.003921569f);
                            float   num8 = 0.5f * magnitude * magnitude / carAI.m_info.m_braking + carAI.m_info.m_generatedInfo.m_size.z * 0.5f;
                            if (Vector3.Distance(frameData.m_position, b2) >= num8 - 1f)
                            {
                                instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].ReserveSpace(num7);
                                flag2 = true;
                            }
                        }
                    }
                    if (!flag2 && instance2.m_pathUnits.m_buffer[(int)((UIntPtr)leaderData.m_path)].GetNextPosition(b >> 1, out pathPos))
                    {
                        uint laneID2 = PathManager.GetLaneID(pathPos);
                        if (laneID2 != 0u)
                        {
                            instance.m_lanes.m_buffer[(int)((UIntPtr)laneID2)].ReserveSpace(num7);
                        }
                    }
                }
                /* -------------------- Congestion Changes ------------------------- */
                // Not everything is new. Changes are commented
                if ((ulong)(currentFrameIndex >> 4 & 15u) == (ulong)((long)(leaderID & 15)))
                {
                    bool flag3 = false;
                    uint path = leaderData.m_path;
                    int  num9 = b >> 1;
                    int  j = 0, count = 0; // the count variable is used to keep track of how many of the next 5 lanes are congested
                    //int j = 0;
                    while (j < 5)
                    {
                        bool flag4;
                        if (PathUnit.GetNextPosition(ref path, ref num9, out pathPos, out flag4))
                        {
                            uint laneID3 = PathManager.GetLaneID(pathPos);
                            if (laneID3 != 0 && !instance.m_lanes.m_buffer[(int)((UIntPtr)laneID3)].CheckSpace(num7))
                            {
                                j++;
                                ++count; // this lane is congested so increase count
                                continue;
                            }
                        }
                        if (flag4)
                        {
                            (carAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                            // flag it as not congested and set count to -1 so that it is neither congested nor completely clear
                            // this is needed here because, contrary to the default code, it does not leave the cycle below
                            if ((CSLTraffic.Options & OptionsManager.ModOptions.ImprovedAI) == OptionsManager.ModOptions.ImprovedAI)
                            {
                                flag3 = true;
                                count = -1;
                                break;
                            }
                        }
                        flag3 = true;
                        ++j;
                        if ((CSLTraffic.Options & OptionsManager.ModOptions.ImprovedAI) != OptionsManager.ModOptions.ImprovedAI)
                        {
                            break;
                        }
                        // the default code would leave the cycle at this point since it found a non congested lane.
                        // this has been changed so that vehicles detect congestions a few lanes in advance.
                        // I am yet to test the performance impact this particular "feature" has.
                    }

                    if ((CSLTraffic.Options & OptionsManager.ModOptions.ImprovedAI) == OptionsManager.ModOptions.ImprovedAI)
                    {
                        // if at least 2 out of the next 5 lanes are congested and it hasn't tried to find a new path yet, then calculates a new path and flags it as such
                        // the amounf of congested lanes necessary to calculate a new path can be tweaked to reduce the amount of new paths being calculated, if performance in bigger cities is severely affected
                        if (count >= 2 && (leaderData.m_flags & (Vehicle.Flags) 1073741824) == 0)
                        {
                            leaderData.m_flags |= (Vehicle.Flags) 1073741824;
                            (carAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                        }
                        // if none of the next 5 lanes is congested and the vehicle has already searched for a new path, then it successfully avoided a congestion and the flag is cleared
                        else if (count == 0 && (leaderData.m_flags & (Vehicle.Flags) 1073741824) != 0)
                        {
                            leaderData.m_flags &= ~((Vehicle.Flags) 1073741824);
                        }
                        // default congestion behavior
                        else if (!flag3)
                        {
                            leaderData.m_flags |= Vehicle.Flags.Congestion;
                        }
                    }
                    else if (!flag3)
                    {
                        leaderData.m_flags |= Vehicle.Flags.Congestion;
                    }
                }
                /* ----------------------------------------------------------------- */
            }
            float num10;

            if ((leaderData.m_flags & Vehicle.Flags.Stopped) != Vehicle.Flags.None)
            {
                num10 = 0f;
            }
            else
            {
                num10 = vehicleData.m_targetPos0.w;
            }
            Quaternion rotation = Quaternion.Inverse(frameData.m_rotation);

            vector = rotation * vector;
            Vector3 vector2 = rotation * frameData.m_velocity;
            Vector3 a       = Vector3.forward;
            Vector3 vector3 = Vector3.zero;
            Vector3 zero    = Vector3.zero;
            float   num11   = 0f;
            float   num12   = 0f;
            bool    flag5   = false;
            float   num13   = 0f;

            if (sqrMagnitude > 1f)
            {
                a = VectorUtils.NormalizeXZ(vector, out num13);
                if (num13 > 1f)
                {
                    Vector3 vector4 = vector;
                    num2 = Mathf.Max(magnitude, 2f);
                    num4 = num2 * num2;
                    if (sqrMagnitude > num4)
                    {
                        vector4 *= num2 / Mathf.Sqrt(sqrMagnitude);
                    }
                    bool flag6 = false;
                    if (vector4.z < Mathf.Abs(vector4.x))
                    {
                        if (vector4.z < 0f)
                        {
                            flag6 = true;
                        }
                        float num14 = Mathf.Abs(vector4.x);
                        if (num14 < 1f)
                        {
                            vector4.x = Mathf.Sign(vector4.x);
                            if (vector4.x == 0f)
                            {
                                vector4.x = 1f;
                            }
                            num14 = 1f;
                        }
                        vector4.z = num14;
                    }
                    float b3;
                    a     = VectorUtils.NormalizeXZ(vector4, out b3);
                    num13 = Mathf.Min(num13, b3);
                    float num15 = 1.57079637f * (1f - a.z);
                    if (num13 > 1f)
                    {
                        num15 /= num13;
                    }
                    float num16 = num13;
                    if (vehicleData.m_targetPos0.w < 0.1f)
                    {
                        num10 = (carAI as IVehicle).CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num15);
                        num10 = Mathf.Min(num10, CalculateMaxSpeed(num16, Mathf.Min(vehicleData.m_targetPos0.w, vehicleData.m_targetPos1.w), braking * 0.9f));
                    }
                    else
                    {
                        num10 = Mathf.Min(num10, (carAI as IVehicle).CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num15));
                        num10 = Mathf.Min(num10, CalculateMaxSpeed(num16, vehicleData.m_targetPos1.w, braking * 0.9f));
                    }
                    num16 += VectorUtils.LengthXZ(vehicleData.m_targetPos1 - vehicleData.m_targetPos0);
                    num10  = Mathf.Min(num10, CalculateMaxSpeed(num16, vehicleData.m_targetPos2.w, braking * 0.9f));
                    num16 += VectorUtils.LengthXZ(vehicleData.m_targetPos2 - vehicleData.m_targetPos1);
                    num10  = Mathf.Min(num10, CalculateMaxSpeed(num16, vehicleData.m_targetPos3.w, braking * 0.9f));
                    num16 += VectorUtils.LengthXZ(vehicleData.m_targetPos3 - vehicleData.m_targetPos2);
                    if (vehicleData.m_targetPos3.w < 0.01f)
                    {
                        num16 = Mathf.Max(0f, num16 - carAI.m_info.m_generatedInfo.m_size.z * 0.5f);
                    }
                    num10 = Mathf.Min(num10, CalculateMaxSpeed(num16, 0f, braking * 0.9f));
                    if (!DisableCollisionCheck(leaderID, ref leaderData))
                    {
                        CustomCarAI.CheckOtherVehicles(carAI, vehicleID, ref vehicleData, ref frameData, ref num10, ref flag5, ref zero, num, braking * 0.9f, lodPhysics);
                    }
                    if (flag6)
                    {
                        num10 = -num10;
                    }
                    if (num10 < magnitude)
                    {
                        float num17 = Mathf.Max(acceleration, Mathf.Min(braking, magnitude));
                        num11 = Mathf.Max(num10, magnitude - num17);
                    }
                    else
                    {
                        float num18 = Mathf.Max(acceleration, Mathf.Min(braking, -magnitude));
                        num11 = Mathf.Min(num10, magnitude + num18);
                    }
                }
            }
            else
            {
                if (magnitude < 0.1f && flag && carAI.ArriveAtDestination(leaderID, ref leaderData))
                {
                    leaderData.Unspawn(leaderID);
                    if (leaderID == vehicleID)
                    {
                        frameData = leaderData.m_frame0;
                    }
                    return;
                }
            }
            if ((leaderData.m_flags & Vehicle.Flags.Stopped) == Vehicle.Flags.None && num10 < 0.1f)
            {
                flag5 = true;
            }
            if (flag5)
            {
                vehicleData.m_blockCounter = (byte)Mathf.Min((int)(vehicleData.m_blockCounter + 1), 255);
                if ((vehicleData.m_blockCounter == 100 || vehicleData.m_blockCounter == 150) && (CSLTraffic.Options & OptionsManager.ModOptions.NoDespawn) == OptionsManager.ModOptions.NoDespawn)
                {
                    vehicleData.m_blockCounter++;
                }
            }
            else
            {
                vehicleData.m_blockCounter = 0;
            }
            if (num13 > 1f)
            {
                num12   = Mathf.Asin(a.x) * Mathf.Sign(num11);
                vector3 = a * num11;
            }
            else
            {
                num11 = 0f;
                Vector3 b4 = Vector3.ClampMagnitude(vector * 0.5f - vector2, braking);
                vector3 = vector2 + b4;
            }
            bool    flag7   = (currentFrameIndex + (uint)leaderID & 16u) != 0u;
            Vector3 a2      = vector3 - vector2;
            Vector3 vector5 = frameData.m_rotation * vector3;

            frameData.m_velocity         = vector5 + zero;
            frameData.m_position        += frameData.m_velocity * 0.5f;
            frameData.m_swayVelocity     = frameData.m_swayVelocity * (1f - carAI.m_info.m_dampers) - a2 * (1f - carAI.m_info.m_springs) - frameData.m_swayPosition * carAI.m_info.m_springs;
            frameData.m_swayPosition    += frameData.m_swayVelocity * 0.5f;
            frameData.m_steerAngle       = num12;
            frameData.m_travelDistance  += vector3.z;
            frameData.m_lightIntensity.x = 5f;
            frameData.m_lightIntensity.y = ((a2.z >= -0.1f) ? 0.5f : 5f);
            frameData.m_lightIntensity.z = ((num12 >= -0.1f || !flag7) ? 0f : 5f);
            frameData.m_lightIntensity.w = ((num12 <= 0.1f || !flag7) ? 0f : 5f);
            frameData.m_underground      = ((vehicleData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None);
            frameData.m_transition       = ((vehicleData.m_flags & Vehicle.Flags.Transition) != Vehicle.Flags.None);
            if ((vehicleData.m_flags & Vehicle.Flags.Parking) != Vehicle.Flags.None && num13 <= 1f && flag)
            {
                Vector3 forward = vehicleData.m_targetPos1 - vehicleData.m_targetPos0;
                if (forward.sqrMagnitude > 0.01f)
                {
                    frameData.m_rotation = Quaternion.LookRotation(forward);
                }
            }
            else
            {
                if (num11 > 0.1f)
                {
                    if (vector5.sqrMagnitude > 0.01f)
                    {
                        frameData.m_rotation = Quaternion.LookRotation(vector5);
                    }
                }
                else
                {
                    if (num11 < -0.1f && vector5.sqrMagnitude > 0.01f)
                    {
                        frameData.m_rotation = Quaternion.LookRotation(-vector5);
                    }
                }
            }
        }
Пример #19
0
        public static void UpdatePathTargetPositions(VehicleAI vehicleAI, ushort vehicleID, ref Vehicle vehicleData, Vector3 refPos, ref int index, int max, float minSqrDistanceA, float minSqrDistanceB)
        {
            PathManager instance  = Singleton <PathManager> .instance;
            NetManager  instance2 = Singleton <NetManager> .instance;
            Vector4     vector    = vehicleData.m_targetPos0;

            vector.w = 1000f;
            float num  = minSqrDistanceA;
            uint  num2 = vehicleData.m_path;
            byte  b    = vehicleData.m_pathPositionIndex;
            byte  b2   = vehicleData.m_lastPathOffset;

            if (b == 255)
            {
                b = 0;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = 0;
                }
                if (!Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)num2)].CalculatePathPositionOffset(b >> 1, vector, out b2))
                {
                    (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
            }
            PathUnit.Position position;
            if (!instance.m_pathUnits.m_buffer[(int)((UIntPtr)num2)].GetPosition(b >> 1, out position))
            {
                (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }
            NetInfo info = instance2.m_segments.m_buffer[(int)position.m_segment].Info;

            if (info.m_lanes.Length <= (int)position.m_lane)
            {
                (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }
            uint num3 = PathManager.GetLaneID(position);

            NetInfo.Lane lane = info.m_lanes[(int)position.m_lane];
            Bezier3      bezier;

            while (true)
            {
                if ((b & 1) == 0)
                {
                    if (lane.m_laneType != NetInfo.LaneType.CargoVehicle)
                    {
                        bool flag = true;
                        while (b2 != position.m_offset)
                        {
                            if (flag)
                            {
                                flag = false;
                            }
                            else
                            {
                                float num4 = Mathf.Sqrt(num) - Vector3.Distance(vector, refPos);
                                int   num5;
                                if (num4 < 0f)
                                {
                                    num5 = 4;
                                }
                                else
                                {
                                    num5 = 4 + Mathf.Max(0, Mathf.CeilToInt(num4 * 256f / (instance2.m_lanes.m_buffer[(int)((UIntPtr)num3)].m_length + 1f)));
                                }
                                if (b2 > position.m_offset)
                                {
                                    b2 = (byte)Mathf.Max((int)b2 - num5, (int)position.m_offset);
                                }
                                else
                                {
                                    if (b2 < position.m_offset)
                                    {
                                        b2 = (byte)Mathf.Min((int)b2 + num5, (int)position.m_offset);
                                    }
                                }
                            }
                            Vector3 a;
                            Vector3 vector2;
                            float   b3;
                            (vehicleAI as IVehicle).CalculateSegmentPosition(vehicleID, ref vehicleData, position, num3, b2, out a, out vector2, out b3);
                            b3 = RestrictSpeed(b3, num3, vehicleData.Info);
                            vector.Set(a.x, a.y, a.z, Mathf.Min(vector.w, b3));
                            float sqrMagnitude = (a - refPos).sqrMagnitude;
                            if (sqrMagnitude >= num)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_lastPathOffset = b2;
                                }
                                vehicleData.SetTargetPos(index++, vector);
                                num      = minSqrDistanceB;
                                refPos   = vector;
                                vector.w = 1000f;
                                if (index == max)
                                {
                                    return;
                                }
                            }
                        }
                    }
                    b += 1;
                    b2 = 0;
                    if (index <= 0)
                    {
                        vehicleData.m_pathPositionIndex = b;
                        vehicleData.m_lastPathOffset    = b2;
                    }
                }
                int  num6 = (b >> 1) + 1;
                uint num7 = num2;
                if (num6 >= (int)instance.m_pathUnits.m_buffer[(int)((UIntPtr)num2)].m_positionCount)
                {
                    num6 = 0;
                    num7 = instance.m_pathUnits.m_buffer[(int)((UIntPtr)num2)].m_nextPathUnit;
                    if (num7 == 0u)
                    {
                        if (index <= 0)
                        {
                            Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                            vehicleData.m_path = 0u;
                        }
                        vector.w = 1f;
                        vehicleData.SetTargetPos(index++, vector);
                        return;
                    }
                }
                PathUnit.Position position2;
                if (!instance.m_pathUnits.m_buffer[(int)((UIntPtr)num7)].GetPosition(num6, out position2))
                {
                    (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
                NetInfo info2 = instance2.m_segments.m_buffer[(int)position2.m_segment].Info;
                if (info2.m_lanes.Length <= (int)position2.m_lane)
                {
                    (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
                uint         laneID     = PathManager.GetLaneID(position2);
                NetInfo.Lane lane2      = info2.m_lanes[(int)position2.m_lane];
                ushort       startNode  = instance2.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                ushort       endNode    = instance2.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                ushort       startNode2 = instance2.m_segments.m_buffer[(int)position2.m_segment].m_startNode;
                ushort       endNode2   = instance2.m_segments.m_buffer[(int)position2.m_segment].m_endNode;
                if (startNode2 != startNode && startNode2 != endNode && endNode2 != startNode && endNode2 != endNode && ((instance2.m_nodes.m_buffer[(int)startNode].m_flags | instance2.m_nodes.m_buffer[(int)endNode].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None && ((instance2.m_nodes.m_buffer[(int)startNode2].m_flags | instance2.m_nodes.m_buffer[(int)endNode2].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None)
                {
                    (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
                if (lane2.m_laneType == NetInfo.LaneType.Pedestrian)
                {
                    if (vehicleID != 0 && (vehicleData.m_flags & Vehicle.Flags.Parking) == Vehicle.Flags.None)
                    {
                        byte offset  = position.m_offset;
                        byte offset2 = position.m_offset;
                        if ((vehicleAI as IVehicle).ParkVehicle(vehicleID, ref vehicleData, position, num7, num6 << 1, out offset2))
                        {
                            if (offset2 != offset)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_pathPositionIndex = (byte)((int)vehicleData.m_pathPositionIndex & -2);
                                    vehicleData.m_lastPathOffset    = offset;
                                }
                                position.m_offset = offset2;
                                instance.m_pathUnits.m_buffer[(int)((UIntPtr)num2)].SetPosition(b >> 1, position);
                            }
                            vehicleData.m_flags |= Vehicle.Flags.Parking;
                        }
                        else
                        {
                            (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    return;
                }
                if ((byte)(lane2.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle | NetInfo.LaneType.TransportVehicle)) == 0)
                {
                    (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
                if (lane2.m_vehicleType != vehicleAI.m_info.m_vehicleType && (vehicleAI as IVehicle).NeedChangeVehicleType(vehicleID, ref vehicleData, position2, laneID, lane2.m_vehicleType, ref vector))
                {
                    float sqrMagnitude3 = (vector - (Vector4)refPos).sqrMagnitude;
                    if (sqrMagnitude3 >= num)
                    {
                        vehicleData.SetTargetPos(index++, vector);
                    }
                    if (index <= 0)
                    {
                        if (num6 == 0)
                        {
                            Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                        }
                        vehicleData.m_pathPositionIndex = (byte)(num6 << 1);
                        PathUnit.CalculatePathPositionOffset(laneID, vector, out vehicleData.m_lastPathOffset);
                        if (vehicleID != 0 && !(vehicleAI as IVehicle).ChangeVehicleType(vehicleID, ref vehicleData, position2, laneID))
                        {
                            (vehicleAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    return;
                }
                if (position2.m_segment != position.m_segment && vehicleID != 0)
                {
                    vehicleData.m_flags &= ~Vehicle.Flags.Leaving;
                }
                byte b4 = 0;
                if ((vehicleData.m_flags & Vehicle.Flags.Flying) != Vehicle.Flags.None)
                {
                    b4 = (byte)((position2.m_offset < 128) ? 255 : 0);
                }
                else
                {
                    if (num3 != laneID && lane.m_laneType != NetInfo.LaneType.CargoVehicle)
                    {
                        PathUnit.CalculatePathPositionOffset(laneID, vector, out b4);
                        bezier = default(Bezier3);
                        Vector3 vector3;
                        float   num8;
                        (vehicleAI as IVehicle).CalculateSegmentPosition(vehicleID, ref vehicleData, position, num3, position.m_offset, out bezier.a, out vector3, out num8);
                        num8 = RestrictSpeed(num8, num3, vehicleData.Info);
                        bool flag2 = b2 == 0;
                        if (flag2)
                        {
                            if ((vehicleData.m_flags & Vehicle.Flags.Reversed) != Vehicle.Flags.None)
                            {
                                flag2 = (vehicleData.m_trailingVehicle == 0);
                            }
                            else
                            {
                                flag2 = (vehicleData.m_leadingVehicle == 0);
                            }
                        }
                        Vector3 vector4;
                        float   num9;
                        if (flag2)
                        {
                            PathUnit.Position nextPosition;
                            if (!instance.m_pathUnits.m_buffer[(int)((UIntPtr)num7)].GetNextPosition(num6, out nextPosition))
                            {
                                nextPosition = default(PathUnit.Position);
                            }
                            (vehicleAI as IVehicle).CalculateSegmentPosition(vehicleID, ref vehicleData, nextPosition, position2, laneID, b4, position, num3, position.m_offset, out bezier.d, out vector4, out num9);
                            num9 = RestrictSpeed(num9, laneID, vehicleData.Info);
                        }
                        else
                        {
                            (vehicleAI as IVehicle).CalculateSegmentPosition(vehicleID, ref vehicleData, position2, laneID, b4, out bezier.d, out vector4, out num9);
                            num9 = RestrictSpeed(num9, laneID, vehicleData.Info);
                        }
                        if (num9 < 0.01f || (instance2.m_segments.m_buffer[(int)position2.m_segment].m_flags & NetSegment.Flags.Flooded) != NetSegment.Flags.None)
                        {
                            if (index <= 0)
                            {
                                vehicleData.m_lastPathOffset = b2;
                            }
                            vector   = bezier.a;
                            vector.w = 0f;
                            while (index < max)
                            {
                                vehicleData.SetTargetPos(index++, vector);
                            }
                        }
                        if (position.m_offset == 0)
                        {
                            vector3 = -vector3;
                        }
                        if (b4 < position2.m_offset)
                        {
                            vector4 = -vector4;
                        }
                        vector3.Normalize();
                        vector4.Normalize();
                        float num10;
                        NetSegment.CalculateMiddlePoints(bezier.a, vector3, bezier.d, vector4, true, true, out bezier.b, out bezier.c, out num10);
                        if (num10 > 1f)
                        {
                            ushort num11;
                            if (b4 == 0)
                            {
                                num11 = instance2.m_segments.m_buffer[(int)position2.m_segment].m_startNode;
                            }
                            else
                            {
                                if (b4 == 255)
                                {
                                    num11 = instance2.m_segments.m_buffer[(int)position2.m_segment].m_endNode;
                                }
                                else
                                {
                                    num11 = 0;
                                }
                            }
                            float num12 = 1.57079637f * (1f + Vector3.Dot(vector3, vector4));
                            if (num10 > 1f)
                            {
                                num12 /= num10;
                            }
                            num9 = Mathf.Min(num9, (vehicleAI as IVehicle).CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num12));
                            while (b2 < 255)
                            {
                                float num13 = Mathf.Sqrt(num) - Vector3.Distance(vector, refPos);
                                int   num14;
                                if (num13 < 0f)
                                {
                                    num14 = 8;
                                }
                                else
                                {
                                    num14 = 8 + Mathf.Max(0, Mathf.CeilToInt(num13 * 256f / (num10 + 1f)));
                                }
                                b2 = (byte)Mathf.Min((int)b2 + num14, 255);
                                Vector3 a2 = bezier.Position((float)b2 * 0.003921569f);
                                vector.Set(a2.x, a2.y, a2.z, Mathf.Min(vector.w, num9));
                                float sqrMagnitude2 = (a2 - refPos).sqrMagnitude;
                                if (sqrMagnitude2 >= num)
                                {
                                    if (index <= 0)
                                    {
                                        vehicleData.m_lastPathOffset = b2;
                                    }
                                    if (num11 != 0)
                                    {
                                        (vehicleAI as IVehicle).UpdateNodeTargetPos(vehicleID, ref vehicleData, num11, ref instance2.m_nodes.m_buffer[(int)num11], ref vector, index);
                                    }
                                    vehicleData.SetTargetPos(index++, vector);
                                    num      = minSqrDistanceB;
                                    refPos   = vector;
                                    vector.w = 1000f;
                                    if (index == max)
                                    {
                                        return;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        PathUnit.CalculatePathPositionOffset(laneID, vector, out b4);
                    }
                }
                if (index <= 0)
                {
                    if (num6 == 0)
                    {
                        Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                    }
                    if (num6 >= (int)(instance.m_pathUnits.m_buffer[(int)((UIntPtr)num7)].m_positionCount - 1) && instance.m_pathUnits.m_buffer[(int)((UIntPtr)num7)].m_nextPathUnit == 0u && vehicleID != 0)
                    {
                        (vehicleAI as IVehicle).ArrivingToDestination(vehicleID, ref vehicleData);
                    }
                }
                num2 = num7;
                b    = (byte)(num6 << 1);
                b2   = b4;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = b;
                    vehicleData.m_lastPathOffset    = b2;
                    vehicleData.m_flags             = ((vehicleData.m_flags & ~(Vehicle.Flags.OnGravel | Vehicle.Flags.Underground | Vehicle.Flags.Transition)) | info2.m_setVehicleFlags);
                }
                position = position2;
                num3     = laneID;
                lane     = lane2;
            }
        }
        private SearchDirection GetImmediateSearchDirection(ushort hearseID)
        {
            Vehicle hearse = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[hearseID];

            PathManager pm = Singleton <PathManager> .instance;

            PathUnit pu = pm.m_pathUnits.m_buffer[hearse.m_path];

            byte pi = hearse.m_pathPositionIndex;

            if (pi == 255)
            {
                pi = 0;
            }

            PathUnit.Position position = pu.GetPosition(pi >> 1);

            NetManager nm = Singleton <NetManager> .instance;

            NetSegment segment = nm.m_segments.m_buffer[position.m_segment];

            int laneCount = 0;

            int   leftLane     = -1;
            float leftPosition = float.PositiveInfinity;

            int   rightLane     = -1;
            float rightPosition = float.NegativeInfinity;

            for (int i = 0; i < segment.Info.m_lanes.Length; i++)
            {
                NetInfo.Lane l = segment.Info.m_lanes[i];

                if (l.m_laneType != NetInfo.LaneType.Vehicle || l.m_vehicleType != VehicleInfo.VehicleType.Car)
                {
                    continue;
                }

                laneCount++;

                if (l.m_position < leftPosition)
                {
                    leftLane     = i;
                    leftPosition = l.m_position;
                }

                if (l.m_position > rightPosition)
                {
                    rightLane     = i;
                    rightPosition = l.m_position;
                }
            }

            SearchDirection dir = SearchDirection.None;

            if (laneCount == 0)
            {
            }
            else if (position.m_lane != leftLane && position.m_lane != rightLane)
            {
                dir = SearchDirection.Ahead;
            }
            else if (leftLane == rightLane)
            {
                dir = SearchDirection.Left | SearchDirection.Right | SearchDirection.Ahead;
            }
            else if (laneCount == 2 && segment.Info.m_lanes[leftLane].m_direction != segment.Info.m_lanes[rightLane].m_direction)
            {
                dir = SearchDirection.Left | SearchDirection.Right | SearchDirection.Ahead;
            }
            else
            {
                if (position.m_lane == leftLane)
                {
                    dir = SearchDirection.Left | SearchDirection.Ahead;
                }
                else
                {
                    dir = SearchDirection.Right | SearchDirection.Ahead;
                }
            }

            return(dir);
        }
        //from source code
        protected void UpdatePathTargetPositions(ushort vehicleID, ref Vehicle vehicleData, Vector3 refPos1, Vector3 refPos2, ushort leaderID, ref Vehicle leaderData, ref int index, int max1, int max2, float minSqrDistanceA, float minSqrDistanceB)
        {
            PathManager instance  = Singleton <PathManager> .instance;
            NetManager  instance2 = Singleton <NetManager> .instance;

            Vector4 vector = vehicleData.m_targetPos0;

            vector.w = 1000f;
            float num  = minSqrDistanceA;
            float num2 = 0f;
            uint  num3 = vehicleData.m_path;
            byte  b    = vehicleData.m_pathPositionIndex;
            byte  b2   = vehicleData.m_lastPathOffset;

            if (b == 255)
            {
                b = 0;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = 0;
                }
                if (!Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)num3)].CalculatePathPositionOffset(b >> 1, vector, out b2))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                    return;
                }
            }
            PathUnit.Position position;
            if (!instance.m_pathUnits.m_buffer[(int)((UIntPtr)num3)].GetPosition(b >> 1, out position))
            {
                this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                return;
            }
            uint num4 = PathManager.GetLaneID(position);
            //try to notify for all vehicles composing the train. however, UpdatePathTargetPositions is not called when train is stopped
            //this.NotifySingleTrack2Ways(vehicleID, vehicleData, num4);
            Bezier3 bezier;

            while (true)
            {
                if ((b & 1) == 0) //is pathPositionIndex even?
                {
                    bool flag = true;
                    while (b2 != position.m_offset)
                    {
                        if (flag)
                        {
                            flag = false;
                        }
                        else
                        {
                            float num5 = Mathf.Max(Mathf.Sqrt(num) - Vector3.Distance(vector, refPos1), Mathf.Sqrt(num2) - Vector3.Distance(vector, refPos2));
                            int   num6;
                            if (num5 < 0f)
                            {
                                num6 = 4;
                            }
                            else
                            {
                                num6 = 4 + Mathf.CeilToInt(num5 * 256f / (instance2.m_lanes.m_buffer[(int)((UIntPtr)num4)].m_length + 1f));
                            }
                            if (b2 > position.m_offset)
                            {
                                b2 = (byte)Mathf.Max((int)b2 - num6, (int)position.m_offset);
                            }
                            else if (b2 < position.m_offset)
                            {
                                b2 = (byte)Mathf.Min((int)b2 + num6, (int)position.m_offset);
                            }
                        }
                        Vector3 a;
                        Vector3 vector2;
                        float   b3;
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, position, num4, b2, out a, out vector2, out b3);
                        vector.Set(a.x, a.y, a.z, Mathf.Min(vector.w, b3));
                        float sqrMagnitude  = (a - refPos1).sqrMagnitude;
                        float sqrMagnitude2 = (a - refPos2).sqrMagnitude;
                        if (sqrMagnitude >= num && sqrMagnitude2 >= num2)
                        {
                            if (index <= 0)
                            {
                                vehicleData.m_lastPathOffset = b2;
                            }
                            vehicleData.SetTargetPos(index++, vector);
                            if (index < max1)
                            {
                                num     = minSqrDistanceB;
                                refPos1 = vector;
                            }
                            else if (index == max1)
                            {
                                num  = (refPos2 - refPos1).sqrMagnitude;
                                num2 = minSqrDistanceA;
                            }
                            else
                            {
                                num2    = minSqrDistanceB;
                                refPos2 = vector;
                            }
                            vector.w = 1000f;
                            if (index == max2)
                            {
                                return;
                            }
                        }
                    }
                    b += 1;
                    b2 = 0;
                    if (index <= 0)
                    {
                        vehicleData.m_pathPositionIndex = b;
                        vehicleData.m_lastPathOffset    = b2;
                    }
                }
                int  num7 = (b >> 1) + 1; //pathPositionIndex is divided by 2 to get the final position index
                uint num8 = num3;
                if (num7 >= (int)instance.m_pathUnits.m_buffer[(int)((UIntPtr)num3)].m_positionCount)
                {
                    num7 = 0;
                    num8 = instance.m_pathUnits.m_buffer[(int)((UIntPtr)num3)].m_nextPathUnit;
                    if (num8 == 0u)
                    {
                        goto Block_19;
                    }
                }
                PathUnit.Position position2;
                if (!instance.m_pathUnits.m_buffer[(int)((UIntPtr)num8)].GetPosition(num7, out position2))
                {
                    goto Block_21;
                }
                NetInfo info = instance2.m_segments.m_buffer[(int)position2.m_segment].Info;
                if (info.m_lanes.Length <= (int)position2.m_lane)
                {
                    goto Block_22;
                }
                uint         laneID = PathManager.GetLaneID(position2);
                NetInfo.Lane lane   = info.m_lanes[(int)position2.m_lane];
                if (lane.m_laneType != NetInfo.LaneType.Vehicle)
                {
                    goto Block_23;
                }
                if (position2.m_segment != position.m_segment && leaderID != 0)
                {
                    leaderData.m_flags &= ~Vehicle.Flags.Leaving;
                }
                byte b4 = 0;

                if (num4 != laneID) //num4 is last path lane, laneID is the new one. This triggers checkNextLane.
                {
                    PathUnit.CalculatePathPositionOffset(laneID, vector, out b4);
                    bezier = default(Bezier3);
                    Vector3 vector3;
                    float   num9;
                    this.CalculateSegmentPosition(vehicleID, ref vehicleData, position, num4, position.m_offset, out bezier.a, out vector3, out num9);
                    bool flag2;
                    //checkNextLane only for the vehicle in front of the train
                    if ((leaderData.m_flags & Vehicle.Flags.Reversed) != (Vehicle.Flags) 0)
                    {
                        flag2 = (vehicleData.m_trailingVehicle == 0);
                    }
                    else
                    {
                        flag2 = (vehicleData.m_leadingVehicle == 0);
                    }

                    bool    flag3 = flag2 && b2 == 0;
                    Vector3 vector4;
                    float   num10;
                    this.CalculateSegmentPosition(vehicleID, ref vehicleData, position2, laneID, b4, out bezier.d, out vector4, out num10);
                    if (position.m_offset == 0)
                    {
                        vector3 = -vector3;
                    }
                    if (b4 < position2.m_offset)
                    {
                        vector4 = -vector4;
                    }
                    vector3.Normalize();
                    vector4.Normalize();
                    float num11;
                    NetSegment.CalculateMiddlePoints(bezier.a, vector3, bezier.d, vector4, true, true, out bezier.b, out bezier.c, out num11);

                    if (flag3)
                    {
                        bool mayNeedFix = false;
                        if (!this.CheckSingleTrack2Ways(vehicleID, vehicleData, ref num10, laneID, num4, ref mayNeedFix))
                        {
                            float savedMaxSpeed = num10;
                            this.CheckNextLane(vehicleID, ref vehicleData, ref num10, position2, laneID, b4, position, num4, position.m_offset, bezier);

                            //address bug where some train are blocked after reversing at a single train track station
                            if (Mod.fixReverseTrainSingleTrackStation && mayNeedFix && num10 < 0.01f)
                            {
                                ushort vehiclePreviouslyReservingSpace = leaderID;
                                if ((leaderData.m_flags & Vehicle.Flags.Reversed) != (Vehicle.Flags) 0)
                                {
                                    //vehiclePreviouslyReservingSpace = vehicleData.GetFirstVehicle(vehicleID);
                                    //CODebug.Log(LogChannel.Modding, Mod.modName + " - attempt fix(1) " + instance2.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(1000f, vehiclePreviouslyReservingSpace));

                                    //try checkspace again with carriage at the other end of the train (the one who has, by supposition, reserved the space previously)
                                    if (instance2.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(1000f, vehiclePreviouslyReservingSpace))
                                    {
                                        num10 = savedMaxSpeed;
                                    }
                                    else
                                    {
                                        Segment3 segment = new Segment3(bezier.Position(0.5f), bezier.d);
                                        //CODebug.Log(LogChannel.Modding, Mod.modName + " - attempt fix(2) " + CheckOverlap(vehicleID, ref vehicleData, segment, vehiclePreviouslyReservingSpace));

                                        if (CheckOverlap(vehicleID, ref vehicleData, segment, vehiclePreviouslyReservingSpace))
                                        {
                                            num10 = savedMaxSpeed;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (flag2 && (num10 < 0.01f || (instance2.m_segments.m_buffer[(int)position2.m_segment].m_flags & (NetSegment.Flags.Collapsed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None))
                    {
                        goto IL_595;
                    }
                    if (num11 > 1f)
                    {
                        ushort num12;
                        if (b4 == 0)
                        {
                            num12 = instance2.m_segments.m_buffer[(int)position2.m_segment].m_startNode;
                        }
                        else if (b4 == 255)
                        {
                            num12 = instance2.m_segments.m_buffer[(int)position2.m_segment].m_endNode;
                        }
                        else
                        {
                            num12 = 0;
                        }
                        float num13 = 1.57079637f * (1f + Vector3.Dot(vector3, vector4));
                        if (num11 > 1f)
                        {
                            num13 /= num11;
                        }
                        num10 = Mathf.Min(num10, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num13));

                        while (b2 < 255)
                        {
                            float num14 = Mathf.Max(Mathf.Sqrt(num) - Vector3.Distance(vector, refPos1), Mathf.Sqrt(num2) - Vector3.Distance(vector, refPos2));
                            int   num15;
                            if (num14 < 0f)
                            {
                                num15 = 8;
                            }
                            else
                            {
                                num15 = 8 + Mathf.CeilToInt(num14 * 256f / (num11 + 1f));
                            }
                            b2 = (byte)Mathf.Min((int)b2 + num15, 255);
                            Vector3 a2 = bezier.Position((float)b2 * 0.003921569f);
                            vector.Set(a2.x, a2.y, a2.z, Mathf.Min(vector.w, num10));
                            float sqrMagnitude3 = (a2 - refPos1).sqrMagnitude;
                            float sqrMagnitude4 = (a2 - refPos2).sqrMagnitude;
                            if (sqrMagnitude3 >= num && sqrMagnitude4 >= num2)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_lastPathOffset = b2;
                                }
                                if (num12 != 0)
                                {
                                    this.UpdateNodeTargetPos(vehicleID, ref vehicleData, num12, ref instance2.m_nodes.m_buffer[(int)num12], ref vector, index);
                                }
                                vehicleData.SetTargetPos(index++, vector);
                                if (index < max1)
                                {
                                    num     = minSqrDistanceB;
                                    refPos1 = vector;
                                }
                                else if (index == max1)
                                {
                                    num  = (refPos2 - refPos1).sqrMagnitude;
                                    num2 = minSqrDistanceA;
                                }
                                else
                                {
                                    num2    = minSqrDistanceB;
                                    refPos2 = vector;
                                }
                                vector.w = 1000f;
                                if (index == max2)
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
                else
                {
                    PathUnit.CalculatePathPositionOffset(laneID, vector, out b4);
                }
                if (index <= 0)
                {
                    if (num7 == 0)
                    {
                        Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                    }
                    if (num7 >= (int)(instance.m_pathUnits.m_buffer[(int)((UIntPtr)num8)].m_positionCount - 1) && instance.m_pathUnits.m_buffer[(int)((UIntPtr)num8)].m_nextPathUnit == 0u && leaderID != 0)
                    {
                        this.ArrivingToDestination(leaderID, ref leaderData);
                    }
                }
                num3 = num8;
                b    = (byte)(num7 << 1);
                b2   = b4;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = b;
                    vehicleData.m_lastPathOffset    = b2;
                    vehicleData.m_flags             = ((vehicleData.m_flags & ~(Vehicle.Flags.OnGravel | Vehicle.Flags.Underground | Vehicle.Flags.Transition)) | info.m_setVehicleFlags);
                    if ((vehicleData.m_flags2 & Vehicle.Flags2.Yielding) != (Vehicle.Flags2) 0)
                    {
                        vehicleData.m_flags2     &= ~Vehicle.Flags2.Yielding;
                        vehicleData.m_waitCounter = 0;
                    }
                }
                position = position2;
                num4     = laneID;
            }
            return;

Block_19:
            if (index <= 0)
            {
                Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                vehicleData.m_path = 0u;
            }
            vector.w = 1f;
            vehicleData.SetTargetPos(index++, vector);
            return;

Block_21:
            this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
            return;

Block_22:
            this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
            return;

Block_23:
            this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
            return;

IL_595:
            if (index <= 0)
            {
                vehicleData.m_lastPathOffset = b2;
            }
            vector   = bezier.a;
            vector.w = 0f;
            while (index < max2)
            {
                vehicleData.SetTargetPos(index++, vector);
            }
        }
        private bool ProcessPathUnit(ref PathUnit unit, byte index, PathPositionProcessor processor)
        {
            if ((unit.m_pathFindFlags & PathUnit.FLAG_READY) == 0)
            {
                return(false);
            }

            switch (index)
            {
            case 0:
                processor(ref unit.m_position00);
                break;

            case 1:
                processor(ref unit.m_position01);
                break;

            case 2:
                processor(ref unit.m_position02);
                break;

            case 3:
                processor(ref unit.m_position03);
                break;

            case 4:
                processor(ref unit.m_position04);
                break;

            case 5:
                processor(ref unit.m_position05);
                break;

            case 6:
                processor(ref unit.m_position06);
                break;

            case 7:
                processor(ref unit.m_position07);
                break;

            case 8:
                processor(ref unit.m_position08);
                break;

            case 9:
                processor(ref unit.m_position09);
                break;

            case 10:
                processor(ref unit.m_position10);
                break;

            case 11:
                processor(ref unit.m_position11);
                break;

            default:
                return(false);
            }
            return(true);
        }
        private bool ProcessPathUnitQuad(ref Vehicle firstVehicleData, ref PathUnit unit1, ref PathUnit unit2, byte index, ref Vehicle secondVehicleData, ref PathUnit.Position secondPos1, ref PathUnit.Position secondPos2, QuadPathPositionProcessor processor)
        {
            if ((unit1.m_pathFindFlags & PathUnit.FLAG_READY) == 0)
            {
                return(false);
            }

            if ((unit2.m_pathFindFlags & PathUnit.FLAG_READY) == 0)
            {
                return(false);
            }

            switch (index)
            {
            case 0:
                processor(ref firstVehicleData, ref unit1.m_position00, ref unit1.m_position01, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 1:
                processor(ref firstVehicleData, ref unit1.m_position01, ref unit1.m_position02, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 2:
                processor(ref firstVehicleData, ref unit1.m_position02, ref unit1.m_position03, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 3:
                processor(ref firstVehicleData, ref unit1.m_position03, ref unit1.m_position04, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 4:
                processor(ref firstVehicleData, ref unit1.m_position04, ref unit1.m_position05, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 5:
                processor(ref firstVehicleData, ref unit1.m_position05, ref unit1.m_position06, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 6:
                processor(ref firstVehicleData, ref unit1.m_position06, ref unit1.m_position07, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 7:
                processor(ref firstVehicleData, ref unit1.m_position07, ref unit1.m_position08, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 8:
                processor(ref firstVehicleData, ref unit1.m_position08, ref unit1.m_position09, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 9:
                processor(ref firstVehicleData, ref unit1.m_position09, ref unit1.m_position10, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 10:
                processor(ref firstVehicleData, ref unit1.m_position10, ref unit1.m_position11, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            case 11:
                processor(ref firstVehicleData, ref unit1.m_position11, ref unit2.m_position00, ref secondVehicleData, ref secondPos1, ref secondPos2);
                break;

            default:
                return(false);
            }

            return(true);
        }
        private bool ProcessPathUnitPair(ref Vehicle vehicleData, ref PathUnit unit1, ref PathUnit unit2, byte index, DualPathPositionProcessor processor)
        {
            if ((unit1.m_pathFindFlags & PathUnit.FLAG_READY) == 0)
            {
                return(false);
            }

            if ((unit2.m_pathFindFlags & PathUnit.FLAG_READY) == 0)
            {
                return(false);
            }

            switch (index)
            {
            case 0:
                processor(ref vehicleData, ref unit1.m_position00, ref unit1.m_position01);
                break;

            case 1:
                processor(ref vehicleData, ref unit1.m_position01, ref unit1.m_position02);
                break;

            case 2:
                processor(ref vehicleData, ref unit1.m_position02, ref unit1.m_position03);
                break;

            case 3:
                processor(ref vehicleData, ref unit1.m_position03, ref unit1.m_position04);
                break;

            case 4:
                processor(ref vehicleData, ref unit1.m_position04, ref unit1.m_position05);
                break;

            case 5:
                processor(ref vehicleData, ref unit1.m_position05, ref unit1.m_position06);
                break;

            case 6:
                processor(ref vehicleData, ref unit1.m_position06, ref unit1.m_position07);
                break;

            case 7:
                processor(ref vehicleData, ref unit1.m_position07, ref unit1.m_position08);
                break;

            case 8:
                processor(ref vehicleData, ref unit1.m_position08, ref unit1.m_position09);
                break;

            case 9:
                processor(ref vehicleData, ref unit1.m_position09, ref unit1.m_position10);
                break;

            case 10:
                processor(ref vehicleData, ref unit1.m_position10, ref unit1.m_position11);
                break;

            case 11:
                processor(ref vehicleData, ref unit1.m_position11, ref unit2.m_position00);
                break;

            default:
                return(false);
            }

            return(true);
        }
Пример #25
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, RoadManager.VehicleType vehicleType)
 {
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, false, false, false, false, vehicleType);
 }
Пример #26
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, RoadManager.VehicleType vehicleType)
 {
     while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT))
     {
     }
     uint num;
     try
     {
         if (!this.m_pathUnits.CreateItem(out num, ref randomizer))
         {
             unit = 0u;
             bool result = false;
             return result;
         }
         this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u);
     }
     finally
     {
         Monitor.Exit(this.m_bufferLock);
     }
     unit = num;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = 1;
     if (isHeavyVehicle)
     {
         PathUnit[] expr_92_cp_0 = this.m_pathUnits.m_buffer;
         UIntPtr expr_92_cp_1 = (UIntPtr)unit;
         expr_92_cp_0[(int)expr_92_cp_1].m_simulationFlags = (byte)(expr_92_cp_0[(int)expr_92_cp_1].m_simulationFlags | 16);
     }
     if (ignoreBlocked)
     {
         PathUnit[] expr_BB_cp_0 = this.m_pathUnits.m_buffer;
         UIntPtr expr_BB_cp_1 = (UIntPtr)unit;
         expr_BB_cp_0[(int)expr_BB_cp_1].m_simulationFlags = (byte)(expr_BB_cp_0[(int)expr_BB_cp_1].m_simulationFlags | 32);
     }
     if (stablePath)
     {
         PathUnit[] expr_E4_cp_0 = this.m_pathUnits.m_buffer;
         UIntPtr expr_E4_cp_1 = (UIntPtr)unit;
         expr_E4_cp_0[(int)expr_E4_cp_1].m_simulationFlags = (byte)(expr_E4_cp_0[(int)expr_E4_cp_1].m_simulationFlags | 64);
     }
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20;
     this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1;
     int num2 = 10000000;
     CustomPathFind pathFind = null;
     for (int i = 0; i < this.m_pathFinds.Length; i++)
     {
         CustomPathFind pathFind2 = this.m_pathFinds[i];
         if (pathFind2.IsAvailable && pathFind2.m_queuedPathFindCount < num2)
         {
             num2 = pathFind2.m_queuedPathFindCount;
             pathFind = pathFind2;
         }
     }
     if (pathFind != null && pathFind.CalculatePath(unit, skipQueue, vehicleType))
     {
         return true;
     }
     this.ReleasePath(unit);
     return false;
 }
 //
 // BEGIN STOCK CODE
 //
 public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPos, PathUnit.Position endPos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength)
 {
     PathUnit.Position position = default(PathUnit.Position);
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPos, position, endPos, position, position, laneTypes, vehicleTypes, maxLength, false, false, false, false);
 }
		private void AddBufferItem(BufferItem item, PathUnit.Position target) {
			//bCurrentState = 0;
#if DEBUGPF
			/*if (m_queuedPathFindCount > 100 && Options.disableSomething1)
				Log._Debug($"THREAD #{Thread.CurrentThread.ManagedThreadId} PF {this._pathFindIndex}: AddBufferItem item {item.m_position.m_segment} {item.m_position.m_lane}");*/
#endif

			uint num = _laneLocation[(int)((UIntPtr)item.m_laneID)];
			uint num2 = num >> 16;
			int num3 = (int)(num & 65535u);
			int comparisonBufferPos;
			if (num2 == _pathFindIndex) {
				//bCurrentState = 1;
				if (item.m_comparisonValue >= _buffer[num3].m_comparisonValue) {
					return;
				}
				//bCurrentState = 2;
				int num4 = num3 >> 6;
				int num5 = num3 & -64;
				if (num4 < _bufferMinPos || (num4 == _bufferMinPos && num5 < _bufferMin[num4])) {
					return;
				}
				//bCurrentState = 3;
				comparisonBufferPos = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), _bufferMinPos);
				if (comparisonBufferPos == num4) {
					_buffer[num3] = item;
					_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
					return;
				}
				//bCurrentState = 4;
				int num7 = num4 << 6 | _bufferMax[num4]--;
				BufferItem bufferItem = _buffer[num7];
				_laneLocation[(int)((UIntPtr)bufferItem.m_laneID)] = num;
				_buffer[num3] = bufferItem;
				//bCurrentState = 5;
			} else {
				//bCurrentState = 6;
				comparisonBufferPos = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), _bufferMinPos);
			}
			//bCurrentState = 7;
			if (comparisonBufferPos >= 1024) {
				return;
			}
			//bCurrentState = 8;
			if (comparisonBufferPos < 0) {
#if DEBUG
				Log.Error("comparisonBufferPos < 0!");
#endif
				return;
			}
			//bCurrentState = 9;
			while (_bufferMax[comparisonBufferPos] == 63) {
				//bCurrentState = 10;
				comparisonBufferPos++;
				if (comparisonBufferPos == 1024) {
					//bCurrentState = 11;
					return;
				}
			}
			//bCurrentState = 12;
			if (comparisonBufferPos > _bufferMaxPos) {
				_bufferMaxPos = comparisonBufferPos;
			}
			//bCurrentState = 13;
			num3 = (comparisonBufferPos << 6 | ++_bufferMax[comparisonBufferPos]);
			_buffer[num3] = item;
			_laneLocation[(int)((UIntPtr)item.m_laneID)] = (_pathFindIndex << 16 | (uint)num3);
			_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
			//bCurrentState = 14;
		}
 protected virtual void AddBufferItem(BufferItem item, PathUnit.Position target)
 {
     uint num = this.m_laneLocation[(int)((UIntPtr)item.m_laneID)];
     uint num2 = num >> 16;
     int num3 = (int)(num & 65535u);
     int num6;
     if (num2 == this.m_pathFindIndex)
     {
         if (item.m_comparisonValue >= this.m_buffer[num3].m_comparisonValue)
         {
             return;
         }
         int num4 = num3 >> 6;
         int num5 = num3 & -64;
         if (num4 < this.m_bufferMinPos || (num4 == this.m_bufferMinPos && num5 < this.m_bufferMin[num4]))
         {
             return;
         }
         num6 = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), this.m_bufferMinPos);
         if (num6 == num4)
         {
             this.m_buffer[num3] = item;
             this.m_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
             return;
         }
         int num7 = num4 << 6 | this.m_bufferMax[num4]--;
         BufferItem bufferItem = this.m_buffer[num7];
         this.m_laneLocation[(int)((UIntPtr)bufferItem.m_laneID)] = num;
         this.m_buffer[num3] = bufferItem;
     }
     else
     {
         num6 = Mathf.Max(Mathf.RoundToInt(item.m_comparisonValue * 1024f), this.m_bufferMinPos);
     }
     if (num6 >= 1024)
     {
         return;
     }
     while (this.m_bufferMax[num6] == 63)
     {
         num6++;
         if (num6 == 1024)
         {
             return;
         }
     }
     if (num6 > this.m_bufferMaxPos)
     {
         this.m_bufferMaxPos = num6;
     }
     num3 = (num6 << 6 | ++this.m_bufferMax[num6]);
     this.m_buffer[num3] = item;
     this.m_laneLocation[(int)((UIntPtr)item.m_laneID)] = (this.m_pathFindIndex << 16 | (uint)num3);
     this.m_laneTarget[(int)((UIntPtr)item.m_laneID)] = target;
 }
        /******** reservation creation algorithm ************/

        public SingleTrack2WSection CreateSingleTrack2WSectionFromTrainPath(ushort vehicle_id, ushort start_segment_id)
        {
            PathManager    instance  = Singleton <PathManager> .instance;
            VehicleManager instance2 = Singleton <VehicleManager> .instance;
            NetManager     instance3 = Singleton <NetManager> .instance;

            Vehicle  vehicleData     = instance2.m_vehicles.m_buffer[vehicle_id];
            PathUnit pathunit        = instance.m_pathUnits.m_buffer[vehicleData.m_path];
            int      posindex        = (vehicleData.m_pathPositionIndex >> 1) + 1;
            bool     continue_search = true;

            bool   found_inspected_segment     = false;
            ushort segments_ahead_from_vehicle = 0;

            SingleTrack2WSection section = new SingleTrack2WSection();
            ushort crt_segment_id        = 0;

            bool buildOldWay = false;

            //browse successive segments in path for single tracks
            while (continue_search)
            {
                continue_search = false;

                if (posindex >= (int)pathunit.m_positionCount)
                {
                    posindex = 0;
                    uint nextPathUnit = pathunit.m_nextPathUnit;
                    if (nextPathUnit == 0u)
                    {
                        //CODebug.Log(LogChannel.Modding, Mod.modName + " - no next path unit ??");

                        //path is at the end, don't know if train will carry after the station
                        //may add further single track segments along the track
                        buildOldWay = true; //start other algorithm, usually in case of a single track station
                        break;
                    }
                    pathunit = instance.m_pathUnits.m_buffer[nextPathUnit];
                }

                PathUnit.Position pathpos;
                if (!pathunit.GetPosition(posindex, out pathpos))
                {
                    return(null);
                }
                crt_segment_id = pathpos.m_segment;

                //activate signal at the end of the single track section
                CheckSpawnSignals(crt_segment_id);

                if (!found_inspected_segment)
                {
                    if (crt_segment_id == start_segment_id)
                    {
                        found_inspected_segment = true;
                    }
                }

                if (found_inspected_segment)
                {
                    if (RequireReservation(crt_segment_id))
                    {
                        section.segment_ids.Add(crt_segment_id);
                        continue_search = true;
                    }
                }

                posindex++;
                segments_ahead_from_vehicle++;
                if (!found_inspected_segment && segments_ahead_from_vehicle < 5)
                {
                    continue_search = true;
                }
            }

            if (buildOldWay && section.segment_ids.Count > 0)
            {
                if (IsStation(section.segment_ids[section.segment_ids.Count - 1]))
                {
                    section.containStopStation = true;


                    //Is use of other algo really needed? Train may or may not go further along the track
                    //Other trains check if other reservation further along the path anyway...

                    // -> yes reserving single tracks after station ensure TrainExitStation is properly resolved
                    // There is not a second, separate reservation made (except when branching...)

                    if (Mod.extendReservationAfterStopStation)
                    {
                        //section.notFromPathSegmentsStartingAt = section.segment_ids.Count; //mark that segments further on have not been path checked
                        AppendNextConnectedSegmentTheOldWay(section, section.segment_ids[section.segment_ids.Count - 1]);
                    }
                }
            }

            if (section.segment_ids.Count > 0)
            {
                return(section);
            }

            return(null);
        }
Пример #31
0
 public void ProcessUnit(uint unitId, ref PathUnit unit, PathUnitHandler handler)
 {
     handler(unitId, ref unit);
 }
 protected virtual void GetLaneDirection(PathUnit.Position pathPos, out NetInfo.Direction direction, out NetInfo.LaneType type)
 {
     NetManager instance = Singleton<NetManager>.instance;
     NetInfo info = instance.m_segments.m_buffer[(int)pathPos.m_segment].Info;
     if (info.m_lanes.Length > (int)pathPos.m_lane)
     {
         direction = info.m_lanes[(int)pathPos.m_lane].m_finalDirection;
         type = info.m_lanes[(int)pathPos.m_lane].m_laneType;
         if ((instance.m_segments.m_buffer[(int)pathPos.m_segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
         {
             direction = NetInfo.InvertDirection(direction);
         }
     }
     else
     {
         direction = NetInfo.Direction.None;
         type = NetInfo.LaneType.None;
     }
 }
Пример #33
0
        public static void SimulationStep(CarAI carAI, ushort vehicleID, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ushort leaderID, ref Vehicle leaderData, int lodPhysics)
        {
            uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            frameData.m_position     += frameData.m_velocity * 0.5f;
            frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f;
            float   acceleration = carAI.m_info.m_acceleration;
            float   braking      = carAI.m_info.m_braking;
            float   magnitude    = frameData.m_velocity.magnitude;
            Vector3 vector       = vehicleData.m_targetPos0 - (Vector4)frameData.m_position;
            float   sqrMagnitude = vector.sqrMagnitude;
            float   num          = (magnitude + acceleration) * (0.5f + 0.5f * (magnitude + acceleration) / braking) + carAI.m_info.m_generatedInfo.m_size.z * 0.5f;
            float   num2         = Mathf.Max(magnitude + acceleration, 5f);

            if (lodPhysics >= 2 && (ulong)(currentFrameIndex >> 4 & 3u) == (ulong)((long)(vehicleID & 3)))
            {
                num2 *= 2f;
            }
            float num3 = Mathf.Max((num - num2) / 3f, 1f);
            float num4 = num2 * num2;
            float num5 = num3 * num3;
            int   i    = 0;
            bool  flag = false;

            if ((sqrMagnitude < num4 || vehicleData.m_targetPos3.w < 0.01f) && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == Vehicle.Flags.None)
            {
                if (leaderData.m_path != 0u)
                {
                    CustomVehicleAI.UpdatePathTargetPositions(carAI, vehicleID, ref vehicleData, frameData.m_position, ref i, 4, num4, num5);
                    if ((leaderData.m_flags & Vehicle.Flags.Spawned) == Vehicle.Flags.None)
                    {
                        frameData = vehicleData.m_frame0;
                        return;
                    }
                }
                if ((leaderData.m_flags & Vehicle.Flags.WaitingPath) == Vehicle.Flags.None)
                {
                    while (i < 4)
                    {
                        float   minSqrDistance;
                        Vector3 refPos;
                        if (i == 0)
                        {
                            minSqrDistance = num4;
                            refPos         = frameData.m_position;
                            flag           = true;
                        }
                        else
                        {
                            minSqrDistance = num5;
                            refPos         = vehicleData.GetTargetPos(i - 1);
                        }
                        int num6 = i;
                        carAI.UpdateBuildingTargetPositions(vehicleID, ref vehicleData, refPos, leaderID, ref leaderData, ref i, minSqrDistance);
                        if (i == num6)
                        {
                            break;
                        }
                    }
                    if (i != 0)
                    {
                        Vector4 targetPos = vehicleData.GetTargetPos(i - 1);
                        while (i < 4)
                        {
                            vehicleData.SetTargetPos(i++, targetPos);
                        }
                    }
                }
                vector       = vehicleData.m_targetPos0 - (Vector4)frameData.m_position;
                sqrMagnitude = vector.sqrMagnitude;
            }
            if (leaderData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == Vehicle.Flags.None)
            {
                NetManager instance       = Singleton <NetManager> .instance;
                byte       b              = leaderData.m_pathPositionIndex;
                byte       lastPathOffset = leaderData.m_lastPathOffset;
                if (b == 255)
                {
                    b = 0;
                }
                float             num7      = 1f + leaderData.CalculateTotalLength(leaderID);
                PathManager       instance2 = Singleton <PathManager> .instance;
                PathUnit.Position pathPos;
                if (instance2.m_pathUnits.m_buffer[(int)((UIntPtr)leaderData.m_path)].GetPosition(b >> 1, out pathPos))
                {
                    instance.m_segments.m_buffer[(int)pathPos.m_segment].AddTraffic(Mathf.RoundToInt(num7 * 2.5f));
                    bool flag2 = false;
                    if ((b & 1) == 0 || lastPathOffset == 0)
                    {
                        uint laneID = PathManager.GetLaneID(pathPos);
                        if (laneID != 0u)
                        {
                            Vector3 b2   = instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePosition((float)pathPos.m_offset * 0.003921569f);
                            float   num8 = 0.5f * magnitude * magnitude / carAI.m_info.m_braking + carAI.m_info.m_generatedInfo.m_size.z * 0.5f;
                            if (Vector3.Distance(frameData.m_position, b2) >= num8 - 1f)
                            {
                                instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].ReserveSpace(num7);
                                flag2 = true;
                            }
                        }
                    }
                    if (!flag2 && instance2.m_pathUnits.m_buffer[(int)((UIntPtr)leaderData.m_path)].GetNextPosition(b >> 1, out pathPos))
                    {
                        uint laneID2 = PathManager.GetLaneID(pathPos);
                        if (laneID2 != 0u)
                        {
                            instance.m_lanes.m_buffer[(int)((UIntPtr)laneID2)].ReserveSpace(num7);
                        }
                    }
                }
                if ((ulong)(currentFrameIndex >> 4 & 15u) == (ulong)((long)(leaderID & 15)))
                {
                    bool flag3 = false;
                    uint path  = leaderData.m_path;
                    int  num9  = b >> 1;
                    int  j     = 0;
                    while (j < 5)
                    {
                        bool flag4;
                        if (PathUnit.GetNextPosition(ref path, ref num9, out pathPos, out flag4))
                        {
                            uint laneID3 = PathManager.GetLaneID(pathPos);
                            if (laneID3 != 0u && !instance.m_lanes.m_buffer[(int)((UIntPtr)laneID3)].CheckSpace(num7))
                            {
                                j++;
                                continue;
                            }
                        }
                        if (flag4)
                        {
                            (carAI as IVehicle).InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                        }
                        flag3 = true;
                        break;
                    }
                    if (!flag3)
                    {
                        leaderData.m_flags |= Vehicle.Flags.Congestion;
                    }
                }
            }
            float num10;

            if ((leaderData.m_flags & Vehicle.Flags.Stopped) != Vehicle.Flags.None)
            {
                num10 = 0f;
            }
            else
            {
                num10 = vehicleData.m_targetPos0.w;
            }
            Quaternion rotation = Quaternion.Inverse(frameData.m_rotation);

            vector = rotation * vector;
            Vector3 vector2 = rotation * frameData.m_velocity;
            Vector3 a       = Vector3.forward;
            Vector3 vector3 = Vector3.zero;
            Vector3 zero    = Vector3.zero;
            float   num11   = 0f;
            float   num12   = 0f;
            bool    flag5   = false;
            float   num13   = 0f;

            if (sqrMagnitude > 1f)
            {
                a = VectorUtils.NormalizeXZ(vector, out num13);
                if (num13 > 1f)
                {
                    Vector3 vector4 = vector;
                    num2 = Mathf.Max(magnitude, 2f);
                    num4 = num2 * num2;
                    if (sqrMagnitude > num4)
                    {
                        vector4 *= num2 / Mathf.Sqrt(sqrMagnitude);
                    }
                    bool flag6 = false;
                    if (vector4.z < Mathf.Abs(vector4.x))
                    {
                        if (vector4.z < 0f)
                        {
                            flag6 = true;
                        }
                        float num14 = Mathf.Abs(vector4.x);
                        if (num14 < 1f)
                        {
                            vector4.x = Mathf.Sign(vector4.x);
                            if (vector4.x == 0f)
                            {
                                vector4.x = 1f;
                            }
                            num14 = 1f;
                        }
                        vector4.z = num14;
                    }
                    float b3;
                    a     = VectorUtils.NormalizeXZ(vector4, out b3);
                    num13 = Mathf.Min(num13, b3);
                    float num15 = 1.57079637f * (1f - a.z);
                    if (num13 > 1f)
                    {
                        num15 /= num13;
                    }
                    float num16 = num13;
                    if (vehicleData.m_targetPos0.w < 0.1f)
                    {
                        num10 = (carAI as IVehicle).CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num15);
                        num10 = Mathf.Min(num10, CalculateMaxSpeed(num16, Mathf.Min(vehicleData.m_targetPos0.w, vehicleData.m_targetPos1.w), braking * 0.9f));
                    }
                    else
                    {
                        num10 = Mathf.Min(num10, (carAI as IVehicle).CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num15));
                        num10 = Mathf.Min(num10, CalculateMaxSpeed(num16, vehicleData.m_targetPos1.w, braking * 0.9f));
                    }
                    num16 += VectorUtils.LengthXZ(vehicleData.m_targetPos1 - vehicleData.m_targetPos0);
                    num10  = Mathf.Min(num10, CalculateMaxSpeed(num16, vehicleData.m_targetPos2.w, braking * 0.9f));
                    num16 += VectorUtils.LengthXZ(vehicleData.m_targetPos2 - vehicleData.m_targetPos1);
                    num10  = Mathf.Min(num10, CalculateMaxSpeed(num16, vehicleData.m_targetPos3.w, braking * 0.9f));
                    num16 += VectorUtils.LengthXZ(vehicleData.m_targetPos3 - vehicleData.m_targetPos2);
                    if (vehicleData.m_targetPos3.w < 0.01f)
                    {
                        num16 = Mathf.Max(0f, num16 - carAI.m_info.m_generatedInfo.m_size.z * 0.5f);
                    }
                    num10 = Mathf.Min(num10, CalculateMaxSpeed(num16, 0f, braking * 0.9f));
                    if (!DisableCollisionCheck(leaderID, ref leaderData))
                    {
                        CustomCarAI.CheckOtherVehicles(carAI, vehicleID, ref vehicleData, ref frameData, ref num10, ref flag5, ref zero, num, braking * 0.9f, lodPhysics);
                    }
                    if (flag6)
                    {
                        num10 = -num10;
                    }
                    if (num10 < magnitude)
                    {
                        float num17 = Mathf.Max(acceleration, Mathf.Min(braking, magnitude));
                        num11 = Mathf.Max(num10, magnitude - num17);
                    }
                    else
                    {
                        float num18 = Mathf.Max(acceleration, Mathf.Min(braking, -magnitude));
                        num11 = Mathf.Min(num10, magnitude + num18);
                    }
                }
            }
            else
            {
                if (magnitude < 0.1f && flag && carAI.ArriveAtDestination(leaderID, ref leaderData))
                {
                    leaderData.Unspawn(leaderID);
                    if (leaderID == vehicleID)
                    {
                        frameData = leaderData.m_frame0;
                    }
                    return;
                }
            }
            if ((leaderData.m_flags & Vehicle.Flags.Stopped) == Vehicle.Flags.None && num10 < 0.1f)
            {
                flag5 = true;
            }
            if (flag5)
            {
                vehicleData.m_blockCounter = (byte)Mathf.Min((int)(vehicleData.m_blockCounter + 1), 255);
                if ((vehicleData.m_blockCounter == 100 || vehicleData.m_blockCounter == 150) && (CSLTraffic.Options & OptionsManager.ModOptions.NoDespawn) == OptionsManager.ModOptions.NoDespawn)
                {
                    vehicleData.m_blockCounter++;
                }
            }
            else
            {
                vehicleData.m_blockCounter = 0;
            }
            if (num13 > 1f)
            {
                num12   = Mathf.Asin(a.x) * Mathf.Sign(num11);
                vector3 = a * num11;
            }
            else
            {
                num11 = 0f;
                Vector3 b4 = Vector3.ClampMagnitude(vector * 0.5f - vector2, braking);
                vector3 = vector2 + b4;
            }
            bool    flag7   = (currentFrameIndex + (uint)leaderID & 16u) != 0u;
            Vector3 a2      = vector3 - vector2;
            Vector3 vector5 = frameData.m_rotation * vector3;

            frameData.m_velocity         = vector5 + zero;
            frameData.m_position        += frameData.m_velocity * 0.5f;
            frameData.m_swayVelocity     = frameData.m_swayVelocity * (1f - carAI.m_info.m_dampers) - a2 * (1f - carAI.m_info.m_springs) - frameData.m_swayPosition * carAI.m_info.m_springs;
            frameData.m_swayPosition    += frameData.m_swayVelocity * 0.5f;
            frameData.m_steerAngle       = num12;
            frameData.m_travelDistance  += vector3.z;
            frameData.m_lightIntensity.x = 5f;
            frameData.m_lightIntensity.y = ((a2.z >= -0.1f) ? 0.5f : 5f);
            frameData.m_lightIntensity.z = ((num12 >= -0.1f || !flag7) ? 0f : 5f);
            frameData.m_lightIntensity.w = ((num12 <= 0.1f || !flag7) ? 0f : 5f);
            frameData.m_underground      = ((vehicleData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None);
            frameData.m_transition       = ((vehicleData.m_flags & Vehicle.Flags.Transition) != Vehicle.Flags.None);
            if ((vehicleData.m_flags & Vehicle.Flags.Parking) != Vehicle.Flags.None && num13 <= 1f && flag)
            {
                Vector3 forward = vehicleData.m_targetPos1 - vehicleData.m_targetPos0;
                if (forward.sqrMagnitude > 0.01f)
                {
                    frameData.m_rotation = Quaternion.LookRotation(forward);
                }
            }
            else
            {
                if (num11 > 0.1f)
                {
                    if (vector5.sqrMagnitude > 0.01f)
                    {
                        frameData.m_rotation = Quaternion.LookRotation(vector5);
                    }
                }
                else
                {
                    if (num11 < -0.1f && vector5.sqrMagnitude > 0.01f)
                    {
                        frameData.m_rotation = Quaternion.LookRotation(-vector5);
                    }
                }
            }
        }
        protected void CustomUpdatePathTargetPositions(ushort vehicleID, ref Vehicle vehicleData, Vector3 refPos, ref int index, int max, float minSqrDistanceA, float minSqrDistanceB)
        {
            PathManager pathMan    = Singleton <PathManager> .instance;
            NetManager  netManager = Singleton <NetManager> .instance;
            Vector4     targetPos0 = vehicleData.m_targetPos0;

            targetPos0.w = 1000f;
            float minSqrDistA    = minSqrDistanceA;
            uint  pathId         = vehicleData.m_path;
            byte  pathPosIndex   = vehicleData.m_pathPositionIndex;
            byte  lastPathOffset = vehicleData.m_lastPathOffset;

            if (pathPosIndex == 255)
            {
                pathPosIndex = 0;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = 0;
                }
                if (!Singleton <PathManager> .instance.m_pathUnits.m_buffer[pathId].CalculatePathPositionOffset(pathPosIndex >> 1, targetPos0, out lastPathOffset))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
            }

            PathUnit.Position position;
            if (!pathMan.m_pathUnits.m_buffer[pathId].GetPosition(pathPosIndex >> 1, out position))
            {
                this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }

            NetInfo curSegmentInfo = netManager.m_segments.m_buffer[(int)position.m_segment].Info;

            if (curSegmentInfo.m_lanes.Length <= (int)position.m_lane)
            {
                this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }

            uint curLaneId = PathManager.GetLaneID(position);

            NetInfo.Lane laneInfo = curSegmentInfo.m_lanes[(int)position.m_lane];
            Bezier3      bezier;
            bool         firstIter = true;     // NON-STOCK CODE

            while (true)
            {
                if ((pathPosIndex & 1) == 0)
                {
                    if (laneInfo.m_laneType != NetInfo.LaneType.CargoVehicle)
                    {
                        bool first = true;
                        while (lastPathOffset != position.m_offset)
                        {
                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                float distDiff = Mathf.Sqrt(minSqrDistA) - Vector3.Distance(targetPos0, refPos);
                                int   pathOffsetDelta;
                                if (distDiff < 0f)
                                {
                                    pathOffsetDelta = 4;
                                }
                                else
                                {
                                    pathOffsetDelta = 4 + Mathf.Max(0, Mathf.CeilToInt(distDiff * 256f / (netManager.m_lanes.m_buffer[curLaneId].m_length + 1f)));
                                }
                                if (lastPathOffset > position.m_offset)
                                {
                                    lastPathOffset = (byte)Mathf.Max((int)lastPathOffset - pathOffsetDelta, (int)position.m_offset);
                                }
                                else if (lastPathOffset < position.m_offset)
                                {
                                    lastPathOffset = (byte)Mathf.Min((int)lastPathOffset + pathOffsetDelta, (int)position.m_offset);
                                }
                            }
                            Vector3 curSegPos;
                            Vector3 curSegDir;
                            float   curSegOffset;
                            this.CalculateSegmentPosition(vehicleID, ref vehicleData, position, curLaneId, lastPathOffset, out curSegPos, out curSegDir, out curSegOffset);
                            targetPos0.Set(curSegPos.x, curSegPos.y, curSegPos.z, Mathf.Min(targetPos0.w, curSegOffset));
                            float refPosSqrDist = (curSegPos - refPos).sqrMagnitude;
                            if (refPosSqrDist >= minSqrDistA)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_lastPathOffset = lastPathOffset;
                                }
                                vehicleData.SetTargetPos(index++, targetPos0);
                                minSqrDistA  = minSqrDistanceB;
                                refPos       = targetPos0;
                                targetPos0.w = 1000f;
                                if (index == max)
                                {
                                    return;
                                }
                            }
                        }
                    }
                    pathPosIndex  += 1;
                    lastPathOffset = 0;
                    if (index <= 0)
                    {
                        vehicleData.m_pathPositionIndex = pathPosIndex;
                        vehicleData.m_lastPathOffset    = lastPathOffset;
                    }
                }

                int  nextPathPosIndex = (pathPosIndex >> 1) + 1;
                uint nextPathId       = pathId;
                if (nextPathPosIndex >= (int)pathMan.m_pathUnits.m_buffer[pathId].m_positionCount)
                {
                    nextPathPosIndex = 0;
                    nextPathId       = pathMan.m_pathUnits.m_buffer[pathId].m_nextPathUnit;
                    if (nextPathId == 0u)
                    {
                        if (index <= 0)
                        {
                            Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                            vehicleData.m_path = 0u;
                        }
                        targetPos0.w = 1f;
                        vehicleData.SetTargetPos(index++, targetPos0);
                        return;
                    }
                }

                PathUnit.Position nextPathPos;
                if (!pathMan.m_pathUnits.m_buffer[nextPathId].GetPosition(nextPathPosIndex, out nextPathPos))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                NetInfo nextSegmentInfo = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].Info;
                if (nextSegmentInfo.m_lanes.Length <= (int)nextPathPos.m_lane)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                int bestLaneIndex = nextPathPos.m_lane;
                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) != (Vehicle.Flags) 0)
                {
                    bestLaneIndex = FindBestLane(vehicleID, ref vehicleData, nextPathPos);
                }
                else
                {
                    // NON-STOCK CODE START
                    if (firstIter &&
                        this.m_info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                        !this.m_info.m_isLargeVehicle
                        )
                    {
                        bool mayFindBestLane = false;
#if BENCHMARK
                        using (var bm = new Benchmark(null, "MayFindBestLane")) {
#endif
                        mayFindBestLane = VehicleBehaviorManager.Instance.MayFindBestLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID]);
#if BENCHMARK
                    }
#endif

                        if (mayFindBestLane)
                        {
                            uint next2PathId       = nextPathId;
                            int  next2PathPosIndex = nextPathPosIndex;
                            bool next2Invalid;
                            PathUnit.Position next2PathPos;
                            NetInfo           next2SegmentInfo = null;
                            PathUnit.Position next3PathPos;
                            NetInfo           next3SegmentInfo = null;
                            PathUnit.Position next4PathPos;
                            if (PathUnit.GetNextPosition(ref next2PathId, ref next2PathPosIndex, out next2PathPos, out next2Invalid))
                            {
                                next2SegmentInfo = netManager.m_segments.m_buffer[(int)next2PathPos.m_segment].Info;

                                uint next3PathId       = next2PathId;
                                int  next3PathPosIndex = next2PathPosIndex;
                                bool next3Invalid;
                                if (PathUnit.GetNextPosition(ref next3PathId, ref next3PathPosIndex, out next3PathPos, out next3Invalid))
                                {
                                    next3SegmentInfo = netManager.m_segments.m_buffer[(int)next3PathPos.m_segment].Info;

                                    uint next4PathId       = next3PathId;
                                    int  next4PathPosIndex = next3PathPosIndex;
                                    bool next4Invalid;
                                    if (!PathUnit.GetNextPosition(ref next4PathId, ref next4PathPosIndex, out next4PathPos, out next4Invalid))
                                    {
                                        next4PathPos = default(PathUnit.Position);
                                    }
                                }
                                else
                                {
                                    next3PathPos = default(PathUnit.Position);
                                    next4PathPos = default(PathUnit.Position);
                                }
                            }
                            else
                            {
                                next2PathPos = default(PathUnit.Position);
                                next3PathPos = default(PathUnit.Position);
                                next4PathPos = default(PathUnit.Position);
                            }

#if BENCHMARK
                            using (var bm = new Benchmark(null, "FindBestLane")) {
#endif
                            bestLaneIndex = VehicleBehaviorManager.Instance.FindBestLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID], curLaneId, position, curSegmentInfo, nextPathPos, nextSegmentInfo, next2PathPos, next2SegmentInfo, next3PathPos, next3SegmentInfo, next4PathPos);
#if BENCHMARK
                        }
#endif
                        }
                        // NON-STOCK CODE END
                    }
                }

                if (bestLaneIndex != (int)nextPathPos.m_lane)
                {
                    nextPathPos.m_lane = (byte)bestLaneIndex;
                    pathMan.m_pathUnits.m_buffer[nextPathId].SetPosition(nextPathPosIndex, nextPathPos);
#if BENCHMARK
                    using (var bm = new Benchmark(null, "AddTraffic")) {
#endif
                    // prevent multiple lane changes to the same lane from happening at the same time
                    TrafficMeasurementManager.Instance.AddTraffic(nextPathPos.m_segment, nextPathPos.m_lane
#if MEASUREDENSITY
                                                                  , VehicleStateManager.Instance.VehicleStates[vehicleID].totalLength
#endif
                                                                  , 0); // NON-STOCK CODE
#if BENCHMARK
                }
#endif
                }

                uint nextLaneId           = PathManager.GetLaneID(nextPathPos);
                NetInfo.Lane nextLaneInfo = nextSegmentInfo.m_lanes[(int)nextPathPos.m_lane];
                ushort curSegStartNodeId  = netManager.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                ushort curSegEndNodeId    = netManager.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                ushort nextSegStartNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_startNode;
                ushort nextSegEndNodeId   = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_endNode;
                if (nextSegStartNodeId != curSegStartNodeId &&
                    nextSegStartNodeId != curSegEndNodeId &&
                    nextSegEndNodeId != curSegStartNodeId &&
                    nextSegEndNodeId != curSegEndNodeId &&
                    ((netManager.m_nodes.m_buffer[(int)curSegStartNodeId].m_flags | netManager.m_nodes.m_buffer[(int)curSegEndNodeId].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None &&
                    ((netManager.m_nodes.m_buffer[(int)nextSegStartNodeId].m_flags | netManager.m_nodes.m_buffer[(int)nextSegEndNodeId].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                if (nextLaneInfo.m_laneType == NetInfo.LaneType.Pedestrian)
                {
                    if (vehicleID != 0 && (vehicleData.m_flags & Vehicle.Flags.Parking) == (Vehicle.Flags) 0)
                    {
                        byte inOffset  = position.m_offset;
                        byte outOffset = position.m_offset;
                        if (this.ParkVehicle(vehicleID, ref vehicleData, position, nextPathId, nextPathPosIndex << 1, out outOffset))
                        {
                            if (outOffset != inOffset)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_pathPositionIndex = (byte)((int)vehicleData.m_pathPositionIndex & -2);
                                    vehicleData.m_lastPathOffset    = inOffset;
                                }
                                position.m_offset = outOffset;
                                pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)pathId)].SetPosition(pathPosIndex >> 1, position);
                            }
                            vehicleData.m_flags |= Vehicle.Flags.Parking;
                        }
                        else
                        {
                            this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    return;
                }

                if ((byte)(nextLaneInfo.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle | NetInfo.LaneType.TransportVehicle)) == 0)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                if (nextLaneInfo.m_vehicleType != this.m_info.m_vehicleType &&
                    this.NeedChangeVehicleType(vehicleID, ref vehicleData, nextPathPos, nextLaneId, nextLaneInfo.m_vehicleType, ref targetPos0)
                    )
                {
                    float targetPos0ToRefPosSqrDist = ((Vector3)targetPos0 - refPos).sqrMagnitude;
                    if (targetPos0ToRefPosSqrDist >= minSqrDistA)
                    {
                        vehicleData.SetTargetPos(index++, targetPos0);
                    }
                    if (index <= 0)
                    {
                        while (index < max)
                        {
                            vehicleData.SetTargetPos(index++, targetPos0);
                        }
                        if (nextPathId != vehicleData.m_path)
                        {
                            Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                        }
                        vehicleData.m_pathPositionIndex = (byte)(nextPathPosIndex << 1);
                        PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos0, out vehicleData.m_lastPathOffset);
                        if (vehicleID != 0 && !this.ChangeVehicleType(vehicleID, ref vehicleData, nextPathPos, nextLaneId))
                        {
                            this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    else
                    {
                        while (index < max)
                        {
                            vehicleData.SetTargetPos(index++, targetPos0);
                        }
                    }
                    return;
                }

                if (nextPathPos.m_segment != position.m_segment && vehicleID != 0)
                {
                    vehicleData.m_flags &= ~Vehicle.Flags.Leaving;
                }

                byte nextSegOffset = 0;
                if ((vehicleData.m_flags & Vehicle.Flags.Flying) != (Vehicle.Flags) 0)
                {
                    nextSegOffset = (byte)((nextPathPos.m_offset < 128) ? 255 : 0);
                }
                else if (curLaneId != nextLaneId && laneInfo.m_laneType != NetInfo.LaneType.CargoVehicle)
                {
                    PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos0, out nextSegOffset);
                    bezier = default(Bezier3);
                    Vector3 curSegDir;
                    float   maxSpeed;
                    this.CalculateSegmentPosition(vehicleID, ref vehicleData, position, curLaneId, position.m_offset, out bezier.a, out curSegDir, out maxSpeed);
                    bool calculateNextNextPos = lastPathOffset == 0;
                    if (calculateNextNextPos)
                    {
                        if ((vehicleData.m_flags & Vehicle.Flags.Reversed) != (Vehicle.Flags) 0)
                        {
                            calculateNextNextPos = (vehicleData.m_trailingVehicle == 0);
                        }
                        else
                        {
                            calculateNextNextPos = (vehicleData.m_leadingVehicle == 0);
                        }
                    }
                    Vector3 nextSegDir;
                    float   nextMaxSpeed;
                    if (calculateNextNextPos)
                    {
                        PathUnit.Position nextNextPathPos;
                        if (!pathMan.m_pathUnits.m_buffer[nextPathId].GetNextPosition(nextPathPosIndex, out nextNextPathPos))
                        {
                            nextNextPathPos = default(PathUnit.Position);
                        }
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, nextNextPathPos, nextPathPos, nextLaneId, nextSegOffset, position, curLaneId, position.m_offset, index, out bezier.d, out nextSegDir, out nextMaxSpeed);
                    }
                    else
                    {
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, nextPathPos, nextLaneId, nextSegOffset, out bezier.d, out nextSegDir, out nextMaxSpeed);
                    }
                    if (nextMaxSpeed < 0.01f || (netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_flags & (NetSegment.Flags.Collapsed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
                    {
                        if (index <= 0)
                        {
                            vehicleData.m_lastPathOffset = lastPathOffset;
                        }
                        targetPos0   = bezier.a;
                        targetPos0.w = 0f;
                        while (index < max)
                        {
                            vehicleData.SetTargetPos(index++, targetPos0);
                        }
                        return;
                    }
                    if (position.m_offset == 0)
                    {
                        curSegDir = -curSegDir;
                    }
                    if (nextSegOffset < nextPathPos.m_offset)
                    {
                        nextSegDir = -nextSegDir;
                    }
                    curSegDir.Normalize();
                    nextSegDir.Normalize();
                    float dist;
                    NetSegment.CalculateMiddlePoints(bezier.a, curSegDir, bezier.d, nextSegDir, true, true, out bezier.b, out bezier.c, out dist);
                    if (dist > 1f)
                    {
                        ushort nextNodeId;
                        if (nextSegOffset == 0)
                        {
                            nextNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_startNode;
                        }
                        else if (nextSegOffset == 255)
                        {
                            nextNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_endNode;
                        }
                        else
                        {
                            nextNodeId = 0;
                        }
                        float curve = 1.57079637f * (1f + Vector3.Dot(curSegDir, nextSegDir));
                        if (dist > 1f)
                        {
                            curve /= dist;
                        }
                        nextMaxSpeed = Mathf.Min(nextMaxSpeed, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve));
                        while (lastPathOffset < 255)
                        {
                            float distDiff = Mathf.Sqrt(minSqrDistA) - Vector3.Distance(targetPos0, refPos);
                            int   pathOffsetDelta;
                            if (distDiff < 0f)
                            {
                                pathOffsetDelta = 8;
                            }
                            else
                            {
                                pathOffsetDelta = 8 + Mathf.Max(0, Mathf.CeilToInt(distDiff * 256f / (dist + 1f)));
                            }
                            lastPathOffset = (byte)Mathf.Min((int)lastPathOffset + pathOffsetDelta, 255);
                            Vector3 bezierPos = bezier.Position((float)lastPathOffset * 0.003921569f);
                            targetPos0.Set(bezierPos.x, bezierPos.y, bezierPos.z, Mathf.Min(targetPos0.w, nextMaxSpeed));
                            float sqrMagnitude2 = (bezierPos - refPos).sqrMagnitude;
                            if (sqrMagnitude2 >= minSqrDistA)
                            {
                                if (index <= 0)
                                {
                                    vehicleData.m_lastPathOffset = lastPathOffset;
                                }
                                if (nextNodeId != 0)
                                {
                                    this.UpdateNodeTargetPos(vehicleID, ref vehicleData, nextNodeId, ref netManager.m_nodes.m_buffer[(int)nextNodeId], ref targetPos0, index);
                                }
                                vehicleData.SetTargetPos(index++, targetPos0);
                                minSqrDistA  = minSqrDistanceB;
                                refPos       = targetPos0;
                                targetPos0.w = 1000f;
                                if (index == max)
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
                else
                {
                    PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos0, out nextSegOffset);
                }

                if (index <= 0)
                {
                    if (nextPathPosIndex == 0)
                    {
                        Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                    }
                    if (nextPathPosIndex >= (int)(pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)nextPathId)].m_positionCount - 1) && pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)nextPathId)].m_nextPathUnit == 0u && vehicleID != 0)
                    {
                        this.ArrivingToDestination(vehicleID, ref vehicleData);
                    }
                }

                pathId         = nextPathId;
                pathPosIndex   = (byte)(nextPathPosIndex << 1);
                lastPathOffset = nextSegOffset;
                if (index <= 0)
                {
                    vehicleData.m_pathPositionIndex = pathPosIndex;
                    vehicleData.m_lastPathOffset    = lastPathOffset;
                    vehicleData.m_flags             = ((vehicleData.m_flags & ~(Vehicle.Flags.OnGravel | Vehicle.Flags.Underground | Vehicle.Flags.Transition)) | nextSegmentInfo.m_setVehicleFlags);
                    if (this.LeftHandDrive(nextLaneInfo))
                    {
                        vehicleData.m_flags |= Vehicle.Flags.LeftHandDrive;
                    }
                    else
                    {
                        vehicleData.m_flags &= (Vehicle.Flags.Created | Vehicle.Flags.Deleted | Vehicle.Flags.Spawned | Vehicle.Flags.Inverted | Vehicle.Flags.TransferToTarget | Vehicle.Flags.TransferToSource | Vehicle.Flags.Emergency1 | Vehicle.Flags.Emergency2 | Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped | Vehicle.Flags.Leaving | Vehicle.Flags.Arriving | Vehicle.Flags.Reversed | Vehicle.Flags.TakingOff | Vehicle.Flags.Flying | Vehicle.Flags.Landing | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo | Vehicle.Flags.GoingBack | Vehicle.Flags.WaitingTarget | Vehicle.Flags.Importing | Vehicle.Flags.Exporting | Vehicle.Flags.Parking | Vehicle.Flags.CustomName | Vehicle.Flags.OnGravel | Vehicle.Flags.WaitingLoading | Vehicle.Flags.Congestion | Vehicle.Flags.DummyTraffic | Vehicle.Flags.Underground | Vehicle.Flags.Transition | Vehicle.Flags.InsideBuilding);
                    }
                }
                position  = nextPathPos;
                curLaneId = nextLaneId;
                laneInfo  = nextLaneInfo;
                firstIter = false;                 // NON-STOCK CODE
            }
        }
Пример #35
0
 private void GetLaneDirection(PathUnit.Position pathPos, out NetInfo.Direction direction, out NetInfo.LaneType type)
 {
     NetManager instance = Singleton<NetManager>.instance;
     //if (instance == null)
     //	Logger.LogInfo("GetLaneDirection -> instance is null!\n");
     NetInfo info = instance.m_segments.m_buffer[(int)pathPos.m_segment].Info;
     //if (info == null)
     //	Logger.LogInfo("GetLaneDirection -> info is null!\n");
     //else if (info.m_lanes == null)
     //	Logger.LogInfo("GetLaneDirection -> info.m_lanes is null!\n");
     if (info.m_lanes.Length > (int)pathPos.m_lane)
     {
         direction = info.m_lanes[(int)pathPos.m_lane].m_finalDirection;
         type = info.m_lanes[(int)pathPos.m_lane].m_laneType;
         if ((instance.m_segments.m_buffer[(int)pathPos.m_segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
         {
             direction = NetInfo.InvertDirection(direction);
         }
     }
     else
     {
         direction = NetInfo.Direction.None;
         type = NetInfo.LaneType.None;
     }
 }
Пример #36
0
 public new bool ChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID)
 {
     return base.ChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID);
 }
Пример #37
0
 public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB, RoadManager.VehicleType vehicleType)
 {
     Bounds bounds = new Bounds(position, new Vector3(maxDistance * 2f, maxDistance * 2f, maxDistance * 2f));
     int num = Mathf.Max((int)((bounds.min.x - 64f) / 64f + 135f), 0);
     int num2 = Mathf.Max((int)((bounds.min.z - 64f) / 64f + 135f), 0);
     int num3 = Mathf.Min((int)((bounds.max.x + 64f) / 64f + 135f), 269);
     int num4 = Mathf.Min((int)((bounds.max.z + 64f) / 64f + 135f), 269);
     NetManager instance = Singleton<NetManager>.instance;
     pathPosA.m_segment = 0;
     pathPosA.m_lane = 0;
     pathPosA.m_offset = 0;
     distanceSqrA = 1E+10f;
     pathPosB.m_segment = 0;
     pathPosB.m_lane = 0;
     pathPosB.m_offset = 0;
     distanceSqrB = 1E+10f;
     float num5 = maxDistance * maxDistance;
     for (int i = num2; i <= num4; i++)
     {
         for (int j = num; j <= num3; j++)
         {
             ushort num6 = instance.m_segmentGrid[i * 270 + j];
             int num7 = 0;
             while (num6 != 0)
             {
                 NetInfo info = instance.m_segments.m_buffer[(int)num6].Info;
                 if (info.m_class.m_service == service && (instance.m_segments.m_buffer[(int)num6].m_flags & NetSegment.Flags.Flooded) == NetSegment.Flags.None && (allowUnderground || !info.m_netAI.IsUnderground()))
                 {
                     ushort startNode = instance.m_segments.m_buffer[(int)num6].m_startNode;
                     ushort endNode = instance.m_segments.m_buffer[(int)num6].m_endNode;
                     Vector3 position2 = instance.m_nodes.m_buffer[(int)startNode].m_position;
                     Vector3 position3 = instance.m_nodes.m_buffer[(int)endNode].m_position;
                     float num8 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position2.x, bounds.min.z - 64f - position2.z), Mathf.Max(position2.x - bounds.max.x - 64f, position2.z - bounds.max.z - 64f));
                     float num9 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position3.x, bounds.min.z - 64f - position3.z), Mathf.Max(position3.x - bounds.max.x - 64f, position3.z - bounds.max.z - 64f));
                     Vector3 b;
                     int num10;
                     float num11;
                     Vector3 b2;
                     int num12;
                     float num13;
                     if ((num8 < 0f || num9 < 0f) && instance.m_segments.m_buffer[(int)num6].m_bounds.Intersects(bounds) && CustomPathManager.GetClosestLanePosition(instance.m_segments.m_buffer[(int)num6], position, laneType, vehicleTypes, requireConnect, out b, out num10, out num11, out b2, out num12, out num13, vehicleType))
                     {
                         float num14 = Vector3.SqrMagnitude(position - b);
                         if (num14 < num5)
                         {
                             num5 = num14;
                             pathPosA.m_segment = num6;
                             pathPosA.m_lane = (byte)num10;
                             pathPosA.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num11 * 255f), 0, 255);
                             distanceSqrA = num14;
                             num14 = Vector3.SqrMagnitude(position - b2);
                             if (num12 == -1 || num14 >= maxDistance * maxDistance)
                             {
                                 pathPosB.m_segment = 0;
                                 pathPosB.m_lane = 0;
                                 pathPosB.m_offset = 0;
                                 distanceSqrB = 1E+10f;
                             }
                             else
                             {
                                 pathPosB.m_segment = num6;
                                 pathPosB.m_lane = (byte)num12;
                                 pathPosB.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num13 * 255f), 0, 255);
                                 distanceSqrB = num14;
                             }
                         }
                     }
                 }
                 num6 = instance.m_segments.m_buffer[(int)num6].m_nextGridSegment;
                 if (++num7 >= 32768)
                 {
                     CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     return pathPosA.m_segment != 0;
 }
Пример #38
0
 public new bool ParkVehicle(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint nextPath, int nextPositionIndex, out byte segmentOffset)
 {
     return base.ParkVehicle(vehicleID, ref vehicleData, pathPos, nextPath, nextPositionIndex, out segmentOffset);
 }
Пример #39
0
 public static bool UnusedOrEmpty(this PathUnit unit)
 => unit.m_referenceCount == 0 || unit.m_positionCount == 0;
		public void CustomCalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			CalculateSegPos(vehicleID, ref vehicleData, position, laneID, offset, out pos, out dir, out maxSpeed);
		}
        protected void CustomUpdatePathTargetPositions(ushort vehicleID, ref Vehicle vehicleData, Vector3 refPos, ref int targetPosIndex, int maxTargetPosIndex, float minSqrDistanceA, float minSqrDistanceB)
        {
            PathManager pathMan    = Singleton <PathManager> .instance;
            NetManager  netManager = Singleton <NetManager> .instance;

            Vector4 targetPos = vehicleData.m_targetPos0;

            targetPos.w = 1000f;
            float minSqrDistA      = minSqrDistanceA;
            uint  pathId           = vehicleData.m_path;
            byte  finePathPosIndex = vehicleData.m_pathPositionIndex;
            byte  lastPathOffset   = vehicleData.m_lastPathOffset;

            // initial position
            if (finePathPosIndex == 255)
            {
                finePathPosIndex = 0;
                if (targetPosIndex <= 0)
                {
                    vehicleData.m_pathPositionIndex = 0;
                }

                if (!Singleton <PathManager> .instance.m_pathUnits.m_buffer[pathId].CalculatePathPositionOffset(finePathPosIndex >> 1, targetPos, out lastPathOffset))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }
            }

            // get current path position, check for errors
            PathUnit.Position currentPosition;
            if (!pathMan.m_pathUnits.m_buffer[pathId].GetPosition(finePathPosIndex >> 1, out currentPosition))
            {
                this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }

            // get current segment info, check for errors
            NetInfo curSegmentInfo = netManager.m_segments.m_buffer[(int)currentPosition.m_segment].Info;

            if (curSegmentInfo.m_lanes.Length <= (int)currentPosition.m_lane)
            {
                this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                return;
            }

            // main loop
            uint curLaneId = PathManager.GetLaneID(currentPosition);

            NetInfo.Lane laneInfo = curSegmentInfo.m_lanes[(int)currentPosition.m_lane];
            Bezier3      bezier;
            bool         firstIter = true;     // NON-STOCK CODE

            while (true)
            {
                if ((finePathPosIndex & 1) == 0)
                {
                    // vehicle is not in transition
                    if (laneInfo.m_laneType != NetInfo.LaneType.CargoVehicle)
                    {
                        bool first = true;
                        while (lastPathOffset != currentPosition.m_offset)
                        {
                            // catch up and update target position until we get to the current segment offset
                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                float distDiff = Mathf.Sqrt(minSqrDistA) - Vector3.Distance(targetPos, refPos);
                                int   pathOffsetDelta;
                                if (distDiff < 0f)
                                {
                                    pathOffsetDelta = 4;
                                }
                                else
                                {
                                    pathOffsetDelta = 4 + Mathf.Max(0, Mathf.CeilToInt(distDiff * 256f / (netManager.m_lanes.m_buffer[curLaneId].m_length + 1f)));
                                }
                                if (lastPathOffset > currentPosition.m_offset)
                                {
                                    lastPathOffset = (byte)Mathf.Max((int)lastPathOffset - pathOffsetDelta, (int)currentPosition.m_offset);
                                }
                                else if (lastPathOffset < currentPosition.m_offset)
                                {
                                    lastPathOffset = (byte)Mathf.Min((int)lastPathOffset + pathOffsetDelta, (int)currentPosition.m_offset);
                                }
                            }

                            Vector3 curSegPos;
                            Vector3 curSegDir;
                            float   curSegOffset;
                            this.CalculateSegmentPosition(vehicleID, ref vehicleData, currentPosition, curLaneId, lastPathOffset, out curSegPos, out curSegDir, out curSegOffset);
                            targetPos.Set(curSegPos.x, curSegPos.y, curSegPos.z, Mathf.Min(targetPos.w, curSegOffset));
                            float refPosSqrDist = (curSegPos - refPos).sqrMagnitude;
                            if (refPosSqrDist >= minSqrDistA)
                            {
                                if (targetPosIndex <= 0)
                                {
                                    vehicleData.m_lastPathOffset = lastPathOffset;
                                }
                                vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                                minSqrDistA = minSqrDistanceB;
                                refPos      = targetPos;
                                targetPos.w = 1000f;
                                if (targetPosIndex == maxTargetPosIndex)
                                {
                                    // maximum target position index reached
                                    return;
                                }
                            }
                        }
                    }

                    // set vehicle in transition
                    finePathPosIndex += 1;
                    lastPathOffset    = 0;
                    if (targetPosIndex <= 0)
                    {
                        vehicleData.m_pathPositionIndex = finePathPosIndex;
                        vehicleData.m_lastPathOffset    = lastPathOffset;
                    }
                }

                if ((vehicleData.m_flags2 & Vehicle.Flags2.EndStop) != 0)
                {
                    if (targetPosIndex <= 0)
                    {
                        targetPos.w = 0f;
                        if (VectorUtils.LengthSqrXZ(vehicleData.GetLastFrameVelocity()) < 0.01f)
                        {
                            vehicleData.m_flags2 &= ~Vehicle.Flags2.EndStop;
                        }
                    }
                    else
                    {
                        targetPos.w = 1f;
                    }
                    while (targetPosIndex < maxTargetPosIndex)
                    {
                        vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                    }
                    return;
                }

                // vehicle is in transition now

                /*
                 * coarse path position format: 0..11 (always equals 'fine path position' / 2 == 'fine path position' >> 1)
                 * fine path position format: 0..23
                 */

                // find next path unit (or abort if at path end)
                int  nextCoarsePathPosIndex = (finePathPosIndex >> 1) + 1;
                uint nextPathId             = pathId;
                if (nextCoarsePathPosIndex >= (int)pathMan.m_pathUnits.m_buffer[pathId].m_positionCount)
                {
                    nextCoarsePathPosIndex = 0;
                    nextPathId             = pathMan.m_pathUnits.m_buffer[pathId].m_nextPathUnit;
                    if (nextPathId == 0u)
                    {
                        if (targetPosIndex <= 0)
                        {
                            Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);

                            vehicleData.m_path = 0u;
                        }
                        targetPos.w = 1f;
                        vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                        return;
                    }
                }

                // check for errors
                PathUnit.Position nextPathPos;
                if (!pathMan.m_pathUnits.m_buffer[nextPathId].GetPosition(nextCoarsePathPosIndex, out nextPathPos))
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                // check for errors
                NetInfo nextSegmentInfo = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].Info;
                if (nextSegmentInfo.m_lanes.Length <= (int)nextPathPos.m_lane)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                // find next lane (emergency vehicles / dynamic lane selection)
                int bestLaneIndex = nextPathPos.m_lane;
                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) != (Vehicle.Flags) 0)
                {
#if ROUTING
                    bestLaneIndex = VehicleBehaviorManager.Instance.FindBestEmergencyLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID], curLaneId, currentPosition, curSegmentInfo, nextPathPos, nextSegmentInfo);
#else
                    // stock procedure for emergency vehicles on duty
                    bestLaneIndex = FindBestLane(vehicleID, ref vehicleData, nextPathPos);
#endif
                }
                else if (VehicleBehaviorManager.Instance.MayFindBestLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID]))
                {
                    // NON-STOCK CODE START
                    if (firstIter &&
                        this.m_info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                        !this.m_info.m_isLargeVehicle
                        )
                    {
                        uint next2PathId       = nextPathId;
                        int  next2PathPosIndex = nextCoarsePathPosIndex;
                        bool next2Invalid;
                        PathUnit.Position next2PathPos;
                        NetInfo           next2SegmentInfo = null;
                        PathUnit.Position next3PathPos;
                        NetInfo           next3SegmentInfo = null;
                        PathUnit.Position next4PathPos;
                        if (PathUnit.GetNextPosition(ref next2PathId, ref next2PathPosIndex, out next2PathPos, out next2Invalid))
                        {
                            next2SegmentInfo = netManager.m_segments.m_buffer[(int)next2PathPos.m_segment].Info;

                            uint next3PathId       = next2PathId;
                            int  next3PathPosIndex = next2PathPosIndex;
                            bool next3Invalid;
                            if (PathUnit.GetNextPosition(ref next3PathId, ref next3PathPosIndex, out next3PathPos, out next3Invalid))
                            {
                                next3SegmentInfo = netManager.m_segments.m_buffer[(int)next3PathPos.m_segment].Info;

                                uint next4PathId       = next3PathId;
                                int  next4PathPosIndex = next3PathPosIndex;
                                bool next4Invalid;
                                if (!PathUnit.GetNextPosition(ref next4PathId, ref next4PathPosIndex, out next4PathPos, out next4Invalid))
                                {
                                    next4PathPos = default(PathUnit.Position);
                                }
                            }
                            else
                            {
                                next3PathPos = default(PathUnit.Position);
                                next4PathPos = default(PathUnit.Position);
                            }
                        }
                        else
                        {
                            next2PathPos = default(PathUnit.Position);
                            next3PathPos = default(PathUnit.Position);
                            next4PathPos = default(PathUnit.Position);
                        }

                        bestLaneIndex = VehicleBehaviorManager.Instance.FindBestLane(vehicleID, ref vehicleData, ref VehicleStateManager.Instance.VehicleStates[vehicleID], curLaneId, currentPosition, curSegmentInfo, nextPathPos, nextSegmentInfo, next2PathPos, next2SegmentInfo, next3PathPos, next3SegmentInfo, next4PathPos);
                    }
                    // NON-STOCK CODE END
                }

                // update lane index
                if (bestLaneIndex != (int)nextPathPos.m_lane)
                {
                    nextPathPos.m_lane = (byte)bestLaneIndex;
                    pathMan.m_pathUnits.m_buffer[nextPathId].SetPosition(nextCoarsePathPosIndex, nextPathPos);
#if BENCHMARK
                    using (var bm = new Benchmark(null, "AddTraffic")) {
#endif
                    // prevent multiple lane changes to the same lane from happening at the same time
                    TrafficMeasurementManager.Instance.AddTraffic(nextPathPos.m_segment, nextPathPos.m_lane
#if MEASUREDENSITY
                                                                  , VehicleStateManager.Instance.VehicleStates[vehicleID].totalLength
#endif
                                                                  , 0); // NON-STOCK CODE
#if BENCHMARK
                }
#endif
                }

                // check for errors
                uint nextLaneId           = PathManager.GetLaneID(nextPathPos);
                NetInfo.Lane nextLaneInfo = nextSegmentInfo.m_lanes[(int)nextPathPos.m_lane];
                ushort curSegStartNodeId  = netManager.m_segments.m_buffer[(int)currentPosition.m_segment].m_startNode;
                ushort curSegEndNodeId    = netManager.m_segments.m_buffer[(int)currentPosition.m_segment].m_endNode;
                ushort nextSegStartNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_startNode;
                ushort nextSegEndNodeId   = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_endNode;
                if (nextSegStartNodeId != curSegStartNodeId &&
                    nextSegStartNodeId != curSegEndNodeId &&
                    nextSegEndNodeId != curSegStartNodeId &&
                    nextSegEndNodeId != curSegEndNodeId &&
                    ((netManager.m_nodes.m_buffer[(int)curSegStartNodeId].m_flags | netManager.m_nodes.m_buffer[(int)curSegEndNodeId].m_flags) & NetNode.Flags.Disabled) == NetNode.Flags.None &&
                    ((netManager.m_nodes.m_buffer[(int)nextSegStartNodeId].m_flags | netManager.m_nodes.m_buffer[(int)nextSegEndNodeId].m_flags) & NetNode.Flags.Disabled) != NetNode.Flags.None)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                // park vehicle
                if (nextLaneInfo.m_laneType == NetInfo.LaneType.Pedestrian)
                {
                    if (vehicleID != 0 && (vehicleData.m_flags & Vehicle.Flags.Parking) == (Vehicle.Flags) 0)
                    {
                        byte inOffset  = currentPosition.m_offset;
                        byte outOffset = currentPosition.m_offset;
                        if (this.ParkVehicle(vehicleID, ref vehicleData, currentPosition, nextPathId, nextCoarsePathPosIndex << 1, out outOffset))
                        {
                            if (outOffset != inOffset)
                            {
                                if (targetPosIndex <= 0)
                                {
                                    vehicleData.m_pathPositionIndex = (byte)((int)vehicleData.m_pathPositionIndex & -2);
                                    vehicleData.m_lastPathOffset    = inOffset;
                                }
                                currentPosition.m_offset = outOffset;
                                pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)pathId)].SetPosition(finePathPosIndex >> 1, currentPosition);
                            }
                            vehicleData.m_flags |= Vehicle.Flags.Parking;
                        }
                        else
                        {
                            this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    return;
                }

                // check for errors
                if ((byte)(nextLaneInfo.m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.CargoVehicle | NetInfo.LaneType.TransportVehicle)) == 0)
                {
                    this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                    return;
                }

                // change vehicle
                if (nextLaneInfo.m_vehicleType != this.m_info.m_vehicleType &&
                    this.NeedChangeVehicleType(vehicleID, ref vehicleData, nextPathPos, nextLaneId, nextLaneInfo.m_vehicleType, ref targetPos)
                    )
                {
                    float targetPos0ToRefPosSqrDist = ((Vector3)targetPos - refPos).sqrMagnitude;
                    if (targetPos0ToRefPosSqrDist >= minSqrDistA)
                    {
                        vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                    }
                    if (targetPosIndex <= 0)
                    {
                        while (targetPosIndex < maxTargetPosIndex)
                        {
                            vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                        }
                        if (nextPathId != vehicleData.m_path)
                        {
                            Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                        }
                        vehicleData.m_pathPositionIndex = (byte)(nextCoarsePathPosIndex << 1);
                        PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos, out vehicleData.m_lastPathOffset);
                        if (vehicleID != 0 && !this.ChangeVehicleType(vehicleID, ref vehicleData, nextPathPos, nextLaneId))
                        {
                            this.InvalidPath(vehicleID, ref vehicleData, vehicleID, ref vehicleData);
                        }
                    }
                    else
                    {
                        while (targetPosIndex < maxTargetPosIndex)
                        {
                            vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                        }
                    }
                    return;
                }

                // unset leaving flag
                if (nextPathPos.m_segment != currentPosition.m_segment && vehicleID != 0)
                {
                    vehicleData.m_flags &= ~Vehicle.Flags.Leaving;
                }

                // calculate next segment offset
                byte nextSegOffset = 0;
                if ((vehicleData.m_flags & Vehicle.Flags.Flying) != (Vehicle.Flags) 0)
                {
                    nextSegOffset = (byte)((nextPathPos.m_offset < 128) ? 255 : 0);
                }
                else if (curLaneId != nextLaneId && laneInfo.m_laneType != NetInfo.LaneType.CargoVehicle)
                {
                    PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos, out nextSegOffset);
                    bezier = default(Bezier3);
                    Vector3 curSegDir;
                    float   maxSpeed;
                    this.CalculateSegmentPosition(vehicleID, ref vehicleData, currentPosition, curLaneId, currentPosition.m_offset, out bezier.a, out curSegDir, out maxSpeed);
                    bool calculateNextNextPos = lastPathOffset == 0;
                    if (calculateNextNextPos)
                    {
                        if ((vehicleData.m_flags & Vehicle.Flags.Reversed) != (Vehicle.Flags) 0)
                        {
                            calculateNextNextPos = (vehicleData.m_trailingVehicle == 0);
                        }
                        else
                        {
                            calculateNextNextPos = (vehicleData.m_leadingVehicle == 0);
                        }
                    }
                    Vector3 nextSegDir;
                    float   nextMaxSpeed;
                    if (calculateNextNextPos)
                    {
                        PathUnit.Position nextNextPathPos;
                        if (!pathMan.m_pathUnits.m_buffer[nextPathId].GetNextPosition(nextCoarsePathPosIndex, out nextNextPathPos))
                        {
                            nextNextPathPos = default(PathUnit.Position);
                        }
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, nextNextPathPos, nextPathPos, nextLaneId, nextSegOffset, currentPosition, curLaneId, currentPosition.m_offset, targetPosIndex, out bezier.d, out nextSegDir, out nextMaxSpeed);
                    }
                    else
                    {
                        this.CalculateSegmentPosition(vehicleID, ref vehicleData, nextPathPos, nextLaneId, nextSegOffset, out bezier.d, out nextSegDir, out nextMaxSpeed);
                    }
                    if (nextMaxSpeed < 0.01f || (netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_flags & (NetSegment.Flags.Collapsed | NetSegment.Flags.Flooded)) != NetSegment.Flags.None)
                    {
                        if (targetPosIndex <= 0)
                        {
                            vehicleData.m_lastPathOffset = lastPathOffset;
                        }
                        targetPos   = bezier.a;
                        targetPos.w = 0f;
                        while (targetPosIndex < maxTargetPosIndex)
                        {
                            vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                        }
                        return;
                    }
                    if (currentPosition.m_offset == 0)
                    {
                        curSegDir = -curSegDir;
                    }
                    if (nextSegOffset < nextPathPos.m_offset)
                    {
                        nextSegDir = -nextSegDir;
                    }
                    curSegDir.Normalize();
                    nextSegDir.Normalize();
                    float dist;
                    NetSegment.CalculateMiddlePoints(bezier.a, curSegDir, bezier.d, nextSegDir, true, true, out bezier.b, out bezier.c, out dist);
                    if (dist > 1f)
                    {
                        ushort nextNodeId;
                        if (nextSegOffset == 0)
                        {
                            nextNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_startNode;
                        }
                        else if (nextSegOffset == 255)
                        {
                            nextNodeId = netManager.m_segments.m_buffer[(int)nextPathPos.m_segment].m_endNode;
                        }
                        else
                        {
                            nextNodeId = 0;
                        }
                        float curve = 1.57079637f * (1f + Vector3.Dot(curSegDir, nextSegDir));
                        if (dist > 1f)
                        {
                            curve /= dist;
                        }
                        nextMaxSpeed = Mathf.Min(nextMaxSpeed, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve));
                        while (lastPathOffset < 255)
                        {
                            float distDiff = Mathf.Sqrt(minSqrDistA) - Vector3.Distance(targetPos, refPos);
                            int   pathOffsetDelta;
                            if (distDiff < 0f)
                            {
                                pathOffsetDelta = 8;
                            }
                            else
                            {
                                pathOffsetDelta = 8 + Mathf.Max(0, Mathf.CeilToInt(distDiff * 256f / (dist + 1f)));
                            }
                            lastPathOffset = (byte)Mathf.Min((int)lastPathOffset + pathOffsetDelta, 255);
                            Vector3 bezierPos = bezier.Position((float)lastPathOffset * 0.003921569f);
                            targetPos.Set(bezierPos.x, bezierPos.y, bezierPos.z, Mathf.Min(targetPos.w, nextMaxSpeed));
                            float sqrMagnitude2 = (bezierPos - refPos).sqrMagnitude;
                            if (sqrMagnitude2 >= minSqrDistA)
                            {
                                if (targetPosIndex <= 0)
                                {
                                    vehicleData.m_lastPathOffset = lastPathOffset;
                                }
                                if (nextNodeId != 0)
                                {
                                    this.UpdateNodeTargetPos(vehicleID, ref vehicleData, nextNodeId, ref netManager.m_nodes.m_buffer[(int)nextNodeId], ref targetPos, targetPosIndex);
                                }
                                vehicleData.SetTargetPos(targetPosIndex++, targetPos);
                                minSqrDistA = minSqrDistanceB;
                                refPos      = targetPos;
                                targetPos.w = 1000f;
                                if (targetPosIndex == maxTargetPosIndex)
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
                else
                {
                    PathUnit.CalculatePathPositionOffset(nextLaneId, targetPos, out nextSegOffset);
                }

                // check for arrival
                if (targetPosIndex <= 0)
                {
                    if ((netManager.m_segments.m_buffer[nextPathPos.m_segment].m_flags & NetSegment.Flags.Untouchable) != 0 && (netManager.m_segments.m_buffer[currentPosition.m_segment].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None)
                    {
                        ushort ownerBuildingId = NetSegment.FindOwnerBuilding(nextPathPos.m_segment, 363f);
                        if (ownerBuildingId != 0)
                        {
                            BuildingManager buildingMan       = Singleton <BuildingManager> .instance;
                            BuildingInfo    ownerBuildingInfo = buildingMan.m_buildings.m_buffer[ownerBuildingId].Info;
                            InstanceID      itemID            = default(InstanceID);
                            itemID.Vehicle = vehicleID;
                            ownerBuildingInfo.m_buildingAI.EnterBuildingSegment(ownerBuildingId, ref buildingMan.m_buildings.m_buffer[ownerBuildingId], nextPathPos.m_segment, nextPathPos.m_offset, itemID);
                        }
                    }

                    if (nextCoarsePathPosIndex == 0)
                    {
                        Singleton <PathManager> .instance.ReleaseFirstUnit(ref vehicleData.m_path);
                    }
                    if (nextCoarsePathPosIndex >= (int)(pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)nextPathId)].m_positionCount - 1) && pathMan.m_pathUnits.m_buffer[(int)((UIntPtr)nextPathId)].m_nextPathUnit == 0u && vehicleID != 0)
                    {
                        this.ArrivingToDestination(vehicleID, ref vehicleData);
                    }
                }

                // prepare next loop iteration: go to next path position
                pathId           = nextPathId;
                finePathPosIndex = (byte)(nextCoarsePathPosIndex << 1);
                lastPathOffset   = nextSegOffset;
                if (targetPosIndex <= 0)
                {
                    vehicleData.m_pathPositionIndex = finePathPosIndex;
                    vehicleData.m_lastPathOffset    = lastPathOffset;
                    vehicleData.m_flags             = ((vehicleData.m_flags & ~(Vehicle.Flags.OnGravel | Vehicle.Flags.Underground | Vehicle.Flags.Transition)) | nextSegmentInfo.m_setVehicleFlags);
                    if (this.LeftHandDrive(nextLaneInfo))
                    {
                        vehicleData.m_flags |= Vehicle.Flags.LeftHandDrive;
                    }
                    else
                    {
                        vehicleData.m_flags &= (Vehicle.Flags.Created | Vehicle.Flags.Deleted | Vehicle.Flags.Spawned | Vehicle.Flags.Inverted | Vehicle.Flags.TransferToTarget | Vehicle.Flags.TransferToSource | Vehicle.Flags.Emergency1 | Vehicle.Flags.Emergency2 | Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped | Vehicle.Flags.Leaving | Vehicle.Flags.Arriving | Vehicle.Flags.Reversed | Vehicle.Flags.TakingOff | Vehicle.Flags.Flying | Vehicle.Flags.Landing | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo | Vehicle.Flags.GoingBack | Vehicle.Flags.WaitingTarget | Vehicle.Flags.Importing | Vehicle.Flags.Exporting | Vehicle.Flags.Parking | Vehicle.Flags.CustomName | Vehicle.Flags.OnGravel | Vehicle.Flags.WaitingLoading | Vehicle.Flags.Congestion | Vehicle.Flags.DummyTraffic | Vehicle.Flags.Underground | Vehicle.Flags.Transition | Vehicle.Flags.InsideBuilding);
                    }
                }
                currentPosition = nextPathPos;
                curLaneId       = nextLaneId;
                laneInfo        = nextLaneInfo;
                firstIter       = false;           // NON-STOCK CODE
            }
        }
		protected virtual void CalculateSegPos(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			NetManager instance = Singleton<NetManager>.instance;
			instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir);
			NetInfo info = instance.m_segments.m_buffer[(int)position.m_segment].Info;
			if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane) {
				var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]);
				maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
			} else {
				maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f);
			}
		}
Пример #43
0
		public void CustomCalculateSegmentPositionPathFinder(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, uint laneId, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			var netManager = Singleton<NetManager>.instance;
			netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f,
				out pos, out dir);
			var info = netManager.m_segments.m_buffer[position.m_segment].Info;
			if (info.m_lanes != null && info.m_lanes.Length > position.m_lane) {
				var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneId, info.m_lanes[position.m_lane]); //info.m_lanes[position.m_lane].m_speedLimit;
				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit,	netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].m_curve);
			} else {
				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
			}

			maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, IsRecklessDriver(vehicleId, ref vehicleData));
		}
Пример #44
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, RoadManager.VehicleType vehicleType)
 {
     return this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, isHeavyVehicle, ignoreBlocked, stablePath, skipQueue, vehicleType);
 }
        private void assignPathProperties(uint unit, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, byte simulationFlags)
        {
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = simulationFlags;

            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20;
            this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1;
        }
 protected override bool SpawnVehicle(ushort instanceID, ref CitizenInstance citizenData, PathUnit.Position pathPos)
 {
     VehicleManager instance = Singleton<VehicleManager>.instance;
     float num = 20f;
     int num2 = Mathf.Max ((int)((citizenData.m_targetPos.x - num) / 32f + 270f), 0);
     int num3 = Mathf.Max ((int)((citizenData.m_targetPos.z - num) / 32f + 270f), 0);
     int num4 = Mathf.Min ((int)((citizenData.m_targetPos.x + num) / 32f + 270f), 539);
     int num5 = Mathf.Min ((int)((citizenData.m_targetPos.z + num) / 32f + 270f), 539);
     for (int i = num3; i <= num5; i++)
     {
         for (int j = num2; j <= num4; j++)
         {
             ushort num6 = instance.m_vehicleGrid [i * 540 + j];
             int num7 = 0;
             while (num6 != 0)
             {
                 if (this.TryJoinVehicle (instanceID, ref citizenData, num6, ref instance.m_vehicles.m_buffer [(int)num6]))
                 {
                     citizenData.m_flags |= CitizenInstance.Flags.EnteringVehicle;
                     citizenData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle;
                     citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
                     citizenData.m_waitCounter = 0;
                     return true;
                 }
                 num6 = instance.m_vehicles.m_buffer [(int)num6].m_nextGridVehicle;
                 if (++num7 > 65536)
                 {
                     CODebugBase<LogChannel>.Error (LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                     break;
                 }
             }
         }
     }
     NetManager instance2 = Singleton<NetManager>.instance;
     CitizenManager instance3 = Singleton<CitizenManager>.instance;
     Vector3 vector = Vector3.zero;
     Quaternion rotation = Quaternion.identity;
     ushort num8 = instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle;
     if (num8 != 0)
     {
         vector = instance.m_parkedVehicles.m_buffer [(int)num8].m_position;
         rotation = instance.m_parkedVehicles.m_buffer [(int)num8].m_rotation;
     }
     VehicleInfo vehicleInfo = this.GetVehicleInfo (instanceID, ref citizenData, false);
     if (vehicleInfo == null || vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
     {
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
         if ((citizenData.m_flags & CitizenInstance.Flags.TryingSpawnVehicle) == CitizenInstance.Flags.None)
         {
             citizenData.m_flags |= CitizenInstance.Flags.TryingSpawnVehicle;
             citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
             citizenData.m_waitCounter = 0;
         }
         return true;
     }
     if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
     {
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
         if ((citizenData.m_flags & CitizenInstance.Flags.WaitingTaxi) == CitizenInstance.Flags.None)
         {
             citizenData.m_flags |= CitizenInstance.Flags.WaitingTaxi;
             citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
             citizenData.m_waitCounter = 0;
         }
         return true;
     }
     uint laneID = PathManager.GetLaneID (pathPos);
     Vector3 vector2 = citizenData.m_targetPos;
     if (num8 != 0 && Vector3.SqrMagnitude (vector - vector2) < 1024f)
     {
         vector2 = vector;
     }
     else
     {
         num8 = 0;
     }
     Vector3 a;
     float num9;
     instance2.m_lanes.m_buffer [(int)((UIntPtr)laneID)].GetClosestPosition (vector2, out a, out num9);
     byte lastPathOffset = (byte)Mathf.Clamp (Mathf.RoundToInt (num9 * 255f), 0, 255);
     a = vector2 + Vector3.ClampMagnitude (a - vector2, 5f);
     ushort num10;
     if (instance.CreateVehicle (out num10, ref Singleton<SimulationManager>.instance.m_randomizer, vehicleInfo, vector2, TransferManager.TransferReason.None, false, false))
     {
         Vehicle.Frame frame = instance.m_vehicles.m_buffer [(int)num10].m_frame0;
         if (num8 != 0)
         {
             frame.m_rotation = rotation;
         }
         else
         {
             Vector3 forward = a - citizenData.GetLastFrameData ().m_position;
             if (forward.sqrMagnitude > 0.01f)
             {
                 frame.m_rotation = Quaternion.LookRotation (forward);
             }
         }
         instance.m_vehicles.m_buffer [(int)num10].m_frame0 = frame;
         instance.m_vehicles.m_buffer [(int)num10].m_frame1 = frame;
         instance.m_vehicles.m_buffer [(int)num10].m_frame2 = frame;
         instance.m_vehicles.m_buffer [(int)num10].m_frame3 = frame;
         vehicleInfo.m_vehicleAI.FrameDataUpdated (num10, ref instance.m_vehicles.m_buffer [(int)num10], ref frame);
         instance.m_vehicles.m_buffer [(int)num10].m_targetPos0 = new Vector4 (a.x, a.y, a.z, 2f);
         Vehicle[] expr_4E5_cp_0 = instance.m_vehicles.m_buffer;
         ushort expr_4E5_cp_1 = num10;
         expr_4E5_cp_0 [(int)expr_4E5_cp_1].m_flags = (expr_4E5_cp_0 [(int)expr_4E5_cp_1].m_flags | Vehicle.Flags.Stopped);
         instance.m_vehicles.m_buffer [(int)num10].m_path = citizenData.m_path;
         instance.m_vehicles.m_buffer [(int)num10].m_pathPositionIndex = citizenData.m_pathPositionIndex;
         instance.m_vehicles.m_buffer [(int)num10].m_lastPathOffset = lastPathOffset;
         instance.m_vehicles.m_buffer [(int)num10].m_transferSize = (ushort)(citizenData.m_citizen & 65535u);
         vehicleInfo.m_vehicleAI.TrySpawn (num10, ref instance.m_vehicles.m_buffer [(int)num10]);
         if (num8 != 0)
         {
             InstanceID empty = InstanceID.Empty;
             empty.ParkedVehicle = num8;
             InstanceID empty2 = InstanceID.Empty;
             empty2.Vehicle = num10;
             Singleton<InstanceManager>.instance.ChangeInstance (empty, empty2);
         }
         citizenData.m_path = 0u;
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
         instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetVehicle (citizenData.m_citizen, num10, 0u);
         citizenData.m_flags |= CitizenInstance.Flags.EnteringVehicle;
         citizenData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle;
         citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
         citizenData.m_waitCounter = 0;
         return true;
     }
     instance3.m_citizens.m_buffer [(int)((UIntPtr)citizenData.m_citizen)].SetParkedVehicle (citizenData.m_citizen, 0);
     if ((citizenData.m_flags & CitizenInstance.Flags.TryingSpawnVehicle) == CitizenInstance.Flags.None)
     {
         citizenData.m_flags |= CitizenInstance.Flags.TryingSpawnVehicle;
         citizenData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting;
         citizenData.m_waitCounter = 0;
     }
     return true;
 }
Пример #47
0
    public override void SimulationStep(ushort vehicleID, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ushort leaderID, ref Vehicle leaderData, int lodPhysics)
    {
        if ((leaderData.m_flags2 & Vehicle.Flags2.Blown) != (Vehicle.Flags2) 0)
        {
            this.SimulationStepBlown(vehicleID, ref vehicleData, ref frameData, leaderID, ref leaderData, lodPhysics);
            return;
        }
        if ((leaderData.m_flags2 & Vehicle.Flags2.Floating) != (Vehicle.Flags2) 0)
        {
            this.SimulationStepFloating(vehicleID, ref vehicleData, ref frameData, leaderID, ref leaderData, lodPhysics);
            return;
        }
        uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

        frameData.m_position     += frameData.m_velocity * 0.5f;
        frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f;
        float accelerationAbility = this.m_info.m_acceleration;
        float brakingAbility      = this.m_info.m_braking;

        if (vehicleData.m_flags.IsFlagSet(Vehicle.Flags.Emergency2))
        {
            accelerationAbility *= 2f;
            brakingAbility      *= 2f;
        }
        float   velocity           = frameData.m_velocity.magnitude;
        Vector3 posdiff0           = (Vector3)vehicleData.m_targetPos0 - frameData.m_position;
        float   postdiff0_len_pow2 = posdiff0.sqrMagnitude;
        float   carLength          = this.m_info.m_generatedInfo.m_size.z;

        float velocity_max_new2 = Mathf.Max(velocity + accelerationAbility, 5f); // maximum new velocity the car is capble of.

        if (lodPhysics >= 2 && (ulong)(currentFrameIndex >> 4 & 3u) == (ulong)(vehicleID & 3))
        {
            velocity_max_new2 *= 2f;
        }

        float num3 = (velocity + accelerationAbility) * (0.5f + 0.5f * (velocity + accelerationAbility) / brakingAbility) + carLength * 0.5f;
        float num5 = Mathf.Max((num3 - velocity_max_new2) / 3f, 1f);
        float velocity_max_new2_pow2 = velocity_max_new2 * velocity_max_new2;
        float num7 = num5 * num5;
        int   i    = 0;
        bool  shortTravelDistanceButStillMoving = false;

        if ((postdiff0_len_pow2 < velocity_max_new2_pow2 || vehicleData.m_targetPos3.w < 0.01f) && !leaderData.m_flags.IsFlagSet(Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped))
        {
            if (leaderData.m_path != 0u)
            {
                base.UpdatePathTargetPositions(vehicleID, ref vehicleData, frameData.m_position, ref i, 4, velocity_max_new2_pow2, num7);
                if (!leaderData.m_flags.IsFlagSet(Vehicle.Flags.Spawned))
                {
                    frameData = vehicleData.m_frame0;
                    return;
                }
            }
            if (!leaderData.m_flags.IsFlagSet(Vehicle.Flags.WaitingPath))
            {
                while (i < 4)
                {
                    float   minSqrDistance;
                    Vector3 refPos;
                    if (i == 0)
                    {
                        minSqrDistance = velocity_max_new2_pow2;
                        refPos         = frameData.m_position;
                        shortTravelDistanceButStillMoving = true;
                    }
                    else
                    {
                        minSqrDistance = num7;
                        refPos         = vehicleData.GetTargetPos(i - 1);
                    }
                    int i0 = i;
                    this.UpdateBuildingTargetPositions(vehicleID, ref vehicleData, refPos, leaderID, ref leaderData, ref i, minSqrDistance);
                    if (i == i0)
                    {
                        break;
                    }
                }
                if (i != 0)
                {
                    Vector4 targetPos = vehicleData.GetTargetPos(i - 1);
                    while (i < 4)
                    {
                        vehicleData.SetTargetPos(i++, targetPos);
                    }
                }
            }
            posdiff0           = (Vector3)vehicleData.m_targetPos0 - frameData.m_position;
            postdiff0_len_pow2 = posdiff0.sqrMagnitude;
        }
        if (leaderData.m_path != 0u && !leaderData.m_flags.IsFlagSet(Vehicle.Flags.WaitingPath))
        {
            byte b = leaderData.m_pathPositionIndex;
            byte lastPathOffset = leaderData.m_lastPathOffset;
            if (b == 255)
            {
                b = 0;
            }
            int               noise;
            float             num9      = 1f + leaderData.CalculateTotalLength(leaderID, out noise);
            PathManager       instance2 = Singleton <PathManager> .instance;
            PathUnit.Position pathPos;
            if (instance2.m_pathUnits.m_buffer[leaderData.m_path].GetPosition(b >> 1, out pathPos))
            {
                if (SegmentBuffer[pathPos.m_segment].m_flags.IsFlagSet(NetSegment.Flags.Flooded) &&
                    Singleton <TerrainManager> .instance.HasWater(VectorUtils.XZ(frameData.m_position)))
                {
                    leaderData.m_flags2 |= Vehicle.Flags2.Floating;
                }
                SegmentBuffer[pathPos.m_segment].AddTraffic(Mathf.RoundToInt(num9 * 2.5f), noise);
                bool flag2 = false;
                if ((b & 1) == 0 || lastPathOffset == 0)
                {
                    uint laneID = PathManager.GetLaneID(pathPos);
                    if (laneID != 0u)
                    {
                        Vector3 b2    = LaneBuffer[laneID].CalculatePosition(pathPos.m_offset * (1f / 255));
                        float   num10 = 0.5f * velocity * velocity / brakingAbility + carLength * 0.5f;
                        if (Vector3.Distance(frameData.m_position, b2) >= num10 - 1f)
                        {
                            LaneBuffer[laneID].ReserveSpace(num9);
                            flag2 = true;
                        }
                    }
                }
                if (!flag2 && instance2.m_pathUnits.m_buffer[leaderData.m_path].GetNextPosition(b >> 1, out pathPos))
                {
                    uint laneID2 = PathManager.GetLaneID(pathPos);
                    if (laneID2 != 0u)
                    {
                        LaneBuffer[laneID2].ReserveSpace(num9);
                    }
                }
            }
            if ((ulong)(currentFrameIndex >> 4 & 15u) == (ulong)((long)(leaderID & 15)))
            {
                bool flag3 = false;
                uint path  = leaderData.m_path;
                int  num11 = b >> 1;
                int  j     = 0;
                while (j < 5)
                {
                    bool flag4;
                    if (PathUnit.GetNextPosition(ref path, ref num11, out pathPos, out flag4))
                    {
                        uint laneID3 = PathManager.GetLaneID(pathPos);
                        if (laneID3 != 0u && !LaneBuffer[laneID3].CheckSpace(num9))
                        {
                            j++;
                            continue;
                        }
                    }
                    if (flag4)
                    {
                        this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData);
                    }
                    flag3 = true;
                    break;
                }
                if (!flag3)
                {
                    leaderData.m_flags |= Vehicle.Flags.Congestion;
                }
            }
        }
        float num12;

        if (leaderData.m_flags.IsFlagSet(Vehicle.Flags.Stopped))
        {
            num12 = 0f;
        }
        else
        {
            num12 = vehicleData.m_targetPos0.w;
            if (!leaderData.m_flags.IsFlagSet(Vehicle.Flags.DummyTraffic))
            {
                VehicleManager instance3 = Singleton <VehicleManager> .instance;
                float          f         = velocity * 100f / Mathf.Max(1f, vehicleData.m_targetPos0.w);
                instance3.m_totalTrafficFlow += (uint)Mathf.RoundToInt(f);
                instance3.m_maxTrafficFlow   += 100u;
            }
        }
        Quaternion rotation = Quaternion.Inverse(frameData.m_rotation);

        posdiff0 = rotation * posdiff0;
        Vector3 vector2     = rotation * frameData.m_velocity;
        Vector3 forwardDir0 = Vector3.forward;
        Vector3 vector3;
        Vector3 zero           = Vector3.zero;
        float   num13          = 0f;
        float   num14          = 0f;
        bool    flag5          = false;
        float   posdiff0_lenxz = 0f;

        if (postdiff0_len_pow2 > 1f)
        {
            forwardDir0 = VectorUtils.NormalizeXZ(posdiff0, out posdiff0_lenxz);
            if (posdiff0_lenxz > 1f)
            {
                Vector3 vector4 = posdiff0;
                velocity_max_new2      = Mathf.Max(velocity, 2f);
                velocity_max_new2_pow2 = velocity_max_new2 * velocity_max_new2;
                if (postdiff0_len_pow2 > velocity_max_new2_pow2)
                {
                    vector4 *= velocity_max_new2 / Mathf.Sqrt(postdiff0_len_pow2);
                }
                bool flag6 = false;
                if (vector4.z < Mathf.Abs(vector4.x))
                {
                    if (vector4.z < 0f)
                    {
                        flag6 = true;
                    }
                    float num16 = Mathf.Abs(vector4.x);
                    if (num16 < 1f)
                    {
                        vector4.x = Mathf.Sign(vector4.x);
                        if (vector4.x == 0f)
                        {
                            vector4.x = 1f;
                        }
                        num16 = 1f;
                    }
                    vector4.z = num16;
                }
                float b3;
                forwardDir0    = VectorUtils.NormalizeXZ(vector4, out b3);
                posdiff0_lenxz = Mathf.Min(posdiff0_lenxz, b3);
                float num17 = 1.57079637f * (1f - forwardDir0.z);
                if (posdiff0_lenxz > 1f)
                {
                    num17 /= posdiff0_lenxz;
                }
                float num18 = posdiff0_lenxz;
                if (vehicleData.m_targetPos0.w < 0.1f)
                {
                    num12 = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num17);
                    num12 = Mathf.Min(num12, CalculateMaxSpeed(num18, Mathf.Min(vehicleData.m_targetPos0.w, vehicleData.m_targetPos1.w), brakingAbility * 0.9f));
                }
                else
                {
                    num12 = Mathf.Min(num12, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, num17));
                    num12 = Mathf.Min(num12, CalculateMaxSpeed(num18, vehicleData.m_targetPos1.w, brakingAbility * 0.9f));
                }
                num18 += VectorUtils.LengthXZ(vehicleData.m_targetPos1 - vehicleData.m_targetPos0);
                num12  = Mathf.Min(num12, CalculateMaxSpeed(num18, vehicleData.m_targetPos2.w, brakingAbility * 0.9f));
                num18 += VectorUtils.LengthXZ(vehicleData.m_targetPos2 - vehicleData.m_targetPos1);
                num12  = Mathf.Min(num12, CalculateMaxSpeed(num18, vehicleData.m_targetPos3.w, brakingAbility * 0.9f));
                num18 += VectorUtils.LengthXZ(vehicleData.m_targetPos3 - vehicleData.m_targetPos2);
                if (vehicleData.m_targetPos3.w < 0.01f)
                {
                    num18 = Mathf.Max(0f, num18 - carLength * 0.5f);
                }
                num12 = Mathf.Min(num12, CalculateMaxSpeed(num18, 0f, brakingAbility * 0.9f));
                if (!DisableCollisionCheck(leaderID, ref leaderData))
                {
                    CarAI.CheckOtherVehicles(vehicleID, ref vehicleData, ref frameData, ref num12, ref flag5, ref zero, num3, brakingAbility * 0.9f, lodPhysics);
                }
                if (flag6)
                {
                    num12 = -num12;
                }
                if (num12 < velocity)
                {
                    float num19 = Mathf.Max(accelerationAbility, Mathf.Min(brakingAbility, velocity));
                    num13 = Mathf.Max(num12, velocity - num19);
                }
                else
                {
                    float num20 = Mathf.Max(accelerationAbility, Mathf.Min(brakingAbility, -velocity));
                    num13 = Mathf.Min(num12, velocity + num20);
                }
            }
        }
        else if (velocity < 0.1f && shortTravelDistanceButStillMoving && this.ArriveAtDestination(leaderID, ref leaderData))
        {
            leaderData.Unspawn(leaderID);
            if (leaderID == vehicleID)
            {
                frameData = leaderData.m_frame0;
            }
            return;
        }
        if (!leaderData.m_flags.IsFlagSet(Vehicle.Flags.Stopped) && num12 < 0.1f)
        {
            flag5 = true;
        }
        if (flag5)
        {
            vehicleData.m_blockCounter = (byte)Mathf.Min((vehicleData.m_blockCounter + 1), 255);
        }
        else
        {
            vehicleData.m_blockCounter = 0;
        }
        if (posdiff0_lenxz > 1f)
        {
            num14   = Mathf.Asin(forwardDir0.x) * Mathf.Sign(num13);
            vector3 = forwardDir0 * num13;
        }
        else
        {
            num13 = 0f;
            Vector3 b4 = Vector3.ClampMagnitude(posdiff0 * 0.5f - vector2, brakingAbility);
            vector3 = vector2 + b4;
        }
        bool    flag7   = (currentFrameIndex + (uint)leaderID & 16u) != 0u;
        Vector3 a2      = vector3 - vector2;
        Vector3 vector5 = frameData.m_rotation * vector3;

        frameData.m_velocity         = vector5 + zero;
        frameData.m_position        += frameData.m_velocity * 0.5f;
        frameData.m_swayVelocity     = frameData.m_swayVelocity * (1f - this.m_info.m_dampers) - a2 * (1f - this.m_info.m_springs) - frameData.m_swayPosition * this.m_info.m_springs;
        frameData.m_swayPosition    += frameData.m_swayVelocity * 0.5f;
        frameData.m_steerAngle       = num14;
        frameData.m_travelDistance  += vector3.z;
        frameData.m_lightIntensity.x = 5f;
        frameData.m_lightIntensity.y = ((a2.z >= -0.1f) ? 0.5f : 5f);
        frameData.m_lightIntensity.z = ((num14 >= -0.1f || !flag7) ? 0f : 5f);
        frameData.m_lightIntensity.w = ((num14 <= 0.1f || !flag7) ? 0f : 5f);
        frameData.m_underground      = (vehicleData.m_flags.IsFlagSet(Vehicle.Flags.Underground));
        frameData.m_transition       = (vehicleData.m_flags.IsFlagSet(Vehicle.Flags.Transition));
        if (vehicleData.m_flags.IsFlagSet(Vehicle.Flags.Parking) && posdiff0_lenxz <= 1f && shortTravelDistanceButStillMoving)
        {
            Vector3 forward = vehicleData.m_targetPos1 - vehicleData.m_targetPos0;
            if (forward.sqrMagnitude > 0.01f)
            {
                frameData.m_rotation = Quaternion.LookRotation(forward);
            }
        }
        else if (num13 > 0.1f)
        {
            if (vector5.sqrMagnitude > 0.01f)
            {
                frameData.m_rotation = Quaternion.LookRotation(vector5);
            }
        }
        else if (num13 < -0.1f && vector5.sqrMagnitude > 0.01f)
        {
            frameData.m_rotation = Quaternion.LookRotation(-vector5);
        }
        base.SimulationStep(vehicleID, ref vehicleData, ref frameData, leaderID, ref leaderData, lodPhysics);
    }
        protected override void CalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition,
            PathUnit.Position position, uint laneId, byte offset, PathUnit.Position prevPos, uint prevLaneId,
            byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            NetManager instance = Singleton<NetManager>.instance;
            instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3 position2 = lastFrameData.m_position;
            Vector3 b = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneId)].CalculatePosition(prevOffset * 0.003921569f);
            float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f;

            if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car)
            {
                if (!TrafficPriority.VehicleList.ContainsKey(vehicleId))
                {
                    TrafficPriority.VehicleList.Add(vehicleId, new PriorityCar());
                }
            }

            if (Vector3.Distance(position2, b) >= num - 1f)
            {
                Segment3 segment;
                segment.a = pos;
                ushort num2;
                ushort num3;
                if (offset < position.m_offset)
                {
                    segment.b = pos + dir.normalized*m_info.m_generatedInfo.m_size.z;
                    num2 = instance.m_segments.m_buffer[position.m_segment].m_startNode;
                    num3 = instance.m_segments.m_buffer[position.m_segment].m_endNode;
                }
                else
                {
                    segment.b = pos - dir.normalized*m_info.m_generatedInfo.m_size.z;
                    num2 = instance.m_segments.m_buffer[position.m_segment].m_endNode;
                    num3 = instance.m_segments.m_buffer[position.m_segment].m_startNode;
                }
                ushort num4;
                if (prevOffset == 0)
                {
                    num4 = instance.m_segments.m_buffer[prevPos.m_segment].m_startNode;
                }
                else
                {
                    num4 = instance.m_segments.m_buffer[prevPos.m_segment].m_endNode;
                }

                if (num2 == num4)
                {
                    uint currentFrameIndex = Singleton<SimulationManager>.instance.m_currentFrameIndex;
                    uint num5 = (uint)((num4 << 8) / 32768);
                    uint num6 = currentFrameIndex - num5 & 255u;

                    NetNode.Flags flags = instance.m_nodes.m_buffer[num2].m_flags;
                    NetLane.Flags flags2 =
                        (NetLane.Flags) instance.m_lanes.m_buffer[(int) ((UIntPtr) prevLaneId)].m_flags;
                    bool flag = (flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
                    bool flag2 = (flags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None;
                    bool flag3 = (flags2 & NetLane.Flags.JoinedJunction) != NetLane.Flags.None;
                    if ((flags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) ==
                        NetNode.Flags.Junction && instance.m_nodes.m_buffer[num2].CountSegments() != 2)
                    {
                        float len = vehicleData.CalculateTotalLength(vehicleId) + 2f;
                        if (!instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId)].CheckSpace(len))
                        {
                            bool flag4 = false;
                            if (nextPosition.m_segment != 0 &&
                                instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId)].m_length < 30f)
                            {
                                NetNode.Flags flags3 = instance.m_nodes.m_buffer[num3].m_flags;
                                if ((flags3 &
                                     (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) !=
                                    NetNode.Flags.Junction || instance.m_nodes.m_buffer[num3].CountSegments() == 2)
                                {
                                    uint laneId2 = PathManager.GetLaneID(nextPosition);
                                    if (laneId2 != 0u)
                                    {
                                        flag4 = instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId2)].CheckSpace(len);
                                    }
                                }
                            }
                            if (!flag4)
                            {
                                maxSpeed = 0f;
                                return;
                            }
                        }
                    }

                    if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                        TrafficPriority.VehicleList.ContainsKey(vehicleId) &&
                        TrafficPriority.IsPrioritySegment(num2, prevPos.m_segment))
                    {
                        uint currentFrameIndex2 = Singleton<SimulationManager>.instance.m_currentFrameIndex;
                        uint frame = currentFrameIndex2 >> 4;

                        var prioritySegment = TrafficPriority.GetPrioritySegment(num2, prevPos.m_segment);
                        if (TrafficPriority.VehicleList[vehicleId].toNode != num2 ||
                            TrafficPriority.VehicleList[vehicleId].fromSegment != prevPos.m_segment)
                        {
                            if (TrafficPriority.VehicleList[vehicleId].toNode != 0 &&
                                TrafficPriority.VehicleList[vehicleId].fromSegment != 0)
                            {
                                var oldNode = TrafficPriority.VehicleList[vehicleId].toNode;
                                var oldSegment = TrafficPriority.VehicleList[vehicleId].fromSegment;

                                if (TrafficPriority.IsPrioritySegment(oldNode, oldSegment))
                                {
                                    var oldPrioritySegment = TrafficPriority.GetPrioritySegment(oldNode, oldSegment);
                                    TrafficPriority.VehicleList[vehicleId].waitTime = 0;
                                    TrafficPriority.VehicleList[vehicleId].stopped = false;
                                    oldPrioritySegment.RemoveCar(vehicleId);
                                }
                            }

                            // prevPos - current segment
                            // position - next segment
                            TrafficPriority.VehicleList[vehicleId].toNode = num2;
                            TrafficPriority.VehicleList[vehicleId].fromSegment = prevPos.m_segment;
                            TrafficPriority.VehicleList[vehicleId].toSegment = position.m_segment;
                            TrafficPriority.VehicleList[vehicleId].toLaneID = PathManager.GetLaneID(position);
                            TrafficPriority.VehicleList[vehicleId].fromLaneID = PathManager.GetLaneID(prevPos);
                            TrafficPriority.VehicleList[vehicleId].fromLaneFlags =
                                instance.m_lanes.m_buffer[PathManager.GetLaneID(prevPos)].m_flags;
                            TrafficPriority.VehicleList[vehicleId].yieldSpeedReduce = Random.Range(13f,
                                18f);

                            prioritySegment.AddCar(vehicleId);
                        }

                        TrafficPriority.VehicleList[vehicleId].lastFrame = frame;
                        TrafficPriority.VehicleList[vehicleId].lastSpeed =
                            vehicleData.GetLastFrameData().m_velocity.sqrMagnitude;
                    }

                    if (flag && (!flag3 || flag2))
                    {
                        var nodeSimulation = CustomRoadAI.GetNodeSimulation(num4);

                        NetInfo info = instance.m_nodes.m_buffer[num2].Info;
                        RoadBaseAI.TrafficLightState vehicleLightState;

                        if (nodeSimulation == null || (nodeSimulation.FlagTimedTrafficLights && !nodeSimulation.TimedTrafficLightsActive))
                        {
                            RoadBaseAI.TrafficLightState pedestrianLightState;
                            bool flag5;
                            bool pedestrians;
                            RoadBaseAI.GetTrafficLightState(num4,
                                ref instance.m_segments.m_buffer[prevPos.m_segment],
                                currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out flag5,
                                out pedestrians);
                            if (!flag5 && num6 >= 196u)
                            {
                                flag5 = true;
                                RoadBaseAI.SetTrafficLightState(num4,
                                    ref instance.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5,
                                    vehicleLightState, pedestrianLightState, flag5, pedestrians);
                            }

                            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None ||
                                info.m_class.m_service != ItemClass.Service.Road)
                            {
                                switch (vehicleLightState)
                                {
                                    case RoadBaseAI.TrafficLightState.RedToGreen:
                                        if (num6 < 60u)
                                        {
                                            maxSpeed = 0f;
                                            return;
                                        }
                                        break;
                                    case RoadBaseAI.TrafficLightState.Red:
                                        maxSpeed = 0f;
                                        return;
                                    case RoadBaseAI.TrafficLightState.GreenToRed:
                                        if (num6 >= 30u)
                                        {
                                            maxSpeed = 0f;
                                            return;
                                        }
                                        break;
                                }
                            }
                        }
                        else
                        {
                            var stopCar = false;

                            if (TrafficPriority.IsLeftSegment(prevPos.m_segment, position.m_segment, num2))
                            {
                                vehicleLightState =
                                    TrafficLightsManual.GetSegmentLight(num4, prevPos.m_segment).GetLightLeft();
                            }
                            else if (TrafficPriority.IsRightSegment(prevPos.m_segment, position.m_segment, num2))
                            {
                                vehicleLightState =
                                    TrafficLightsManual.GetSegmentLight(num4, prevPos.m_segment).GetLightRight();
                            }
                            else
                            {
                                vehicleLightState =
                                    TrafficLightsManual.GetSegmentLight(num4, prevPos.m_segment).GetLightMain();
                            }

                            if (vehicleLightState == RoadBaseAI.TrafficLightState.Green)
                            {
                                var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                if (hasIncomingCars)
                                {
                                    stopCar = true;
                                }
                            }

                            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None ||
                                info.m_class.m_service != ItemClass.Service.Road)
                            {
                                switch (vehicleLightState)
                                {
                                    case RoadBaseAI.TrafficLightState.RedToGreen:
                                        if (num6 < 60u)
                                        {
                                            stopCar = true;
                                        }
                                        break;
                                    case RoadBaseAI.TrafficLightState.Red:
                                        stopCar = true;
                                        break;
                                    case RoadBaseAI.TrafficLightState.GreenToRed:
                                        if (num6 >= 30u)
                                        {
                                            stopCar = true;
                                        }
                                        break;
                                }
                            }

                            if (stopCar)
                            {
                                maxSpeed = 0f;
                                return;
                            }
                        }
                    }
                    else
                    {
                        if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car &&
                            TrafficPriority.VehicleList.ContainsKey(vehicleId) &&
                            TrafficPriority.IsPrioritySegment(num2, prevPos.m_segment))
                        {
                            var currentFrameIndex2 = Singleton<SimulationManager>.instance.m_currentFrameIndex;
                            var frame = currentFrameIndex2 >> 4;

                            var prioritySegment = TrafficPriority.GetPrioritySegment(num2, prevPos.m_segment);

                            if (TrafficPriority.VehicleList[vehicleId].carState == PriorityCar.CarState.None)
                            {
                                TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Enter;
                            }

                            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == Vehicle.Flags.None &&
                                TrafficPriority.VehicleList[vehicleId].carState != PriorityCar.CarState.Leave)
                            {
                                if (prioritySegment.Type == PrioritySegment.PriorityType.Stop)
                                {
                                    if (TrafficPriority.VehicleList[vehicleId].waitTime < 75)
                                    {
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Stop;

                                        if (vehicleData.GetLastFrameData().m_velocity.sqrMagnitude < 0.1f ||
                                            TrafficPriority.VehicleList[vehicleId].stopped)
                                        {
                                            TrafficPriority.VehicleList[vehicleId].stopped = true;
                                            TrafficPriority.VehicleList[vehicleId].waitTime++;

                                            if (TrafficPriority.VehicleList[vehicleId].waitTime > 2)
                                            {
                                                var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                                if (hasIncomingCars)
                                                {
                                                    maxSpeed = 0f;
                                                    return;
                                                }
                                            }
                                            else
                                            {
                                                maxSpeed = 0f;
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            maxSpeed = 0f;
                                            return;
                                        }
                                    }
                                    else
                                    {
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Leave;
                                    }
                                }
                                else if (prioritySegment.Type == PrioritySegment.PriorityType.Yield)
                                {
                                    if (TrafficPriority.VehicleList[vehicleId].waitTime < 75)
                                    {
                                        TrafficPriority.VehicleList[vehicleId].waitTime++;
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Stop;
                                        maxSpeed = 0f;

                                        if (vehicleData.GetLastFrameData().m_velocity.sqrMagnitude <
                                            TrafficPriority.VehicleList[vehicleId].yieldSpeedReduce)
                                        {
                                            var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                            if (hasIncomingCars)
                                            {
                                                return;
                                            }
                                        }
                                        else
                                        {
                                            return;
                                        }
                                    }
                                    else
                                    {
                                        TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Leave;
                                    }
                                }
                                else if (prioritySegment.Type == PrioritySegment.PriorityType.Main)
                                {
                                    TrafficPriority.VehicleList[vehicleId].waitTime++;
                                    TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Stop;
                                    maxSpeed = 0f;

                                    var hasIncomingCars = TrafficPriority.IncomingVehicles(vehicleId, num2);

                                    if (hasIncomingCars)
                                    {
                                        TrafficPriority.VehicleList[vehicleId].stopped = true;
                                        return;
                                    }
                                    TrafficPriority.VehicleList[vehicleId].stopped = false;

                                    NetInfo info3 = instance.m_segments.m_buffer[position.m_segment].Info;
                                    if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane)
                                    {
                                        maxSpeed =
                                            CalculateTargetSpeed(vehicleId, ref vehicleData,
                                                info3.m_lanes[position.m_lane].m_speedLimit,
                                                instance.m_lanes.m_buffer[(int) ((UIntPtr) laneId)].m_curve)*0.8f;
                                    }
                                    else
                                    {
                                        maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f)*
                                                   0.8f;
                                    }
                                    return;
                                }
                            }
                            else
                            {
                                TrafficPriority.VehicleList[vehicleId].carState = PriorityCar.CarState.Transit;
                            }
                        }
                    }
                }
            }

            NetInfo info2 = instance.m_segments.m_buffer[position.m_segment].Info;
            if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane)
            {
                var laneSpeedLimit = info2.m_lanes[position.m_lane].m_speedLimit;

                if (TrafficRoadRestrictions.IsSegment(position.m_segment))
                {
                    var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment);

                    if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f)
                    {
                        laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane];
                    }
                }

                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, instance.m_lanes.m_buffer[(int)((UIntPtr)laneId)].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }
        }
Пример #49
0
		public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition,
			PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID,
			byte prevOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed) {
			var netManager = Singleton<NetManager>.instance;
			//var vehicleManager = Singleton<VehicleManager>.instance;
			netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
			bool isRecklessDriver = IsRecklessDriver(vehicleId, ref vehicleData);

			var lastFrameData = vehicleData.GetLastFrameData();
			var lastFrameVehiclePos = lastFrameData.m_position;

			var camPos = Camera.main.transform.position;
			bool simulatePrioritySigns = (lastFrameVehiclePos - camPos).sqrMagnitude < FarLod && !isRecklessDriver;

			if (Options.simAccuracy <= 0) {
				if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) {
					VehiclePosition vehiclePos = TrafficPriority.GetVehiclePosition(vehicleId);
					if (vehiclePos.Valid && simulatePrioritySigns) { // TODO check if this should be !vehiclePos.Valid
						try {
							CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton<VehicleManager>.instance.m_vehicles.m_buffer[vehicleId], false, false);
						} catch (Exception e) {
							Log.Error("CarAI TmCalculateSegmentPosition Error: " + e.ToString());
						}
					}
				} else {
					//Log._Debug($"TmCalculateSegmentPosition does not handle vehicles of type {vehicleData.Info.m_vehicleType}");
				}
			}

			// I think this is supposed to be the lane position?
			// [VN, 12/23/2015] It's the 3D car position on the Bezier curve of the lane.
			// This crazy 0.003921569f equals to 1f/255 and prevOffset is the byte value (0..255) of the car position.
			var vehiclePosOnBezier = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].CalculatePosition(prevOffset * 0.003921569f);
			//ushort currentSegmentId = netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment;

			ushort destinationNodeId;
			ushort sourceNodeId;
			if (offset < position.m_offset) {
				destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
				sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
			} else {
				destinationNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
				sourceNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
			}
			var previousDestinationNode = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode;

			// this seems to be like the required braking force in order to stop the vehicle within its half length.
			var crazyValue = 0.5f * lastFrameData.m_velocity.sqrMagnitude / m_info.m_braking + m_info.m_generatedInfo.m_size.z * 0.5f;

			// Essentially, this is true if the car has enough time and space to brake (e.g. for a red traffic light)
			if (destinationNodeId == previousDestinationNode) {
				if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f) {
					var currentFrameIndex = Singleton<SimulationManager>.instance.m_currentFrameIndex;
					var num5 = (uint)((previousDestinationNode << 8) / 32768);
					var num6 = currentFrameIndex - num5 & 255u;

					var nodeFlags = netManager.m_nodes.m_buffer[destinationNodeId].m_flags;
					var prevLaneFlags = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags;
					var hasTrafficLight = (nodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
					var hasCrossing = (nodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None;
					var isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None;
					bool checkSpace = !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId) && !isRecklessDriver;
					//TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId);
					/*if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) {
						checkSpace = false;
					}*/

					if (checkSpace) {
						// check if there is enough space
						if ((nodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction &&
							netManager.m_nodes.m_buffer[destinationNodeId].CountSegments() != 2) {
							var len = vehicleData.CalculateTotalLength(vehicleId) + 2f;
							if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len)) {
								var sufficientSpace = false;
								if (nextPosition.m_segment != 0 &&
									netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f) {
									var flags3 = netManager.m_nodes.m_buffer[sourceNodeId].m_flags;
									if ((flags3 &
										 (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) !=
										NetNode.Flags.Junction || netManager.m_nodes.m_buffer[sourceNodeId].CountSegments() == 2) {
										var laneId2 = PathManager.GetLaneID(nextPosition);
										if (laneId2 != 0u) {
											sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId2)].CheckSpace(len);
										}
									}
								}
								if (!sufficientSpace) {
									maxSpeed = 0f;
									return;
								}
							}
						}
					}

					try {
						VehiclePosition globalTargetPos = TrafficPriority.GetVehiclePosition(vehicleId);

						if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0) {
							if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car) {
								if (hasTrafficLight && (!isJoinedJunction || hasCrossing)) {
									var destinationInfo = netManager.m_nodes.m_buffer[destinationNodeId].Info;

									if (globalTargetPos.CarState == VehicleJunctionTransitState.None) {
										globalTargetPos.CarState = VehicleJunctionTransitState.Enter;
									}

									RoadBaseAI.TrafficLightState vehicleLightState;
									RoadBaseAI.TrafficLightState pedestrianLightState;
									bool vehicles;
									bool pedestrians;
									CustomRoadAI.GetTrafficLightState(vehicleId, ref vehicleData, destinationNodeId, prevPos.m_segment, position.m_segment, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);

									if (isRecklessDriver && (destinationInfo.GetConnectionClass().m_service & ItemClass.Service.PublicTransport) == ItemClass.Service.None) { // no reckless driving at railroad crossings
										vehicleLightState = RoadBaseAI.TrafficLightState.Green;
									}

									if (!vehicles && num6 >= 196u) {
										vehicles = true;
										RoadBaseAI.SetTrafficLightState(destinationNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - num5, vehicleLightState, pedestrianLightState, vehicles, pedestrians);
									}

									var stopCar = false;
									switch (vehicleLightState) {
										case RoadBaseAI.TrafficLightState.RedToGreen:
											if (num6 < 60u) {
												stopCar = true;
											} else {
												globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
											}
											break;
										case RoadBaseAI.TrafficLightState.Red:
											stopCar = true;
											break;
										case RoadBaseAI.TrafficLightState.GreenToRed:
											if (num6 >= 30u) {
												stopCar = true;
											} else {
												globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
											}
											break;
									}

									if ((vehicleLightState == RoadBaseAI.TrafficLightState.Green || vehicleLightState == RoadBaseAI.TrafficLightState.RedToGreen) && !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == destinationNodeId)) {
										var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);

										if (hasIncomingCars) {
											// green light but other cars are incoming and they have priority: stop
											stopCar = true;
										}
									}

									if (stopCar) {
										globalTargetPos.CarState = VehicleJunctionTransitState.Stop;
										maxSpeed = 0f;
										return;
									}
								} else if (simulatePrioritySigns) {
#if DEBUG
									//bool debug = destinationNodeId == 10864;
									//bool debug = destinationNodeId == 13531;
									bool debug = false;
#endif
									//bool debug = false;
#if DEBUG
									if (debug)
										Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light.");
#endif

									var prioritySegment = TrafficPriority.GetPrioritySegment(destinationNodeId, prevPos.m_segment);
									if (prioritySegment != null) {
#if DEBUG
										if (debug)
											Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {destinationNodeId} which is not a traffic light and is a priority segment.");
#endif
										if (prioritySegment.HasVehicle(vehicleId)) {
#if DEBUG
											if (debug)
												Log._Debug($"Vehicle {vehicleId}: segment target position found");
#endif
											if (globalTargetPos.Valid) {
#if DEBUG
												if (debug)
													Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {globalTargetPos.CarState.ToString()}");
#endif
												var currentFrameIndex2 = Singleton<SimulationManager>.instance.m_currentFrameIndex;
												var frame = currentFrameIndex2 >> 4;

												if (globalTargetPos.CarState == VehicleJunctionTransitState.None) {
													globalTargetPos.CarState = VehicleJunctionTransitState.Enter;
												}

												if (globalTargetPos.CarState != VehicleJunctionTransitState.Leave) {
													bool hasIncomingCars;
													switch (prioritySegment.Type) {
														case SegmentEnd.PriorityType.Stop:
#if DEBUG
															if (debug)
																Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={globalTargetPos.WaitTime}, vel={lastFrameData.m_velocity.magnitude}");
#endif
															if (globalTargetPos.WaitTime < MaxPriorityWaitTime) {
																globalTargetPos.CarState = VehicleJunctionTransitState.Stop;

																if (lastFrameData.m_velocity.magnitude < 0.5f ||
																	globalTargetPos.Stopped) {
																	globalTargetPos.Stopped = true;
																	globalTargetPos.WaitTime++;

																	float minStopWaitTime = Random.Range(0f, 3f);
																	if (globalTargetPos.WaitTime >= minStopWaitTime) {
																		hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);
#if DEBUG
																		if (debug)
																			Log._Debug($"hasIncomingCars: {hasIncomingCars}");
#endif

																		if (hasIncomingCars) {
																			maxSpeed = 0f;
																			return;
																		}
																		globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
																	} else {
																		maxSpeed = 0;
																		return;
																	}
																} else {
																	maxSpeed = 0f;
																	return;
																}
															} else {
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
															}
															break;
														case SegmentEnd.PriorityType.Yield:
#if DEBUG
															if (debug)
																Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={globalTargetPos.WaitTime}");
#endif
															if (globalTargetPos.WaitTime < MaxPriorityWaitTime) {
																globalTargetPos.WaitTime++;
																globalTargetPos.CarState = VehicleJunctionTransitState.Stop;
																hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);
#if DEBUG
																if (debug)
																	Log._Debug($"hasIncomingCars: {hasIncomingCars}");
#endif
																if (hasIncomingCars) {
																	if (lastFrameData.m_velocity.magnitude > 0) {
																		maxSpeed = Math.Max(0f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield);
																	} else {
																		maxSpeed = 0;
																	}
#if DEBUG
																	/*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621)
																		Log.Message($"Vehicle {vehicleId} is yielding at node {destinationNodeId}. Speed: {maxSpeed}, Waiting time: {TrafficPriority.Vehicles[vehicleId].WaitTime}");*/
#endif
																	return;
																} else {
#if DEBUG
																	/*if (TrafficPriority.Vehicles[vehicleId].ToNode == 8621)
																		Log.Message($"Vehicle {vehicleId} is NOT yielding at node {destinationNodeId}.");*/
#endif
																	if (lastFrameData.m_velocity.magnitude > 0) {
																		maxSpeed = Math.Max(1f, lastFrameData.m_velocity.magnitude - globalTargetPos.ReduceSpeedByValueToYield * 0.5f);
																	}
																}
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
															} else {
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
															}
															break;
														case SegmentEnd.PriorityType.Main:
#if DEBUG
															if (debug)
																Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={globalTargetPos.WaitTime}");
#endif
															if (globalTargetPos.WaitTime < MaxPriorityWaitTime) {
																globalTargetPos.WaitTime++;
																globalTargetPos.CarState = VehicleJunctionTransitState.Stop;
																maxSpeed = 0f;

																hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, destinationNodeId);
#if DEBUG
																if (debug)
																	Log._Debug($"hasIncomingCars: {hasIncomingCars}");
#endif

																if (hasIncomingCars) {
																	globalTargetPos.Stopped = true;
																	return;
																}
																globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
																globalTargetPos.Stopped = false;
															}

															var info3 = netManager.m_segments.m_buffer[position.m_segment].Info;
															if (info3.m_lanes != null && info3.m_lanes.Length > position.m_lane) {
																//maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, info3.m_lanes[position.m_lane].m_speedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve) * 0.8f;
																maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info3.m_lanes[position.m_lane]), netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
															} else {
																maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
															}
															return;
													}
												} else {
													globalTargetPos.CarState = VehicleJunctionTransitState.Leave;
												}
											} else {
#if DEBUG
												if (debug)
													Log._Debug($"globalTargetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}");
#endif
											}
										} else {
#if DEBUG
											if (debug)
												Log._Debug($"targetPos is null! {vehicleId} @ seg. {prevPos.m_segment} @ node {destinationNodeId}");
#endif
										}
									}
								}
							}
						}
					} catch (Exception e) {
						Log.Error($"Error occured in TmCalculateSegmentPosition: {e.ToString()}");
					}
				}
			}

			var info2 = netManager.m_segments.m_buffer[position.m_segment].Info;
			if (info2.m_lanes != null && info2.m_lanes.Length > position.m_lane) {
				var laneSpeedLimit = SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info2.m_lanes[position.m_lane]); // info2.m_lanes[position.m_lane].m_speedLimit;

#if DEBUG
				/*if (position.m_segment == 275) {
					Log._Debug($"Applying lane speed limit of {laneSpeedLimit} to lane {laneID} @ seg. {position.m_segment}");
                }*/
#endif

				/*if (TrafficRoadRestrictions.IsSegment(position.m_segment)) {
					var restrictionSegment = TrafficRoadRestrictions.GetSegment(position.m_segment);

					if (restrictionSegment.SpeedLimits[position.m_lane] > 0.1f) {
						laneSpeedLimit = restrictionSegment.SpeedLimits[position.m_lane];
					}
				}*/

				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_curve);
			} else {
				maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
			}

			maxSpeed = CalcMaxSpeed(vehicleId, ref vehicleData, position, pos, maxSpeed, isRecklessDriver);
		}
		public static bool GetStopLane(ref PathUnit.Position pos, VehicleInfo.VehicleType vehicleType) {
			if (pos.m_segment != 0) {
				NetManager instance = Singleton<NetManager>.instance;
				int num;
				uint num2;
				if (instance.m_segments.m_buffer[(int)pos.m_segment].GetClosestLane((int)pos.m_lane, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, out num, out num2)) {
					pos.m_lane = (byte)num;
					return true;
				}
			}
			pos = default(PathUnit.Position);
			return false;
		}
Пример #51
0
		internal static float CalcMaxSpeed(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, Vector3 pos, float maxSpeed, bool isRecklessDriver) {
			var netManager = Singleton<NetManager>.instance;
			NetInfo segmentInfo = netManager.m_segments.m_buffer[(int)position.m_segment].Info;
			bool highwayRules = (segmentInfo.m_netAI is RoadBaseAI && ((RoadBaseAI)segmentInfo.m_netAI).m_highwayRules);

			if (!highwayRules) {
				if (netManager.m_treatWetAsSnow) {
					DistrictManager districtManager = Singleton<DistrictManager>.instance;
					byte district = districtManager.GetDistrict(pos);
					DistrictPolicies.CityPlanning cityPlanningPolicies = districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPolicies;
					if ((cityPlanningPolicies & DistrictPolicies.CityPlanning.StuddedTires) != DistrictPolicies.CityPlanning.None) {
						if (Options.strongerRoadConditionEffects) {
							if (maxSpeed > ICY_ROADS_STUDDED_MIN_SPEED)
								maxSpeed = ICY_ROADS_STUDDED_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - ICY_ROADS_STUDDED_MIN_SPEED);
						} else {
							maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f; // vanilla: -15% .. �
						}
						districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= DistrictPolicies.CityPlanning.StuddedTires;
					} else {
						if (Options.strongerRoadConditionEffects) {
							if (maxSpeed > ICY_ROADS_MIN_SPEED)
								maxSpeed = ICY_ROADS_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - ICY_ROADS_MIN_SPEED);
						} else {
							maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.00117647066f; // vanilla: -30% .. �
						}
					}
				} else {
					if (Options.strongerRoadConditionEffects) {
						float minSpeed = Math.Min(maxSpeed * WET_ROADS_FACTOR, WET_ROADS_MAX_SPEED);
						if (maxSpeed > minSpeed)
							maxSpeed = minSpeed + (float)(255 - netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - minSpeed);
					} else {
						maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_wetness * 0.0005882353f; // vanilla: -15% .. �
					}
				}

				if (Options.strongerRoadConditionEffects) {
					float minSpeed = Math.Min(maxSpeed * BROKEN_ROADS_FACTOR, BROKEN_ROADS_MAX_SPEED);
					if (maxSpeed > minSpeed) {
						maxSpeed = minSpeed + (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0039215686f * (maxSpeed - minSpeed);
					}
				} else {
					maxSpeed *= 1f + (float)netManager.m_segments.m_buffer[(int)position.m_segment].m_condition * 0.0005882353f; // vanilla: � .. +15 %
				}
			}

			ExtVehicleType? vehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicle(vehicleId, ref vehicleData);
			float vehicleRand = Math.Min(1f, (float)(vehicleId % 101) * 0.01f); // we choose 101 because it's a prime number
			if (isRecklessDriver)
				maxSpeed *= 1.5f + vehicleRand * 1.5f; // woohooo, 1.5 .. 3
			else if ((vehicleType & ExtVehicleType.PassengerCar) != ExtVehicleType.None)
				maxSpeed *= 0.8f + vehicleRand * 0.3f; // a little variance, 0.8 .. 1.1
			else if ((vehicleType & ExtVehicleType.Taxi) != ExtVehicleType.None)
				maxSpeed *= 0.9f + vehicleRand * 0.4f; // a little variance, 0.9 .. 1.3

			maxSpeed = Math.Max(MIN_SPEED, maxSpeed); // at least 10 km/h

			return maxSpeed;
		}