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); }
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); } }
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); }
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; }
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); } }
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); }
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); }
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); }
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); } }
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); } } } }
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); }
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); }
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); }
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; } }
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 } }
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; } }
public new bool ChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID) { return base.ChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID); }
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; }
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); }
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); } }
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)); }
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; }
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); } }
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; }
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; }