예제 #1
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
                        ExtBuildingManager.Instance.ExtBuildings[targetBuildingId].AddParkingSpaceDemand(GlobalConfig.Instance.ParkingAI.FailedParkingSpaceDemandIncrement * (uint)driverExtInstance.failedParkingAttempts);
                    }

                    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);
        }
        public bool IsAtOutsideConnection(ushort instanceId, ref CitizenInstance instanceData, ref ExtCitizenInstance extInstance, Vector3 startPos)
        {
#if DEBUG
            bool citDebug =
                (GlobalConfig.Instance.Debug.CitizenId == 0 || GlobalConfig.Instance.Debug.CitizenId == extInstance.GetCitizenId()) &&
                (GlobalConfig.Instance.Debug.CitizenInstanceId == 0 || GlobalConfig.Instance.Debug.CitizenInstanceId == instanceId) &&
                (GlobalConfig.Instance.Debug.SourceBuildingId == 0 || GlobalConfig.Instance.Debug.SourceBuildingId == Singleton <CitizenManager> .instance.m_instances.m_buffer[extInstance.instanceId].m_sourceBuilding) &&
                (GlobalConfig.Instance.Debug.TargetBuildingId == 0 || GlobalConfig.Instance.Debug.TargetBuildingId == Singleton <CitizenManager> .instance.m_instances.m_buffer[extInstance.instanceId].m_targetBuilding)
            ;
            bool debug     = GlobalConfig.Instance.Debug.Switches[2] && citDebug;
            bool fineDebug = GlobalConfig.Instance.Debug.Switches[4] && citDebug;

            if (debug)
            {
                Log._Debug($"ExtCitizenInstanceManager.IsAtOutsideConnection({extInstance.instanceId}): called. Path: {instanceData.m_path} sourceBuilding={instanceData.m_sourceBuilding}");
            }
#endif

            bool ret =
                (Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_sourceBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None &&
                (startPos - Singleton <BuildingManager> .instance.m_buildings.m_buffer[instanceData.m_sourceBuilding].m_position).magnitude <= GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance;

#if DEBUG
            if (debug)
            {
                Log._Debug($"ExtCitizenInstanceManager.IsAtOutsideConnection({instanceId}): ret={ret}");
            }
#endif
            return(ret);
        }
예제 #3
0
        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;
                    if (driverExtInstance.pathMode == ExtPathMode.ParkingFailed)
                    {
                        // previous parking attempt failed
                        driverExtInstance.pathMode = ExtPathMode.CalculatingCarPathToAltParkPos;
                        allowTourists = 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(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.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);
        }
예제 #4
0
        /// <summary>
        /// Finds a free parking space in the vicinity of the given target position <paramref name="endPos"/> for the given citizen instance <paramref name="extDriverInstance"/>.
        /// </summary>
        /// <param name="endPos">target position</param>
        /// <param name="vehicleInfo">vehicle type that is being used</param>
        /// <param name="extDriverInstance">cititzen instance that is driving the car</param>
        /// <param name="homeId">Home building of the citizen (may be 0 for tourists/homeless cims)</param>
        /// <param name="vehicleId">Vehicle that is being used (used for logging)</param>
        /// <param name="allowTourists">If true, method fails if given citizen is a tourist (TODO remove this parameter)</param>
        /// <param name="parkPos">parking position (output)</param>
        /// <param name="endPathPos">sidewalk path position near parking space (output). only valid if <paramref name="calculateEndPos"/> yields false.</param>
        /// <param name="calculateEndPos">if false, a parking space path position could be calculated (TODO negate & rename parameter)</param>
        /// <returns>true if a parking space could be found, false otherwise</returns>
        public static bool FindParkingSpaceForExtInstance(Vector3 endPos, VehicleInfo vehicleInfo, ExtCitizenInstance extDriverInstance, ushort homeId, ushort vehicleId, bool allowTourists, out Vector3 parkPos, ref PathUnit.Position endPathPos, out bool calculateEndPos)
        {
            calculateEndPos = true;
            parkPos         = default(Vector3);

            if (!allowTourists)
            {
                // TODO remove this from this method
                uint citizenId = extDriverInstance.GetCitizenId();
                if (citizenId == 0 ||
                    (Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Tourist) != Citizen.Flags.None)
                {
                    return(false);
                }
            }

#if DEBUG
            if (GlobalConfig.Instance.DebugSwitches[4])
            {
                Log._Debug($"Citizen instance {extDriverInstance.InstanceId} (CurrentPathMode={extDriverInstance.PathMode}) can still use their passenger car and is either not a tourist or wants to find an alternative parking spot. Finding a parking space before starting path-finding.");
            }
#endif

            ExtParkingSpaceLocation knownParkingSpaceLocation;
            ushort     knownParkingSpaceLocationId;
            Quaternion parkRot;
            float      parkOffset;

            // find a free parking space
            bool success = CustomPassengerCarAI.FindParkingSpaceInVicinity(endPos, vehicleInfo, homeId, vehicleId, out knownParkingSpaceLocation, out knownParkingSpaceLocationId, out parkPos, out parkRot, out parkOffset);

            extDriverInstance.ParkingSpaceLocation   = knownParkingSpaceLocation;
            extDriverInstance.ParkingSpaceLocationId = knownParkingSpaceLocationId;

            if (success)
            {
#if DEBUG
                if (GlobalConfig.Instance.DebugSwitches[4])
                {
                    Log._Debug($"Found a parking spot for citizen instance {extDriverInstance.InstanceId} (CurrentPathMode={extDriverInstance.PathMode}) before starting car path: {knownParkingSpaceLocation} @ {knownParkingSpaceLocationId}");
                }
#endif

                if (knownParkingSpaceLocation == ExtParkingSpaceLocation.RoadSide)
                {
                    // found segment with parking space
                    Vector3 pedPos;
                    uint    laneId;
                    int     laneIndex;
                    float   laneOffset;

#if DEBUG
                    if (GlobalConfig.Instance.DebugSwitches[2])
                    {
                        Log._Debug($"Found segment {knownParkingSpaceLocationId} for road-side parking position for citizen instance {extDriverInstance.InstanceId}!");
                    }
#endif

                    // determine nearest sidewalk position for parking position at segment
                    if (Singleton <NetManager> .instance.m_segments.m_buffer[knownParkingSpaceLocationId].GetClosestLanePosition(parkPos, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, out pedPos, out laneId, out laneIndex, out laneOffset))
                    {
                        endPathPos.m_segment = knownParkingSpaceLocationId;
                        endPathPos.m_lane    = (byte)laneIndex;
                        endPathPos.m_offset  = (byte)(parkOffset * 255f);
                        calculateEndPos      = false;

                        //extDriverInstance.CurrentPathMode = successMode;// ExtCitizenInstance.PathMode.CalculatingKnownCarPath;
#if DEBUG
                        if (GlobalConfig.Instance.DebugSwitches[2])
                        {
                            Log._Debug($"Found an parking spot sidewalk position for citizen instance {extDriverInstance.InstanceId} @ segment {knownParkingSpaceLocationId}, laneId {laneId}, laneIndex {laneIndex}, offset={endPathPos.m_offset}! CurrentPathMode={extDriverInstance.PathMode}");
                        }
#endif
                        return(true);
                    }
                    else
                    {
#if DEBUG
                        if (GlobalConfig.Instance.DebugSwitches[2])
                        {
                            Log._Debug($"Could not find an alternative parking spot sidewalk position for citizen instance {extDriverInstance.InstanceId}! CurrentPathMode={extDriverInstance.PathMode}");
                        }
#endif
                        return(false);
                    }
                }
                else if (knownParkingSpaceLocation == ExtParkingSpaceLocation.Building)
                {
                    // found a building with parking space
                    if (CustomPathManager.FindPathPositionWithSpiralLoop(parkPos, endPos, ItemClass.Service.Road, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, false, false, GlobalConfig.Instance.MaxBuildingToPedestrianLaneDistance, out endPathPos))
                    {
                        calculateEndPos = false;
                    }

                    //endPos = parkPos;

                    //extDriverInstance.CurrentPathMode = successMode;// ExtCitizenInstance.PathMode.CalculatingKnownCarPath;
#if DEBUG
                    if (GlobalConfig.Instance.DebugSwitches[2])
                    {
                        Log._Debug($"Navigating citizen instance {extDriverInstance.InstanceId} to parking building {knownParkingSpaceLocationId}! segment={endPathPos.m_segment}, laneIndex={endPathPos.m_lane}, offset={endPathPos.m_offset}. CurrentPathMode={extDriverInstance.PathMode} calculateEndPos={calculateEndPos}");
                    }
#endif
                    return(true);
                }
            }
            return(false);
        }