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