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[laneId].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
            var segmentInfo = netManager.m_segments.m_buffer[position.m_segment].Info;

            if (segmentInfo.m_lanes != null && segmentInfo.m_lanes.Length > position.m_lane)
            {
                // NON-STOCK CODE START
                float laneSpeedLimit = 1f;
                if (!Options.customSpeedLimitsEnabled)
                {
                    laneSpeedLimit = segmentInfo.m_lanes[position.m_lane].m_speedLimit;
                }
                else
                {
                    laneSpeedLimit = Constants.ManagerFactory.SpeedLimitManager.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneId, segmentInfo.m_lanes[position.m_lane]);
                }
                // NON-STOCK CODE END
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[laneId].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }

            // NON-STOCK CODE START
            maxSpeed = VehicleBehaviorManager.Instance.CalcMaxSpeed(vehicleId, ref VehicleStateManager.Instance.VehicleStates[vehicleId], this.m_info, position, ref netManager.m_segments.m_buffer[position.m_segment], pos, maxSpeed);
            // NON-STOCK CODE END
        }
Пример #2
0
 public new bool ChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID)
 {
     return(base.ChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID));
 }
Пример #3
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 FindPathPositionWithSpiralLoop(Vector3 position, Vector3?secondaryPosition, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleType, VehicleInfo.VehicleType stopType, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB)
        {
            int iMin = Mathf.Max((int)((position.z - (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), 0);
            int iMax = Mathf.Min((int)((position.z + (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), NetManager.NODEGRID_RESOLUTION - 1);

            int jMin = Mathf.Max((int)((position.x - (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), 0);
            int jMax = Mathf.Min((int)((position.x + (float)NetManager.NODEGRID_CELL_SIZE) / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f), NetManager.NODEGRID_RESOLUTION - 1);

            int width  = iMax - iMin + 1;
            int height = jMax - jMin + 1;

            int centerI = (int)(position.z / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f);
            int centerJ = (int)(position.x / (float)NetManager.NODEGRID_CELL_SIZE + (float)NetManager.NODEGRID_RESOLUTION / 2f);

            NetManager netManager = 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 minDist = float.MaxValue;

            PathUnit.Position myPathPosA     = default(PathUnit.Position);
            float             myDistanceSqrA = float.MaxValue;

            PathUnit.Position myPathPosB     = default(PathUnit.Position);
            float             myDistanceSqrB = float.MaxValue;

            int  lastSpiralDist = 0;
            bool found          = false;

            LoopUtil.SpiralLoop(centerI, centerJ, width, height, delegate(int i, int j) {
                if (i < 0 || i >= NetManager.NODEGRID_RESOLUTION || j < 0 || j >= NetManager.NODEGRID_RESOLUTION)
                {
                    return(true);
                }

                int spiralDist = Math.Max(Math.Abs(i - centerI), Math.Abs(j - centerJ));                 // maximum norm

                if (found && spiralDist > lastSpiralDist)
                {
                    // last iteration
                    return(false);
                }

                ushort segmentId = netManager.m_segmentGrid[i * NetManager.NODEGRID_RESOLUTION + j];
                int iterations   = 0;
                while (segmentId != 0)
                {
                    NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;
                    if (segmentInfo != null &&
                        segmentInfo.m_class.m_service == service &&
                        (netManager.m_segments.m_buffer[segmentId].m_flags & (NetSegment.Flags.Collapsed | NetSegment.Flags.Flooded)) == NetSegment.Flags.None && (allowUnderground || !segmentInfo.m_netAI.IsUnderground())
                        )
                    {
                        ushort startNodeId   = netManager.m_segments.m_buffer[segmentId].m_startNode;
                        ushort endNodeId     = netManager.m_segments.m_buffer[segmentId].m_endNode;
                        Vector3 startNodePos = netManager.m_nodes.m_buffer[startNodeId].m_position;
                        Vector3 endNodePos   = netManager.m_nodes.m_buffer[endNodeId].m_position;

                        Vector3 posA; int laneIndexA; float laneOffsetA;
                        Vector3 posB; int laneIndexB; float laneOffsetB;

                        if (netManager.m_segments.m_buffer[segmentId].GetClosestLanePosition(position, laneType, vehicleType, stopType, requireConnect, out posA, out laneIndexA, out laneOffsetA, out posB, out laneIndexB, out laneOffsetB))
                        {
                            float dist = Vector3.SqrMagnitude(position - posA);
                            if (secondaryPosition != null)
                            {
                                dist += Vector3.SqrMagnitude((Vector3)secondaryPosition - posA);
                            }

                            if (dist < minDist)
                            {
                                found = true;

                                minDist = dist;
                                myPathPosA.m_segment = segmentId;
                                myPathPosA.m_lane    = (byte)laneIndexA;
                                myPathPosA.m_offset  = (byte)Mathf.Clamp(Mathf.RoundToInt(laneOffsetA * 255f), 0, 255);
                                myDistanceSqrA       = dist;

                                dist = Vector3.SqrMagnitude(position - posB);
                                if (secondaryPosition != null)
                                {
                                    dist += Vector3.SqrMagnitude((Vector3)secondaryPosition - posB);
                                }

                                if (laneIndexB < 0)
                                {
                                    myPathPosB.m_segment = 0;
                                    myPathPosB.m_lane    = 0;
                                    myPathPosB.m_offset  = 0;
                                    myDistanceSqrB       = float.MaxValue;
                                }
                                else
                                {
                                    myPathPosB.m_segment = segmentId;
                                    myPathPosB.m_lane    = (byte)laneIndexB;
                                    myPathPosB.m_offset  = (byte)Mathf.Clamp(Mathf.RoundToInt(laneOffsetB * 255f), 0, 255);
                                    myDistanceSqrB       = dist;
                                }
                            }
                        }
                    }

                    segmentId = netManager.m_segments.m_buffer[segmentId].m_nextGridSegment;
                    if (++iterations >= NetManager.MAX_SEGMENT_COUNT)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);
                        break;
                    }
                }

                lastSpiralDist = spiralDist;
                return(true);
            });

            pathPosA     = myPathPosA;
            distanceSqrA = myDistanceSqrA;
            pathPosB     = myPathPosB;
            distanceSqrB = myDistanceSqrB;

            return(pathPosA.m_segment != 0);
        }
        internal bool ExtParkVehicle(ushort vehicleID, ref Vehicle vehicleData, uint driverCitizenId, ushort driverCitizenInstanceId, ref ExtCitizenInstance driverExtInstance, ushort targetBuildingId, PathUnit.Position pathPos, uint nextPath, int nextPositionIndex, out byte segmentOffset)
        {
#if DEBUG
            bool citDebug  = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == driverExtInstance.GetCitizenId();
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && citDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug;
#endif

            PathManager pathManager       = Singleton <PathManager> .instance;
            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            NetManager netManager         = Singleton <NetManager> .instance;
            VehicleManager vehicleManager = Singleton <VehicleManager> .instance;

            // NON-STOCK CODE START
            bool prohibitPocketCars = false;
            // NON-STOCK CODE END

            if (driverCitizenId != 0u)
            {
                if (Options.prohibitPocketCars && driverCitizenInstanceId != 0)
                {
                    prohibitPocketCars = true;
                }

                uint laneID = PathManager.GetLaneID(pathPos);
                segmentOffset = (byte)Singleton <SimulationManager> .instance.m_randomizer.Int32(1, 254);

                Vector3 refPos;
                Vector3 vector;
                netManager.m_lanes.m_buffer[laneID].CalculatePositionAndDirection((float)segmentOffset * 0.003921569f, out refPos, out vector);
                NetInfo info           = netManager.m_segments.m_buffer[(int)pathPos.m_segment].Info;
                bool isSegmentInverted = (netManager.m_segments.m_buffer[(int)pathPos.m_segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
                bool isPosNegative     = info.m_lanes[(int)pathPos.m_lane].m_position < 0f;
                vector.Normalize();
                Vector3 searchDir;
                if (isSegmentInverted != isPosNegative)
                {
                    searchDir.x = -vector.z;
                    searchDir.y = 0f;
                    searchDir.z = vector.x;
                }
                else
                {
                    searchDir.x = vector.z;
                    searchDir.y = 0f;
                    searchDir.z = -vector.x;
                }
                ushort homeID = 0;
                if (driverCitizenId != 0u)
                {
                    homeID = Singleton <CitizenManager> .instance.m_citizens.m_buffer[driverCitizenId].m_homeBuilding;
                }
                Vector3 parkPos    = default(Vector3);
                Quaternion parkRot = default(Quaternion);
                float parkOffset   = -1f;

                // NON-STOCK CODE START
                bool foundParkingSpace = false;

                if (prohibitPocketCars)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"Vehicle {vehicleID} tries to park on a parking position now (flags: {vehicleData.m_flags})! CurrentPathMode={driverExtInstance.pathMode} path={vehicleData.m_path} pathPositionIndex={vehicleData.m_pathPositionIndex} segmentId={pathPos.m_segment} laneIndex={pathPos.m_lane} offset={pathPos.m_offset} nextPath={nextPath} refPos={refPos} searchDir={searchDir} home={homeID} driverCitizenId={driverCitizenId} driverCitizenInstanceId={driverCitizenInstanceId}");
                    }
#endif

                    if (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToAltParkPos || driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToKnownParkPos)
                    {
                        // try to use previously found parking space
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"Vehicle {vehicleID} tries to park on an (alternative) parking position now! CurrentPathMode={driverExtInstance.pathMode} altParkingSpaceLocation={driverExtInstance.parkingSpaceLocation} altParkingSpaceLocationId={driverExtInstance.parkingSpaceLocationId}");
                        }
#endif

                        switch (driverExtInstance.parkingSpaceLocation)
                        {
                        case ExtCitizenInstance.ExtParkingSpaceLocation.RoadSide:
                            uint parkLaneID; int parkLaneIndex;
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleID} wants to park road-side @ segment {driverExtInstance.parkingSpaceLocationId}");
                            }
#endif
                            foundParkingSpace = AdvancedParkingManager.Instance.FindParkingSpaceRoadSideForVehiclePos(this.m_info, 0, driverExtInstance.parkingSpaceLocationId, refPos, out parkPos, out parkRot, out parkOffset, out parkLaneID, out parkLaneIndex);
                            break;

                        case ExtCitizenInstance.ExtParkingSpaceLocation.Building:
                            float maxDist = 9999f;
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleID} wants to park @ building {driverExtInstance.parkingSpaceLocationId}");
                            }
#endif
                            foundParkingSpace = AdvancedParkingManager.Instance.FindParkingSpacePropAtBuilding(this.m_info, homeID, 0, driverExtInstance.parkingSpaceLocationId, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[driverExtInstance.parkingSpaceLocationId], pathPos.m_segment, refPos, ref maxDist, true, out parkPos, out parkRot, out parkOffset);
                            break;

                        default:
#if DEBUG
                            Log.Error($"No alternative parking position stored for vehicle {vehicleID}! PathMode={driverExtInstance.pathMode}");
#endif
                            foundParkingSpace = CustomFindParkingSpace(this.m_info, homeID, refPos, searchDir, pathPos.m_segment, out parkPos, out parkRot, out parkOffset);
                            break;
                        }
                    }
                }

                if (!foundParkingSpace)
                {
                    foundParkingSpace =                     /*prohibitPocketCars ?*/
                                        CustomFindParkingSpace(this.m_info, homeID, refPos, searchDir, pathPos.m_segment, out parkPos, out parkRot, out parkOffset) /*:
                                                                                                                                                                     * FindParkingSpace(homeID, refPos, searchDir, pathPos.m_segment, this.m_info.m_generatedInfo.m_size.x, this.m_info.m_generatedInfo.m_size.z, out parkPos, out parkRot, out parkOffset)*/;
                }

                // NON-STOCK CODE END
                ushort parkedVehicleId = 0;
                bool parkedCarCreated  = foundParkingSpace && vehicleManager.CreateParkedVehicle(out parkedVehicleId, ref Singleton <SimulationManager> .instance.m_randomizer, this.m_info, parkPos, parkRot, driverCitizenId);
                if (foundParkingSpace && parkedCarCreated)
                {
                    // we have reached a parking position
#if DEBUG
                    float sqrDist = (refPos - parkPos).sqrMagnitude;
                    if (fineDebug)
                    {
                        Log._Debug($"Vehicle {vehicleID} succeeded in parking! CurrentPathMode={driverExtInstance.pathMode} sqrDist={sqrDist}");
                    }

                    if (GlobalConfig.Instance.Debug.Switches[6] && sqrDist >= 16000)
                    {
                        Log._Debug($"CustomPassengerCarAI.CustomParkVehicle: FORCED PAUSE. Distance very large! Vehicle {vehicleID}. dist={sqrDist}");
                        Singleton <SimulationManager> .instance.SimulationPaused = true;
                    }
#endif

                    citizenManager.m_citizens.m_buffer[driverCitizenId].SetParkedVehicle(driverCitizenId, parkedVehicleId);
                    if (parkOffset >= 0f)
                    {
                        segmentOffset = (byte)(parkOffset * 255f);
                    }

                    // NON-STOCK CODE START
                    if (prohibitPocketCars)
                    {
                        if ((driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToAltParkPos || driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToKnownParkPos) && targetBuildingId != 0)
                        {
                            // decrease parking space demand of target building
                            ExtBuildingManager.Instance.ExtBuildings[targetBuildingId].ModifyParkingSpaceDemand(parkPos, GlobalConfig.Instance.ParkingAI.MinFoundParkPosParkingSpaceDemandDelta, GlobalConfig.Instance.ParkingAI.MaxFoundParkPosParkingSpaceDemandDelta);
                        }

                        //if (driverExtInstance.CurrentPathMode == ExtCitizenInstance.PathMode.DrivingToAltParkPos || driverExtInstance.CurrentPathMode == ExtCitizenInstance.PathMode.DrivingToKnownParkPos) {
                        // we have reached an (alternative) parking position and succeeded in finding a parking space
                        driverExtInstance.pathMode = ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget;
                        driverExtInstance.failedParkingAttempts  = 0;
                        driverExtInstance.parkingSpaceLocation   = ExtCitizenInstance.ExtParkingSpaceLocation.None;
                        driverExtInstance.parkingSpaceLocationId = 0;
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"Vehicle {vehicleID} has reached an (alternative) parking position! CurrentPathMode={driverExtInstance.pathMode} position={parkPos}");
                        }
#endif
                        //}
                    }
                }
                else if (prohibitPocketCars)
                {
                    // could not find parking space. vehicle would despawn.
                    if (targetBuildingId != 0 && (Singleton <BuildingManager> .instance.m_buildings.m_buffer[targetBuildingId].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None)
                    {
                        // target is an outside connection
                        return(true);
                    }

                    // Find parking space in the vicinity, redo path-finding to the parking space, park the vehicle and do citizen path-finding to the current target

                    if (!foundParkingSpace && (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToAltParkPos || driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.DrivingToKnownParkPos) && targetBuildingId != 0)
                    {
                        // increase parking space demand of target building
                        if (driverExtInstance.failedParkingAttempts > 1)
                        {
                            ExtBuildingManager.Instance.ExtBuildings[targetBuildingId].AddParkingSpaceDemand(GlobalConfig.Instance.ParkingAI.FailedParkingSpaceDemandIncrement * (uint)(driverExtInstance.failedParkingAttempts - 1));
                        }
                    }

                    if (!foundParkingSpace)
                    {
                        ++driverExtInstance.failedParkingAttempts;
                    }
                    else
                    {
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"Parking failed for vehicle {vehicleID}: Parked car could not be created. ABORT.");
                        }
#endif
                        driverExtInstance.failedParkingAttempts = GlobalConfig.Instance.ParkingAI.MaxParkingAttempts + 1;
                    }
                    driverExtInstance.pathMode = ExtCitizenInstance.ExtPathMode.ParkingFailed;
                    driverExtInstance.parkingPathStartPosition = pathPos;

#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"Parking failed for vehicle {vehicleID}! (flags: {vehicleData.m_flags}) pathPos segment={pathPos.m_segment}, lane={pathPos.m_lane}, offset={pathPos.m_offset}. Trying to find parking space in the vicinity. FailedParkingAttempts={driverExtInstance.failedParkingAttempts}, CurrentPathMode={driverExtInstance.pathMode} foundParkingSpace={foundParkingSpace}");
                    }
#endif

                    // invalidate paths of all passengers in order to force path recalculation
                    uint curUnitId = vehicleData.m_citizenUnits;
                    int numIter    = 0;
                    while (curUnitId != 0u)
                    {
                        uint nextUnit = citizenManager.m_units.m_buffer[curUnitId].m_nextUnit;
                        for (int i = 0; i < 5; i++)
                        {
                            uint curCitizenId = citizenManager.m_units.m_buffer[curUnitId].GetCitizen(i);
                            if (curCitizenId != 0u)
                            {
                                ushort citizenInstanceId = citizenManager.m_citizens.m_buffer[curCitizenId].m_instance;
                                if (citizenInstanceId != 0)
                                {
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Releasing path for citizen instance {citizenInstanceId} sitting in vehicle {vehicleID} (was {citizenManager.m_instances.m_buffer[citizenInstanceId].m_path}).");
                                    }
#endif
                                    if (citizenInstanceId != driverCitizenInstanceId)
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Resetting pathmode for passenger citizen instance {citizenInstanceId} sitting in vehicle {vehicleID} (was {ExtCitizenInstanceManager.Instance.ExtInstances[citizenInstanceId].pathMode}).");
                                        }
#endif

                                        ExtCitizenInstanceManager.Instance.ExtInstances[citizenInstanceId].Reset();
                                    }

                                    if (citizenManager.m_instances.m_buffer[citizenInstanceId].m_path != 0)
                                    {
                                        Singleton <PathManager> .instance.ReleasePath(citizenManager.m_instances.m_buffer[citizenInstanceId].m_path);

                                        citizenManager.m_instances.m_buffer[citizenInstanceId].m_path = 0u;
                                    }
                                }
                            }
                        }
                        curUnitId = nextUnit;
                        if (++numIter > CitizenManager.MAX_UNIT_COUNT)
                        {
                            CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                            break;
                        }
                    }
                    return(false);
                    // NON-STOCK CODE END
                }
            }
            else
            {
                segmentOffset = pathPos.m_offset;
            }

            // parking has succeeded
            if (driverCitizenId != 0u)
            {
                uint curCitizenUnitId = vehicleData.m_citizenUnits;
                int numIter           = 0;
                while (curCitizenUnitId != 0u)
                {
                    uint nextUnit = citizenManager.m_units.m_buffer[curCitizenUnitId].m_nextUnit;
                    for (int j = 0; j < 5; j++)
                    {
                        uint citId = citizenManager.m_units.m_buffer[curCitizenUnitId].GetCitizen(j);
                        if (citId != 0u)
                        {
                            ushort citizenInstanceId = citizenManager.m_citizens.m_buffer[citId].m_instance;
                            if (citizenInstanceId != 0)
                            {
                                // NON-STOCK CODE START
                                if (prohibitPocketCars)
                                {
                                    if (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget)
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Parking succeeded: Doing nothing for citizen instance {citizenInstanceId}! path: {citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path}");
                                        }
#endif
                                        ExtCitizenInstanceManager.Instance.ExtInstances[citizenInstanceId].pathMode = ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget;
                                        continue;
                                    }
                                }
                                // NON-STOCK CODE END

                                if (pathManager.AddPathReference(nextPath))
                                {
                                    if (citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path != 0u)
                                    {
                                        pathManager.ReleasePath(citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path);
                                    }
                                    citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_path = nextPath;
                                    citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_pathPositionIndex = (byte)nextPositionIndex;
                                    citizenManager.m_instances.m_buffer[(int)citizenInstanceId].m_lastPathOffset    = segmentOffset;
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Parking succeeded (default): Setting path of citizen instance {citizenInstanceId} to {nextPath}!");
                                    }
#endif
                                }
                            }
                        }
                    }
                    curCitizenUnitId = nextUnit;
                    if (++numIter > 524288)
                    {
                        CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                        break;
                    }
                }
            }

            if (prohibitPocketCars)
            {
                if (driverExtInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresWalkingPathToTarget)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"Parking succeeded (alternative parking spot): Citizen instance {driverExtInstance} has to walk for the remaining path!");
                    }
#endif

                    /*driverExtInstance.CurrentPathMode = ExtCitizenInstance.PathMode.CalculatingWalkingPathToTarget;
                     * if (debug)
                     *      Log._Debug($"Setting CurrentPathMode of vehicle {vehicleID} to {driverExtInstance.CurrentPathMode}");*/
                }
            }

            return(true);
        }
Пример #6
0
        public bool ExtStartPathFind(ushort instanceID, ref CitizenInstance instanceData, ref ExtCitizenInstance extInstance, ref ExtCitizen extCitizen, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo, bool enableTransport, bool ignoreCost)
        {
#if DEBUG
            bool citDebug  = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == instanceData.m_citizen;
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && citDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug;

            if (debug)
            {
                Log.Warning($"CustomCitizenAI.ExtStartPathFind({instanceID}): called for citizen {instanceData.m_citizen}, startPos={startPos}, endPos={endPos}, sourceBuilding={instanceData.m_sourceBuilding}, targetBuilding={instanceData.m_targetBuilding}, pathMode={extInstance.pathMode}, enableTransport={enableTransport}, ignoreCost={ignoreCost}");
            }
#endif

            // NON-STOCK CODE START
            CitizenManager citizenManager  = Singleton <CitizenManager> .instance;
            ushort         parkedVehicleId = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_parkedVehicle;
            ushort         homeId          = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_homeBuilding;
            CarUsagePolicy carUsageMode    = CarUsagePolicy.Allowed;

#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI.Preparation")) {
#endif
            if (Options.prohibitPocketCars)
            {
                switch (extInstance.pathMode)
                {
                case ExtPathMode.RequiresWalkingPathToParkedCar:
                case ExtPathMode.CalculatingWalkingPathToParkedCar:
                case ExtPathMode.WalkingToParkedCar:
                case ExtPathMode.ApproachingParkedCar:
                    if (parkedVehicleId == 0)
                    {
                        /*
                         * Parked vehicle not present but citizen wants to reach it
                         * -> Reset path mode
                         */
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode} but no parked vehicle present. Change to 'None'.");
                        }
#endif

                        extInstance.Reset();
                    }
                    else
                    {
                        /*
                         * Parked vehicle is present and citizen wants to reach it
                         * -> Prohibit car usage
                         */
#if DEBUG
                        if (fineDebug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}.  Change to 'CalculatingWalkingPathToParkedCar'.");
                        }
#endif
                        extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToParkedCar;
                        carUsageMode         = CarUsagePolicy.Forbidden;
                    }
                    break;

                case ExtPathMode.RequiresWalkingPathToTarget:
                case ExtPathMode.CalculatingWalkingPathToTarget:
                case ExtPathMode.WalkingToTarget:
                    /*
                     * Citizen walks to target
                     * -> Reset path mode
                     */
#if DEBUG
                    if (fineDebug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}. Change to 'CalculatingWalkingPathToTarget'.");
                    }
#endif
                    extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                    carUsageMode         = CarUsagePolicy.Forbidden;
                    break;

                case ExtPathMode.RequiresCarPath:
                case ExtPathMode.DrivingToTarget:
                case ExtPathMode.DrivingToKnownParkPos:
                case ExtPathMode.DrivingToAltParkPos:
                case ExtPathMode.CalculatingCarPathToAltParkPos:
                case ExtPathMode.CalculatingCarPathToKnownParkPos:
                case ExtPathMode.CalculatingCarPathToTarget:
                    if (parkedVehicleId == 0)
                    {
                        /*
                         * Citizen wants to drive to target but parked vehicle is not present
                         * -> Reset path mode
                         */

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode} but no parked vehicle present. Change to 'None'.");
                        }
#endif

                        extInstance.Reset();
                    }
                    else
                    {
                        /*
                         * Citizen wants to drive to target and parked vehicle is present
                         * -> Force parked car usage
                         */

#if DEBUG
                        if (fineDebug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}.  Change to 'RequiresCarPath'.");
                        }
#endif

                        extInstance.pathMode = ExtPathMode.RequiresCarPath;
                        carUsageMode         = CarUsagePolicy.ForcedParked;
                        startPos             = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;                   // force to start from the parked car
                    }
                    break;

                default:
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen has CurrentPathMode={extInstance.pathMode}. Change to 'None'.");
                    }
#endif
                    extInstance.Reset();
                    break;
                }

                if (extInstance.pathMode == ExtPathMode.None)
                {
                    if ((instanceData.m_flags & CitizenInstance.Flags.OnTour) != CitizenInstance.Flags.None || ignoreCost)
                    {
                        /*
                         * Citizen is on a walking tour or is a mascot
                         * -> Prohibit car usage
                         */
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen ignores cost ({ignoreCost}) or is on a walking tour ({(instanceData.m_flags & CitizenInstance.Flags.OnTour) != CitizenInstance.Flags.None}): Setting path mode to 'CalculatingWalkingPathToTarget'");
                        }
#endif
                        carUsageMode         = CarUsagePolicy.Forbidden;
                        extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                    }
                    else
                    {
                        /*
                         * Citizen is not on a walking tour and is not a mascot
                         * -> Check if citizen is located at an outside connection and make them obey Parking AI restrictions
                         */

                        if (instanceData.m_sourceBuilding != 0)
                        {
                            ItemClass.Service sourceBuildingService = Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_sourceBuilding].Info.m_class.m_service;

                            if (Constants.ManagerFactory.ExtCitizenInstanceManager.IsAtOutsideConnection(instanceID, ref instanceData, ref citizenManager.m_citizens.m_buffer[instanceData.m_citizen]))
                            {
                                if (sourceBuildingService == ItemClass.Service.Road)
                                {
                                    if (vehicleInfo != null)
                                    {
                                        /*
                                         * Citizen is located at a road outside connection and can spawn a car
                                         * -> Force car usage
                                         */
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is located at a road outside connection: Setting path mode to 'RequiresCarPath' and carUsageMode to 'ForcedPocket'");
                                        }
#endif
                                        extInstance.pathMode = ExtPathMode.RequiresCarPath;
                                        carUsageMode         = CarUsagePolicy.ForcedPocket;
                                    }
                                    else
                                    {
                                        /*
                                         * Citizen is located at a non-road outside connection and cannot spawn a car
                                         * -> Path-finding fails
                                         */
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is located at a road outside connection but does not have a car template: ABORTING PATH-FINDING");
                                        }
#endif
                                        return(false);
                                    }
                                }
                                else
                                {
                                    /*
                                     * Citizen is located at a non-road outside connection
                                     * -> Prohibit car usage
                                     */
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is located at a non-road outside connection: Setting path mode to 'CalculatingWalkingPathToTarget'");
                                    }
#endif
                                    extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget;
                                    carUsageMode         = CarUsagePolicy.Forbidden;
                                }
                            }
                        }
                    }
                }

                if ((carUsageMode == CarUsagePolicy.Allowed || carUsageMode == CarUsagePolicy.ForcedParked) && parkedVehicleId != 0)
                {
                    /*
                     * Reuse parked vehicle info
                     */
                    vehicleInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info;

                    /*
                     * Check if the citizen should return their car back home
                     */
                    if (extInstance.pathMode == ExtPathMode.None && // initiating a new path
                        homeId != 0 &&                              // home building present
                        instanceData.m_targetBuilding == homeId     // current target is home
                        )
                    {
                        /*
                         * citizen travels back home
                         * -> check if their car should be returned
                         */
                        if ((extCitizen.lastTransportMode & ExtCitizen.ExtTransportMode.Car) != ExtCitizen.ExtTransportMode.None)
                        {
                            /*
                             * citizen travelled by car
                             * -> return car back home
                             */
                            extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar;
                            carUsageMode         = CarUsagePolicy.Forbidden;

#if DEBUG
                            if (fineDebug)
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen used their car before and is not at home. Forcing to walk to parked car.");
                            }
#endif
                        }
                        else
                        {
                            /*
                             * citizen travelled by other means of transport
                             * -> check distance between home and parked car. if too far away: force to take the car back home
                             */
                            float distHomeToParked = (Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position - Singleton <BuildingManager> .instance.m_buildings.m_buffer[homeId].m_position).magnitude;

                            if (distHomeToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToHome)
                            {
                                /*
                                 * force to take car back home
                                 */
                                extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar;
                                carUsageMode         = CarUsagePolicy.Forbidden;

#if DEBUG
                                if (fineDebug)
                                {
                                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen wants to go home and parked car is too far away ({distHomeToParked}). Forcing walking to parked car.");
                                }
#endif
                            }
                        }
                    }
                }

                /*
                 * The following holds:
                 * - pathMode is now either CalculatingWalkingPathToParkedCar, CalculatingWalkingPathToTarget, RequiresCarPath or None.
                 * - if pathMode is CalculatingWalkingPathToParkedCar or RequiresCarPath: parked car is present and citizen is not on a walking tour
                 * - carUsageMode is valid
                 * - if pathMode is RequiresCarPath: carUsageMode is either ForcedParked or ForcedPocket
                 */

                /*
                 * modify path-finding constraints (vehicleInfo, endPos) if citizen is forced to walk
                 */
                if (extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToParkedCar || extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToTarget)
                {
                    /*
                     * vehicle must not be used since we need a walking path to either
                     * 1. a parked car or
                     * 2. the target building
                     */

                    if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar)
                    {
                        /*
                         * walk to parked car
                         * -> end position is parked car
                         */
                        endPos = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
#if DEBUG
                        if (fineDebug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen shall go to parked vehicle @ {endPos}");
                        }
#endif
                    }
                }
            }
#if BENCHMARK
        }
#endif
#if DEBUG
            if (fineDebug)
            {
                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen is allowed to drive their car? {carUsageMode}");
            }
#endif
            // NON-STOCK CODE END

            /*
             * semi-stock code: determine path-finding parameters (laneTypes, vehicleTypes, extVehicleType, etc.)
             */
            NetInfo.LaneType laneTypes           = NetInfo.LaneType.Pedestrian;
            VehicleInfo.VehicleType vehicleTypes = VehicleInfo.VehicleType.None;
            bool randomParking            = false;
            bool combustionEngine         = false;
            ExtVehicleType extVehicleType = ExtVehicleType.None;
            if (vehicleInfo != null)
            {
                if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi)
                {
                    if ((instanceData.m_flags & CitizenInstance.Flags.CannotUseTaxi) == CitizenInstance.Flags.None && Singleton <DistrictManager> .instance.m_districts.m_buffer[0].m_productionData.m_finalTaxiCapacity != 0u)
                    {
                        SimulationManager instance = Singleton <SimulationManager> .instance;
                        if (instance.m_isNightTime || instance.m_randomizer.Int32(2u) == 0)
                        {
                            laneTypes     |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                            vehicleTypes  |= vehicleInfo.m_vehicleType;
                            extVehicleType = ExtVehicleType.Taxi;                             // NON-STOCK CODE
                            // NON-STOCK CODE START
                            if (Options.prohibitPocketCars)
                            {
                                extInstance.pathMode = ExtPathMode.TaxiToTarget;
                            }
                            // NON-STOCK CODE END
                        }
                    }
                }
                else
                // NON-STOCK CODE START
                if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Car)
                {
                    if (carUsageMode != CarUsagePolicy.Forbidden)
                    {
                        extVehicleType   = ExtVehicleType.PassengerCar;
                        laneTypes       |= NetInfo.LaneType.Vehicle;
                        vehicleTypes    |= vehicleInfo.m_vehicleType;
                        combustionEngine = vehicleInfo.m_class.m_subService == ItemClass.SubService.ResidentialLow;
                    }
                }
                else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle)
                {
                    extVehicleType = ExtVehicleType.Bicycle;
                    laneTypes     |= NetInfo.LaneType.Vehicle;
                    vehicleTypes  |= vehicleInfo.m_vehicleType;
                }
                // NON-STOCK CODE END
            }

            // NON-STOCK CODE START
            ExtPathType extPathType   = ExtPathType.None;
            PathUnit.Position endPosA = default(PathUnit.Position);
            bool calculateEndPos      = true;
            bool allowRandomParking   = true;
#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI.Main")) {
#endif
            if (Options.prohibitPocketCars)
            {
                // Parking AI

                if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.RequiresCarPath)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Setting startPos={startPos} for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode}");
                    }
#endif

                    if (
                        instanceData.m_targetBuilding == 0 ||
                        (Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None
                        )
                    {
                        /*
                         * the citizen is starting their journey and the target is not an outside connection
                         * -> find a suitable parking space near the target
                         */

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Finding parking space at target for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode} parkedVehicleId={parkedVehicleId}");
                        }
#endif

                        // find a parking space in the vicinity of the target
                        bool    calcEndPos;
                        Vector3 parkPos;
                        if (
                            AdvancedParkingManager.Instance.FindParkingSpaceForCitizen(endPos, vehicleInfo, ref extInstance, homeId, instanceData.m_targetBuilding == homeId, 0, false, out parkPos, ref endPosA, out calcEndPos) &&
                            extInstance.CalculateReturnPath(parkPos, endPos)
                            )
                        {
                            // success
                            extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingCarPathToKnownParkPos;
                            calculateEndPos      = calcEndPos;                      // if true, the end path position still needs to be calculated
                            allowRandomParking   = false;                           // find a direct path to the calculated parking position
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Finding known parking space for citizen instance {instanceID}, parked vehicle {parkedVehicleId} succeeded and return path {extInstance.returnPathId} ({extInstance.returnPathState}) is calculating. PathMode={extInstance.pathMode}");
                            }
#endif

                            /*if (! extInstance.CalculateReturnPath(parkPos, endPos)) {
                             *      // TODO retry?
                             *      if (debug)
                             *              Log._Debug($"CustomCitizenAI.CustomStartPathFind: [PFFAIL] Could not calculate return path for citizen instance {instanceID}, parked vehicle {parkedVehicleId}. Calling OnPathFindFailed.");
                             *      CustomHumanAI.OnPathFindFailure(extInstance);
                             *      return false;
                             * }*/
                        }
                    }

                    if (extInstance.pathMode == ExtPathMode.RequiresCarPath)
                    {
                        /*
                         * no known parking space found (pathMode has not been updated in the block above)
                         * -> calculate direct path to target
                         */
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} is still at CurrentPathMode={extInstance.pathMode} (no parking space found?). Setting it to CalculatingCarPath. parkedVehicleId={parkedVehicleId}");
                        }
#endif
                        extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingCarPathToTarget;
                    }
                }

                /*
                 * determine path type from path mode
                 */
                extPathType = extInstance.GetPathType();

                /*
                 * the following holds:
                 * - pathMode is now either CalculatingWalkingPathToParkedCar, CalculatingWalkingPathToTarget, CalculatingCarPathToTarget, CalculatingCarPathToKnownParkPos or None.
                 */
            }
#if BENCHMARK
        }
#endif

            /*
             * enable random parking if exact parking space was not calculated yet
             */
            if (extVehicleType == ExtVehicleType.PassengerCar || extVehicleType == ExtVehicleType.Bicycle)
            {
                if (allowRandomParking &&
                    instanceData.m_targetBuilding != 0 &&
                    (
                        Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office ||
                        (instanceData.m_flags & CitizenInstance.Flags.TargetIsNode) != 0
                    ))
                {
                    randomParking = true;
                }
            }
            // NON-STOCK CODE END

            /*
             * determine the path position of the parked vehicle
             */
            PathUnit.Position parkedVehiclePathPos = default(PathUnit.Position);
            if (parkedVehicleId != 0 && extVehicleType == ExtVehicleType.PassengerCar)
            {
                Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position;
                CustomPathManager.FindPathPositionWithSpiralLoop(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, false, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out parkedVehiclePathPos);
            }
            bool allowUnderground = (instanceData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None;

#if DEBUG
            if (debug)
            {
                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Requesting path-finding for citizen instance {instanceID}, citizen {instanceData.m_citizen}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPos={startPos}, endPos={endPos}, sourceBuilding={instanceData.m_sourceBuilding}, targetBuilding={instanceData.m_targetBuilding} pathMode={extInstance.pathMode}");
            }
#endif

            /*
             * determine start & end path positions
             */
            bool foundEndPos   = !calculateEndPos || FindPathPosition(instanceID, ref instanceData, endPos, Options.prohibitPocketCars && (instanceData.m_targetBuilding == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None) ? NetInfo.LaneType.Pedestrian : laneTypes, vehicleTypes, false, out endPosA);         // NON-STOCK CODE: with Parking AI enabled, the end position must be a pedestrian position
            bool foundStartPos = false;
            PathUnit.Position startPosA;

            if (Options.prohibitPocketCars && (extInstance.pathMode == ExtPathMode.CalculatingCarPathToTarget || extInstance.pathMode == ExtPathMode.CalculatingCarPathToKnownParkPos))
            {
                /*
                 * citizen will enter their car now
                 * -> find a road start position
                 */
                foundStartPos = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, laneTypes & ~NetInfo.LaneType.Pedestrian, vehicleTypes, allowUnderground, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out startPosA);
            }
            else
            {
                foundStartPos = FindPathPosition(instanceID, ref instanceData, startPos, laneTypes, vehicleTypes, allowUnderground, out startPosA);
            }

            /*
             * start path-finding
             */
            if (foundStartPos &&            // TODO probably fails if vehicle is parked too far away from road
                foundEndPos                 // NON-STOCK CODE
                )
            {
                if (enableTransport)
                {
                    /*
                     * public transport usage is allowed for this path
                     */
                    if ((instanceData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
                    {
                        /*
                         * citizen may use public transport
                         */
                        laneTypes |= NetInfo.LaneType.PublicTransport;

                        uint citizenId = instanceData.m_citizen;
                        if (citizenId != 0u && (citizenManager.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None)
                        {
                            laneTypes |= NetInfo.LaneType.EvacuationTransport;
                        }
                    }
                    else if (Options.prohibitPocketCars)                         // TODO check for incoming connection

                    /*
                     * citizen tried to use public transport but waiting time was too long
                     * -> add public transport demand for source building
                     */
                    {
                        if (instanceData.m_sourceBuilding != 0)
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} cannot uses public transport from building {instanceData.m_sourceBuilding} to {instanceData.m_targetBuilding}. Incrementing public transport demand.");
                            }
#endif
                            ExtBuildingManager.Instance.ExtBuildings[instanceData.m_sourceBuilding].AddPublicTransportDemand((uint)GlobalConfig.Instance.ParkingAI.PublicTransportDemandWaitingIncrement, true);
                        }
                    }
                }

                PathUnit.Position dummyPathPos = default(PathUnit.Position);
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = extPathType;
                args.extVehicleType      = extVehicleType;
                args.vehicleId           = 0;
                args.spawned             = (instanceData.m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None;
                args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = dummyPathPos;
                args.endPosA             = endPosA;
                args.endPosB             = dummyPathPos;
                args.vehiclePosition     = parkedVehiclePathPos;
                args.laneTypes           = laneTypes;
                args.vehicleTypes        = vehicleTypes;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = false;
                args.hasCombustionEngine = combustionEngine;
                args.ignoreBlocked       = false;
                args.ignoreFlooded       = false;
                args.ignoreCosts         = ignoreCost;
                args.randomParking       = randomParking;
                args.stablePath          = false;
                args.skipQueue           = false;

                if ((instanceData.m_flags & CitizenInstance.Flags.OnTour) != 0)
                {
                    args.stablePath = true;
                    args.maxLength  = 160000f;
                    //args.laneTypes &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
                }
                else
                {
                    args.stablePath = false;
                    args.maxLength  = 20000f;
                }

                bool res = CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args);
                // NON-STOCK CODE END

                if (res)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Path-finding starts for citizen instance {instanceID}, path={path}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, laneType={laneTypes}, vehicleType={vehicleTypes}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, vehiclePos.m_segment={parkedVehiclePathPos.m_segment}, vehiclePos.m_lane={parkedVehiclePathPos.m_lane}, vehiclePos.m_offset={parkedVehiclePathPos.m_offset}");
                    }
#endif

                    if (instanceData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(instanceData.m_path);
                    }
                    instanceData.m_path   = path;
                    instanceData.m_flags |= CitizenInstance.Flags.WaitingPath;
                    return(true);
                }
            }

#if DEBUG
            if (Options.prohibitPocketCars)
            {
                if (debug)
                {
                    Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): CustomCitizenAI.CustomStartPathFind: [PFFAIL] failed for citizen instance {instanceID} (CurrentPathMode={extInstance.pathMode}). startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, startPosA.offset={startPosA.m_offset}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}, endPosA.offset={endPosA.m_offset}, foundStartPos={foundStartPos}, foundEndPos={foundEndPos}");
                }
            }
#endif
            return(false);
        }
        public static bool FindPathPositionWithSpiralLoop(Vector3 position, Vector3?secondaryPosition, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleType, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPos)
        {
            PathUnit.Position position2;
            float             distanceSqrA;
            float             distanceSqrB;

            return(FindPathPositionWithSpiralLoop(position, secondaryPosition, service, laneType, vehicleType, VehicleInfo.VehicleType.None, allowUnderground, requireConnect, maxDistance, out pathPos, out position2, out distanceSqrA, out distanceSqrB));
        }
        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[laneId].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);
            var segmentInfo = netManager.m_segments.m_buffer[position.m_segment].Info;

            if (segmentInfo.m_lanes != null && segmentInfo.m_lanes.Length > position.m_lane)
            {
                // NON-STOCK CODE START
                float laneSpeedLimit = 1f;
#if BENCHMARK
                using (var bm = new Benchmark(null, "GetLockFreeGameSpeedLimit")) {
#endif
                if (!Options.customSpeedLimitsEnabled)
                {
                    laneSpeedLimit = segmentInfo.m_lanes[position.m_lane].m_speedLimit;
                }
                else
                {
                    // === START INLINED VERSION OF SpeedLimitManager.GetLockFreeGameSpeedLimit ===
                    ushort?[] fastArray = Flags.laneSpeedLimitArray[position.m_segment];
                    if (fastArray != null && fastArray.Length > position.m_lane && fastArray[position.m_lane] != null)
                    {
                        // === START INLINED VERSION OF SpeedLimitManager.ToGameSpeedLimit ===
                        laneSpeedLimit = (float)fastArray[position.m_lane];
                        if (laneSpeedLimit == 0)
                        {
                            laneSpeedLimit = SpeedLimitManager.MAX_SPEED;
                        }
                        else
                        {
                            laneSpeedLimit = laneSpeedLimit / 50f;
                        }
                        // === END INLINED VERSION OF SpeedLimitManager.ToGameSpeedLimit ===
                        // laneSpeedLimit = ToGameSpeedLimit((ushort)fastArray[position.m_lane]);
                    }
                    else
                    {
                        laneSpeedLimit = segmentInfo.m_lanes[position.m_lane].m_speedLimit;
                    }
                    // === END INLINED VERSION OF SpeedLimitManager.GetLockFreeGameSpeedLimit ===
                    //laneSpeedLimit = SpeedLimitManager.Instance.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, segmentInfo.m_lanes[position.m_lane]); // info2.m_lanes[position.m_lane].m_speedLimit; // NON-STOCK CODE
                }
                //laneSpeedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneId, info.m_lanes[position.m_lane]) : info.m_lanes[position.m_lane].m_speedLimit; // NON-STOCK CODE
#if BENCHMARK
            }
#endif
                // NON-STOCK CODE END
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[laneId].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }

            // NON-STOCK CODE START (stock code replaced)
            bool isRecklessDriver = VehicleStateManager.Instance.VehicleStates[vehicleId].recklessDriver;
#if BENCHMARK
            using (var bm = new Benchmark(null, "CalcMaxSpeed")) {
#endif
            // === START INLINED VERSION OF VehicleBehaviorManager.CalcMaxSpeed ===
            if (Singleton <NetManager> .instance.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 > VehicleBehaviorManager.ICY_ROADS_STUDDED_MIN_SPEED)
                        {
                            maxSpeed = VehicleBehaviorManager.ICY_ROADS_STUDDED_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - VehicleBehaviorManager.ICY_ROADS_STUDDED_MIN_SPEED);
                        }
                    }
                    else
                    {
                        maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[position.m_segment].m_wetness * 0.0005882353f;                                 // vanilla: -15% .. ±0%
                    }
                    districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= DistrictPolicies.CityPlanning.StuddedTires;
                }
                else
                {
                    if (Options.strongerRoadConditionEffects)
                    {
                        if (maxSpeed > VehicleBehaviorManager.ICY_ROADS_MIN_SPEED)
                        {
                            maxSpeed = VehicleBehaviorManager.ICY_ROADS_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - VehicleBehaviorManager.ICY_ROADS_MIN_SPEED);
                        }
                    }
                    else
                    {
                        maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[position.m_segment].m_wetness * 0.00117647066f;                                 // vanilla: -30% .. ±0%
                    }
                }
            }
            else
            {
                if (Options.strongerRoadConditionEffects)
                {
                    float minSpeed = Math.Min(maxSpeed * VehicleBehaviorManager.WET_ROADS_FACTOR, VehicleBehaviorManager.WET_ROADS_MAX_SPEED);                             // custom: -25% .. 0
                    if (maxSpeed > minSpeed)
                    {
                        maxSpeed = minSpeed + (float)(255 - netManager.m_segments.m_buffer[position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - minSpeed);
                    }
                }
                else
                {
                    maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[position.m_segment].m_wetness * 0.0005882353f;                             // vanilla: -15% .. ±0%
                }
            }

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

            // === START INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===
            if (Options.realisticSpeeds)
            {
                // === START INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===
                float vehicleRand = 0.01f * (float)(vehicleId % 100);
                // float vehicleRand = 0.01f * (float)GetVehicleRand(vehicleId);
                // === END INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===
                if (this.m_info.m_isLargeVehicle)
                {
                    maxSpeed *= 0.9f + vehicleRand * 0.1f;                             // a little variance, 0.9 .. 1
                }
                else if (isRecklessDriver)
                {
                    maxSpeed *= 1.3f + vehicleRand * 1.7f;                             // woohooo, 1.3 .. 3
                }
                else
                {
                    maxSpeed *= 0.8f + vehicleRand * 0.5f;                             // a little variance, 0.8 .. 1.3
                }
            }
            else if (isRecklessDriver)
            {
                maxSpeed *= 1.5f;
            }
            // === END INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===

            //maxSpeed = ApplyRealisticSpeeds(maxSpeed, vehicleId, this.m_info, isRecklessDriver);
            maxSpeed = Math.Max(VehicleBehaviorManager.MIN_SPEED, maxSpeed);                     // at least 10 km/h
            // === END INLINED VERSION OF VehicleBehaviorManager.CalcMaxSpeed ===
            //maxSpeed = VehicleBehaviorManager.Instance.CalcMaxSpeed(vehicleId, this.m_info, position, ref netManager.m_segments.m_buffer[position.m_segment], pos, maxSpeed, isRecklessDriver);
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END
        }
Пример #9
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPos, PathUnit.Position endPos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isServiceVehicle)
 {
     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, isServiceVehicle));
 }
Пример #10
0
        public void CustomCalculateSegmentPositionPathFinder(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, uint laneId, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            var netManager = Singleton <NetManager> .instance;

            netManager.m_lanes.m_buffer[(int)((UIntPtr)laneId)].CalculatePositionAndDirection(offset * 0.003921569f,
                                                                                              out pos, out dir);
            var info = netManager.m_segments.m_buffer[position.m_segment].Info;

            if (info.m_lanes != null && info.m_lanes.Length > position.m_lane)
            {
                var laneSpeedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance().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 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;
            ushort targetNodeId;
            ushort nextTargetNodeId;

            if (offset < position.m_offset)
            {
                targetNodeId     = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
                nextTargetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
            }
            else
            {
                targetNodeId     = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
                nextTargetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
            }
            var prevTargetNodeId = prevOffset == 0 ? netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode : netManager.m_segments.m_buffer[prevPos.m_segment].m_endNode;

            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3 lastFrameVehiclePos = lastFrameData.m_position;
            float sqrVelocity           = lastFrameData.m_velocity.sqrMagnitude;

            netManager.m_lanes.m_buffer[laneID].CalculatePositionAndDirection(offset * 0.003921569f, out pos, out dir);

            float braking = this.m_info.m_braking;

            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) != (Vehicle.Flags) 0)
            {
                braking *= 2f;
            }

            // car position on the Bezier curve of the lane
            var vehiclePosOnBezier = netManager.m_lanes.m_buffer[prevLaneID].CalculatePosition(prevOffset * 0.003921569f);
            //ushort currentSegmentId = netManager.m_lanes.m_buffer[prevLaneID].m_segment;

            // this seems to be like the required braking force in order to stop the vehicle within its half length.
            var crazyValue             = 0.5f * sqrVelocity / braking + m_info.m_generatedInfo.m_size.z * 0.5f;
            bool withinBrakingDistance = Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f;

            // NON-STOCK CODE START
#if BENCHMARK
            using (var bm = new Benchmark(null, "UpdateVehiclePosition")) {
#endif
            VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData, lastFrameData.m_velocity.magnitude);
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END

            bool isRecklessDriver = VehicleStateManager.Instance.VehicleStates[vehicleId].recklessDriver;
            if (targetNodeId == prevTargetNodeId && withinBrakingDistance)
            {
                // NON-STOCK CODE START (stock code replaced)
#if BENCHMARK
                using (var bm = new Benchmark(null, "MayChangeSegment")) {
#endif
                //bool isRecklessDriver = VehicleStateManager.Instance.IsRecklessDriver(vehicleId, ref vehicleData); // NON-STOCK CODE

                if (!VehicleBehaviorManager.Instance.MayChangeSegment(vehicleId, ref VehicleStateManager.Instance.VehicleStates[vehicleId], ref vehicleData, sqrVelocity, isRecklessDriver, ref prevPos, ref netManager.m_segments.m_buffer[prevPos.m_segment], prevTargetNodeId, prevLaneID, ref position, targetNodeId, ref netManager.m_nodes.m_buffer[targetNodeId], laneID, ref nextPosition, nextTargetNodeId, out maxSpeed))                         // NON-STOCK CODE
                {
                    return;
                }
#if BENCHMARK
            }
#endif
                // NON-STOCK CODE END
            }

            var segmentInfo = netManager.m_segments.m_buffer[position.m_segment].Info;
            if (segmentInfo.m_lanes != null && segmentInfo.m_lanes.Length > position.m_lane)
            {
                // NON-STOCK CODE START
                // NON-STOCK CODE START
                float laneSpeedLimit = 1f;
#if BENCHMARK
                using (var bm = new Benchmark(null, "GetLockFreeGameSpeedLimit")) {
#endif
                if (!Options.customSpeedLimitsEnabled)
                {
                    laneSpeedLimit = segmentInfo.m_lanes[position.m_lane].m_speedLimit;
                }
                else
                {
                    // === START INLINED VERSION OF SpeedLimitManager.GetLockFreeGameSpeedLimit ===
                    ushort?[] fastArray = Flags.laneSpeedLimitArray[position.m_segment];
                    if (fastArray != null && fastArray.Length > position.m_lane && fastArray[position.m_lane] != null)
                    {
                        // === START INLINED VERSION OF SpeedLimitManager.ToGameSpeedLimit ===
                        laneSpeedLimit = (float)fastArray[position.m_lane];
                        if (laneSpeedLimit == 0)
                        {
                            laneSpeedLimit = SpeedLimitManager.MAX_SPEED;
                        }
                        else
                        {
                            laneSpeedLimit = laneSpeedLimit / 50f;
                        }
                        // === END INLINED VERSION OF SpeedLimitManager.ToGameSpeedLimit ===
                        // laneSpeedLimit = ToGameSpeedLimit((ushort)fastArray[position.m_lane]);
                    }
                    else
                    {
                        laneSpeedLimit = segmentInfo.m_lanes[position.m_lane].m_speedLimit;
                    }
                    // === END INLINED VERSION OF SpeedLimitManager.GetLockFreeGameSpeedLimit ===
                    //laneSpeedLimit = SpeedLimitManager.Instance.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, segmentInfo.m_lanes[position.m_lane]); // info2.m_lanes[position.m_lane].m_speedLimit; // NON-STOCK CODE
                }
#if BENCHMARK
            }
#endif
                // NON-STOCK CODE END
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[laneID].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }

            // NON-STOCK CODE START (stock code replaced)
#if BENCHMARK
            using (var bm = new Benchmark(null, "CalcMaxSpeed")) {
#endif
            // === START INLINED VERSION OF VehicleBehaviorManager.CalcMaxSpeed ===
            if (Singleton <NetManager> .instance.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 > VehicleBehaviorManager.ICY_ROADS_STUDDED_MIN_SPEED)
                        {
                            maxSpeed = VehicleBehaviorManager.ICY_ROADS_STUDDED_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - VehicleBehaviorManager.ICY_ROADS_STUDDED_MIN_SPEED);
                        }
                    }
                    else
                    {
                        maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[position.m_segment].m_wetness * 0.0005882353f;                                 // vanilla: -15% .. ±0%
                    }
                    districtManager.m_districts.m_buffer[(int)district].m_cityPlanningPoliciesEffect |= DistrictPolicies.CityPlanning.StuddedTires;
                }
                else
                {
                    if (Options.strongerRoadConditionEffects)
                    {
                        if (maxSpeed > VehicleBehaviorManager.ICY_ROADS_MIN_SPEED)
                        {
                            maxSpeed = VehicleBehaviorManager.ICY_ROADS_MIN_SPEED + (float)(255 - netManager.m_segments.m_buffer[position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - VehicleBehaviorManager.ICY_ROADS_MIN_SPEED);
                        }
                    }
                    else
                    {
                        maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[position.m_segment].m_wetness * 0.00117647066f;                                 // vanilla: -30% .. ±0%
                    }
                }
            }
            else
            {
                if (Options.strongerRoadConditionEffects)
                {
                    float minSpeed = Math.Min(maxSpeed * VehicleBehaviorManager.WET_ROADS_FACTOR, VehicleBehaviorManager.WET_ROADS_MAX_SPEED);                             // custom: -25% .. 0
                    if (maxSpeed > minSpeed)
                    {
                        maxSpeed = minSpeed + (float)(255 - netManager.m_segments.m_buffer[position.m_segment].m_wetness) * 0.0039215686f * (maxSpeed - minSpeed);
                    }
                }
                else
                {
                    maxSpeed *= 1f - (float)netManager.m_segments.m_buffer[position.m_segment].m_wetness * 0.0005882353f;                             // vanilla: -15% .. ±0%
                }
            }

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

            // === START INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===
            if (Options.realisticSpeeds)
            {
                // === START INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===
                float vehicleRand = 0.01f * (float)(vehicleId % 100);
                // float vehicleRand = 0.01f * (float)GetVehicleRand(vehicleId);
                // === END INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===
                if (this.m_info.m_isLargeVehicle)
                {
                    maxSpeed *= 0.9f + vehicleRand * 0.1f;                             // a little variance, 0.9 .. 1
                }
                else if (isRecklessDriver)
                {
                    maxSpeed *= 1.3f + vehicleRand * 1.7f;                             // woohooo, 1.3 .. 3
                }
                else
                {
                    maxSpeed *= 0.8f + vehicleRand * 0.5f;                             // a little variance, 0.8 .. 1.3
                }
            }
            else if (isRecklessDriver)
            {
                maxSpeed *= 1.5f;
            }
            // === END INLINED VERSION OF VehicleBehaviorManager.ApplyRealisticSpeeds ===

            //maxSpeed = ApplyRealisticSpeeds(maxSpeed, vehicleId, this.m_info, isRecklessDriver);
            maxSpeed = Math.Max(VehicleBehaviorManager.MIN_SPEED, maxSpeed);                     // at least 10 km/h
            // === END INLINED VERSION OF VehicleBehaviorManager.CalcMaxSpeed ===
            //maxSpeed = VehicleBehaviorManager.Instance.CalcMaxSpeed(vehicleId, this.m_info, position, ref netManager.m_segments.m_buffer[position.m_segment], pos, maxSpeed, isRecklessDriver);
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END
        }
Пример #12
0
        internal static float CalcMaxSpeed(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position position, Vector3 pos, float maxSpeed, bool isRecklessDriver)
        {
            var     netManager   = Singleton <NetManager> .instance;
            NetInfo segmentInfo  = netManager.m_segments.m_buffer[(int)position.m_segment].Info;
            bool    highwayRules = (segmentInfo.m_netAI is RoadBaseAI && ((RoadBaseAI)segmentInfo.m_netAI).m_highwayRules);

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

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

            //ExtVehicleType? vehicleType = VehicleStateManager.GetVehicleState(vehicleId)?.VehicleType;
            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 * 0.5f;                 // woohooo, 1.5 .. 2
            }
            else
            {
                maxSpeed *= 0.7f + vehicleRand * 0.6f;                 // a little variance, 0.7 .. 1.3
            }

            /*else if ((vehicleType & ExtVehicleType.PassengerCar) != ExtVehicleType.None)
             *      maxSpeed *= 0.7f + vehicleRand * 0.4f; // a little variance, 0.7 .. 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);
        }
Пример #13
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)
        {
            if ((Options.prioritySignsEnabled || Options.timedLightsEnabled) && Options.simAccuracy <= 1)
            {
                try {
                    VehicleStateManager.Instance().UpdateVehiclePos(vehicleId, ref vehicleData, ref prevPos, ref position);
                } catch (Exception e) {
                    Log.Error("CarAI CustomCalculateSegmentPosition Error: " + e.ToString());
                }
            }

            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);

            Vehicle.Frame lastFrameData       = vehicleData.GetLastFrameData();
            Vector3       lastFrameVehiclePos = lastFrameData.m_position;

            var camPos = Camera.main.transform.position;

#if DEBUG
            //bool isEmergency = VehicleStateManager._GetVehicleState(vehicleId).VehicleType == ExtVehicleType.Emergency;
#endif

            // 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 targetNodeId;
            ushort nextTargetNodeId;
            if (offset < position.m_offset)
            {
                targetNodeId     = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
                nextTargetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
            }
            else
            {
                targetNodeId     = netManager.m_segments.m_buffer[position.m_segment].m_endNode;
                nextTargetNodeId = netManager.m_segments.m_buffer[position.m_segment].m_startNode;
            }
            var prevTargetNodeId = 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;

            /*try {
             *      VehicleStateManager.UpdateVehiclePos(vehicleId, ref vehicleData);
             * } catch (Exception e) {
             *      Log.Error("CarAI TmCalculateSegmentPosition Error: " + e.ToString());
             * }*/

            bool isRecklessDriver = IsRecklessDriver(vehicleId, ref vehicleData);
            if (targetNodeId == prevTargetNodeId)
            {
                if (Vector3.Distance(lastFrameVehiclePos, vehiclePosOnBezier) >= crazyValue - 1f)
                {
                    if (!CustomVehicleAI.MayChangeSegment(vehicleId, ref vehicleData, ref lastFrameData, isRecklessDriver, ref prevPos, prevTargetNodeId, prevLaneID, ref position, targetNodeId, laneID, ref nextPosition, nextTargetNodeId, out maxSpeed))
                    {
                        return;
                    }
                }
            }

            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 = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance().GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info2.m_lanes[position.m_lane]) : info2.m_lanes[position.m_lane].m_speedLimit;                 // 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
                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);
        }
Пример #14
0
        public static bool Prefix(TrolleybusAI __instance,
                                  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)
        {
            NetManager netManager = Singleton <NetManager> .instance;
            ushort     prevSourceNodeId;
            ushort     prevTargetNodeId;

            NetSegment[] segBuffer = netManager.m_segments.m_buffer;

            if (offset < position.m_offset)
            {
                prevSourceNodeId = segBuffer[position.m_segment].m_startNode;
                prevTargetNodeId = segBuffer[position.m_segment].m_endNode;
            }
            else
            {
                prevSourceNodeId = segBuffer[position.m_segment].m_endNode;
                prevTargetNodeId = segBuffer[position.m_segment].m_startNode;
            }

            ushort refTargetNodeId = prevOffset == 0
                                         ? segBuffer[prevPos.m_segment].m_startNode
                                         : segBuffer[prevPos.m_segment].m_endNode;

            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            float         sqrVelocity   = lastFrameData.m_velocity.sqrMagnitude;

            netManager.m_lanes.m_buffer[laneID].CalculatePositionAndDirection(
                Constants.ByteToFloat(offset),
                out pos,
                out dir);
            Vector3 b = netManager.m_lanes.m_buffer[prevLaneID].CalculatePosition(
                Constants.ByteToFloat(prevOffset));
            Vector3 a  = lastFrameData.m_position;
            Vector3 a2 = lastFrameData.m_position;
            Vector3 b2 = lastFrameData.m_rotation * new Vector3(
                0f,
                0f,
                __instance.m_info.m_generatedInfo.m_wheelBase * 0.5f);

            a  += b2;
            a2 -= b2;
            float crazyValue = 0.5f * sqrVelocity / __instance.m_info.m_braking;
            float a3         = Vector3.Distance(a, b);
            float b3         = Vector3.Distance(a2, b);

            if (Mathf.Min(a3, b3) >= crazyValue - 1f)
            {
                if (prevSourceNodeId == refTargetNodeId)
                {
                    if (!VehicleBehaviorManager.Instance.MayChangeSegment(
                            vehicleID,
                            ref vehicleData,
                            sqrVelocity,
                            ref prevPos,
                            ref segBuffer[prevPos.m_segment],
                            refTargetNodeId,
                            prevLaneID,
                            ref position,
                            prevSourceNodeId,
                            ref netManager.m_nodes.m_buffer[
                                prevSourceNodeId],
                            laneID,
                            ref nextPosition,
                            prevTargetNodeId,
                            out maxSpeed))
                    {
                        maxSpeed = 0;
                        return(false);
                    }

                    ExtVehicleManager.Instance.UpdateVehiclePosition(
                        vehicleID,
                        ref vehicleData);
                }
            }

            NetInfo info = segBuffer[position.m_segment].Info;

            VehicleAICommons.CustomCalculateTargetSpeed(
                __instance,
                vehicleID,
                ref vehicleData,
                position,
                laneID,
                info,
                out maxSpeed);
            // NON-STOCK CODE END
            return(false);
        }
Пример #15
0
        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);
        }
Пример #16
0
 public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, bool isServiceVehicle)
 {
     return(this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, isHeavyVehicle, ignoreBlocked, stablePath, skipQueue, isServiceVehicle));
 }
Пример #17
0
        public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            //Log._Debug($"CustomTaxiAI.CustomStartPathFind called for vehicle {vehicleID}");
#endif

            CitizenManager instance            = Singleton <CitizenManager> .instance;
            ushort         passengerInstanceId = CustomTaxiAI.GetPassengerInstance(vehicleID, ref vehicleData);
            if (passengerInstanceId == 0 || (instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None)
            {
                return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget));
            }
            VehicleInfo             info         = this.m_info;
            CitizenInfo             info2        = instance.m_instances.m_buffer[(int)passengerInstanceId].Info;
            NetInfo.LaneType        laneTypes    = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.TransportVehicle;
            VehicleInfo.VehicleType vehicleTypes = this.m_info.m_vehicleType;
            bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            PathUnit.Position startPosA;
            PathUnit.Position startPosB;
            float             startSqrDistA;
            float             startSqrDistB;
            PathUnit.Position endPosA;
            if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startSqrDistA, out startSqrDistB) &&
                info2.m_citizenAI.FindPathPosition(passengerInstanceId, ref instance.m_instances.m_buffer[(int)passengerInstanceId], endPos, laneTypes, vehicleTypes, undergroundTarget, out endPosA))
            {
                if ((instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None)
                {
                    laneTypes |= NetInfo.LaneType.PublicTransport;

                    uint citizenId = instance.m_instances.m_buffer[passengerInstanceId].m_citizen;
                    if (citizenId != 0u && (instance.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None)
                    {
                        laneTypes |= NetInfo.LaneType.EvacuationTransport;
                    }
                }
                if (!startBothWays || startSqrDistA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB = default(PathUnit.Position);
                SimulationManager simMan  = Singleton <SimulationManager> .instance;
                uint path;
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = ExtCitizenInstance.ExtPathType.None;
                args.extVehicleType      = ExtVehicleType.Taxi;
                args.vehicleId           = vehicleID;
                args.buildIndex          = simMan.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = startPosB;
                args.endPosA             = endPosA;
                args.endPosB             = endPosB;
                args.vehiclePosition     = default(PathUnit.Position);
                args.laneTypes           = laneTypes;
                args.vehicleTypes        = vehicleTypes;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = this.IsHeavyVehicle();
                args.hasCombustionEngine = this.CombustionEngine();
                args.ignoreBlocked       = this.IgnoreBlocked(vehicleID, ref vehicleData);
                args.ignoreFlooded       = false;
                args.ignoreCosts         = false;
                args.randomParking       = false;
                args.stablePath          = false;
                args.skipQueue           = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;

                if (CustomPathManager._instance.CreatePath(out path, ref simMan.m_randomizer, args))
                {
                    // NON-STOCK CODE END
                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
Пример #18
0
        public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, bool isServiceVehicle)
        {
            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 (isServiceVehicle)
            {
                PathUnit[] pathUnits = this.m_pathUnits.m_buffer;
                UIntPtr    unitIndex = (UIntPtr)unit;
                pathUnits[(int)unitIndex].m_simulationFlags = (byte)(pathUnits[(int)unitIndex].m_simulationFlags | 8);
            }
            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))
            {
                return(true);
            }
            this.ReleasePath(unit);
            return(false);
        }
Пример #19
0
        public bool CustomFindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position)
        {
            position = default(PathUnit.Position);
            float minDist = 1E+10f;

            PathUnit.Position posA;
            PathUnit.Position posB;
            float             distA;
            float             distB;

            if (PathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, false, Options.prohibitPocketCars ? GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance : 32f, out posA, out posB, out distA, out distB) && distA < minDist)
            {
                minDist  = distA;
                position = posA;
            }
            if (PathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, false, Options.prohibitPocketCars ? GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance : 32f, out posA, out posB, out distA, out distB) && distA < minDist)
            {
                minDist  = distA;
                position = posA;
            }
            if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && PathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, false, Options.prohibitPocketCars ? GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance : 32f, out posA, out posB, out distA, out distB) && distA < minDist)
            {
                minDist  = distA;
                position = posA;
            }
            return(position.m_segment != 0);
        }
        public static void CargoTruckAI_PreChangeVehicleType(out CargoParcel __state, /*ushort vehicleID,*/ ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID)
        {
            Vector3 vector     = NetManager.instance.m_lanes.m_buffer[laneID].CalculatePosition(0.5f);
            NetInfo info       = NetManager.instance.m_segments.m_buffer[pathPos.m_segment].Info;
            ushort  buildingID = BuildingManager.instance.FindBuilding(vector, 100f, info.m_class.m_service, ItemClass.SubService.None, Building.Flags.None, Building.Flags.None);

            __state = new CargoParcel(buildingID, true, vehicleData.m_transferType, vehicleData.m_transferSize, vehicleData.m_flags);
        }
 public static bool FindPathPositionWithSpiralLoop(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleType, VehicleInfo.VehicleType stopType, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB)
 {
     return(FindPathPositionWithSpiralLoop(position, null, service, laneType, vehicleType, stopType, allowUnderground, requireConnect, maxDistance, out pathPosA, out pathPosB, out distanceSqrA, out distanceSqrB));
 }
        /// <summary>
        /// Starts path-finding of the walking path from parking position <paramref name="parkPos"/> to target position <paramref name="targetPos"/>.
        /// </summary>
        /// <param name="parkPos">Parking position</param>
        /// <param name="targetPos">Target position</param>
        /// <returns></returns>
        internal bool CalculateReturnPath(Vector3 parkPos, Vector3 targetPos)
        {
#if DEBUG
            bool citDebug  = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == GetCitizenId();
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && citDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug;
#endif

            ReleaseReturnPath();

            PathUnit.Position parkPathPos;
            PathUnit.Position targetPathPos;
            if (CustomPathManager.FindPathPositionWithSpiralLoop(parkPos, ItemClass.Service.Road, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, NetInfo.LaneType.None, VehicleInfo.VehicleType.None, false, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out parkPathPos) &&
                CustomPathManager.FindPathPositionWithSpiralLoop(targetPos, ItemClass.Service.Road, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, NetInfo.LaneType.None, VehicleInfo.VehicleType.None, false, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out targetPathPos))
            {
                PathUnit.Position dummyPathPos = default(PathUnit.Position);
                uint             pathId;
                PathCreationArgs args;
                args.extPathType         = ExtCitizenInstance.ExtPathType.WalkingOnly;
                args.extVehicleType      = ExtVehicleType.None;
                args.vehicleId           = 0;
                args.buildIndex          = Singleton <SimulationManager> .instance.m_currentBuildIndex;
                args.startPosA           = parkPathPos;
                args.startPosB           = dummyPathPos;
                args.endPosA             = targetPathPos;
                args.endPosB             = dummyPathPos;
                args.vehiclePosition     = dummyPathPos;
                args.laneTypes           = NetInfo.LaneType.Pedestrian;
                args.vehicleTypes        = VehicleInfo.VehicleType.None;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = false;
                args.hasCombustionEngine = false;
                args.ignoreBlocked       = false;
                args.ignoreFlooded       = false;
                args.ignoreCosts         = false;
                args.randomParking       = false;
                args.stablePath          = false;
                args.skipQueue           = false;

                if (CustomPathManager._instance.CreatePath(out pathId, ref Singleton <SimulationManager> .instance.m_randomizer, args))
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"ExtCitizenInstance.CalculateReturnPath: Path-finding starts for return path of citizen instance {instanceId}, path={pathId}, parkPathPos.segment={parkPathPos.m_segment}, parkPathPos.lane={parkPathPos.m_lane}, targetPathPos.segment={targetPathPos.m_segment}, targetPathPos.lane={targetPathPos.m_lane}");
                    }
#endif

                    returnPathId    = pathId;
                    returnPathState = ExtPathState.Calculating;
                    return(true);
                }
            }

#if DEBUG
            if (debug)
            {
                Log._Debug($"ExtCitizenInstance.CalculateReturnPath: Could not find path position(s) for either the parking position or target position of citizen instance {instanceId}.");
            }
#endif

            return(false);
        }
        public bool ExtStartPathFind(ushort vehicleID, ref Vehicle vehicleData, ushort driverInstanceId, ref ExtCitizenInstance driverExtInstance, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget)
        {
#if DEBUG
            bool citDebug  = GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == driverExtInstance.GetCitizenId();
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && citDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug;

            if (debug)
            {
                Log.Warning($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): called for vehicle {vehicleID}, driverInstanceId={driverInstanceId}, startPos={startPos}, endPos={endPos}, sourceBuilding={vehicleData.m_sourceBuilding}, targetBuilding={vehicleData.m_targetBuilding} pathMode={driverExtInstance.pathMode}");
            }
#endif

            PathUnit.Position startPosA = default(PathUnit.Position);
            PathUnit.Position startPosB = default(PathUnit.Position);
            PathUnit.Position endPosA   = default(PathUnit.Position);
            float sqrDistA = 0f;
            float sqrDistB;

            CitizenManager citizenManager = Singleton <CitizenManager> .instance;
            ushort targetBuildingId       = citizenManager.m_instances.m_buffer[(int)driverInstanceId].m_targetBuilding;
            uint driverCitizenId          = citizenManager.m_instances.m_buffer[(int)driverInstanceId].m_citizen;

            // NON-STOCK CODE START
            bool calculateEndPos    = true;
            bool allowRandomParking = true;
            bool movingToParkingPos = false;
            bool foundStartingPos   = false;
            bool skipQueue          = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;
            ExtPathType extPathType = ExtPathType.None;
#if BENCHMARK
            using (var bm = new Benchmark(null, "ParkingAI")) {
#endif
            if (Options.prohibitPocketCars)
            {
                //if (driverExtInstance != null) {
#if DEBUG
                if (debug)
                {
                    Log.Warning($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): PathMode={driverExtInstance.pathMode} for vehicle {vehicleID}, driver citizen instance {driverExtInstance.instanceId}!");
                }
#endif

                if (targetBuildingId != 0 && (Singleton <BuildingManager> .instance.m_buildings.m_buffer[targetBuildingId].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None)
                {
                    // target is outside connection
                    driverExtInstance.pathMode = ExtPathMode.CalculatingCarPathToTarget;
                }
                else
                {
                    if (driverExtInstance.pathMode == ExtPathMode.DrivingToTarget || driverExtInstance.pathMode == ExtPathMode.DrivingToKnownParkPos || driverExtInstance.pathMode == ExtPathMode.ParkingFailed)
                    {
                        skipQueue = true;
                    }

                    bool allowTourists      = false;
                    bool searchAtCurrentPos = false;
                    if (driverExtInstance.pathMode == ExtPathMode.ParkingFailed)
                    {
                        // previous parking attempt failed
                        driverExtInstance.pathMode = ExtPathMode.CalculatingCarPathToAltParkPos;
                        allowTourists      = true;
                        searchAtCurrentPos = true;

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Vehicle {vehicleID} shall move to an alternative parking position! CurrentPathMode={driverExtInstance.pathMode} FailedParkingAttempts={driverExtInstance.failedParkingAttempts}");
                        }
#endif

                        if (driverExtInstance.parkingPathStartPosition != null)
                        {
                            startPosA        = (PathUnit.Position)driverExtInstance.parkingPathStartPosition;
                            foundStartingPos = true;
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Setting starting pos for {vehicleID} to segment={startPosA.m_segment}, laneIndex={startPosA.m_lane}, offset={startPosA.m_offset}");
                            }
#endif
                        }
                        startBothWays = false;

                        if (driverExtInstance.failedParkingAttempts > GlobalConfig.Instance.ParkingAI.MaxParkingAttempts)
                        {
                            // maximum number of parking attempts reached
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Reached maximum number of parking attempts for vehicle {vehicleID}! GIVING UP.");
                            }
#endif
                            driverExtInstance.Reset();

                            // pocket car fallback
                            //vehicleData.m_flags |= Vehicle.Flags.Parking;
                            return(false);
                        }
                        else
                        {
#if DEBUG
                            if (fineDebug)
                            {
                                Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Increased number of parking attempts for vehicle {vehicleID}: {driverExtInstance.failedParkingAttempts}/{GlobalConfig.Instance.ParkingAI.MaxParkingAttempts}");
                            }
#endif
                        }
                    }
                    else
                    {
                        driverExtInstance.pathMode = ExtPathMode.CalculatingCarPathToKnownParkPos;
                    }

                    ushort homeId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[driverCitizenId].m_homeBuilding;
                    bool calcEndPos;
                    Vector3 parkPos;

                    if (AdvancedParkingManager.Instance.FindParkingSpaceForCitizen(searchAtCurrentPos ? vehicleData.GetLastFramePosition() : endPos, vehicleData.Info, ref driverExtInstance, homeId, targetBuildingId == homeId, vehicleID, allowTourists, out parkPos, ref endPosA, out calcEndPos))
                    {
                        calculateEndPos    = calcEndPos;
                        allowRandomParking = false;
                        movingToParkingPos = true;

                        if (!driverExtInstance.CalculateReturnPath(parkPos, endPos))
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Could not calculate return path for citizen instance {driverExtInstance.instanceId}, vehicle {vehicleID}. Resetting instance.");
                            }
#endif
                            driverExtInstance.Reset();
                            return(false);
                        }
                    }
                    else if (driverExtInstance.pathMode == ExtPathMode.CalculatingCarPathToAltParkPos)
                    {
                        // no alternative parking spot found: abort
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): No alternative parking spot found for vehicle {vehicleID}, citizen instance {driverExtInstance.instanceId} with CurrentPathMode={driverExtInstance.pathMode}! GIVING UP.");
                        }
#endif
                        driverExtInstance.Reset();
                        return(false);
                    }
                    else
                    {
                        // calculate a direct path to target
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): No alternative parking spot found for vehicle {vehicleID}, citizen instance {driverExtInstance.instanceId} with CurrentPathMode={driverExtInstance.pathMode}! Setting CurrentPathMode to 'CalculatingCarPath'.");
                        }
#endif
                        driverExtInstance.pathMode = ExtPathMode.CalculatingCarPathToTarget;
                    }
                }

                extPathType = driverExtInstance.GetPathType();

                /*} else {
                 #if DEBUG
                 *      if (debug)
                 *              Log.Warning($"CustomPassengerCarAI.CustomStartPathFind: No driver citizen instance found for vehicle {vehicleID}!");
                 #endif
                 * }*/
            }
#if BENCHMARK
        }
#endif

            NetInfo.LaneType laneTypes = NetInfo.LaneType.Vehicle;
            if (!movingToParkingPos)
            {
                laneTypes |= NetInfo.LaneType.Pedestrian;
            }
            // NON-STOCK CODE END

            VehicleInfo.VehicleType vehicleTypes = this.m_info.m_vehicleType;
            bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0;
            bool randomParking    = false;
            bool combustionEngine = this.m_info.m_class.m_subService == ItemClass.SubService.ResidentialLow;
            if (allowRandomParking &&             // NON-STOCK CODE
                !movingToParkingPos &&
                targetBuildingId != 0 &&
                (
                    Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuildingId].Info.m_class.m_service > ItemClass.Service.Office ||
                    (citizenManager.m_instances.m_buffer[driverInstanceId].m_flags & CitizenInstance.Flags.TargetIsNode) != CitizenInstance.Flags.None
                ))
            {
                randomParking = true;
            }

#if DEBUG
            if (fineDebug)
            {
                Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Requesting path-finding for passenger car {vehicleID}, startPos={startPos}, endPos={endPos}, extPathType={extPathType}");
            }
#endif

            // NON-STOCK CODE START
            if (!foundStartingPos)
            {
                foundStartingPos = CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleTypes, allowUnderground, false, 32f, out startPosA, out startPosB, out sqrDistA, out sqrDistB);
            }

            bool foundEndPos = !calculateEndPos || citizenManager.m_instances.m_buffer[(int)driverInstanceId].Info.m_citizenAI.FindPathPosition(driverInstanceId, ref citizenManager.m_instances.m_buffer[(int)driverInstanceId], endPos, Options.prohibitPocketCars && (targetBuildingId == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[targetBuildingId].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None) ? NetInfo.LaneType.Pedestrian : (laneTypes | NetInfo.LaneType.Pedestrian), vehicleTypes, undergroundTarget, out endPosA);
            // NON-STOCK CODE END

            if (foundStartingPos &&
                foundEndPos)                   // NON-STOCK CODE

            {
                if (!startBothWays || sqrDistA < 10f)
                {
                    startPosB = default(PathUnit.Position);
                }
                PathUnit.Position endPosB = default(PathUnit.Position);
                SimulationManager simMan  = Singleton <SimulationManager> .instance;
                uint path;
                PathUnit.Position dummyPathPos = default(PathUnit.Position);
                // NON-STOCK CODE START
                PathCreationArgs args;
                args.extPathType         = extPathType;
                args.extVehicleType      = ExtVehicleType.PassengerCar;
                args.vehicleId           = vehicleID;
                args.spawned             = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;
                args.buildIndex          = simMan.m_currentBuildIndex;
                args.startPosA           = startPosA;
                args.startPosB           = startPosB;
                args.endPosA             = endPosA;
                args.endPosB             = endPosB;
                args.vehiclePosition     = dummyPathPos;
                args.laneTypes           = laneTypes;
                args.vehicleTypes        = vehicleTypes;
                args.maxLength           = 20000f;
                args.isHeavyVehicle      = this.IsHeavyVehicle();
                args.hasCombustionEngine = this.CombustionEngine();
                args.ignoreBlocked       = this.IgnoreBlocked(vehicleID, ref vehicleData);
                args.ignoreFlooded       = false;
                args.ignoreCosts         = false;
                args.randomParking       = randomParking;
                args.stablePath          = false;
                args.skipQueue           = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0;

                if (CustomPathManager._instance.CreatePath(out path, ref simMan.m_randomizer, args))
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"CustomPassengerCarAI.ExtStartPathFind({vehicleID}): Path-finding starts for passenger car {vehicleID}, path={path}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, laneType={laneTypes}, vehicleType={vehicleTypes}, endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}");
                    }
#endif
                    // NON-STOCK CODE END

                    if (vehicleData.m_path != 0u)
                    {
                        Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path);
                    }
                    vehicleData.m_path   = path;
                    vehicleData.m_flags |= Vehicle.Flags.WaitingPath;
                    return(true);
                }
            }
            return(false);
        }
        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);
        }
Пример #25
0
        // from CitizenAI
        public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, 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, 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, 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, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num)
            {
                position = position6;
            }
            return(position.m_segment != 0);
        }
Пример #26
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)
        {
            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            float sqrVelocity           = lastFrameData.m_velocity.sqrMagnitude;

            // NON-STOCK CODE START
#if BENCHMARK
            using (var bm = new Benchmark(null, "UpdateVehiclePosition")) {
#endif
            VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData, lastFrameData.m_velocity.magnitude);
#if BENCHMARK
        }
#endif
            // NON-STOCK CODE END

            NetManager netManager = Singleton <NetManager> .instance;
            netManager.m_lanes.m_buffer[laneID].CalculatePositionAndDirection((float)offset * 0.003921569f, out pos, out dir);
            Vector3 b  = netManager.m_lanes.m_buffer[prevLaneID].CalculatePosition((float)prevOffset * 0.003921569f);
            Vector3 a  = lastFrameData.m_position;
            Vector3 a2 = lastFrameData.m_position;
            Vector3 b2 = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);
            a  += b2;
            a2 -= b2;
            float crazyValue = 0.5f * sqrVelocity / this.m_info.m_braking;
            float a3         = Vector3.Distance(a, b);
            float b3         = Vector3.Distance(a2, b);
            if (Mathf.Min(a3, b3) >= crazyValue - 1f)
            {
                Segment3 segment;
                segment.a = pos;
                ushort targetNodeId;
                ushort nextTargetNodeId;
                if (offset < position.m_offset)
                {
                    segment.b        = pos + dir.normalized * this.m_info.m_generatedInfo.m_size.z;
                    targetNodeId     = netManager.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                    nextTargetNodeId = netManager.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                }
                else
                {
                    segment.b        = pos - dir.normalized * this.m_info.m_generatedInfo.m_size.z;
                    targetNodeId     = netManager.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                    nextTargetNodeId = netManager.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                }
                ushort prevTargetNodeId;
                if (prevOffset == 0)
                {
                    prevTargetNodeId = netManager.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode;
                }
                else
                {
                    prevTargetNodeId = netManager.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode;
                }
                if (targetNodeId == prevTargetNodeId)
                {
#if BENCHMARK
                    using (var bm = new Benchmark(null, "MayChangeSegment")) {
#endif
                    if (!VehicleBehaviorManager.Instance.MayChangeSegment(vehicleId, ref VehicleStateManager.Instance.VehicleStates[vehicleId], ref vehicleData, sqrVelocity, false, ref prevPos, ref netManager.m_segments.m_buffer[prevPos.m_segment], prevTargetNodeId, prevLaneID, ref position, targetNodeId, ref netManager.m_nodes.m_buffer[targetNodeId], laneID, ref nextPosition, nextTargetNodeId, out maxSpeed))
                    {
                        return;
                    }
#if BENCHMARK
                }
#endif
                }
            }

            NetInfo info = netManager.m_segments.m_buffer[(int)position.m_segment].Info;
            if (info.m_lanes != null && info.m_lanes.Length > (int)position.m_lane)
            {
                float speedLimit = 1;
#if BENCHMARK
                using (var bm = new Benchmark(null, "GetLockFreeGameSpeedLimit")) {
#endif
                speedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]) : info.m_lanes[position.m_lane].m_speedLimit;
#if BENCHMARK
            }
#endif
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, speedLimit, netManager.m_lanes.m_buffer[laneID].m_curve);
            }
            else
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }
        }
Пример #27
0
 public new void CalculateSegmentPosition(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position nextPosition, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
 {
     base.CalculateSegmentPosition(vehicleID, ref vehicleData, nextPosition, position, laneID, offset, prevPos, prevLaneID, prevOffset, out pos, out dir, out maxSpeed);
 }
Пример #28
0
        public void CustomCalculateSegmentPositionPathFinder(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position position, uint laneID, byte offset, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            NetManager instance = Singleton <NetManager> .instance;

            instance.m_lanes.m_buffer[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)
            {
                float speedLimit = 1;
#if BENCHMARK
                using (var bm = new Benchmark(null, "GetLockFreeGameSpeedLimit")) {
#endif
                speedLimit = Options.customSpeedLimitsEnabled ? SpeedLimitManager.Instance.GetLockFreeGameSpeedLimit(position.m_segment, position.m_lane, laneID, info.m_lanes[position.m_lane]) : info.m_lanes[position.m_lane].m_speedLimit;
#if BENCHMARK
            }
#endif
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, speedLimit, instance.m_lanes.m_buffer[laneID].m_curve);
            }
            else
            {
                maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1f, 0f);
            }
        }
Пример #29
0
 public new bool NeedChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID, VehicleInfo.VehicleType laneVehicleType, ref Vector4 target)
 {
     return(base.NeedChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID, laneVehicleType, ref target));
 }
        public void CustomCalculateSegmentPosition(ushort vehicleId, ref Vehicle vehicleData, PathUnit.Position nextPosition,
                                                   PathUnit.Position prevPosition, uint prevLaneId, byte prevOffset, PathUnit.Position refPosition, uint refLaneId,
                                                   byte refOffset, int index, out Vector3 pos, out Vector3 dir, out float maxSpeed)
        {
            var netManager = Singleton <NetManager> .instance;
            ushort prevSourceNodeId;
            ushort prevTargetNodeId;

            if (prevOffset < prevPosition.m_offset)
            {
                prevSourceNodeId = netManager.m_segments.m_buffer[prevPosition.m_segment].m_startNode;
                prevTargetNodeId = netManager.m_segments.m_buffer[prevPosition.m_segment].m_endNode;
            }
            else
            {
                prevSourceNodeId = netManager.m_segments.m_buffer[prevPosition.m_segment].m_endNode;
                prevTargetNodeId = netManager.m_segments.m_buffer[prevPosition.m_segment].m_startNode;
            }

            ushort refTargetNodeId;

            if (refOffset == 0)
            {
                refTargetNodeId = netManager.m_segments.m_buffer[(int)refPosition.m_segment].m_startNode;
            }
            else
            {
                refTargetNodeId = netManager.m_segments.m_buffer[(int)refPosition.m_segment].m_endNode;
            }

#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[21] && (GlobalConfig.Instance.Debug.NodeId <= 0 || refTargetNodeId == GlobalConfig.Instance.Debug.NodeId) && (GlobalConfig.Instance.Debug.ExtVehicleType == ExtVehicleType.None || GlobalConfig.Instance.Debug.ExtVehicleType == ExtVehicleType.RoadVehicle) && (GlobalConfig.Instance.Debug.VehicleId == 0 || GlobalConfig.Instance.Debug.VehicleId == vehicleId);

            if (debug)
            {
                Log._Debug($"CustomCarAI.CustomCalculateSegmentPosition({vehicleId}) called.\n" +
                           $"\trefPosition.m_segment={refPosition.m_segment}, refPosition.m_offset={refPosition.m_offset}\n" +
                           $"\tprevPosition.m_segment={prevPosition.m_segment}, prevPosition.m_offset={prevPosition.m_offset}\n" +
                           $"\tnextPosition.m_segment={nextPosition.m_segment}, nextPosition.m_offset={nextPosition.m_offset}\n" +
                           $"\trefLaneId={refLaneId}, refOffset={refOffset}\n" +
                           $"\tprevLaneId={prevLaneId}, prevOffset={prevOffset}\n" +
                           $"\tprevSourceNodeId={prevSourceNodeId}, prevTargetNodeId={prevTargetNodeId}\n" +
                           $"\trefTargetNodeId={refTargetNodeId}, refTargetNodeId={refTargetNodeId}\n" +
                           $"\tindex={index}");
            }
#endif

            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3 lastFrameVehiclePos = lastFrameData.m_position;
            float sqrVelocity           = lastFrameData.m_velocity.sqrMagnitude;

            netManager.m_lanes.m_buffer[prevLaneId].CalculatePositionAndDirection(prevOffset * 0.003921569f, out pos, out dir);

            float braking = this.m_info.m_braking;
            if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) != (Vehicle.Flags) 0)
            {
                braking *= 2f;
            }

            // car position on the Bezier curve of the lane
            var refVehiclePosOnBezier = netManager.m_lanes.m_buffer[refLaneId].CalculatePosition(refOffset * 0.003921569f);
            //ushort currentSegmentId = netManager.m_lanes.m_buffer[prevLaneID].m_segment;

            // this seems to be like the required braking force in order to stop the vehicle within its half length.
            var crazyValue             = 0.5f * sqrVelocity / braking + m_info.m_generatedInfo.m_size.z * 0.5f;
            bool withinBrakingDistance = Vector3.Distance(lastFrameVehiclePos, refVehiclePosOnBezier) >= crazyValue - 1f;

            if (prevSourceNodeId == refTargetNodeId && withinBrakingDistance)
            {
                // NON-STOCK CODE START (stock code replaced)
#if BENCHMARK
                using (var bm = new Benchmark(null, "MayChangeSegment")) {
#endif
                //bool isRecklessDriver = VehicleStateManager.Instance.IsRecklessDriver(vehicleId, ref vehicleData); // NON-STOCK CODE

                if (!VehicleBehaviorManager.Instance.MayChangeSegment(vehicleId, ref vehicleData, sqrVelocity, ref refPosition, ref netManager.m_segments.m_buffer[refPosition.m_segment], refTargetNodeId, refLaneId, ref prevPosition, prevSourceNodeId, ref netManager.m_nodes.m_buffer[prevSourceNodeId], prevLaneId, ref nextPosition, prevTargetNodeId, out maxSpeed))                   // NON-STOCK CODE
                {
                    return;
                }
                else
                {
#if BENCHMARK
                    using (var bm = new Benchmark(null, "UpdateVehiclePosition")) {
#endif
                    VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData /*, lastFrameData.m_velocity.magnitude*/);
#if BENCHMARK
                }
#endif
                }
#if BENCHMARK
            }
#endif
                // NON-STOCK CODE END
            }

            var segmentInfo = netManager.m_segments.m_buffer[prevPosition.m_segment].Info;
            if (segmentInfo.m_lanes != null && segmentInfo.m_lanes.Length > prevPosition.m_lane)
            {
                // NON-STOCK CODE START
                float laneSpeedLimit = 1f;

                if (!Options.customSpeedLimitsEnabled)
                {
                    laneSpeedLimit = segmentInfo.m_lanes[prevPosition.m_lane].m_speedLimit;
                }
                else
                {
                    laneSpeedLimit = Constants.ManagerFactory.SpeedLimitManager.GetLockFreeGameSpeedLimit(prevPosition.m_segment, prevPosition.m_lane, prevLaneId, segmentInfo.m_lanes[prevPosition.m_lane]);
                }

                // NON-STOCK CODE END
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, laneSpeedLimit, netManager.m_lanes.m_buffer[prevLaneId].m_curve);
            }
            else
            {
                maxSpeed = CalculateTargetSpeed(vehicleId, ref vehicleData, 1f, 0f);
            }

            // NON-STOCK CODE START (stock code replaced)
            maxSpeed = Constants.ManagerFactory.VehicleBehaviorManager.CalcMaxSpeed(vehicleId, ref VehicleStateManager.Instance.VehicleStates[vehicleId], this.m_info, prevPosition, ref netManager.m_segments.m_buffer[prevPosition.m_segment], pos, maxSpeed);
            // NON-STOCK CODE END
        }