public void CustomUpdateParkedVehicle(ushort parkedId, ref VehicleParked data) { float x = this.m_info.m_generatedInfo.m_size.x; float z = this.m_info.m_generatedInfo.m_size.z; uint ownerCitizenId = data.m_ownerCitizen; ushort homeID = 0; if (ownerCitizenId != 0u) { homeID = Singleton <CitizenManager> .instance.m_citizens.m_buffer[ownerCitizenId].m_homeBuilding; } ExtParkingSpaceLocation parkingSpaceLocation; ushort parkingSpaceLocationId; Vector3 parkPos; Quaternion parkRot; float parkOffset; if (AdvancedParkingManager.Instance.FindParkingSpaceInVicinity(data.m_position, data.Info, homeID, 0, GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding, out parkingSpaceLocation, out parkingSpaceLocationId, out parkPos, out parkRot, out parkOffset)) { Singleton <VehicleManager> .instance.RemoveFromGrid(parkedId, ref data); data.m_position = parkPos; data.m_rotation = parkRot; Singleton <VehicleManager> .instance.AddToGrid(parkedId, ref data); } else { Singleton <VehicleManager> .instance.ReleaseParkedVehicle(parkedId); } }
private static ushort CheckOverlap(ushort ignoreParked, ref Bezier3 bezier, Vector3 pos, Vector3 dir, float offset, float length, ushort otherID, ref VehicleParked otherData, ref bool overlap, ref float minPos, ref float maxPos) { if (otherID != ignoreParked) { VehicleInfo info = otherData.Info; Vector3 otherPos = otherData.m_position; Vector3 diff = otherPos - pos; float carLength = info.m_generatedInfo.m_size.z; float lengthAvr = (length + carLength) * 0.5f + 1f; float diffLength = diff.magnitude; if (diffLength < lengthAvr - 0.5f) { overlap = true; float l1; float l2; if (Vector3.Dot(diff, dir) >= 0f) { l1 = lengthAvr + diffLength; l2 = lengthAvr - diffLength; } else { l1 = lengthAvr - diffLength; l2 = lengthAvr + diffLength; } maxPos = Mathf.Max(maxPos, bezier.Travel(offset, l1)); minPos = Mathf.Min(minPos, bezier.Travel(offset, -l2)); } } return(otherData.m_nextGridParked); }
public static IEnumerator RemoveAllUnwantedVehicles(ThreadBase t) { ushort vehId = 1; while (vehId < Singleton <VehicleManager> .instance.m_vehicles.m_size) { Vehicle vehicle = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehId]; VehicleInfo vehicleInfo = vehicle.Info; if (vehicleInfo != null && !VehicleUtils.IsTrailer(vehicleInfo) && vehicle.m_transportLine == 0) { uint citizenOwner = vehicle.Info.m_vehicleAI.GetOwnerID(vehId, ref vehicle).Citizen; if (citizenOwner > 0) { var ownerWealth = CitizenWealthDefinition.from(CitizenManager.instance.m_citizens.m_buffer[citizenOwner].WealthLevel); if (ownerWealth != null) { var ext = ownerWealth.GetVehicleExtension(); if (!ext.IsModelCompatible(vehicleInfo)) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehId); } } } } if (vehId % 256 == 255) { yield return(vehId); } vehId++; } vehId = 1; while (vehId < Singleton <VehicleManager> .instance.m_parkedVehicles.m_size) { VehicleParked vehicle = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[vehId]; VehicleInfo vehicleInfo = vehicle.Info; if (vehicleInfo != null && !VehicleUtils.IsTrailer(vehicleInfo)) { uint citizenOwner = vehicle.m_ownerCitizen; if (citizenOwner > 0) { var ownerWealth = CitizenWealthDefinition.from(CitizenManager.instance.m_citizens.m_buffer[citizenOwner].WealthLevel); if (ownerWealth != null) { if (!ownerWealth.GetVehicleExtension().IsModelCompatible(vehicleInfo)) { Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[vehId].Info = ownerWealth.GetVehicleExtension().GetAModel(); } } } } if (vehId % 256 == 255) { yield return(vehId); } vehId++; } yield break; }
public override string GetLocalizedStatus( ushort parkedVehicleID, ref VehicleParked data, out InstanceID target) { target = InstanceID.Empty; return(ColossalFramework.Globalization.Locale.Get("VEHICLE_STATUS_CARGOSHIP_LOADING")); }
private void clickGoToParkedVehicle(UIComponent component, UIMouseEventParameter eventParam) { ushort parkedVehicleId = Convert.ToUInt16(_goToField.text); VehicleParked parkedVehicle = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId]; if ((parkedVehicle.m_flags & (ushort)VehicleParked.Flags.Created) != 0) { CSUtil.CameraControl.CameraController.Instance.GoToParkedVehicle(parkedVehicleId); } }
private void clickGoToParkedVehicle(UIComponent component, UIMouseEventParameter eventParam) { ushort parkedVehicleId = Convert.ToUInt16(_goToField.text); VehicleParked parkedVehicle = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId]; if ((parkedVehicle.m_flags & (ushort)VehicleParked.Flags.Created) != 0) { CameraCtrl.GoToParkedVehicle(parkedVehicleId, new Vector3(parkedVehicle.m_position.x, Camera.main.transform.position.y, parkedVehicle.m_position.z)); } }
public static bool PreGetColorParked(ushort parkedVehicleID, ref VehicleParked data, InfoManager.InfoMode infoMode, ref Color __result) { if (infoMode != InfoManager.InfoMode.None) { LogUtils.DoLog($"NOT GETTING COLOR FOR VEHICLE: {parkedVehicleID} INFO = {infoMode}"); return(true); } if (!m_colorConfigData.TryGetValue(data.Info.name, out ColorConfigurationXml itemData) && !m_colorConfigData.TryGetValue(data.Info.m_vehicleAI.GetType().Name, out itemData) && !m_colorConfigData.TryGetValue("*", out itemData)) { LogUtils.DoLog($"NOT GETTING COLOR FOR VEHICLE: {parkedVehicleID} ({data.Info.m_vehicleAI.GetType().Name} | {data.Info.name}) - not found"); return(true); } LogUtils.DoLog($"GETTING COLOR FOR VEHICLE: {parkedVehicleID} ({data.Info.m_vehicleAI.GetType().Name} | {data.Info.name}) "); return(GetNewColor(parkedVehicleID, ref __result, itemData)); }
public void CustomUpdateParkedVehicle(ushort parkedId, ref VehicleParked data) { float x = this.m_info.m_generatedInfo.m_size.x; float z = this.m_info.m_generatedInfo.m_size.z; uint ownerCitizenId = data.m_ownerCitizen; ushort homeID = 0; if (ownerCitizenId != 0u) { homeID = Singleton <CitizenManager> .instance.m_citizens.m_buffer[ownerCitizenId].m_homeBuilding; } // NON-STOCK CODE START if (!AdvancedParkingManager.Instance.TryMoveParkedVehicle(parkedId, ref data, data.m_position, GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding, homeID)) { Singleton <VehicleManager> .instance.ReleaseParkedVehicle(parkedId); } // NON-STOCK CODE END }
public static bool Prefix(ushort parkedID, ref VehicleParked parkedData) { uint ownerCitizenId = parkedData.m_ownerCitizen; ushort homeId = 0; if (ownerCitizenId != 0u) { homeId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[ownerCitizenId].m_homeBuilding; } // NON-STOCK CODE START if (!AdvancedParkingManager.Instance.TryMoveParkedVehicle( parkedID, ref parkedData, parkedData.m_position, GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding, homeId)) { Singleton <VehicleManager> .instance.ReleaseParkedVehicle(parkedID); } // NON-STOCK CODE STOP return(false); }
public void ProcessParkedVehicle(ushort parkedVehicleId, ref VehicleParked parkedVehicle, ParkedVehicleHandler handler) { handler(parkedVehicleId, ref parkedVehicle); }
private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref VehicleParked otherData, ref Vector3 pushAmount, ref float pushDivider) { VehicleInfo info = otherData.Info; Vector3 position = otherData.m_position; Vector3 b = otherData.m_rotation * new Vector3 (0f, 0f, Mathf.Max (0.5f, info.m_generatedInfo.m_size.z * 0.5f - 1f)); Segment3 segment2; segment2.a = position - b; segment2.b = position + b; Vector3 vector = segment2.Min (); vector.x -= 1f; vector.z -= 1f; Vector3 vector2 = segment2.Max (); vector2.x += 1f; vector2.y += 1f; vector2.z += 1f; if (min.x < vector2.x && max.x > vector.x && min.z < vector2.z && max.z > vector.z && min.y < vector2.y && max.y > vector.y) { float num = this.m_info.m_radius + 1f; float num3; float t; float num2 = segment.DistanceSqr (segment2, out num3, out t); if (num2 < num * num) { float num4 = num - Mathf.Sqrt (num2); float num5 = 1f - num2 / (num * num); Vector3 a = segment.Position (num3 * 0.9f); Vector3 b2 = segment2.Position (t); a.y = 0f; b2.y = 0f; Vector3 vector3 = Vector3.Normalize (a - b2); Vector3 rhs = Vector3.Normalize (new Vector3 (segment.b.x - segment.a.x, 0f, segment.b.z - segment.a.z)); Vector3 vector4 = new Vector3 (rhs.z, 0f, -rhs.x) * Mathf.Abs (Vector3.Dot (vector3, rhs) * 0.5f); if (Vector3.Dot (vector3, vector4) >= 0f) { vector3 += vector4; } else { vector3 -= vector4; } pushAmount += vector3 * (num4 * num5); pushDivider += num5; } } return otherData.m_nextGridParked; }
public bool ExtStartPathFind(ushort instanceID, ref CitizenInstance citizenData, ref ExtCitizenInstance extInstance, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log.Warning($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID}, citizen {citizenData.m_citizen}, startPos={startPos}, endPos={endPos}, sourceBuilding={citizenData.m_sourceBuilding}, targetBuilding={citizenData.m_targetBuilding}, pathMode={extInstance.pathMode}"); } #endif // NON-STOCK CODE START ExtVehicleType extVehicleType = ExtVehicleType.None; ushort parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle; //bool mayUseOwnPassengerCar = true; // allowed to use a passenger car? bool canUseOwnPassengerCar = false; // allowed to use a passenger car AND given vehicle type is a passenger car? CarUsagePolicy carUsageMode = CarUsagePolicy.Allowed; //bool forceUseCar = false; #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 DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'CalculatingWalkingPathToParkedCar'."); } #endif extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToParkedCar; break; case ExtPathMode.RequiresWalkingPathToTarget: case ExtPathMode.CalculatingWalkingPathToTarget: case ExtPathMode.WalkingToTarget: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'CalculatingWalkingPathToTarget'."); } #endif extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget; break; case ExtPathMode.RequiresCarPath: case ExtPathMode.DrivingToTarget: case ExtPathMode.DrivingToKnownParkPos: case ExtPathMode.DrivingToAltParkPos: case ExtPathMode.CalculatingCarPathToAltParkPos: case ExtPathMode.CalculatingCarPathToKnownParkPos: case ExtPathMode.CalculatingCarPathToTarget: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'RequiresCarPath'."); } #endif extInstance.pathMode = ExtPathMode.RequiresCarPath; break; default: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} has CurrentPathMode={extInstance.pathMode}. Change to 'None'."); } #endif extInstance.Reset(); break; } // pathMode is now either CalculatingWalkingPathToParkedCar, CalculatingWalkingPathToTarget, RequiresCarPath or None. if (parkedVehicleId != 0 && extInstance.pathMode != ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToTarget) { // Reuse parked vehicle info VehicleParked vehicleParked = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId]; vehicleInfo = vehicleParked.Info; // Does citizen need to move their car if (extInstance.pathMode != ExtCitizenInstance.ExtPathMode.RequiresCarPath) { // Citizen may use their car if they want to carUsageMode = CarUsagePolicy.Allowed; // Is citizen going home ushort homeId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_homeBuilding; if (homeId != 0 && citizenData.m_targetBuilding == homeId) { // Check distance between home and parked car. If too far away: force citizen to take their car back home float distHomeToParked = (vehicleParked.m_position - Singleton <BuildingManager> .instance.m_buildings.m_buffer[homeId].m_position).magnitude; if (distHomeToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToHome) { // Force citizen to go to car first, using public transport if required extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar; #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} will try to go to parkedVehicleId={parkedVehicleId}. distHomeToParked={distHomeToParked}"); } #endif } // Don't force citizen to use their car if they are at home } else if (homeId == 0 || citizenData.m_sourceBuilding != homeId) { // Check if citizen parked their car nearby BuildingManager buildingManager = Singleton <BuildingManager> .instance; float distSourceToParked = (vehicleParked.m_position - buildingManager.m_buildings.m_buffer[citizenData.m_sourceBuilding].m_position).magnitude; if (distSourceToParked <= GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding) { // Check if target is far enough away to drive to float distTargetToParked = (vehicleParked.m_position - buildingManager.m_buildings.m_buffer[citizenData.m_targetBuilding].m_position).magnitude; if (distTargetToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToBuilding) { // Make sure car isn't parked near home float distHomeToParked = 0.0f; if (homeId != 0) { distHomeToParked = (vehicleParked.m_position - buildingManager.m_buildings.m_buffer[homeId].m_position).magnitude; } if (homeId == 0 || distHomeToParked > GlobalConfig.Instance.ParkingAI.MaxParkedCarDistanceToHome) { // Force citizen to go to car first, using public transport if required extInstance.pathMode = ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar; #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} will try to go to parkedVehicleId={parkedVehicleId}. distSourceToParked={distSourceToParked}, distTargetToParked={distTargetToParked}, distHomeToParked={distHomeToParked}"); } #endif } } } } } else { // Citizen has reached their car, force them to drive it carUsageMode = CarUsagePolicy.Forced; #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} will try to use parkedVehicleId={parkedVehicleId} to get to target={citizenData.m_targetBuilding}."); } #endif } } if (extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToParkedCar || extInstance.pathMode == ExtPathMode.CalculatingWalkingPathToTarget) { // vehicle must not be used since we need a walking path vehicleInfo = null; carUsageMode = CarUsagePolicy.Forbidden; if (extInstance.pathMode == ExtCitizenInstance.ExtPathMode.CalculatingWalkingPathToParkedCar) { // check if parked car is present if (parkedVehicleId == 0) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} should go to parked car (CurrentPathMode={extInstance.pathMode}) but parked vehicle could not be found. Setting CurrentPathMode='CalculatingWalkingPathToTarget'."); } #endif extInstance.pathMode = ExtPathMode.CalculatingWalkingPathToTarget; } else { endPos = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position; #if DEBUG if (GlobalConfig.Instance.Debug.Switches[4]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} shall go to parked vehicle @ {endPos}"); } #endif } } } } #if BENCHMARK } #endif /*if (Options.parkingRestrictionsEnabled && carUsageMode == CarUsagePolicy.Allowed && parkedVehicleId != 0) { * // force removal of illegaly parked vehicle * PathUnit.Position parkedPathPos; * if (PathManager.FindPathPosition(Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position, ItemClass.Service.Road, NetInfo.LaneType.Parking, VehicleInfo.VehicleType.Car, false, false, 32f, out parkedPathPos)) { * if (! ParkingRestrictionsManager.Instance.IsParkingAllowed(parkedPathPos.m_segment, Singleton<NetManager>.instance.m_segments.m_buffer[parkedPathPos.m_segment].Info.m_lanes[parkedPathPos.m_lane].m_finalDirection)) { * carUsageMode = CarUsagePolicy.Forced; * vehicleInfo = Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info; * } * } * }*/ // NON-STOCK CODE END NetInfo.LaneType laneTypes = NetInfo.LaneType.Pedestrian; VehicleInfo.VehicleType vehicleTypes = VehicleInfo.VehicleType.None; bool randomParking = false; bool combustionEngine = false; if (vehicleInfo != null) { if (vehicleInfo.m_class.m_subService == ItemClass.SubService.PublicTransportTaxi) { if ((citizenData.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.Allowed || carUsageMode == CarUsagePolicy.Forced) { extVehicleType = ExtVehicleType.PassengerCar; laneTypes |= NetInfo.LaneType.Vehicle; vehicleTypes |= vehicleInfo.m_vehicleType; combustionEngine = vehicleInfo.m_class.m_subService == ItemClass.SubService.ResidentialLow; canUseOwnPassengerCar = true; } } else if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { extVehicleType = ExtVehicleType.Bicycle; laneTypes |= NetInfo.LaneType.Vehicle; vehicleTypes |= vehicleInfo.m_vehicleType; if (citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office) { randomParking = true; } } // NON-STOCK CODE END } } NetInfo.LaneType startLaneType = laneTypes; // NON-STOCK CODE START if (Options.prohibitPocketCars) { if (carUsageMode == CarUsagePolicy.Forced && !canUseOwnPassengerCar) { carUsageMode = CarUsagePolicy.Forbidden; } } 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 (canUseOwnPassengerCar) { ushort homeId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_homeBuilding; startLaneType &= ~NetInfo.LaneType.Pedestrian; // force to use the car from the beginning startPos = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position; // force to start from the parked car #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Setting startLaneType={startLaneType}, startPos={startPos} for citizen instance {instanceID}. CurrentDepartureMode={extInstance.pathMode}"); } #endif if (citizenData.m_targetBuilding == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.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 (GlobalConfig.Instance.Debug.Switches[2]) { 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, citizenData.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 (GlobalConfig.Instance.Debug.Switches[2]) { 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 (GlobalConfig.Instance.Debug.Switches[2]) * 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. calculate direct path to target #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { 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; } } else if (extInstance.pathMode == ExtPathMode.RequiresCarPath) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} requires car path but no parked car present. Citizen will need to walk to target."); } #endif extInstance.Reset(); } } } #if BENCHMARK } #endif if (canUseOwnPassengerCar) { if (allowRandomParking && citizenData.m_targetBuilding != 0 && Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office) { randomParking = true; } } // determine path type ExtPathType extPathType = ExtPathType.None; if (Options.prohibitPocketCars) { extPathType = extInstance.GetPathType(); } // NON-STOCK CODE END PathUnit.Position vehiclePosition = default(PathUnit.Position); if (parkedVehicleId != 0 && canUseOwnPassengerCar) { Vector3 position = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].m_position; CustomPathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, out vehiclePosition); } bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None; #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Requesting path-finding for citizen instance {instanceID}, citizen {citizenData.m_citizen}, extVehicleType={extVehicleType}, extPathType={extPathType}, startPos={startPos}, endPos={endPos}, sourceBuilding={citizenData.m_sourceBuilding}, targetBuilding={citizenData.m_targetBuilding} pathMode={extInstance.pathMode}"); } #endif bool foundEndPos = !calculateEndPos || FindPathPosition(instanceID, ref citizenData, endPos, Options.prohibitPocketCars && (citizenData.m_targetBuilding == 0 || (Singleton <BuildingManager> .instance.m_buildings.m_buffer[citizenData.m_targetBuilding].m_flags & Building.Flags.IncomingOutgoing) == Building.Flags.None) ? NetInfo.LaneType.Pedestrian : (laneTypes | NetInfo.LaneType.Pedestrian), 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)) { 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 citizenData, startPos, startLaneType, vehicleTypes, allowUnderground, out startPosA); } if (foundStartPos && // TODO probably fails if vehicle is parked too far away from road foundEndPos // NON-STOCK CODE ) { bool canUseTransport = (citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None; if (canUseTransport) { if (carUsageMode != CarUsagePolicy.Forced) // NON-STOCK CODE { laneTypes |= NetInfo.LaneType.PublicTransport; CitizenManager citizenManager = Singleton <CitizenManager> .instance; uint citizenId = citizenManager.m_instances.m_buffer[instanceID].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 // cim tried to use public transport but waiting time was too long { if (citizenData.m_sourceBuilding != 0) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Citizen instance {instanceID} cannot uses public transport from building {citizenData.m_sourceBuilding} to {citizenData.m_targetBuilding}. Incrementing public transport demand."); } #endif ExtBuildingManager.Instance.ExtBuildings[citizenData.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.buildIndex = Singleton <SimulationManager> .instance.m_currentBuildIndex; args.startPosA = startPosA; args.startPosB = dummyPathPos; args.endPosA = endPosA; args.endPosB = dummyPathPos; args.vehiclePosition = vehiclePosition; args.laneTypes = laneTypes; args.vehicleTypes = vehicleTypes; args.maxLength = 20000f; args.isHeavyVehicle = false; args.hasCombustionEngine = combustionEngine; args.ignoreBlocked = false; args.ignoreFlooded = false; args.randomParking = randomParking; args.stablePath = false; args.skipQueue = false; bool res = CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args); // NON-STOCK CODE END if (res) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCitizenAI.ExtStartPathFind({instanceID}): Path-finding starts for citizen instance {instanceID}, path={path}, extVehicleType={extVehicleType}, 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={vehiclePosition.m_segment}, vehiclePos.m_lane={vehiclePosition.m_lane}, vehiclePos.m_offset={vehiclePosition.m_offset}"); } #endif if (citizenData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(citizenData.m_path); } citizenData.m_path = path; citizenData.m_flags |= CitizenInstance.Flags.WaitingPath; return(true); } } #if DEBUG if (Options.prohibitPocketCars) { if (GlobalConfig.Instance.Debug.Switches[2]) { 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); }
private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref VehicleParked otherData, ref Vector3 pushAmount, ref float pushDivider) { VehicleInfo info = otherData.Info; Vector3 position = otherData.m_position; Vector3 b = otherData.m_rotation * new Vector3(0f, 0f, Mathf.Max(0.5f, info.m_generatedInfo.m_size.z * 0.5f - 1f)); Segment3 segment2; segment2.a = position - b; segment2.b = position + b; Vector3 vector = segment2.Min(); vector.x -= 1f; vector.z -= 1f; Vector3 vector2 = segment2.Max(); vector2.x += 1f; vector2.y += 1f; vector2.z += 1f; if (min.x < vector2.x && max.x > vector.x && min.z < vector2.z && max.z > vector.z && min.y < vector2.y && max.y > vector.y) { float num = this.m_info.m_radius + 1f; float num3; float t; float num2 = segment.DistanceSqr(segment2, out num3, out t); if (num2 < num * num) { float num4 = num - Mathf.Sqrt(num2); float num5 = 1f - num2 / (num * num); Vector3 a = segment.Position(num3 * 0.9f); Vector3 b2 = segment2.Position(t); a.y = 0f; b2.y = 0f; Vector3 vector3 = Vector3.Normalize(a - b2); Vector3 rhs = Vector3.Normalize(new Vector3(segment.b.x - segment.a.x, 0f, segment.b.z - segment.a.z)); Vector3 vector4 = new Vector3(rhs.z, 0f, -rhs.x) * Mathf.Abs(Vector3.Dot(vector3, rhs) * 0.5f); if (Vector3.Dot(vector3, vector4) >= 0f) { vector3 += vector4; } else { vector3 -= vector4; } pushAmount += vector3 * (num4 * num5); pushDivider += num5; } } return(otherData.m_nextGridParked); }