public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, ItemClass.Service vehicleService) { while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT)) { } uint num; try { if (!this.m_pathUnits.CreateItem(out num, ref randomizer)) { unit = 0u; bool result = false; return result; } this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u); } finally { Monitor.Exit(this.m_bufferLock); } unit = num; byte simulationFlags = createSimulationFlag(isHeavyVehicle, ignoreBlocked, stablePath, vehicleService); assignPathProperties(unit, buildIndex, startPosA, startPosB, endPosA, endPosB, vehiclePosition, laneTypes, vehicleTypes, maxLength, simulationFlags); return findShortestPath(unit, skipQueue); }
public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPos, RoadManager.VehicleType vehicleType) { PathUnit.Position position2; float num; float num2; return CustomPathManager.FindPathPosition(position, service, laneType, vehicleTypes, allowUnderground, requireConnect, maxDistance, out pathPos, out position2, out num, out num2, vehicleType); }
protected new bool StartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo) { NetInfo.LaneType laneType = NetInfo.LaneType.Pedestrian; VehicleInfo.VehicleType vehicleType = VehicleInfo.VehicleType.None; bool randomParking = 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) { laneType |= (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle); vehicleType |= vehicleInfo.m_vehicleType; } } } else { laneType |= NetInfo.LaneType.Vehicle; vehicleType |= vehicleInfo.m_vehicleType; if (citizenData.m_targetBuilding != 0 && Singleton<BuildingManager>.instance.m_buildings.m_buffer[(int)citizenData.m_targetBuilding].Info.m_class.m_service > ItemClass.Service.Office) { randomParking = true; } } } PathUnit.Position vehiclePosition = default(PathUnit.Position); ushort parkedVehicle = Singleton<CitizenManager>.instance.m_citizens.m_buffer[(int)((UIntPtr)citizenData.m_citizen)].m_parkedVehicle; if (parkedVehicle != 0) { Vector3 position = Singleton<VehicleManager>.instance.m_parkedVehicles.m_buffer[(int)parkedVehicle].m_position; PathManager.FindPathPosition(position, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, false, false, 32f, out vehiclePosition); } bool allowUnderground = (citizenData.m_flags & (CitizenInstance.Flags.Underground | CitizenInstance.Flags.Transition)) != CitizenInstance.Flags.None; PathUnit.Position startPosA; PathUnit.Position endPosA; if (this.FindPathPosition(instanceID, ref citizenData, startPos, laneType, vehicleType, allowUnderground, out startPosA) && this.FindPathPosition(instanceID, ref citizenData, endPos, laneType, vehicleType, false, out endPosA)) { if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) { laneType |= NetInfo.LaneType.PublicTransport; } PathUnit.Position position2 = default(PathUnit.Position); uint path; if (Singleton<PathManager>.instance.CreatePath(ExtendedVehicleType.PassengerCar, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, position2, endPosA, position2, vehiclePosition, laneType, vehicleType, 20000f, false, false, false, false, randomParking)) { if (citizenData.m_path != 0u) { Singleton<PathManager>.instance.ReleasePath(citizenData.m_path); } citizenData.m_path = path; citizenData.m_flags |= CitizenInstance.Flags.WaitingPath; return true; } } return false; }
void vhs_GetVehicleInfoByVehicleIDCompleted(object sender, GetVehicleInfoByVehicleIDCompletedEventArgs e) { if (e.Result != null) { vinfo = e.Result; } }
// from CitizenAI public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position) { position = default(PathUnit.Position); float num = 1E+10f; PathUnit.Position position2; PathUnit.Position position3; float num2; float num3; if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, 32f, out position2, out position3, out num2, out num3, RoadManager.VehicleType.PassengerCar) && num2 < num) { num = num2; position = position2; } PathUnit.Position position4; PathUnit.Position position5; float num4; float num5; if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, 32f, out position4, out position5, out num4, out num5, RoadManager.VehicleType.PassengerCar) && num4 < num) { num = num4; position = position4; } PathUnit.Position position6; PathUnit.Position position7; float num6; float num7; if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && CustomPathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num) { position = position6; } return position.m_segment != 0; }
public SlowVehicleInfo(VehicleInfo i) { this.i = i; BaseMaxSpeed = i.m_maxSpeed; BaseLeanMultiplier = i.m_leanMultiplier; BaseAcceleration = i.m_acceleration; BaseBraking = i.m_braking; BaseTurning = i.m_turning; }
public List<HashSet<ushort>> GetMapping(VehicleInfo vehicle) { int prefabID = vehicle.m_prefabDataIndex; if (!_mapping.PrefabMapped(prefabID)) CategorizePrefab(vehicle); return _mapping.GetMapping(prefabID); }
public static float RestrictSpeed(float calculatedSpeed, uint laneId, VehicleInfo info) { if (calculatedSpeed == 0f || (CSLTraffic.Options & OptionsManager.ModOptions.BetaTestRoadCustomizerTool) == OptionsManager.ModOptions.None) return calculatedSpeed; float speedLimit = RoadManager.GetLaneSpeed(laneId); float curve = NetManager.instance.m_lanes.m_buffer[laneId].m_curve; float a = 1000f / (1f + curve * 1000f / info.m_turning) + 2f; float b = 8f * speedLimit; return Mathf.Min(Mathf.Min(a, b), info.m_maxSpeed); }
private void CategorizePrefab(VehicleInfo vehicle) { VehicleAI ai = vehicle.m_vehicleAI; int prefabID = vehicle.m_prefabDataIndex; _mapping.AddMapping(prefabID, _data._Vehicles); if (ai is CarTrailerAI) return; else if (ai is CarAI) { _mapping.AddMapping(prefabID, _data._Cars); if (ai is HearseAI) _mapping.AddMapping(prefabID, _data._Hearses); else if (ai is GarbageTruckAI) _mapping.AddMapping(prefabID, _data._GarbageTrucks); else if (ai is FireTruckAI) _mapping.AddMapping(prefabID, _data._FireTrucks); else if (ai is PoliceCarAI) _mapping.AddMapping(prefabID, _data._PoliceCars); else if (ai is AmbulanceAI) _mapping.AddMapping(prefabID, _data._Ambulances); else if (ai is BusAI) _mapping.AddMapping(prefabID, _data._Buses); else _mapping.AddMapping(prefabID, _data._CarOther); } else if (ai is TrainAI) { _mapping.AddMapping(prefabID, _data._Trains); if (ai is MetroTrainAI) _mapping.AddMapping(prefabID, _data._MetroTrains); else if (ai is PassengerTrainAI) _mapping.AddMapping(prefabID, _data._PassengerTrains); else if (ai is CargoTrainAI) _mapping.AddMapping(prefabID, _data._CargoTrains); else _mapping.AddMapping(prefabID, _data._TrainOther); } else if (ai is AircraftAI) _mapping.AddMapping(prefabID, _data._Aircraft); else if (ai is ShipAI) _mapping.AddMapping(prefabID, _data._Ships); else _mapping.AddMapping(prefabID, _data._VehicleOther); }
private ushort CheckCollisions(ushort instanceID, ref CitizenInstance citizenData, Segment3 segment, Vector3 min, Vector3 max, ushort otherID, ref Vehicle otherData, ref Vector3 pushAmount, ref float pushDivider) { VehicleInfo info = otherData.Info; if (info.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { return(otherData.m_nextGridVehicle); } if ((otherData.m_flags & Vehicle.Flags.Transition) == Vehicle.Flags.None && (citizenData.m_flags & CitizenInstance.Flags.Transition) == CitizenInstance.Flags.None && (otherData.m_flags & Vehicle.Flags.Underground) != Vehicle.Flags.None != ((citizenData.m_flags & CitizenInstance.Flags.Underground) != CitizenInstance.Flags.None)) { return(otherData.m_nextGridVehicle); } Segment3 segment2 = otherData.m_segment; Vector3 vector = Vector3.Min(segment2.Min(), otherData.m_targetPos1); vector.x -= 1f; vector.z -= 1f; Vector3 vector2 = Vector3.Max(segment2.Max(), otherData.m_targetPos1); 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 b = segment2.Position(t); a.y = 0f; b.y = 0f; Vector3 vector3 = Vector3.Normalize(a - b); 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; } float magnitude = otherData.GetLastFrameVelocity().magnitude; if (magnitude > 0.1f) { float num6 = this.m_info.m_radius + 3f; segment2.a = segment2.b; segment2.b += Vector3.ClampMagnitude(((Vector3)otherData.m_targetPos1) - segment2.b, magnitude * 4f); num2 = segment.DistanceSqr(segment2, out num3, out t); if (num2 > num * num && num2 < num6 * num6) { float num7 = num6 - Mathf.Sqrt(num2); float num8 = 1f - num2 / (num6 * num6); Vector3 a2 = segment.Position(num3 * 0.9f); Vector3 b2 = segment2.Position(t); a2.y = 0f; b2.y = 0f; Vector3 vector5 = a2 - b2; pushAmount += vector5.normalized * (num7 * num8); pushDivider += num8; } } } return(otherData.m_nextGridVehicle); }
public HomePage() { InitializeComponent(); //Get User data from login if (tNetUserLoginData.Contains("UserLoginData")) { mySelectedVehicle = new VehicleInfo(); userData = (DriverLogin)tNetUserLoginData["UserLoginData"]; userId = (string)tNetUserLoginData["UserId"]; pwmd5 = (string)tNetUserLoginData["PasswordMd5"]; mySelectedVehicle = (VehicleInfo)tNetUserLoginData["MySelectedVehicle"]; rawPass = (string)tNetUserLoginData["RawPassword"]; } updateLocationTimer = new DispatcherTimer(); updateLocationTimer.Tick += new EventHandler(updateLocationTimer_Tick); updateLocationTimer.Interval = new TimeSpan(0, 0, 0, 20); //Sau năm dây sẽ chạy cập nhật nếu như lần cập nhật trước không thành công //Tạo kênh Notification CreatePushChannel(); //get First Local Position GetCurrentCorrdinate(); UpdateCurrentLocation(currentLat, currentLng); //Open Status Screen ShowLoadingScreen(); LoadDriverProfile(); UpdateDriverStatus(ConstantVariable.dStatusNotAvailable); //"NA" LoadCityNameDataBase(); TripTrackingOnMap(); //Chuẩn bị cho việc tracking }
public VehicleInfo CustomGetVehicleInfo(ushort instanceID, ref CitizenInstance citizenData, bool forceCar) { if (citizenData.m_citizen == 0u) { return(null); } // NON-STOCK CODE START bool forceTaxi = false; #if BENCHMARK using (var bm = new Benchmark(null, "forceTaxi")) { #endif if (Options.prohibitPocketCars) { if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceID].pathMode == ExtPathMode.TaxiToTarget) { forceTaxi = true; } } #if BENCHMARK } #endif // NON-STOCK CODE END int carProb; int bikeProb; int taxiProb; // NON-STOCK CODE START if (forceTaxi) { carProb = 0; bikeProb = 0; taxiProb = 100; } else // NON-STOCK CODE END if (forceCar || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None) { carProb = 100; bikeProb = 0; taxiProb = 0; } else { carProb = GetCarProbability(); bikeProb = GetBikeProbability(); taxiProb = GetTaxiProbability(); } Randomizer randomizer = new Randomizer(citizenData.m_citizen); bool useCar = randomizer.Int32(100u) < carProb; bool useBike = !useCar && randomizer.Int32(100u) < bikeProb; bool useTaxi = !useCar && !useBike && randomizer.Int32(100u) < taxiProb; bool useElectricCar = false; if (useCar) { int electricProb = GetElectricCarProbability(Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].WealthLevel); useElectricCar = randomizer.Int32(100u) < electricProb; } ItemClass.Service service = ItemClass.Service.Residential; ItemClass.SubService subService = useElectricCar ? ItemClass.SubService.ResidentialLowEco : ItemClass.SubService.ResidentialLow; if (useTaxi) { service = ItemClass.Service.PublicTransport; subService = ItemClass.SubService.PublicTransportTaxi; } // NON-STOCK CODE START VehicleInfo carInfo = null; #if BENCHMARK using (var bm = new Benchmark(null, "find-parked-vehicle")) { #endif if (Options.prohibitPocketCars && useCar && !useTaxi) { ushort parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen].m_parkedVehicle; if (parkedVehicleId != 0) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomTouristAI.CustomGetVehicleInfo({instanceID}): Citizen instance {instanceID} owns a parked vehicle {parkedVehicleId}. Reusing vehicle info."); } #endif carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info; } } #if BENCHMARK } #endif if (carInfo == null && (useCar || useTaxi)) { // NON-STOCK CODE END carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref randomizer, service, subService, ItemClass.Level.Level1); } if (useBike) { VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo(ref randomizer, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, ItemClass.Level.Level2); if (bikeInfo != null) { return(bikeInfo); } } if ((useCar || useTaxi) && carInfo != null) { return(carInfo); } return(null); }
/// <summary> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; // NON-STOCK CODE START ExtPathState mainPathState = ExtPathState.Calculating; if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { mainPathState = ExtPathState.Failed; } else if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { mainPathState = ExtPathState.Ready; } if (Options.prohibitPocketCars && VehicleStateManager.Instance.VehicleStates[vehicleId].vehicleType == ExtVehicleType.PassengerCar) { mainPathState = AdvancedParkingManager.Instance.UpdateCarPathState(vehicleId, ref vehicleData, ref ExtCitizenInstanceManager.Instance.ExtInstances[CustomPassengerCarAI.GetDriverInstanceId(vehicleId, ref vehicleData)], mainPathState); } // NON-STOCK CODE END if (mainPathState == ExtPathState.Ready) { vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); } else if (mainPathState == ExtPathState.Failed) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } // NON-STOCK CODE START VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData); if (!Options.isStockLaneChangerUsed()) { // Advanced AI traffic measurement VehicleStateManager.Instance.LogTraffic(vehicleId); } // NON-STOCK CODE END Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager vehManager = Singleton <VehicleManager> .instance; ushort trailerId = vehicleData.m_trailingVehicle; int numIters = 0; while (trailerId != 0) { ushort trailingVehicle = vehManager.m_vehicles.m_buffer[(int)trailerId].m_trailingVehicle; VehicleInfo info = vehManager.m_vehicles.m_buffer[(int)trailerId].Info; info.m_vehicleAI.SimulationStep(trailerId, ref vehManager.m_vehicles.m_buffer[(int)trailerId], vehicleId, ref vehicleData, lodPhysics); trailerId = trailingVehicle; if (++numIters > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter >= maxBlockCounter && VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData)) // NON-STOCK CODE { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } }
public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPosA, out PathUnit.Position pathPosB, out float distanceSqrA, out float distanceSqrB, RoadManager.VehicleType vehicleType) { Bounds bounds = new Bounds(position, new Vector3(maxDistance * 2f, maxDistance * 2f, maxDistance * 2f)); int num = Mathf.Max((int)((bounds.min.x - 64f) / 64f + 135f), 0); int num2 = Mathf.Max((int)((bounds.min.z - 64f) / 64f + 135f), 0); int num3 = Mathf.Min((int)((bounds.max.x + 64f) / 64f + 135f), 269); int num4 = Mathf.Min((int)((bounds.max.z + 64f) / 64f + 135f), 269); NetManager instance = Singleton<NetManager>.instance; pathPosA.m_segment = 0; pathPosA.m_lane = 0; pathPosA.m_offset = 0; distanceSqrA = 1E+10f; pathPosB.m_segment = 0; pathPosB.m_lane = 0; pathPosB.m_offset = 0; distanceSqrB = 1E+10f; float num5 = maxDistance * maxDistance; for (int i = num2; i <= num4; i++) { for (int j = num; j <= num3; j++) { ushort num6 = instance.m_segmentGrid[i * 270 + j]; int num7 = 0; while (num6 != 0) { NetInfo info = instance.m_segments.m_buffer[(int)num6].Info; if (info.m_class.m_service == service && (instance.m_segments.m_buffer[(int)num6].m_flags & NetSegment.Flags.Flooded) == NetSegment.Flags.None && (allowUnderground || !info.m_netAI.IsUnderground())) { ushort startNode = instance.m_segments.m_buffer[(int)num6].m_startNode; ushort endNode = instance.m_segments.m_buffer[(int)num6].m_endNode; Vector3 position2 = instance.m_nodes.m_buffer[(int)startNode].m_position; Vector3 position3 = instance.m_nodes.m_buffer[(int)endNode].m_position; float num8 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position2.x, bounds.min.z - 64f - position2.z), Mathf.Max(position2.x - bounds.max.x - 64f, position2.z - bounds.max.z - 64f)); float num9 = Mathf.Max(Mathf.Max(bounds.min.x - 64f - position3.x, bounds.min.z - 64f - position3.z), Mathf.Max(position3.x - bounds.max.x - 64f, position3.z - bounds.max.z - 64f)); Vector3 b; int num10; float num11; Vector3 b2; int num12; float num13; if ((num8 < 0f || num9 < 0f) && instance.m_segments.m_buffer[(int)num6].m_bounds.Intersects(bounds) && CustomPathManager.GetClosestLanePosition(instance.m_segments.m_buffer[(int)num6], position, laneType, vehicleTypes, requireConnect, out b, out num10, out num11, out b2, out num12, out num13, vehicleType)) { float num14 = Vector3.SqrMagnitude(position - b); if (num14 < num5) { num5 = num14; pathPosA.m_segment = num6; pathPosA.m_lane = (byte)num10; pathPosA.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num11 * 255f), 0, 255); distanceSqrA = num14; num14 = Vector3.SqrMagnitude(position - b2); if (num12 == -1 || num14 >= maxDistance * maxDistance) { pathPosB.m_segment = 0; pathPosB.m_lane = 0; pathPosB.m_offset = 0; distanceSqrB = 1E+10f; } else { pathPosB.m_segment = num6; pathPosB.m_lane = (byte)num12; pathPosB.m_offset = (byte)Mathf.Clamp(Mathf.RoundToInt(num13 * 255f), 0, 255); distanceSqrB = num14; } } } } num6 = instance.m_segments.m_buffer[(int)num6].m_nextGridSegment; if (++num7 >= 32768) { CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } return pathPosA.m_segment != 0; }
public class CustomTrainAI : TrainAI { // correct would be to inherit from VehicleAI (in order to keep the correct references to `base`) public void TrafficManagerSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { try { if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { this.PathFindReady(vehicleId, ref vehicleData); } else if ((pathFindFlags & 8) != 0 || vehicleData.m_path == 0u) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; vehicleData.Unspawn(vehicleId); return; } } else if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } bool reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0; ushort frontVehicleId; if (reversed) { frontVehicleId = vehicleData.GetLastVehicle(vehicleId); } else { frontVehicleId = vehicleId; } /// NON-STOCK CODE START /// try { CustomVehicleAI.HandleVehicle(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId], false, false, 5); } catch (Exception e) { Log.Error("TrainAI TrafficManagerSimulationStep Error: " + e.ToString()); } /// NON-STOCK CODE END /// VehicleManager instance = Singleton <VehicleManager> .instance; VehicleInfo info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info; info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } bool flag2 = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0; if (flag2 != reversed) { reversed = flag2; if (reversed) { frontVehicleId = vehicleData.GetLastVehicle(vehicleId); } else { frontVehicleId = vehicleId; } info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info; info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } flag2 = ((vehicleData.m_flags & Vehicle.Flags.Reversed) != 0); if (flag2 != reversed) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); return; } } if (reversed) { frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_leadingVehicle; int num2 = 0; while (frontVehicleId != 0) { info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info; info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_leadingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } else { frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_trailingVehicle; int num3 = 0; while (frontVehicleId != 0) { info = instance.m_vehicles.m_buffer[(int)frontVehicleId].Info; info.m_vehicleAI.SimulationStep(frontVehicleId, ref instance.m_vehicles.m_buffer[(int)frontVehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } frontVehicleId = instance.m_vehicles.m_buffer[(int)frontVehicleId].m_trailingVehicle; if (++num3 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0 || (vehicleData.m_blockCounter == 255 && Options.enableDespawning)) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } } catch (Exception ex) { Log.Error("Error in TrainAI.SimulationStep: " + ex.ToString()); } }
public void CustomSimulationStep(ushort instanceID, ref CitizenInstance instanceData, Vector3 physicsLodRefPos) { uint citizenId = instanceData.m_citizen; if ((instanceData.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None && (instanceData.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None) { Singleton <CitizenManager> .instance.ReleaseCitizenInstance(instanceID); if (citizenId != 0u) { Singleton <CitizenManager> .instance.ReleaseCitizen(citizenId); } return; } if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags; // NON-STOCK CODE START ExtPathState mainPathState = ExtPathState.Calculating; if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || instanceData.m_path == 0) { mainPathState = ExtPathState.Failed; } else if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { mainPathState = ExtPathState.Ready; } #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path: {instanceData.m_path}, mainPathState={mainPathState}"); } #endif ExtSoftPathState finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState); if (Options.prohibitPocketCars) { finalPathState = AdvancedParkingManager.Instance.UpdateCitizenPathState(instanceID, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], ref Singleton <CitizenManager> .instance.m_citizens.m_buffer[instanceData.m_citizen], mainPathState); #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Applied Parking AI logic. Path: {instanceData.m_path}, mainPathState={mainPathState}, finalPathState={finalPathState}, extCitizenInstance={ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]}"); } #endif } switch (finalPathState) { case ExtSoftPathState.Ready: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding succeeded for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.PathfindSuccess"); } #endif this.Spawn(instanceID, ref instanceData); instanceData.m_pathPositionIndex = 255; instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown); // NON-STOCK CODE START (transferred from ResidentAI.PathfindSuccess) if (citizenId != 0 && (Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenId].m_flags & (Citizen.Flags.Tourist | Citizen.Flags.MovingIn | Citizen.Flags.DummyTraffic)) == Citizen.Flags.MovingIn) { StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.MoveRate); statisticBase.Add(1); } // NON-STOCK CODE END this.PathfindSuccess(instanceID, ref instanceData); break; case ExtSoftPathState.Ignore: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding result shall be ignored for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- ignoring"); } #endif return; case ExtSoftPathState.Calculating: default: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): Path-finding result undetermined for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- continue"); } #endif break; case ExtSoftPathState.FailedHard: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): HARD path-finding failure for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.PathfindFailure"); } #endif instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown); Singleton <PathManager> .instance.ReleasePath(instanceData.m_path); instanceData.m_path = 0u; this.PathfindFailure(instanceID, ref instanceData); return; case ExtSoftPathState.FailedSoft: #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.CustomSimulationStep({instanceID}): SOFT path-finding failure for citizen instance {instanceID} (finalPathState={finalPathState}). Path: {instanceData.m_path} -- calling HumanAI.InvalidPath"); } #endif // path mode has been updated, repeat path-finding instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown); this.InvalidPath(instanceID, ref instanceData); return; } // NON-STOCK CODE END } // NON-STOCK CODE START if (Options.prohibitPocketCars) { if (ExtSimulationStep(instanceID, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], physicsLodRefPos)) { return; } } // NON-STOCK CODE END base.SimulationStep(instanceID, ref instanceData, physicsLodRefPos); CitizenManager citizenManager = Singleton <CitizenManager> .instance; VehicleManager vehicleManager = Singleton <VehicleManager> .instance; ushort vehicleId = 0; if (instanceData.m_citizen != 0u) { vehicleId = citizenManager.m_citizens.m_buffer[instanceData.m_citizen].m_vehicle; } if (vehicleId != 0) { VehicleInfo vehicleInfo = vehicleManager.m_vehicles.m_buffer[(int)vehicleId].Info; if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { vehicleInfo.m_vehicleAI.SimulationStep(vehicleId, ref vehicleManager.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleManager.m_vehicles.m_buffer[(int)vehicleId], 0); vehicleId = 0; } } if (vehicleId == 0 && (instanceData.m_flags & (CitizenInstance.Flags.Character | CitizenInstance.Flags.WaitingPath | CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) == CitizenInstance.Flags.None) { instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown); this.ArriveAtDestination(instanceID, ref instanceData, false); citizenManager.ReleaseCitizenInstance(instanceID); } }
public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, RoadManager.VehicleType vehicleType) { return this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, false, false, false, false, vehicleType); }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { #if DEBUG //Log._Debug($"CustomTaxiAI.CustomStartPathFind called for vehicle {vehicleID}"); #endif #if PATHRECALC VehicleState state = VehicleStateManager._GetVehicleState(vehicleID); bool recalcRequested = state.PathRecalculationRequested; state.PathRecalculationRequested = false; #endif CitizenManager instance = Singleton <CitizenManager> .instance; ushort passengerInstance = CustomTaxiAI.GetPassengerInstance(vehicleID, ref vehicleData); if (passengerInstance == 0 || (instance.m_instances.m_buffer[(int)passengerInstance].m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None) { return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget)); } VehicleInfo info = this.m_info; CitizenInfo info2 = instance.m_instances.m_buffer[(int)passengerInstance].Info; NetInfo.LaneType laneType = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.TransportVehicle; VehicleInfo.VehicleType vehicleType = this.m_info.m_vehicleType; bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0; PathUnit.Position startPosA; PathUnit.Position startPosB; float num; float num2; PathUnit.Position endPosA; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) && info2.m_citizenAI.FindPathPosition(passengerInstance, ref instance.m_instances.m_buffer[(int)passengerInstance], endPos, laneType, vehicleType, undergroundTarget, out endPosA)) { if ((instance.m_instances.m_buffer[(int)passengerInstance].m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) { laneType |= NetInfo.LaneType.PublicTransport; } if (!startBothWays || num < 10f) { startPosB = default(PathUnit.Position); } PathUnit.Position endPosB = default(PathUnit.Position); SimulationManager instance2 = Singleton <SimulationManager> .instance; uint path; if (Singleton <CustomPathManager> .instance.CreatePath( #if PATHRECALC recalcRequested, #endif ExtVehicleType.Taxi, vehicleID, out path, ref instance2.m_randomizer, instance2.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, laneType, vehicleType, 20000f)) { #if USEPATHWAITCOUNTER VehicleState state = VehicleStateManager.Instance()._GetVehicleState(vehicleID); state.PathWaitCounter = 0; #endif 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); }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { #if DEBUG //Log._Debug($"CustomTaxiAI.CustomStartPathFind called for vehicle {vehicleID}"); #endif CitizenManager instance = Singleton <CitizenManager> .instance; ushort passengerInstanceId = CustomTaxiAI.GetPassengerInstance(vehicleID, ref vehicleData); if (passengerInstanceId == 0 || (instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.Character) != CitizenInstance.Flags.None) { return(base.StartPathFind(vehicleID, ref vehicleData, startPos, endPos, startBothWays, endBothWays, undergroundTarget)); } VehicleInfo info = this.m_info; CitizenInfo info2 = instance.m_instances.m_buffer[(int)passengerInstanceId].Info; NetInfo.LaneType laneTypes = NetInfo.LaneType.Vehicle | NetInfo.LaneType.Pedestrian | NetInfo.LaneType.TransportVehicle; VehicleInfo.VehicleType vehicleTypes = this.m_info.m_vehicleType; bool allowUnderground = (vehicleData.m_flags & Vehicle.Flags.Underground) != 0; PathUnit.Position startPosA; PathUnit.Position startPosB; float startSqrDistA; float startSqrDistB; PathUnit.Position endPosA; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startSqrDistA, out startSqrDistB) && info2.m_citizenAI.FindPathPosition(passengerInstanceId, ref instance.m_instances.m_buffer[(int)passengerInstanceId], endPos, laneTypes, vehicleTypes, undergroundTarget, out endPosA)) { if ((instance.m_instances.m_buffer[(int)passengerInstanceId].m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None) { laneTypes |= NetInfo.LaneType.PublicTransport; uint citizenId = instance.m_instances.m_buffer[passengerInstanceId].m_citizen; if (citizenId != 0u && (instance.m_citizens.m_buffer[citizenId].m_flags & Citizen.Flags.Evacuating) != Citizen.Flags.None) { laneTypes |= NetInfo.LaneType.EvacuationTransport; } } if (!startBothWays || startSqrDistA < 10f) { startPosB = default(PathUnit.Position); } PathUnit.Position endPosB = default(PathUnit.Position); SimulationManager simMan = Singleton <SimulationManager> .instance; uint path; // NON-STOCK CODE START PathCreationArgs args; args.extPathType = ExtCitizenInstance.ExtPathType.None; args.extVehicleType = ExtVehicleType.Taxi; args.vehicleId = vehicleID; args.spawned = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; args.buildIndex = simMan.m_currentBuildIndex; args.startPosA = startPosA; args.startPosB = startPosB; args.endPosA = endPosA; args.endPosB = endPosB; args.vehiclePosition = default(PathUnit.Position); args.laneTypes = laneTypes; args.vehicleTypes = vehicleTypes; args.maxLength = 20000f; args.isHeavyVehicle = this.IsHeavyVehicle(); args.hasCombustionEngine = this.CombustionEngine(); args.ignoreBlocked = this.IgnoreBlocked(vehicleID, ref vehicleData); args.ignoreFlooded = false; args.ignoreCosts = false; args.randomParking = false; args.stablePath = false; args.skipQueue = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; if (CustomPathManager._instance.CreatePath(out path, ref simMan.m_randomizer, args)) { // NON-STOCK CODE END if (vehicleData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); } vehicleData.m_path = path; vehicleData.m_flags |= Vehicle.Flags.WaitingPath; return(true); } } return(false); }
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); }
public bool CustomStartPathFind(ushort instanceID, ref CitizenInstance citizenData, Vector3 startPos, Vector3 endPos, VehicleInfo vehicleInfo) { return(ExtStartPathFind(instanceID, ref citizenData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID], startPos, endPos, vehicleInfo)); }
private static bool CustomFindParkingSpace(VehicleInfo vehicleInfo, ushort homeID, Vector3 refPos, Vector3 searchDir, ushort segmentId, out Vector3 parkPos, out Quaternion parkRot, out float parkOffset) { float searchRadius = Options.prohibitPocketCars ? 32f : 16f; uint chanceOfParkingOffRoad = 3u; Vector3 searchMagnitude = refPos + searchDir * 16f; if (GlobalConfig.RushHourParkingSearchRadius != null) { searchRadius = (int)GlobalConfig.RushHourParkingSearchRadius; #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"RushHour's Improved Parking AI is active. searchRadius={searchRadius}"); } #endif chanceOfParkingOffRoad = 80u; } else { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug("RushHour's Improved Parking AI is NOT active."); } #endif } /*if (Options.prohibitPocketCars) { * //searchRadius = Mathf.Max(32f, searchRadius); * }*/ Vector3 refPos2 = refPos + searchDir * 16f; if (Singleton <SimulationManager> .instance.m_randomizer.Int32(chanceOfParkingOffRoad) == 0) { float width = vehicleInfo.m_generatedInfo.m_size.x; float length = vehicleInfo.m_generatedInfo.m_size.z; if (FindParkingSpaceRoadSide(0, segmentId, refPos, width - 0.2f, length, out parkPos, out parkRot, out parkOffset)) { if (Options.parkingRestrictionsEnabled) { Vector3 innerParkPos; uint laneId; int laneIndex; float laneOffset; if (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].GetClosestLanePosition(refPos, NetInfo.LaneType.Parking, VehicleInfo.VehicleType.Car, out innerParkPos, out laneId, out laneIndex, out laneOffset)) { if (ParkingRestrictionsManager.Instance.IsParkingAllowed(segmentId, Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info.m_lanes[laneIndex].m_finalDirection)) { return(true); } } } else { return(true); } } if (AdvancedParkingManager.Instance.FindParkingSpaceBuilding(vehicleInfo, homeID, 0, segmentId, refPos2, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, searchRadius, out parkPos, out parkRot, out parkOffset)) { return(true); } } else { if (AdvancedParkingManager.Instance.FindParkingSpaceBuilding(vehicleInfo, homeID, 0, segmentId, refPos2, GlobalConfig.Instance.ParkingAI.MaxBuildingToPedestrianLaneDistance, searchRadius, out parkPos, out parkRot, out parkOffset)) { return(true); } float width = vehicleInfo.m_generatedInfo.m_size.x; float length = vehicleInfo.m_generatedInfo.m_size.z; if (FindParkingSpaceRoadSide(0, segmentId, refPos, width - 0.2f, length, out parkPos, out parkRot, out parkOffset)) { if (Options.parkingRestrictionsEnabled) { Vector3 innerParkPos; uint laneId; int laneIndex; float laneOffset; if (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].GetClosestLanePosition(refPos, NetInfo.LaneType.Parking, VehicleInfo.VehicleType.Car, out innerParkPos, out laneId, out laneIndex, out laneOffset)) { if (ParkingRestrictionsManager.Instance.IsParkingAllowed(segmentId, Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info.m_lanes[laneIndex].m_finalDirection)) { return(true); } } } else { return(true); } } } return(false); }
// // BEGIN STOCK CODE // public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPos, PathUnit.Position endPos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength) { PathUnit.Position position = default(PathUnit.Position); return this.CreatePath(out unit, ref randomizer, buildIndex, startPos, position, endPos, position, position, laneTypes, vehicleTypes, maxLength, false, false, false, false); }
/// <summary> /// Makes the given citizen instance enter their parked car. /// </summary> /// <param name="instanceID">Citizen instance id</param> /// <param name="instanceData">Citizen instance data</param> /// <param name="parkedVehicleId">Parked vehicle id</param> /// <param name="vehicleId">Vehicle id</param> /// <returns>true if entering the car succeeded, false otherwise</returns> public static bool EnterParkedCar(ushort instanceID, ref CitizenInstance instanceData, ushort parkedVehicleId, out ushort vehicleId) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.EnterParkedCar({instanceID}, ..., {parkedVehicleId}) called."); } #endif VehicleManager vehManager = Singleton <VehicleManager> .instance; NetManager netManager = Singleton <NetManager> .instance; CitizenManager citManager = Singleton <CitizenManager> .instance; Vector3 parkedVehPos = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].m_position; Quaternion parkedVehRot = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].m_rotation; VehicleInfo vehicleInfo = vehManager.m_parkedVehicles.m_buffer[parkedVehicleId].Info; PathUnit.Position vehLanePathPos; if (!CustomPathManager._instance.m_pathUnits.m_buffer[instanceData.m_path].GetPosition(0, out vehLanePathPos)) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.EnterParkedCar: Could not get first car path position of citizen instance {instanceID}!"); } #endif vehicleId = 0; return(false); } uint vehLaneId = PathManager.GetLaneID(vehLanePathPos); #if DEBUG if (GlobalConfig.Instance.Debug.Switches[4]) { Log._Debug($"CustomHumanAI.EnterParkedCar: Determined vehicle position for citizen instance {instanceID}: seg. {vehLanePathPos.m_segment}, lane {vehLanePathPos.m_lane}, off {vehLanePathPos.m_offset} (lane id {vehLaneId})"); } #endif Vector3 vehLanePos; float vehLaneOff; netManager.m_lanes.m_buffer[vehLaneId].GetClosestPosition(parkedVehPos, out vehLanePos, out vehLaneOff); byte vehLaneOffset = (byte)Mathf.Clamp(Mathf.RoundToInt(vehLaneOff * 255f), 0, 255); // movement vector from parked vehicle position to road position Vector3 forwardVector = parkedVehPos + Vector3.ClampMagnitude(vehLanePos - parkedVehPos, 5f); if (vehManager.CreateVehicle(out vehicleId, ref Singleton <SimulationManager> .instance.m_randomizer, vehicleInfo, parkedVehPos, TransferManager.TransferReason.None, false, false)) { // update frame data Vehicle.Frame frame = vehManager.m_vehicles.m_buffer[(int)vehicleId].m_frame0; frame.m_rotation = parkedVehRot; vehManager.m_vehicles.m_buffer[vehicleId].m_frame0 = frame; vehManager.m_vehicles.m_buffer[vehicleId].m_frame1 = frame; vehManager.m_vehicles.m_buffer[vehicleId].m_frame2 = frame; vehManager.m_vehicles.m_buffer[vehicleId].m_frame3 = frame; vehicleInfo.m_vehicleAI.FrameDataUpdated(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId], ref frame); // update vehicle target position vehManager.m_vehicles.m_buffer[vehicleId].m_targetPos0 = new Vector4(vehLanePos.x, vehLanePos.y, vehLanePos.z, 2f); // update other fields vehManager.m_vehicles.m_buffer[vehicleId].m_flags = (vehManager.m_vehicles.m_buffer[vehicleId].m_flags | Vehicle.Flags.Stopped); vehManager.m_vehicles.m_buffer[vehicleId].m_path = instanceData.m_path; vehManager.m_vehicles.m_buffer[vehicleId].m_pathPositionIndex = 0; vehManager.m_vehicles.m_buffer[vehicleId].m_lastPathOffset = vehLaneOffset; vehManager.m_vehicles.m_buffer[vehicleId].m_transferSize = (ushort)(instanceData.m_citizen & 65535u); if (!vehicleInfo.m_vehicleAI.TrySpawn(vehicleId, ref vehManager.m_vehicles.m_buffer[vehicleId])) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.EnterParkedCar: Could not spawn a {vehicleInfo.m_vehicleType} for citizen instance {instanceID}!"); } #endif return(false); } // change instances InstanceID parkedVehInstance = InstanceID.Empty; parkedVehInstance.ParkedVehicle = parkedVehicleId; InstanceID vehInstance = InstanceID.Empty; vehInstance.Vehicle = vehicleId; Singleton <InstanceManager> .instance.ChangeInstance(parkedVehInstance, vehInstance); // set vehicle id for citizen instance instanceData.m_path = 0u; citManager.m_citizens.m_buffer[instanceData.m_citizen].SetParkedVehicle(instanceData.m_citizen, 0); citManager.m_citizens.m_buffer[instanceData.m_citizen].SetVehicle(instanceData.m_citizen, vehicleId, 0u); // update citizen instance flags instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~CitizenInstance.Flags.EnteringVehicle; instanceData.m_flags &= ~CitizenInstance.Flags.TryingSpawnVehicle; instanceData.m_flags &= ~CitizenInstance.Flags.BoredOfWaiting; instanceData.m_waitCounter = 0; // unspawn citizen instance instanceData.Unspawn(instanceID); #if DEBUG if (GlobalConfig.Instance.Debug.Switches[4]) { Log._Debug($"CustomHumanAI.EnterParkedCar: Citizen instance {instanceID} is now entering vehicle {vehicleId}. Set vehicle target position to {vehLanePos} (segment={vehLanePathPos.m_segment}, lane={vehLanePathPos.m_lane}, offset={vehLanePathPos.m_offset})"); } #endif return(true); } else { // failed to find a road position #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomHumanAI.EnterParkedCar: Could not find a road position for citizen instance {instanceID} near parked vehicle {parkedVehicleId}!"); } #endif return(false); } }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log.Warning($"CustomCarAI.CustomStartPathFind({vehicleID}): called for vehicle {vehicleID}, startPos={startPos}, endPos={endPos}, startBothWays={startBothWays}, endBothWays={endBothWays}, undergroundTarget={undergroundTarget}"); } #endif ExtVehicleType vehicleType = VehicleStateManager.Instance.OnStartPathFind(vehicleID, ref vehicleData, null); if (vehicleType == ExtVehicleType.None) { #if DEBUG Log.Warning($"CustomCarAI.CustomStartPathFind({vehicleID}): Vehicle {vehicleID} does not have a valid vehicle type!"); #endif vehicleType = ExtVehicleType.RoadVehicle; } VehicleInfo info = this.m_info; bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0; PathUnit.Position startPosA; PathUnit.Position startPosB; float startDistSqrA; float startDistSqrB; PathUnit.Position endPosA; PathUnit.Position endPosB; float endDistSqrA; float endDistSqrB; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startDistSqrA, out startDistSqrB) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out endPosA, out endPosB, out endDistSqrA, out endDistSqrB)) { if (!startBothWays || startDistSqrA < 10f) { startPosB = default(PathUnit.Position); } if (!endBothWays || endDistSqrA < 10f) { endPosB = default(PathUnit.Position); } uint path; // NON-STOCK CODE START if (CustomPathManager._instance.CreatePath((ExtVehicleType)vehicleType, vehicleID, ExtCitizenInstance.ExtPathType.None, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0)) { #if DEBUG if (GlobalConfig.Instance.Debug.Switches[2]) { Log._Debug($"CustomCarAI.CustomStartPathFind({vehicleID}): Path-finding starts for vehicle {vehicleID}, path={path}, extVehicleType={vehicleType}, startPosA.segment={startPosA.m_segment}, startPosA.lane={startPosA.m_lane}, info.m_vehicleType={info.m_vehicleType}, 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> /// Lightweight simulation step method. /// This method is occasionally being called for different cars. /// </summary> /// <param name="vehicleId"></param> /// <param name="vehicleData"></param> /// <param name="physicsLodRefPos"></param> public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { #if USEPATHWAITCOUNTER VehicleState state = VehicleStateManager._GetVehicleState(vehicleId); #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager instance = Singleton <PathManager> .instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags; if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; this.PathfindSuccess(vehicleId, ref vehicleData); this.TrySpawn(vehicleId, ref vehicleData); VehicleStateManager.OnPathFindReady(vehicleId, ref vehicleData); // NON-STOCK CODE } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0 #if USEPATHWAITCOUNTER || ((pathFindFlags & PathUnit.FLAG_CREATED) != 0 && state.PathWaitCounter == ushort.MaxValue) #endif ) // NON-STOCK CODE { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } try { VehicleStateManager.LogTraffic(vehicleId, ref vehicleData, true); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } try { VehicleStateManager.UpdateVehiclePos(vehicleId, ref vehicleData); } catch (Exception e) { Log.Error("CarAI CustomSimulationStep Error: " + e.ToString()); } Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1210000f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude(Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 250000f) { lodPhysics = 1; } else { lodPhysics = 0; } this.SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; ushort num = vehicleData.m_trailingVehicle; int num2 = 0; while (num != 0) { ushort trailingVehicle = instance2.m_vehicles.m_buffer[(int)num].m_trailingVehicle; VehicleInfo info = instance2.m_vehicles.m_buffer[(int)num].Info; info.m_vehicleAI.SimulationStep(num, ref instance2.m_vehicles.m_buffer[(int)num], vehicleId, ref vehicleData, lodPhysics); num = trailingVehicle; if (++num2 > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } #if PATHRECALC ushort recalcSegmentId = 0; #endif int privateServiceIndex = ItemClass.GetPrivateServiceIndex(this.m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if ((int)vehicleData.m_blockCounter == maxBlockCounter && Options.enableDespawning) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } #if PATHRECALC else if (vehicleData.m_leadingVehicle == 0 && CustomVehicleAI.ShouldRecalculatePath(vehicleId, ref vehicleData, maxBlockCounter, out recalcSegmentId)) { CustomVehicleAI.MarkPathRecalculation(vehicleId, recalcSegmentId); InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); } #endif }
public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, RoadManager.VehicleType vehicleType) { while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT)) { } uint num; try { if (!this.m_pathUnits.CreateItem(out num, ref randomizer)) { unit = 0u; bool result = false; return result; } this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u); } finally { Monitor.Exit(this.m_bufferLock); } unit = num; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = 1; if (isHeavyVehicle) { PathUnit[] expr_92_cp_0 = this.m_pathUnits.m_buffer; UIntPtr expr_92_cp_1 = (UIntPtr)unit; expr_92_cp_0[(int)expr_92_cp_1].m_simulationFlags = (byte)(expr_92_cp_0[(int)expr_92_cp_1].m_simulationFlags | 16); } if (ignoreBlocked) { PathUnit[] expr_BB_cp_0 = this.m_pathUnits.m_buffer; UIntPtr expr_BB_cp_1 = (UIntPtr)unit; expr_BB_cp_0[(int)expr_BB_cp_1].m_simulationFlags = (byte)(expr_BB_cp_0[(int)expr_BB_cp_1].m_simulationFlags | 32); } if (stablePath) { PathUnit[] expr_E4_cp_0 = this.m_pathUnits.m_buffer; UIntPtr expr_E4_cp_1 = (UIntPtr)unit; expr_E4_cp_0[(int)expr_E4_cp_1].m_simulationFlags = (byte)(expr_E4_cp_0[(int)expr_E4_cp_1].m_simulationFlags | 64); } this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1; int num2 = 10000000; CustomPathFind pathFind = null; for (int i = 0; i < this.m_pathFinds.Length; i++) { CustomPathFind pathFind2 = this.m_pathFinds[i]; if (pathFind2.IsAvailable && pathFind2.m_queuedPathFindCount < num2) { num2 = pathFind2.m_queuedPathFindCount; pathFind = pathFind2; } } if (pathFind != null && pathFind.CalculatePath(unit, skipQueue, vehicleType)) { return true; } this.ReleasePath(unit); return false; }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { #if DEBUG //Log._Debug($"CustomBusAI.CustomStartPathFind called for vehicle {vehicleID}"); #endif VehicleInfo info = this.m_info; bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0; PathUnit.Position startPosA; PathUnit.Position startPosB; float startDistSqrA; float startDistSqrB; PathUnit.Position endPosA; PathUnit.Position endPosB; float endDistSqrA; float endDistSqrB; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startDistSqrA, out startDistSqrB) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out endPosA, out endPosB, out endDistSqrA, out endDistSqrB)) { if (!startBothWays || startDistSqrA < 10f) { startPosB = default(PathUnit.Position); } if (!endBothWays || endDistSqrA < 10f) { endPosB = default(PathUnit.Position); } uint path; // NON-STOCK CODE START PathCreationArgs args; args.extPathType = ExtCitizenInstance.ExtPathType.None; args.extVehicleType = ExtVehicleType.Bus; args.vehicleId = vehicleID; args.spawned = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; args.buildIndex = Singleton <SimulationManager> .instance.m_currentBuildIndex; args.startPosA = startPosA; args.startPosB = startPosB; args.endPosA = endPosA; args.endPosB = endPosB; args.vehiclePosition = default(PathUnit.Position); args.laneTypes = NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle; args.vehicleTypes = info.m_vehicleType; args.maxLength = 20000f; args.isHeavyVehicle = this.IsHeavyVehicle(); args.hasCombustionEngine = this.CombustionEngine(); args.ignoreBlocked = this.IgnoreBlocked(vehicleID, ref vehicleData); args.ignoreFlooded = false; args.randomParking = false; args.ignoreCosts = false; args.stablePath = true; args.skipQueue = true; if (CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args)) { // NON-STOCK CODE END if (vehicleData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); } vehicleData.m_path = path; vehicleData.m_flags |= Vehicle.Flags.WaitingPath; return(true); } } return(false); }
public static bool GetStopLane(ref PathUnit.Position pos, VehicleInfo.VehicleType vehicleType) { if (pos.m_segment != 0) { NetManager instance = Singleton<NetManager>.instance; int num; uint num2; if (instance.m_segments.m_buffer[(int)pos.m_segment].GetClosestLane((int)pos.m_lane, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, out num, out num2)) { pos.m_lane = (byte)num; return true; } } pos = default(PathUnit.Position); return false; }
public static new bool UpdatePath(ushort segmentID, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue) { if (data.m_path == 0u) { return BusTransportLineAI.StartPathFind(segmentID, ref data, netService, vehicleType, skipQueue); } if ((data.m_flags & NetSegment.Flags.WaitingPath) == NetSegment.Flags.None) { return true; } PathManager instance = Singleton<PathManager>.instance; NetManager instance2 = Singleton<NetManager>.instance; byte pathFindFlags = instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { bool flag = false; PathUnit.Position pathPos; if (instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].GetPosition(0, out pathPos)) { flag = TransportLineAI.CheckNodePosition(data.m_startNode, pathPos); } if (instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].GetLastPosition(out pathPos)) { TransportLineAI.CheckNodePosition(data.m_endNode, pathPos); } float length = instance.m_pathUnits.m_buffer[(int)((UIntPtr)data.m_path)].m_length; if (length != data.m_averageLength) { data.m_averageLength = length; ushort transportLine = instance2.m_nodes.m_buffer[(int)data.m_startNode].m_transportLine; if (transportLine != 0) { Singleton<TransportManager>.instance.UpdateLine(transportLine); } } if (data.m_lanes != 0u) { instance2.m_lanes.m_buffer[(int)((UIntPtr)data.m_lanes)].m_length = data.m_averageLength * ((!flag) ? 1f : 0.75f); } data.m_flags &= ~NetSegment.Flags.WaitingPath; data.m_flags &= ~NetSegment.Flags.PathFailed; return true; } if ((pathFindFlags & 8) != 0) { if (data.m_averageLength == 0f) { Vector3 position = instance2.m_nodes.m_buffer[(int)data.m_startNode].m_position; Vector3 position2 = instance2.m_nodes.m_buffer[(int)data.m_endNode].m_position; data.m_averageLength = Vector3.Distance(position, position2); } data.m_flags &= ~NetSegment.Flags.WaitingPath; data.m_flags |= NetSegment.Flags.PathFailed; return true; } return false; }
public string CustomGetLocalizedStatus(ushort instanceID, ref CitizenInstance data, out InstanceID target) { if ((data.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None) { target = InstanceID.Empty; return(Locale.Get("CITIZEN_STATUS_CONFUSED")); } CitizenManager instance = Singleton <CitizenManager> .instance; uint citizenId = data.m_citizen; ushort vehicleId = 0; if (citizenId != 0u) { vehicleId = instance.m_citizens.m_buffer[citizenId].m_vehicle; } ushort targetBuilding = data.m_targetBuilding; if (targetBuilding == 0) { target = InstanceID.Empty; return(Locale.Get("CITIZEN_STATUS_CONFUSED")); } bool flag = (Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)targetBuilding].m_flags & Building.Flags.IncomingOutgoing) != Building.Flags.None; bool flag2 = data.m_path == 0u && (data.m_flags & CitizenInstance.Flags.HangAround) != CitizenInstance.Flags.None; String ret = ""; if (vehicleId != 0) { VehicleManager instance2 = Singleton <VehicleManager> .instance; VehicleInfo info = instance2.m_vehicles.m_buffer[(int)vehicleId].Info; if (info.m_class.m_service == ItemClass.Service.Residential && info.m_vehicleType != VehicleInfo.VehicleType.Bicycle) { if (info.m_vehicleAI.GetOwnerID(vehicleId, ref instance2.m_vehicles.m_buffer[(int)vehicleId]).Citizen == citizenId) { if (flag) { target = InstanceID.Empty; return(Locale.Get("CITIZEN_STATUS_DRIVINGTO_OUTSIDE")); } target = InstanceID.Empty; target.Building = targetBuilding; return(Locale.Get("CITIZEN_STATUS_DRIVINGTO")); } } else if (info.m_class.m_service == ItemClass.Service.PublicTransport || info.m_class.m_service == ItemClass.Service.Disaster) { if (flag) { target = InstanceID.Empty; return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO_OUTSIDE")); } target = InstanceID.Empty; target.Building = targetBuilding; return(Locale.Get("CITIZEN_STATUS_TRAVELLINGTO")); } } if (flag) { target = InstanceID.Empty; return(Locale.Get("CITIZEN_STATUS_GOINGTO_OUTSIDE")); } if (flag2) { target = InstanceID.Empty; target.Building = targetBuilding; return(Locale.Get("CITIZEN_STATUS_VISITING")); } target = InstanceID.Empty; target.Building = targetBuilding; ret = Locale.Get("CITIZEN_STATUS_GOINGTO"); // NON-STOCK CODE START #if BENCHMARK using (var bm = new Benchmark(null, "EnrichLocalizedCitizenStatus")) { #endif if (Options.prohibitPocketCars) { ret = AdvancedParkingManager.Instance.EnrichLocalizedCitizenStatus(ret, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceID]); } #if BENCHMARK } #endif // NON-STOCK CODE END return(ret); }
public void ApplySpeedMultiplier(VehicleInfo vehicle) { vehicle.m_acceleration *= speedMultiplier; //vehicle.m_braking *= speedMultiplier; //vehicle.m_turning *= speedMultiplier; vehicle.m_maxSpeed *= speedMultiplier; }
public VehicleInfo CustomGetVehicleInfo(ushort instanceId, ref CitizenInstance citizenData, bool forceCar, out VehicleInfo trailer) { #if DEBUG bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 || DebugSettings.CitizenInstanceId == instanceId) && (DebugSettings.CitizenId == 0 || DebugSettings.CitizenId == citizenData.m_citizen) && (DebugSettings.SourceBuildingId == 0 || DebugSettings.SourceBuildingId == citizenData.m_sourceBuilding) && (DebugSettings.TargetBuildingId == 0 || DebugSettings.TargetBuildingId == citizenData.m_targetBuilding); bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug; #else var logParkingAi = false; #endif trailer = null; if (citizenData.m_citizen == 0u) { return(null); } // NON-STOCK CODE START bool forceTaxi = false; if (Options.parkingAI) { if (ExtCitizenInstanceManager.Instance.ExtInstances[instanceId] .pathMode == ExtPathMode.TaxiToTarget) { forceTaxi = true; } } // NON-STOCK CODE END Citizen.AgeGroup ageGroup = Constants.ManagerFactory.ExtCitizenManager.GetAgeGroup(citizenData.Info.m_agePhase); int carProb; int bikeProb; int taxiProb; // NON-STOCK CODE START if (forceTaxi) { carProb = 0; bikeProb = 0; taxiProb = 100; } else // NON-STOCK CODE END if (forceCar || (citizenData.m_flags & CitizenInstance.Flags.BorrowCar) != CitizenInstance.Flags.None) { carProb = 100; bikeProb = 0; taxiProb = 0; } else { carProb = GetCarProbability(instanceId, ref citizenData, ageGroup); bikeProb = GetBikeProbability(instanceId, ref citizenData, ageGroup); taxiProb = GetTaxiProbability(instanceId, ref citizenData, ageGroup); } Randomizer randomizer = new Randomizer(citizenData.m_citizen); bool useCar = randomizer.Int32(100u) < carProb; bool useBike = !useCar && randomizer.Int32(100u) < bikeProb; bool useTaxi = !useCar && !useBike && randomizer.Int32(100u) < taxiProb; bool useElectricCar = false; if (useCar) { int electricProb = GetElectricCarProbability( instanceId, ref citizenData, m_info.m_agePhase); useElectricCar = randomizer.Int32(100u) < electricProb; } ItemClass.Service service = ItemClass.Service.Residential; ItemClass.SubService subService = useElectricCar ? ItemClass.SubService.ResidentialLowEco : ItemClass.SubService.ResidentialLow; if (useTaxi) { service = ItemClass.Service.PublicTransport; subService = ItemClass.SubService.PublicTransportTaxi; } // NON-STOCK CODE START VehicleInfo carInfo = null; if (Options.parkingAI && useCar) { ushort parkedVehicleId = Singleton <CitizenManager> .instance.m_citizens.m_buffer[citizenData.m_citizen] .m_parkedVehicle; if (parkedVehicleId != 0) { Log._DebugIf( logParkingAi, () => $"CustomResidentAI.CustomGetVehicleInfo({instanceId}): " + $"Citizen instance {instanceId} owns a parked vehicle {parkedVehicleId}. " + $"Reusing vehicle info."); carInfo = Singleton <VehicleManager> .instance.m_parkedVehicles.m_buffer[parkedVehicleId].Info; } } if (carInfo == null && (useCar || useTaxi)) { // NON-STOCK CODE END carInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo( ref randomizer, service, subService, ItemClass.Level.Level1); } if (useBike) { ItemClass.Level ageGroupLvl = ageGroup != Citizen.AgeGroup.Child ? ItemClass.Level.Level2 : ItemClass.Level.Level1; VehicleInfo bikeInfo = Singleton <VehicleManager> .instance.GetRandomVehicleInfo( ref randomizer, ItemClass.Service.Residential, ItemClass.SubService.ResidentialHigh, ageGroupLvl); if (bikeInfo != null) { return(bikeInfo); } } if ((useCar || useTaxi) && carInfo != null) { return(carInfo); } return(null); }
private IEnumerable<Vehicle> GetValidVehicles(VehicleInfo.VehicleType vType, int? districId) { Vehicle[] vehicles = Singleton<VehicleManager>.instance.m_vehicles.m_buffer; if (vehicles == null) yield break; var districtManager = Singleton<DistrictManager>.instance; foreach (var vehicle in vehicles) { if (!((vehicle.Info.m_vehicleType & vType) == vType)) { continue; } if (!((vehicle.m_flags & Vehicle.Flags.Created) == Vehicle.Flags.Created)) { continue; } if (!((vehicle.m_flags & Vehicle.Flags.Spawned) == Vehicle.Flags.Spawned)) { continue; } if (vehicle.m_leadingVehicle != 0) { continue; } if (districId.HasValue) { var vehicleDistrictID = (int)districtManager.GetDistrict(vehicle.GetLastFramePosition()); if (vehicleDistrictID != districId.Value) continue; } yield return vehicle; } }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { ExtVehicleType?vehicleType = VehicleStateManager.DetermineVehicleType(vehicleID, ref vehicleData); #if PATHRECALC VehicleState state = VehicleStateManager._GetVehicleState(vehicleID); bool recalcRequested = state.PathRecalculationRequested; state.PathRecalculationRequested = false; #endif /*if (vehicleType == null) { * Log._Debug($"CustomCarAI.CustomStartPathFind: Could not determine ExtVehicleType from class type. typeof this={this.GetType().ToString()}"); * } else { * Log._Debug($"CustomCarAI.CustomStartPathFind: vehicleType={vehicleType}. typeof this={this.GetType().ToString()}"); * }*/ VehicleInfo info = this.m_info; bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0; PathUnit.Position startPosA; PathUnit.Position startPosB; float num; float num2; PathUnit.Position endPosA; PathUnit.Position endPosB; float num3; float num4; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out endPosA, out endPosB, out num3, out num4)) { if (!startBothWays || num < 10f) { startPosB = default(PathUnit.Position); } if (!endBothWays || num3 < 10f) { endPosB = default(PathUnit.Position); } uint path; bool res = false; if (vehicleType == null) { res = Singleton <CustomPathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false); } else { res = Singleton <CustomPathManager> .instance.CreatePath( #if PATHRECALC recalcRequested, #endif (ExtVehicleType)vehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, ref startPosA, ref startPosB, ref endPosA, ref endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, this.IsHeavyVehicle(), this.IgnoreBlocked(vehicleID, ref vehicleData), false, false); } if (res) { 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); }
public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { #if USEPATHWAITCOUNTER VehicleState state = VehicleStateManager._GetVehicleState(vehicleId); #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[(int)((UIntPtr)vehicleData.m_path)].m_pathFindFlags; if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif try { this.PathfindSuccess(vehicleId, ref vehicleData); this.PathFindReady(vehicleId, ref vehicleData); VehicleStateManager.OnPathFindReady(vehicleId, ref vehicleData); // NON-STOCK CODE } catch (Exception e) { Log.Warning($"TramBaseAI.PathFindSuccess/PathFindReady({vehicleId}) threw an exception: {e.ToString()}"); vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0 #if USEPATHWAITCOUNTER || ((pathFindFlags & PathUnit.FLAG_CREATED) != 0 && state.PathWaitCounter == ushort.MaxValue) #endif ) // NON-STOCK CODE { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } #if USEPATHWAITCOUNTER else { state.PathWaitCounter = (ushort)Math.Min(ushort.MaxValue, (int)state.PathWaitCounter + 1); // NON-STOCK CODE } #endif } else { #if USEPATHWAITCOUNTER state.PathWaitCounter = 0; // NON-STOCK CODE #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } /// NON-STOCK CODE START /// bool reversed = (vehicleData.m_flags & Vehicle.Flags.Reversed) != 0; ushort frontVehicleId; if (reversed) { frontVehicleId = vehicleData.GetLastVehicle(vehicleId); } else { frontVehicleId = vehicleId; } try { //Log._Debug($"HandleVehicle for trams. vehicleId={vehicleId} frontVehicleId={frontVehicleId}"); VehicleStateManager.LogTraffic(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId], true); } catch (Exception e) { Log.Error("TramAI CustomSimulationStep (1) Error: " + e.ToString()); } try { VehicleStateManager.UpdateVehiclePos(frontVehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[frontVehicleId]); } catch (Exception e) { Log.Error("TramAI CustomSimulationStep (2) Error: " + e.ToString()); } /// NON-STOCK CODE END /// VehicleManager instance = Singleton <VehicleManager> .instance; VehicleInfo info = instance.m_vehicles.m_buffer[(int)vehicleId].Info; info.m_vehicleAI.SimulationStep(vehicleId, ref instance.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } ushort trailingVehicle = instance.m_vehicles.m_buffer[(int)vehicleId].m_trailingVehicle; int num = 0; while (trailingVehicle != 0) { info = instance.m_vehicles.m_buffer[(int)trailingVehicle].Info; info.m_vehicleAI.SimulationStep(trailingVehicle, ref instance.m_vehicles.m_buffer[(int)trailingVehicle], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } trailingVehicle = instance.m_vehicles.m_buffer[(int)trailingVehicle].m_trailingVehicle; if (++num > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0 || (vehicleData.m_blockCounter == 255 && Options.enableDespawning)) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } }
public static new bool StartPathFind(ushort segmentID, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue) { if (data.m_path != 0u) { Singleton<PathManager>.instance.ReleasePath(data.m_path); data.m_path = 0u; } NetManager instance = Singleton<NetManager>.instance; if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) { for (int i = 0; i < 8; i++) { ushort segment = instance.m_nodes.m_buffer[(int)data.m_startNode].GetSegment(i); if (segment != 0 && segment != segmentID && instance.m_segments.m_buffer[(int)segment].m_path != 0u) { return true; } } } if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) { for (int j = 0; j < 8; j++) { ushort segment2 = instance.m_nodes.m_buffer[(int)data.m_endNode].GetSegment(j); if (segment2 != 0 && segment2 != segmentID && instance.m_segments.m_buffer[(int)segment2].m_path != 0u) { return true; } } } Vector3 position = instance.m_nodes.m_buffer[(int)data.m_startNode].m_position; Vector3 position2 = instance.m_nodes.m_buffer[(int)data.m_endNode].m_position; PathUnit.Position startPosA; PathUnit.Position startPosB; float num; float num2; if (!PathManager.FindPathPosition(position, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, false, 32f, out startPosA, out startPosB, out num, out num2)) { return true; } PathUnit.Position endPosA; PathUnit.Position endPosB; float num3; float num4; if (!PathManager.FindPathPosition(position2, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, false, 32f, out endPosA, out endPosB, out num3, out num4)) { return true; } if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) { startPosB = default(PathUnit.Position); } if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) { endPosB = default(PathUnit.Position); } startPosA.m_offset = 128; startPosB.m_offset = 128; endPosA.m_offset = 128; endPosB.m_offset = 128; bool stopLane = BusTransportLineAI.GetStopLane(ref startPosA, vehicleType); bool stopLane2 = BusTransportLineAI.GetStopLane(ref startPosB, vehicleType); bool stopLane3 = BusTransportLineAI.GetStopLane(ref endPosA, vehicleType); bool stopLane4 = BusTransportLineAI.GetStopLane(ref endPosB, vehicleType); if ((!stopLane && !stopLane2) || (!stopLane3 && !stopLane4)) { return true; } uint path; bool createPathResult; CustomPathManager customPathManager = Singleton<PathManager>.instance as CustomPathManager; if (customPathManager != null) createPathResult = customPathManager.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, 20000f, false, true, true, skipQueue, RoadManager.VehicleType.Bus); else createPathResult = Singleton<PathManager>.instance.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, 20000f, false, true, true, skipQueue); if (createPathResult) { if (startPosA.m_segment != 0 && startPosB.m_segment != 0) { NetNode[] expr_2D9_cp_0 = instance.m_nodes.m_buffer; ushort expr_2D9_cp_1 = data.m_startNode; expr_2D9_cp_0[(int)expr_2D9_cp_1].m_flags = (expr_2D9_cp_0[(int)expr_2D9_cp_1].m_flags | NetNode.Flags.Ambiguous); } else { NetNode[] expr_305_cp_0 = instance.m_nodes.m_buffer; ushort expr_305_cp_1 = data.m_startNode; expr_305_cp_0[(int)expr_305_cp_1].m_flags = (expr_305_cp_0[(int)expr_305_cp_1].m_flags & ~NetNode.Flags.Ambiguous); } if (endPosA.m_segment != 0 && endPosB.m_segment != 0) { NetNode[] expr_344_cp_0 = instance.m_nodes.m_buffer; ushort expr_344_cp_1 = data.m_endNode; expr_344_cp_0[(int)expr_344_cp_1].m_flags = (expr_344_cp_0[(int)expr_344_cp_1].m_flags | NetNode.Flags.Ambiguous); } else { NetNode[] expr_370_cp_0 = instance.m_nodes.m_buffer; ushort expr_370_cp_1 = data.m_endNode; expr_370_cp_0[(int)expr_370_cp_1].m_flags = (expr_370_cp_0[(int)expr_370_cp_1].m_flags & ~NetNode.Flags.Ambiguous); } data.m_path = path; data.m_flags |= NetSegment.Flags.WaitingPath; return false; } return true; }
public void CustomSimulationStep(ushort instanceId, ref CitizenInstance instanceData, Vector3 physicsLodRefPos) { #if DEBUG bool citizenDebug = (DebugSettings.CitizenInstanceId == 0 || DebugSettings.CitizenInstanceId == instanceId) && (DebugSettings.CitizenId == 0 || DebugSettings.CitizenId == instanceData.m_citizen) && (DebugSettings.SourceBuildingId == 0 || DebugSettings.SourceBuildingId == instanceData.m_sourceBuilding) && (DebugSettings.TargetBuildingId == 0 || DebugSettings.TargetBuildingId == instanceData.m_targetBuilding); bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && citizenDebug; #else var logParkingAi = false; #endif CitizenManager citizenManager = Singleton <CitizenManager> .instance; uint citizenId = instanceData.m_citizen; if ((instanceData.m_flags & (CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None && (instanceData.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None) { citizenManager.ReleaseCitizenInstance(instanceId); if (citizenId != 0u) { citizenManager.ReleaseCitizen(citizenId); } return; } Citizen[] citizensBuffer = citizenManager.m_citizens.m_buffer; if ((instanceData.m_flags & CitizenInstance.Flags.WaitingPath) != CitizenInstance.Flags.None) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[instanceData.m_path].m_pathFindFlags; // NON-STOCK CODE START ExtPathState mainPathState = ExtPathState.Calculating; if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || instanceData.m_path == 0) { mainPathState = ExtPathState.Failed; } else if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { mainPathState = ExtPathState.Ready; } if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): " + $"Path: {instanceData.m_path}, mainPathState={mainPathState}"); } ExtSoftPathState finalPathState; using (var bm = Benchmark.MaybeCreateBenchmark( null, "ConvertPathStateToSoftPathState+UpdateCitizenPathState")) { finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState); if (Options.parkingAI) { finalPathState = AdvancedParkingManager.Instance.UpdateCitizenPathState( instanceId, ref instanceData, ref ExtCitizenInstanceManager .Instance.ExtInstances[ instanceId], ref ExtCitizenManager .Instance.ExtCitizens[ citizenId], ref citizensBuffer[ instanceData.m_citizen], mainPathState); if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): " + $"Applied Parking AI logic. Path: {instanceData.m_path}, " + $"mainPathState={mainPathState}, finalPathState={finalPathState}, " + $"extCitizenInstance={ExtCitizenInstanceManager.Instance.ExtInstances[instanceId]}"); } } // if Options.parkingAi } switch (finalPathState) { case ExtSoftPathState.Ready: { if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): Path-finding " + $"succeeded for citizen instance {instanceId} " + $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " + "-- calling HumanAI.PathfindSuccess"); } if (citizenId == 0 || citizensBuffer[instanceData.m_citizen].m_vehicle == 0) { Spawn(instanceId, ref instanceData); } instanceData.m_pathPositionIndex = 255; instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering); // NON-STOCK CODE START (transferred from ResidentAI.PathfindSuccess) const Citizen.Flags CTZ_MASK = Citizen.Flags.Tourist | Citizen.Flags.MovingIn | Citizen.Flags.DummyTraffic; if (citizenId != 0 && (citizensBuffer[citizenId].m_flags & CTZ_MASK) == Citizen.Flags.MovingIn) { StatisticBase statisticBase = Singleton <StatisticsManager> .instance.Acquire <StatisticInt32>(StatisticType.MoveRate); statisticBase.Add(1); } // NON-STOCK CODE END PathfindSuccess(instanceId, ref instanceData); break; } case ExtSoftPathState.Ignore: { if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): " + "Path-finding result shall be ignored for citizen instance " + $"{instanceId} (finalPathState={finalPathState}). " + $"Path: {instanceData.m_path} -- ignoring"); } return; } case ExtSoftPathState.Calculating: default: { if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): " + $"Path-finding result undetermined for citizen instance {instanceId} " + $"(finalPathState={finalPathState}). " + $"Path: {instanceData.m_path} -- continue"); } break; } case ExtSoftPathState.FailedHard: { if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): " + $"HARD path-finding failure for citizen instance {instanceId} " + $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " + "-- calling HumanAI.PathfindFailure"); } instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering); Singleton <PathManager> .instance.ReleasePath(instanceData.m_path); instanceData.m_path = 0u; PathfindFailure(instanceId, ref instanceData); return; } case ExtSoftPathState.FailedSoft: { if (logParkingAi) { Log._Debug( $"CustomHumanAI.CustomSimulationStep({instanceId}): " + $"SOFT path-finding failure for citizen instance {instanceId} " + $"(finalPathState={finalPathState}). Path: {instanceData.m_path} " + "-- calling HumanAI.InvalidPath"); } // path mode has been updated, repeat path-finding instanceData.m_flags &= ~CitizenInstance.Flags.WaitingPath; instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown | CitizenInstance.Flags.Cheering); InvalidPath(instanceId, ref instanceData); break; } } // NON-STOCK CODE END } // NON-STOCK CODE START using (var bm = Benchmark.MaybeCreateBenchmark(null, "ExtSimulationStep")) { if (Options.parkingAI) { if (ExtSimulationStep( instanceId, ref instanceData, ref ExtCitizenInstanceManager.Instance.ExtInstances[instanceId], physicsLodRefPos)) { return; } } } // NON-STOCK CODE END base.SimulationStep(instanceId, ref instanceData, physicsLodRefPos); VehicleManager vehicleManager = Singleton <VehicleManager> .instance; ushort vehicleId = 0; if (instanceData.m_citizen != 0u) { vehicleId = citizensBuffer[instanceData.m_citizen].m_vehicle; } if (vehicleId != 0) { Vehicle[] vehiclesBuffer = vehicleManager.m_vehicles.m_buffer; VehicleInfo vehicleInfo = vehiclesBuffer[vehicleId].Info; if (vehicleInfo.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { vehicleInfo.m_vehicleAI.SimulationStep( vehicleId, ref vehiclesBuffer[vehicleId], vehicleId, ref vehiclesBuffer[vehicleId], 0); vehicleId = 0; } } if (vehicleId != 0 || (instanceData.m_flags & (CitizenInstance.Flags.Character | CitizenInstance.Flags.WaitingPath | CitizenInstance.Flags.Blown | CitizenInstance.Flags.Floating)) != CitizenInstance.Flags.None) { return; } instanceData.m_flags &= ~(CitizenInstance.Flags.HangAround | CitizenInstance.Flags.Panicking | CitizenInstance.Flags.SittingDown); ArriveAtDestination(instanceId, ref instanceData, false); citizenManager.ReleaseCitizenInstance(instanceId); }
//Fare Cal public static Double FareCalculate(VehicleInfo taxiInput, double kmInput) { double price; double oKm = taxiInput.oKm; double oPrice = taxiInput.oPrice; double f1Km = 0; if (taxiInput.f1Km != null) { f1Km = (double)taxiInput.f1Km; } double f2Km = 0; if (taxiInput.f2Km != null) { f2Km = (double)taxiInput.f2Km; } double f3Km = 0; if (taxiInput.f3Km != null) { f3Km = (double)taxiInput.f3Km; } double f4Km = 0; if (taxiInput.f4Km != null) { f4Km = (double)taxiInput.f4Km; } double f1Price = 0; if (taxiInput.f1Price != null) { f1Price = (double)taxiInput.f1Price; } double f2Price = 0; if (taxiInput.f2Price != null) { f2Price = (double)taxiInput.f2Price; } double f3Price = 0; if (taxiInput.f3Price != null) { f3Price = (double)taxiInput.f3Price; } double f4Price = 0; if (taxiInput.f4Price != null) { f4Price = (double)taxiInput.f4Price; } price = oPrice; if (kmInput > 0 && kmInput < oKm) { price = oPrice; // Nếu như mới lên xe hoặc đi quãng đường nhỏ hơn open km (0.6) thì bằng giá mở cửa } else if (kmInput > oKm && kmInput < (f1Km + oKm)) //Nếu đi trong khoảng từ 0.6 đến 15.6 (+ thêm 15km) thì { price = oPrice + ((kmInput - oKm) * f1Price); } else if (kmInput > (f1Km + oKm) && kmInput < (f2Km + f1Km + oKm)) { price = oPrice + (f1Km * f1Price) + (kmInput - (f1Km + oKm)) * f2Price; } else if (f4Km == 0 && f3Km == 0) { price = oPrice + (f1Km * f1Price) + (kmInput - (f1Km + oKm)) * f2Price; } else if (f4Km == 0 && f3Km != 0) { price = oPrice + (f1Km * f1Price) + (f2Km * f2Price) + (kmInput - (f1Km + oKm + f2Km)) * f3Price; } else if (f4Km != 0 && f3Km != 0) { if (kmInput > (oKm + f1Km + f2Km + f3Km) && kmInput < (oKm + f1Km + f2Km + f3Km + f4Km)) { price = oPrice + (f1Km * f1Price) + (f2Km * f2Price) + (f3Km * f3Price) + (kmInput - (f1Km + oKm + f2Km + f3Km)) * f4Price; } else { price = oPrice + (f1Km * f1Price) + (f2Km * f2Price) + (kmInput - (f1Km + oKm + f2Km)) * f3Price; } } return price; }
public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { #if DEBUG bool vehDebug = DebugSettings.VehicleId == 0 || DebugSettings.VehicleId == vehicleId; bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && vehDebug; #else var logParkingAi = false; #endif if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { PathManager pathManager = Singleton <PathManager> .instance; byte pathFindFlags = pathManager.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; // NON-STOCK CODE START ExtPathState mainPathState = ExtPathState.Calculating; if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { mainPathState = ExtPathState.Failed; } else if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { mainPathState = ExtPathState.Ready; } #if DEBUG uint logVehiclePath = vehicleData.m_path; Log._DebugIf( logParkingAi, () => $"CustomCarAI.CustomSimulationStep({vehicleId}): " + $"Path: {logVehiclePath}, mainPathState={mainPathState}"); #endif IExtVehicleManager extVehicleManager = Constants.ManagerFactory.ExtVehicleManager; ExtSoftPathState finalPathState = ExtCitizenInstance.ConvertPathStateToSoftPathState(mainPathState); if (Options.parkingAI && extVehicleManager.ExtVehicles[vehicleId].vehicleType == ExtVehicleType.PassengerCar) { ushort driverInstanceId = extVehicleManager.GetDriverInstanceId(vehicleId, ref vehicleData); finalPathState = AdvancedParkingManager.Instance.UpdateCarPathState( vehicleId, ref vehicleData, ref Singleton <CitizenManager> .instance.m_instances.m_buffer[driverInstanceId], ref ExtCitizenInstanceManager.Instance.ExtInstances[driverInstanceId], mainPathState); #if DEBUG if (logParkingAi) { Log._Debug($"CustomCarAI.CustomSimulationStep({vehicleId}): " + $"Applied Parking AI logic. Path: {vehicleData.m_path}, " + $"mainPathState={mainPathState}, finalPathState={finalPathState}"); } #endif } switch (finalPathState) { case ExtSoftPathState.Ready: { #if DEBUG if (logParkingAi) { Log._Debug( $"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding " + $"succeeded for vehicle {vehicleId} (finalPathState={finalPathState}). " + $"Path: {vehicleData.m_path} -- calling CarAI.PathfindSuccess"); } #endif vehicleData.m_pathPositionIndex = 255; vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; vehicleData.m_flags &= ~Vehicle.Flags.Arriving; PathfindSuccess(vehicleId, ref vehicleData); TrySpawn(vehicleId, ref vehicleData); break; } case ExtSoftPathState.Ignore: { #if DEBUG if (logParkingAi) { Log._Debug( $"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding " + $"result shall be ignored for vehicle {vehicleId} " + $"(finalPathState={finalPathState}). Path: {vehicleData.m_path} -- ignoring"); } #endif return; } case ExtSoftPathState.Calculating: default: { #if DEBUG if (logParkingAi) { Log._Debug( $"CustomCarAI.CustomSimulationStep({vehicleId}): Path-finding " + $"result undetermined for vehicle {vehicleId} (finalPathState={finalPathState}). " + $"Path: {vehicleData.m_path} -- continue"); } #endif break; } case ExtSoftPathState.FailedHard: { #if DEBUG if (logParkingAi) { Log._Debug( $"CustomCarAI.CustomSimulationStep({vehicleId}): HARD path-finding " + $"failure for vehicle {vehicleId} (finalPathState={finalPathState}). " + $"Path: {vehicleData.m_path} -- calling CarAI.PathfindFailure"); } #endif vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; PathfindFailure(vehicleId, ref vehicleData); return; } case ExtSoftPathState.FailedSoft: { #if DEBUG if (logParkingAi) { Log._Debug( $"CustomCarAI.CustomSimulationStep({vehicleId}): SOFT path-finding " + $"failure for vehicle {vehicleId} (finalPathState={finalPathState}). " + $"Path: {vehicleData.m_path} -- calling CarAI.InvalidPath"); } #endif // path mode has been updated, repeat path-finding vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; InvalidPath(vehicleId, ref vehicleData, vehicleId, ref vehicleData); break; } } // NON-STOCK CODE END } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { TrySpawn(vehicleId, ref vehicleData); } } // NON-STOCK CODE START IExtVehicleManager extVehicleMan = Constants.ManagerFactory.ExtVehicleManager; extVehicleMan.UpdateVehiclePosition(vehicleId, ref vehicleData); if (Options.advancedAI && (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0) { extVehicleMan.LogTraffic(vehicleId, ref vehicleData); } // NON-STOCK CODE END Vector3 lastFramePosition = vehicleData.GetLastFramePosition(); int lodPhysics; if (Vector3.SqrMagnitude(physicsLodRefPos - lastFramePosition) >= 1100f * 1100f) { lodPhysics = 2; } else if (Vector3.SqrMagnitude( Singleton <SimulationManager> .instance.m_simulationView.m_position - lastFramePosition) >= 500f * 500f) { lodPhysics = 1; } else { lodPhysics = 0; } SimulationStep(vehicleId, ref vehicleData, vehicleId, ref vehicleData, lodPhysics); if (vehicleData.m_leadingVehicle == 0 && vehicleData.m_trailingVehicle != 0) { VehicleManager vehManager = Singleton <VehicleManager> .instance; ushort trailerId = vehicleData.m_trailingVehicle; int numIters = 0; while (trailerId != 0) { ushort trailingVehicle = vehManager.m_vehicles.m_buffer[trailerId].m_trailingVehicle; VehicleInfo info = vehManager.m_vehicles.m_buffer[trailerId].Info; info.m_vehicleAI.SimulationStep( trailerId, ref vehManager.m_vehicles.m_buffer[trailerId], vehicleId, ref vehicleData, lodPhysics); trailerId = trailingVehicle; if (++numIters > 16384) { CODebugBase <LogChannel> .Error( LogChannel.Core, $"Invalid list detected!\n{Environment.StackTrace}"); break; } } } int privateServiceIndex = ItemClass.GetPrivateServiceIndex(m_info.m_class.m_service); int maxBlockCounter = (privateServiceIndex == -1) ? 150 : 100; if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace)) == 0 && vehicleData.m_cargoParent == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (vehicleData.m_blockCounter >= maxBlockCounter) { // NON-STOCK CODE START if (VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData)) { // NON-STOCK CODE END Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } // NON-STOCK CODE } }
public void RestoreVehicleSpeed(VehicleInfo vehicle) { vehicle.m_acceleration /= speedMultiplier; //vehicle.m_braking /= speedMultiplier; //vehicle.m_turning /= speedMultiplier; vehicle.m_maxSpeed /= speedMultiplier; }
public bool CustomStartPathFind(ushort vehicleId, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays, bool undergroundTarget) { #if DEBUG bool vehDebug = DebugSettings.VehicleId == 0 || DebugSettings.VehicleId == vehicleId; bool logParkingAi = DebugSwitch.BasicParkingAILog.Get() && vehDebug; #else var logParkingAi = false; #endif Log._DebugOnlyWarningIf( logParkingAi, () => $"CustomCarAI.CustomStartPathFind({vehicleId}): called for vehicle " + $"{vehicleId}, startPos={startPos}, endPos={endPos}, " + $"startBothWays={startBothWays}, endBothWays={endBothWays}, " + $"undergroundTarget={undergroundTarget}"); ExtVehicleType vehicleType; using (var bm = Benchmark.MaybeCreateBenchmark(null, "OnStartPathFind")) { vehicleType = ExtVehicleManager.Instance.OnStartPathFind(vehicleId, ref vehicleData, null); if (vehicleType == ExtVehicleType.None) { Log._DebugOnlyWarning( $"CustomCarAI.CustomStartPathFind({vehicleId}): Vehicle {vehicleId} " + "does not have a valid vehicle type!"); vehicleType = ExtVehicleType.RoadVehicle; } } VehicleInfo info = m_info; bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0; if (!PathManager.FindPathPosition( startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, allowUnderground, false, 32f, out PathUnit.Position startPosA, out PathUnit.Position startPosB, out float startDistSqrA, out _) || !PathManager.FindPathPosition( endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, info.m_vehicleType, undergroundTarget, false, 32f, out PathUnit.Position endPosA, out PathUnit.Position endPosB, out float endDistSqrA, out _)) { return(false); } if (!startBothWays || startDistSqrA < 10f) { startPosB = default; } if (!endBothWays || endDistSqrA < 10f) { endPosB = default; } // NON-STOCK CODE START PathCreationArgs args; args.extPathType = ExtPathType.None; args.extVehicleType = vehicleType; args.vehicleId = vehicleId; args.spawned = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; args.buildIndex = Singleton <SimulationManager> .instance.m_currentBuildIndex; args.startPosA = startPosA; args.startPosB = startPosB; args.endPosA = endPosA; args.endPosB = endPosB; args.vehiclePosition = default; args.laneTypes = NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle; args.vehicleTypes = info.m_vehicleType; args.maxLength = 20000f; args.isHeavyVehicle = IsHeavyVehicle(); args.hasCombustionEngine = CombustionEngine(); args.ignoreBlocked = IgnoreBlocked(vehicleId, ref vehicleData); args.ignoreFlooded = false; args.ignoreCosts = false; args.randomParking = false; args.stablePath = false; args.skipQueue = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; if (!CustomPathManager._instance.CustomCreatePath( out uint path, ref Singleton <SimulationManager> .instance.m_randomizer, args)) { return(false); } Log._DebugIf( logParkingAi, () => $"CustomCarAI.CustomStartPathFind({vehicleId}): " + $"Path-finding starts for vehicle {vehicleId}, path={path}, " + $"extVehicleType={vehicleType}, startPosA.segment={startPosA.m_segment}, " + $"startPosA.lane={startPosA.m_lane}, info.m_vehicleType={info.m_vehicleType}, " + $"endPosA.segment={endPosA.m_segment}, endPosA.lane={endPosA.m_lane}"); // 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); }
private async void SelectVehicle(int myVehicleId) { var did = userData.content.driverInfo.did.ToString(); var uid = userId; var mid = pushChannelURI; var mType = ConstantVariable.mTypeWIN; //Chuyển did thành id var input = string.Format("{{\"id\":\"{0}\",\"uid\":\"{1}\",\"vehicleId\":\"{2}\",\"mid\":\"{3}\",\"mType\":\"{4}\"}}", did, uid, myVehicleId, mid, mType); try { //Thử xem có lấy được thông tin về ko, nếu không thì do lỗi máy chủ var output = await GetJsonFromPOSTMethod.GetJsonString(ConstantVariable.tNetDriverSelectVehicle, input); var selectVehicle = JsonConvert.DeserializeObject<DriverLogin>(output); if (selectVehicle.status.Equals("0000")) //0000 { //Lấy thông tin giá xe foreach (var car in userData.content.vehicleInfos) { if (car.vehicleId == myVehicleId) { myVehicle = new VehicleInfo { status = car.status, lmd = car.lmd, content = car.content, oPrice = car.oPrice, oKm = car.oKm, f1Price = car.f1Price, f1Km = car.f1Km, f2Price = car.f2Price, f2Km = car.f2Km, f3Price = car.f3Price, f3Km = car.f3Km, f4Price = car.f4Price, f4Km = car.f4Km, vehicleId = car.vehicleId, plate = car.plate, carTitle = car.carTitle, carLevel = car.carLevel, vRegDate = car.vRegDate, manuYear = car.manuYear, cap = car.cap }; // tNetUserLoginData["MySelectedVehicle"] = myVehicle; tNetUserLoginData["UserLmd"] = selectVehicle.lmd; //Cái này là để cập nhật lmd cho việc update thông tin } } NavigationService.Navigate(new Uri("/Pages/HomePage.xaml", UriKind.Relative)); Thread.Sleep(1000); grv_ProcessScreen.Visibility = Visibility.Collapsed;//Disable Process bar } else { MessageBox.Show("(Mã lỗi 1802) " + ConstantVariable.errServerError); grv_ProcessScreen.Visibility = Visibility.Collapsed; //Disable Process bar Debug.WriteLine("Mã lối ght67 ở SelectVehicle"); } } catch (Exception) { //máy chủ lỗi MessageBox.Show("(Mã lỗi 1801) " + ConstantVariable.errServerError); grv_ProcessScreen.Visibility = Visibility.Collapsed; //Disable Process bar Debug.WriteLine("Mã lối 7hgtr3 ở SelectVehicle"); } }
/// <summary> /// Gets the spawn position. /// </summary> /// <param name="vehicleId">The vehicle identifier.</param> /// <param name="vehicleInfo">The vehicle information.</param> /// <param name="buildingId">The building identifier.</param> /// <returns>The spawn position.</returns> public static Vector3 GetSpawnPosition(ushort vehicleId, VehicleInfo vehicleInfo, ushort buildingId) { try { Building building = BuildingHelper.GetBuilding(buildingId); Randomizer randomizer = new Randomizer((int)buildingId); Vector3 position; Vector3 target; building.Info.m_buildingAI.CalculateSpawnPosition(buildingId, ref building, ref randomizer, vehicleInfo, out position, out target); return position; } catch (Exception) { return Vector3.zero; } }
private void assignPathProperties(uint unit, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, byte simulationFlags) { this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_simulationFlags = simulationFlags; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_pathFindFlags = 0; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_buildIndex = buildIndex; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position00 = startPosA; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position01 = endPosA; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position02 = startPosB; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position03 = endPosB; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_position11 = vehiclePosition; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_nextPathUnit = 0u; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_laneTypes = (byte)laneTypes; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_vehicleTypes = (byte)vehicleTypes; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_length = maxLength; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_positionCount = 20; this.m_pathUnits.m_buffer[(int)((UIntPtr)unit)].m_referenceCount = 1; }
internal static ExtVehicleType? DetermineVehicleTypeFromVehicleInfo(VehicleInfo vehicleInfo) { VehicleAI ai = vehicleInfo.m_vehicleAI; return DetermineVehicleTypeFromAIType(ai, false); }
public static ushort CustomCheckOtherVehicle(ushort vehicleId, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ref float maxSpeed, ref bool blocked, ref Vector3 collisionPush, float maxBraking, ushort otherID, ref Vehicle otherData, Vector3 min, Vector3 max, int lodPhysics) { if (otherID == vehicleId || vehicleData.m_leadingVehicle == otherID || vehicleData.m_trailingVehicle == otherID) { return(otherData.m_nextGridVehicle); } VehicleInfo info = otherData.Info; if (info.m_vehicleType == VehicleInfo.VehicleType.Bicycle) { return(otherData.m_nextGridVehicle); } if (((vehicleData.m_flags | otherData.m_flags) & Vehicle.Flags.Transition) == 0 && (vehicleData.m_flags & Vehicle.Flags.Underground) != (otherData.m_flags & Vehicle.Flags.Underground)) { return(otherData.m_nextGridVehicle); } #if DEBUG bool logLogic = DebugSwitch.ResourceLoading.Get() && (GlobalConfig.Instance.Debug.ApiExtVehicleType == ExtVehicleType.None || GlobalConfig.Instance.Debug.ApiExtVehicleType == ExtVehicleType.RoadVehicle) && (DebugSettings.VehicleId == 0 || DebugSettings.VehicleId == vehicleId); #else const bool logLogic = false; #endif Log._DebugIf( logLogic, () => $"CustomCarAI.CustomCheckOtherVehicle({vehicleId}, {otherID}) called."); Vector3 otherSegMin; Vector3 otherSegMax; if (lodPhysics >= 2) { otherSegMin = otherData.m_segment.Min(); otherSegMax = otherData.m_segment.Max(); } else { otherSegMin = Vector3.Min(otherData.m_segment.Min(), otherData.m_targetPos3); otherSegMax = Vector3.Max(otherData.m_segment.Max(), otherData.m_targetPos3); } if (min.x >= otherSegMax.x + 2f && min.y >= otherSegMax.y + 2f && min.z >= otherSegMax.z + 2f && otherSegMin.x >= max.x + 2f && otherSegMin.y >= max.y + 2f && otherSegMin.z >= max.z + 2f) { return(otherData.m_nextGridVehicle); } Vehicle.Frame otherFrameData = otherData.GetLastFrameData(); if (lodPhysics < 2) { float segSqrDist = vehicleData.m_segment.DistanceSqr(otherData.m_segment, out _, out _); if (segSqrDist < 4f) { Vector3 vehPos = vehicleData.m_segment.Position(0.5f); Vector3 otherPos = otherData.m_segment.Position(0.5f); Vector3 vehBounds = vehicleData.m_segment.b - vehicleData.m_segment.a; if (Vector3.Dot(vehBounds, vehPos - otherPos) < 0f) { collisionPush -= vehBounds.normalized * (0.1f - (segSqrDist * 0.025f)); } else { collisionPush += vehBounds.normalized * (0.1f - (segSqrDist * 0.025f)); } blocked = true; } } float vehVelocity = frameData.m_velocity.magnitude + 0.01f; float otherVehVelocity = otherFrameData.m_velocity.magnitude; float otherBreakingDist = (otherVehVelocity * (0.5f + (0.5f * otherVehVelocity / info.m_braking))) + Mathf.Min(1f, otherVehVelocity); otherVehVelocity += 0.01f; float prevLength = 0f; Vector3 prevTargetPos = vehicleData.m_segment.b; Vector3 prevBounds = vehicleData.m_segment.b - vehicleData.m_segment.a; int startI = (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Tram) ? 1 : 0; for (int i = startI; i < 4; i++) { Vector3 targetPos = vehicleData.GetTargetPos(i); Vector3 targetPosDiff = targetPos - prevTargetPos; if (Vector3.Dot(prevBounds, targetPosDiff) <= 0f) { continue; } float targetPosDiffLen = targetPosDiff.magnitude; Segment3 curSegment = new Segment3(prevTargetPos, targetPos); min = curSegment.Min(); max = curSegment.Max(); curSegment.a.y *= 0.5f; curSegment.b.y *= 0.5f; if (targetPosDiffLen > 0.01f && min.x < otherSegMax.x + 2f && min.y < otherSegMax.y + 2f && min.z < otherSegMax.z + 2f && otherSegMin.x < max.x + 2f && otherSegMin.y < max.y + 2f && otherSegMin.z < max.z + 2f) { Vector3 otherVehFrontPos = otherData.m_segment.a; otherVehFrontPos.y *= 0.5f; if (curSegment.DistanceSqr(otherVehFrontPos, out float u) < 4f) { float otherCosAngleToTargetPosDiff = Vector3.Dot(otherFrameData.m_velocity, targetPosDiff) / targetPosDiffLen; float uDist = prevLength + (targetPosDiffLen * u); if (uDist >= 0.01f) { uDist -= otherCosAngleToTargetPosDiff + 3f; float speed = Mathf.Max( 0f, CalculateMaxSpeed(uDist, otherCosAngleToTargetPosDiff, maxBraking)); if (speed < 0.01f) { blocked = true; } Vector3 normOtherDir = Vector3.Normalize((Vector3)otherData.m_targetPos0 - otherData.m_segment.a); float blockFactor = 1.2f - (1f / ((vehicleData.m_blockCounter * 0.02f) + 0.5f)); if (Vector3.Dot(targetPosDiff, normOtherDir) > blockFactor * targetPosDiffLen) { maxSpeed = Mathf.Min(maxSpeed, speed); } } break; } if (lodPhysics < 2) { float totalDist = 0f; float otherBreakDist = otherBreakingDist; Vector3 otherFrontPos = otherData.m_segment.b; Vector3 otherBounds = otherData.m_segment.b - otherData.m_segment.a; int startOtherTargetPosIndex = (info.m_vehicleType == VehicleInfo.VehicleType.Tram) ? 1 : 0; bool exitTargetPosLoop = false; int otherTargetPosIndex = startOtherTargetPosIndex; while (otherTargetPosIndex < 4 && otherBreakDist > 0.1f) { Vector3 otherTargetPos; if (otherData.m_leadingVehicle == 0) { otherTargetPos = otherData.GetTargetPos(otherTargetPosIndex); } else { if (otherTargetPosIndex != startOtherTargetPosIndex) { break; } Vehicle[] vehiclesBuffer = Singleton <VehicleManager> .instance.m_vehicles.m_buffer; otherTargetPos = vehiclesBuffer[otherData.m_leadingVehicle].m_segment.b; } Vector3 minBreakPos = Vector3.ClampMagnitude(otherTargetPos - otherFrontPos, otherBreakDist); if (Vector3.Dot(otherBounds, minBreakPos) > 0f) { otherTargetPos = otherFrontPos + minBreakPos; float breakPosDist = minBreakPos.magnitude; otherBreakDist -= breakPosDist; Segment3 otherVehNextSegment = new Segment3(otherFrontPos, otherTargetPos); otherVehNextSegment.a.y *= 0.5f; otherVehNextSegment.b.y *= 0.5f; if (breakPosDist > 0.01f) { float otherVehNextSegmentDistToCurSegment = otherID >= vehicleId ? curSegment.DistanceSqr( otherVehNextSegment, out float otherVehNextSegU, out float otherVehNextSegV) : otherVehNextSegment.DistanceSqr( curSegment, out otherVehNextSegV, out otherVehNextSegU); if (otherVehNextSegmentDistToCurSegment < 4f) { float uDist = prevLength + (targetPosDiffLen * otherVehNextSegU); float vDist = totalDist + (breakPosDist * otherVehNextSegV) + 0.1f; if (uDist >= 0.01f && uDist * otherVehVelocity > vDist * vehVelocity) { float otherCosAngleToTargetPosDiff = Vector3.Dot( otherFrameData.m_velocity, targetPosDiff) / targetPosDiffLen; if (uDist >= 0.01f) { uDist -= otherCosAngleToTargetPosDiff + 1f + otherData.Info.m_generatedInfo.m_size.z; float speed = Mathf.Max( 0f, CalculateMaxSpeed(uDist, otherCosAngleToTargetPosDiff, maxBraking)); if (speed < 0.01f) { blocked = true; } maxSpeed = Mathf.Min(maxSpeed, speed); } } exitTargetPosLoop = true; break; } } otherBounds = minBreakPos; totalDist += breakPosDist; otherFrontPos = otherTargetPos; } otherTargetPosIndex++; } if (exitTargetPosLoop) { break; } } } prevBounds = targetPosDiff; prevLength += targetPosDiffLen; prevTargetPos = targetPos; } return(otherData.m_nextGridVehicle); }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays) { /// NON-STOCK CODE START /// ExtVehicleType?vehicleType = CustomVehicleAI.DetermineVehicleTypeFromVehicle(vehicleID, ref vehicleData); //Log._Debug($"CustomTrainAI.CustomStartPathFind. vehicleID={vehicleID}. type={this.GetType().ToString()} vehicleType={vehicleType}"); /// NON-STOCK CODE END /// VehicleInfo info = this.m_info; if ((vehicleData.m_flags & Vehicle.Flags.Spawned) == 0 && Vector3.Distance(startPos, endPos) < 100f) { startPos = endPos; } bool allowUnderground; bool allowUnderground2; if (info.m_vehicleType == VehicleInfo.VehicleType.Metro) { allowUnderground = true; allowUnderground2 = true; } else { allowUnderground = ((vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0); allowUnderground2 = false; } PathUnit.Position startPosA; PathUnit.Position startPosB; float num; float num2; PathUnit.Position endPosA; PathUnit.Position endPosB; float num3; float num4; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out num, out num2) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.PublicTransport, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground2, false, 32f, out endPosA, out endPosB, out num3, out num4)) { if (!startBothWays || num2 > num * 1.2f) { startPosB = default(PathUnit.Position); } if (!endBothWays || num4 > num3 * 1.2f) { endPosB = default(PathUnit.Position); } uint path; bool res = false; if (vehicleType == null) { res = Singleton <PathManager> .instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, false, false, true, false); } else { res = Singleton <CustomPathManager> .instance.CreatePath((ExtVehicleType)vehicleType, out path, ref Singleton <SimulationManager> .instance.m_randomizer, Singleton <SimulationManager> .instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, info.m_vehicleType, 20000f, false, false, true, false); } if (res) { 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); }
public new bool NeedChangeVehicleType(ushort vehicleID, ref Vehicle vehicleData, PathUnit.Position pathPos, uint laneID, VehicleInfo.VehicleType laneVehicleType, ref Vector4 target) { return base.NeedChangeVehicleType(vehicleID, ref vehicleData, pathPos, laneID, laneVehicleType, ref target); }
public bool CustomStartPathFind(ushort vehicleID, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays) { #if DEBUG //Log._Debug($"CustomTramBaseAI.CustomStartPathFind called for vehicle {vehicleID}"); #endif #if BENCHMARK using (var bm = new Benchmark(null, "OnStartPathFind")) { #endif VehicleStateManager.Instance.OnStartPathFind(vehicleID, ref vehicleData, null); #if BENCHMARK } #endif VehicleInfo info = this.m_info; bool allowUnderground; bool allowUnderground2; if (info.m_vehicleType == VehicleInfo.VehicleType.Metro) { allowUnderground = true; allowUnderground2 = true; } else { allowUnderground = ((vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0); allowUnderground2 = false; } PathUnit.Position startPosA; PathUnit.Position startPosB; float startSqrDistA; float startSqrDistB; PathUnit.Position endPosA; PathUnit.Position endPosB; float endSqrDistA; float endSqrDistB; if (CustomPathManager.FindPathPosition(startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground, false, 32f, out startPosA, out startPosB, out startSqrDistA, out startSqrDistB) && CustomPathManager.FindPathPosition(endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground2, false, 32f, out endPosA, out endPosB, out endSqrDistA, out endSqrDistB)) { if (!startBothWays || startSqrDistB > startSqrDistA * 1.2f) { startPosB = default(PathUnit.Position); } if (!endBothWays || endSqrDistB > endSqrDistA * 1.2f) { endPosB = default(PathUnit.Position); } uint path; // NON-STOCK CODE START PathCreationArgs args; args.extPathType = ExtCitizenInstance.ExtPathType.None; args.extVehicleType = ExtVehicleType.Tram; args.vehicleId = vehicleID; args.buildIndex = Singleton <SimulationManager> .instance.m_currentBuildIndex; args.startPosA = startPosA; args.startPosB = startPosB; args.endPosA = endPosA; args.endPosB = endPosB; args.vehiclePosition = default(PathUnit.Position); args.laneTypes = NetInfo.LaneType.Vehicle; args.vehicleTypes = info.m_vehicleType; args.maxLength = 20000f; args.isHeavyVehicle = false; args.hasCombustionEngine = false; args.ignoreBlocked = this.IgnoreBlocked(vehicleID, ref vehicleData); args.ignoreFlooded = false; args.randomParking = false; args.stablePath = true; args.skipQueue = true; if (CustomPathManager._instance.CreatePath(out path, ref Singleton <SimulationManager> .instance.m_randomizer, args)) { // NON-STOCK CODE END if (vehicleData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); } vehicleData.m_path = path; vehicleData.m_flags |= Vehicle.Flags.WaitingPath; return(true); } } return(false); }
// NetSegment.GetClosestLane -- it's only called by the PathManager public static bool GetClosestLanePosition(NetSegment seg, Vector3 point, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool requireConnect, out Vector3 positionA, out int laneIndexA, out float laneOffsetA, out Vector3 positionB, out int laneIndexB, out float laneOffsetB, RoadManager.VehicleType vehicleType) { positionA = point; laneIndexA = -1; laneOffsetA = 0f; positionB = point; laneIndexB = -1; laneOffsetB = 0f; if (seg.m_flags != NetSegment.Flags.None && seg.m_lanes != 0u) { NetInfo info = seg.Info; if (info.m_lanes != null) { float num = 1E+09f; float num2 = 1E+09f; uint num3 = seg.m_lanes; int num4 = 0; while (num4 < info.m_lanes.Length && num3 != 0u) { NetInfo.Lane lane = info.m_lanes[num4]; if (lane.CheckType(laneTypes, vehicleTypes) && (lane.m_allowConnect || !requireConnect) && RoadManager.CanUseLane(vehicleType, num3)) { Vector3 vector; float num5; Singleton<NetManager>.instance.m_lanes.m_buffer[(int)((UIntPtr)num3)].GetClosestPosition(point, out vector, out num5); float num6 = Vector3.SqrMagnitude(point - vector); if (lane.m_finalDirection == NetInfo.Direction.Backward || lane.m_finalDirection == NetInfo.Direction.AvoidForward) { if (num6 < num2) { num2 = num6; positionB = vector; laneIndexB = num4; laneOffsetB = num5; } } else if (num6 < num) { num = num6; positionA = vector; laneIndexA = num4; laneOffsetA = num5; } } num3 = Singleton<NetManager>.instance.m_lanes.m_buffer[(int)((UIntPtr)num3)].m_nextLane; num4++; } if (num2 < num) { Vector3 vector2 = positionA; int num7 = laneIndexA; float num8 = laneOffsetA; positionA = positionB; laneIndexA = laneIndexB; laneOffsetA = laneOffsetB; positionB = vector2; laneIndexB = num7; laneOffsetB = num8; } if (!info.m_canCrossLanes) { positionB = point; laneIndexB = -1; laneOffsetB = 0f; } } } return laneIndexA != -1; }
class CustomTramBaseAI : TramBaseAI { // TODO inherit from VehicleAI (in order to keep the correct references to `base`) public void CustomSimulationStep(ushort vehicleId, ref Vehicle vehicleData, Vector3 physicsLodRefPos) { if ((vehicleData.m_flags & Vehicle.Flags.WaitingPath) != 0) { byte pathFindFlags = Singleton <PathManager> .instance.m_pathUnits.m_buffer[vehicleData.m_path].m_pathFindFlags; if ((pathFindFlags & PathUnit.FLAG_READY) != 0) { try { this.PathfindSuccess(vehicleId, ref vehicleData); this.PathFindReady(vehicleId, ref vehicleData); } catch (Exception e) { Log.Warning($"TramBaseAI.PathFindSuccess/PathFindReady({vehicleId}) threw an exception: {e.ToString()}"); vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else if ((pathFindFlags & PathUnit.FLAG_FAILED) != 0 || vehicleData.m_path == 0) { vehicleData.m_flags &= ~Vehicle.Flags.WaitingPath; Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); vehicleData.m_path = 0u; this.PathfindFailure(vehicleId, ref vehicleData); return; } } else { if ((vehicleData.m_flags & Vehicle.Flags.WaitingSpace) != 0) { this.TrySpawn(vehicleId, ref vehicleData); } } // NON-STOCK CODE START #if BENCHMARK using (var bm = new Benchmark(null, "UpdateVehiclePosition")) { #endif VehicleStateManager.Instance.UpdateVehiclePosition(vehicleId, ref vehicleData); #if BENCHMARK } #endif if (!Options.isStockLaneChangerUsed()) { #if BENCHMARK using (var bm = new Benchmark(null, "LogTraffic")) { #endif // Advanced AI traffic measurement VehicleStateManager.Instance.LogTraffic(vehicleId); #if BENCHMARK } #endif } // NON-STOCK CODE END VehicleManager instance = Singleton <VehicleManager> .instance; VehicleInfo info = instance.m_vehicles.m_buffer[(int)vehicleId].Info; info.m_vehicleAI.SimulationStep(vehicleId, ref instance.m_vehicles.m_buffer[(int)vehicleId], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } ushort trailingVehicle = instance.m_vehicles.m_buffer[(int)vehicleId].m_trailingVehicle; int num = 0; while (trailingVehicle != 0) { info = instance.m_vehicles.m_buffer[(int)trailingVehicle].Info; info.m_vehicleAI.SimulationStep(trailingVehicle, ref instance.m_vehicles.m_buffer[(int)trailingVehicle], vehicleId, ref vehicleData, 0); if ((vehicleData.m_flags & (Vehicle.Flags.Created | Vehicle.Flags.Deleted)) != Vehicle.Flags.Created) { return; } trailingVehicle = instance.m_vehicles.m_buffer[(int)trailingVehicle].m_trailingVehicle; if (++num > 16384) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if ((vehicleData.m_flags & (Vehicle.Flags.Spawned | Vehicle.Flags.WaitingPath | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo)) == 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } else if (vehicleData.m_blockCounter == 255) { // NON-STOCK CODE START bool mayDespawn = true; #if BENCHMARK using (var bm = new Benchmark(null, "MayDespawn")) { #endif mayDespawn = VehicleBehaviorManager.Instance.MayDespawn(ref vehicleData); #if BENCHMARK } #endif if (mayDespawn) { // NON-STOCK CODE END Singleton <VehicleManager> .instance.ReleaseVehicle(vehicleId); } // NON-STOCK CODE } }
public bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, RoadManager.VehicleType vehicleType) { return this.CreatePath(out unit, ref randomizer, buildIndex, startPosA, startPosB, endPosA, endPosB, default(PathUnit.Position), laneTypes, vehicleTypes, maxLength, isHeavyVehicle, ignoreBlocked, stablePath, skipQueue, vehicleType); }
public void CustomSimulationStep(ushort vehicleID, ref Vehicle vehicleData, ref Vehicle.Frame frameData, ushort leaderID, ref Vehicle leaderData, int lodPhysics) { #if DEBUG bool debug = GlobalConfig.Instance.Debug.Switches[16] && GlobalConfig.Instance.Debug.NodeId == vehicleID; #endif ushort leadingVehicle = vehicleData.m_leadingVehicle; uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; VehicleInfo leaderInfo; if (leaderID != vehicleID) { leaderInfo = leaderData.Info; } else { leaderInfo = this.m_info; } TramBaseAI tramBaseAI = leaderInfo.m_vehicleAI as TramBaseAI; if (leadingVehicle != 0) { frameData.m_position += frameData.m_velocity * 0.4f; } else { frameData.m_position += frameData.m_velocity * 0.5f; } frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f; Vector3 wheelBaseRot = frameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f); Vector3 posAfterWheelRot = frameData.m_position + wheelBaseRot; Vector3 posBeforeWheelRot = frameData.m_position - wheelBaseRot; float acceleration = this.m_info.m_acceleration; float braking = this.m_info.m_braking; float curSpeed = frameData.m_velocity.magnitude; Vector3 afterRotToTargetPos1Diff = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot; float afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude; Quaternion curInvRot = Quaternion.Inverse(frameData.m_rotation); Vector3 curveTangent = curInvRot * frameData.m_velocity; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): ================================================"); Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): leadingVehicle={leadingVehicle} frameData.m_position={frameData.m_position} frameData.m_swayPosition={frameData.m_swayPosition} wheelBaseRot={wheelBaseRot} posAfterWheelRot={posAfterWheelRot} posBeforeWheelRot={posBeforeWheelRot} acceleration={acceleration} braking={braking} curSpeed={curSpeed} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag} curInvRot={curInvRot} curveTangent={curveTangent} this.m_info.m_generatedInfo.m_wheelBase={this.m_info.m_generatedInfo.m_wheelBase}"); } #endif Vector3 forward = Vector3.forward; Vector3 targetMotion = Vector3.zero; float targetSpeed = 0f; float motionFactor = 0.5f; float turnAngle = 0f; if (leadingVehicle != 0) { VehicleManager vehMan = Singleton <VehicleManager> .instance; Vehicle.Frame leadingVehLastFrameData = vehMan.m_vehicles.m_buffer[(int)leadingVehicle].GetLastFrameData(); VehicleInfo leadingVehInfo = vehMan.m_vehicles.m_buffer[(int)leadingVehicle].Info; float attachOffset; if ((vehicleData.m_flags & Vehicle.Flags.Inverted) != (Vehicle.Flags) 0) { attachOffset = this.m_info.m_attachOffsetBack - this.m_info.m_generatedInfo.m_size.z * 0.5f; } else { attachOffset = this.m_info.m_attachOffsetFront - this.m_info.m_generatedInfo.m_size.z * 0.5f; } float leadingAttachOffset; if ((vehMan.m_vehicles.m_buffer[(int)leadingVehicle].m_flags & Vehicle.Flags.Inverted) != (Vehicle.Flags) 0) { leadingAttachOffset = leadingVehInfo.m_attachOffsetFront - leadingVehInfo.m_generatedInfo.m_size.z * 0.5f; } else { leadingAttachOffset = leadingVehInfo.m_attachOffsetBack - leadingVehInfo.m_generatedInfo.m_size.z * 0.5f; } Vector3 curPosMinusRotAttachOffset = frameData.m_position - frameData.m_rotation * new Vector3(0f, 0f, attachOffset); Vector3 leadingPosPlusRotAttachOffset = leadingVehLastFrameData.m_position + leadingVehLastFrameData.m_rotation * new Vector3(0f, 0f, leadingAttachOffset); wheelBaseRot = leadingVehLastFrameData.m_rotation * new Vector3(0f, 0f, leadingVehInfo.m_generatedInfo.m_wheelBase * 0.5f); Vector3 leadingPosBeforeWheelRot = leadingVehLastFrameData.m_position - wheelBaseRot; if (Vector3.Dot(vehicleData.m_targetPos1 - vehicleData.m_targetPos0, (Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) < 0f && vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0) { int someIndex = -1; InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, 0, ref leaderData, ref someIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f); afterRotToTargetPos1DiffSqrMag = 0f; } float attachRotDist = Mathf.Max(Vector3.Distance(curPosMinusRotAttachOffset, leadingPosPlusRotAttachOffset), 2f); float one = 1f; float attachRotSqrDist = attachRotDist * attachRotDist; float oneSqr = one * one; int i = 0; if (afterRotToTargetPos1DiffSqrMag < attachRotSqrDist) { if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0) { InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, posBeforeWheelRot, posAfterWheelRot, 0, ref leaderData, ref i, 1, 2, attachRotSqrDist, oneSqr); } while (i < 4) { vehicleData.SetTargetPos(i, vehicleData.GetTargetPos(i - 1)); i++; } afterRotToTargetPos1Diff = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot; afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude; } afterRotToTargetPos1Diff = curInvRot * afterRotToTargetPos1Diff; float negTotalAttachLen = -((this.m_info.m_generatedInfo.m_wheelBase + leadingVehInfo.m_generatedInfo.m_wheelBase) * 0.5f + attachOffset + leadingAttachOffset); bool hasPath = false; if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0) { float u1; float u2; if (Line3.Intersect(posAfterWheelRot, vehicleData.m_targetPos1, leadingPosBeforeWheelRot, negTotalAttachLen, out u1, out u2)) { targetMotion = afterRotToTargetPos1Diff * Mathf.Clamp(Mathf.Min(u1, u2) / 0.6f, 0f, 2f); } else { Line3.DistanceSqr(posAfterWheelRot, vehicleData.m_targetPos1, leadingPosBeforeWheelRot, out u1); targetMotion = afterRotToTargetPos1Diff * Mathf.Clamp(u1 / 0.6f, 0f, 2f); } hasPath = true; } if (hasPath) { if (Vector3.Dot(leadingPosBeforeWheelRot - posAfterWheelRot, posAfterWheelRot - posBeforeWheelRot) < 0f) { motionFactor = 0f; } } else { float leadingPosBeforeToAfterWheelRotDist = Vector3.Distance(leadingPosBeforeWheelRot, posAfterWheelRot); motionFactor = 0f; targetMotion = curInvRot * ((leadingPosBeforeWheelRot - posAfterWheelRot) * (Mathf.Max(0f, leadingPosBeforeToAfterWheelRotDist - negTotalAttachLen) / Mathf.Max(1f, leadingPosBeforeToAfterWheelRotDist * 0.6f))); } } else { float estimatedFrameDist = (curSpeed + acceleration) * (0.5f + 0.5f * (curSpeed + acceleration) / braking) + (this.m_info.m_generatedInfo.m_size.z - this.m_info.m_generatedInfo.m_wheelBase) * 0.5f; float maxSpeedAdd = Mathf.Max(curSpeed + acceleration, 2f); float meanSpeedAdd = Mathf.Max((estimatedFrameDist - maxSpeedAdd) / 2f, 2f); float maxSpeedAddSqr = maxSpeedAdd * maxSpeedAdd; float meanSpeedAddSqr = meanSpeedAdd * meanSpeedAdd; if (Vector3.Dot(vehicleData.m_targetPos1 - vehicleData.m_targetPos0, (Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) < 0f && vehicleData.m_path != 0u && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == (Vehicle.Flags) 0) { int someIndex = -1; InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, leaderID, ref leaderData, ref someIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f); afterRotToTargetPos1DiffSqrMag = 0f; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): dot < 0"); } #endif } #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Leading vehicle is 0. vehicleData.m_targetPos0={vehicleData.m_targetPos0} vehicleData.m_targetPos1={vehicleData.m_targetPos1} posBeforeWheelRot={posBeforeWheelRot} posBeforeWheelRot={posAfterWheelRot} estimatedFrameDist={estimatedFrameDist} maxSpeedAdd={maxSpeedAdd} meanSpeedAdd={meanSpeedAdd} maxSpeedAddSqr={maxSpeedAddSqr} meanSpeedAddSqr={meanSpeedAddSqr} afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag}"); } #endif int posIndex = 0; bool hasValidPathTargetPos = false; if ((afterRotToTargetPos1DiffSqrMag < maxSpeedAddSqr || vehicleData.m_targetPos3.w < 0.01f) && (leaderData.m_flags & (Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped)) == (Vehicle.Flags) 0) { if (vehicleData.m_path != 0u) { InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, posBeforeWheelRot, posAfterWheelRot, leaderID, ref leaderData, ref posIndex, 1, 4, maxSpeedAddSqr, meanSpeedAddSqr); } if (posIndex < 4) { hasValidPathTargetPos = true; while (posIndex < 4) { vehicleData.SetTargetPos(posIndex, vehicleData.GetTargetPos(posIndex - 1)); posIndex++; } } afterRotToTargetPos1Diff = (Vector3)vehicleData.m_targetPos1 - posAfterWheelRot; afterRotToTargetPos1DiffSqrMag = afterRotToTargetPos1Diff.sqrMagnitude; } #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): posIndex={posIndex} hasValidPathTargetPos={hasValidPathTargetPos}"); } #endif if (leaderData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0) { NetManager netMan = Singleton <NetManager> .instance; byte leaderPathPosIndex = leaderData.m_pathPositionIndex; byte leaderLastPathOffset = leaderData.m_lastPathOffset; if (leaderPathPosIndex == 255) { leaderPathPosIndex = 0; } int noise; float leaderLen = 1f + leaderData.CalculateTotalLength(leaderID, out noise); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): leaderPathPosIndex={leaderPathPosIndex} leaderLastPathOffset={leaderLastPathOffset} leaderPathPosIndex={leaderPathPosIndex} leaderLen={leaderLen}"); } #endif // reserve space / add traffic PathManager pathMan = Singleton <PathManager> .instance; PathUnit.Position pathPos; if (pathMan.m_pathUnits.m_buffer[leaderData.m_path].GetPosition(leaderPathPosIndex >> 1, out pathPos)) { netMan.m_segments.m_buffer[(int)pathPos.m_segment].AddTraffic(Mathf.RoundToInt(leaderLen * 2.5f), noise); bool reservedSpaceOnCurrentLane = false; if ((leaderPathPosIndex & 1) == 0 || leaderLastPathOffset == 0) { uint laneId = PathManager.GetLaneID(pathPos); if (laneId != 0u) { Vector3 curPathOffsetPos = netMan.m_lanes.m_buffer[laneId].CalculatePosition((float)pathPos.m_offset * 0.003921569f); float speedAdd = 0.5f * curSpeed * curSpeed / this.m_info.m_braking; float afterWheelRotCurPathOffsetDist = Vector3.Distance(posAfterWheelRot, curPathOffsetPos); float beforeWheelRotCurPathOffsetDist = Vector3.Distance(posBeforeWheelRot, curPathOffsetPos); if (Mathf.Min(afterWheelRotCurPathOffsetDist, beforeWheelRotCurPathOffsetDist) >= speedAdd - 1f) { netMan.m_lanes.m_buffer[laneId].ReserveSpace(leaderLen); reservedSpaceOnCurrentLane = true; } } } if (!reservedSpaceOnCurrentLane && pathMan.m_pathUnits.m_buffer[leaderData.m_path].GetNextPosition(leaderPathPosIndex >> 1, out pathPos)) { uint nextLaneId = PathManager.GetLaneID(pathPos); if (nextLaneId != 0u) { netMan.m_lanes.m_buffer[nextLaneId].ReserveSpace(leaderLen); } } } if ((ulong)(currentFrameIndex >> 4 & 15u) == (ulong)((long)(leaderID & 15))) { // check if vehicle can proceed to next path position bool canProceeed = false; uint curLeaderPathId = leaderData.m_path; int curLeaderPathPosIndex = leaderPathPosIndex >> 1; int k = 0; while (k < 5) { bool invalidPos; if (PathUnit.GetNextPosition(ref curLeaderPathId, ref curLeaderPathPosIndex, out pathPos, out invalidPos)) { uint laneId = PathManager.GetLaneID(pathPos); if (laneId != 0u && !netMan.m_lanes.m_buffer[laneId].CheckSpace(leaderLen)) { k++; continue; } } if (invalidPos) { this.InvalidPath(vehicleID, ref vehicleData, leaderID, ref leaderData); } canProceeed = true; break; } if (!canProceeed) { leaderData.m_flags |= Vehicle.Flags.Congestion; } } } float maxSpeed; if ((leaderData.m_flags & Vehicle.Flags.Stopped) != (Vehicle.Flags) 0) { maxSpeed = 0f; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is stopped. maxSpeed={maxSpeed}"); } #endif } else { maxSpeed = Mathf.Min(vehicleData.m_targetPos1.w, GetMaxSpeed(leaderID, ref leaderData)); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is not stopped. maxSpeed={maxSpeed}"); } #endif } #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Start of second part. curSpeed={curSpeed} curInvRot={curInvRot}"); } #endif afterRotToTargetPos1Diff = curInvRot * afterRotToTargetPos1Diff; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} (old afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag})"); } #endif Vector3 zero = Vector3.zero; bool blocked = false; float forwardLen = 0f; if (afterRotToTargetPos1DiffSqrMag > 1f) // TODO why is this not recalculated? { forward = VectorUtils.NormalizeXZ(afterRotToTargetPos1Diff, out forwardLen); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1DiffSqrMag > 1f. forward={forward} forwardLen={forwardLen}"); } #endif if (forwardLen > 1f) { Vector3 fwd = afterRotToTargetPos1Diff; maxSpeedAdd = Mathf.Max(curSpeed, 2f); maxSpeedAddSqr = maxSpeedAdd * maxSpeedAdd; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): forwardLen > 1f. fwd={fwd} maxSpeedAdd={maxSpeedAdd} maxSpeedAddSqr={maxSpeedAddSqr}"); } #endif if (afterRotToTargetPos1DiffSqrMag > maxSpeedAddSqr) { float fwdLimiter = maxSpeedAdd / Mathf.Sqrt(afterRotToTargetPos1DiffSqrMag); fwd.x *= fwdLimiter; fwd.y *= fwdLimiter; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1DiffSqrMag > maxSpeedAddSqr. afterRotToTargetPos1DiffSqrMag={afterRotToTargetPos1DiffSqrMag} maxSpeedAddSqr={maxSpeedAddSqr} fwdLimiter={fwdLimiter} fwd={fwd}"); } #endif } if (fwd.z < -1f) // !!! { #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): fwd.z < -1f. fwd={fwd}"); } #endif if (vehicleData.m_path != 0u && (leaderData.m_flags & Vehicle.Flags.WaitingPath) == (Vehicle.Flags) 0) { Vector3 targetPos0TargetPos1Diff = vehicleData.m_targetPos1 - vehicleData.m_targetPos0; if ((curInvRot * targetPos0TargetPos1Diff).z < -0.01f) // !!! { #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): (curInvRot * targetPos0TargetPos1Diff).z < -0.01f. curInvRot={curInvRot} targetPos0TargetPos1Diff={targetPos0TargetPos1Diff}"); } #endif if (afterRotToTargetPos1Diff.z < Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f) // !!! { #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff.z < Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f. fwd={fwd} targetPos0TargetPos1Diff={targetPos0TargetPos1Diff} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff}"); } #endif /*fwd.z = 0f; * afterRotToTargetPos1Diff = Vector3.zero;*/ maxSpeed = 0.5f; // NON-STOCK CODE #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): (1) set maxSpeed={maxSpeed}"); } #endif } else { posAfterWheelRot = posBeforeWheelRot + Vector3.Normalize(vehicleData.m_targetPos1 - vehicleData.m_targetPos0) * this.m_info.m_generatedInfo.m_wheelBase; posIndex = -1; InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, vehicleData.m_targetPos1, leaderID, ref leaderData, ref posIndex, 0, 0, Vector3.SqrMagnitude(vehicleData.m_targetPos1 - vehicleData.m_targetPos0) + 1f, 1f); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): afterRotToTargetPos1Diff.z >= Mathf.Abs(afterRotToTargetPos1Diff.x) * -10f. Invoked UpdatePathTargetPositions. posAfterWheelRot={posAfterWheelRot} posBeforeWheelRot={posBeforeWheelRot} this.m_info.m_generatedInfo.m_wheelBase={this.m_info.m_generatedInfo.m_wheelBase}"); } #endif } } else { posIndex = -1; InvokeUpdatePathTargetPositions(tramBaseAI, vehicleID, ref vehicleData, vehicleData.m_targetPos0, posBeforeWheelRot, leaderID, ref leaderData, ref posIndex, 0, 0, Vector3.SqrMagnitude(posBeforeWheelRot - (Vector3)vehicleData.m_targetPos0) + 1f, 1f); vehicleData.m_targetPos1 = posAfterWheelRot; fwd.z = 0f; afterRotToTargetPos1Diff = Vector3.zero; maxSpeed = 0f; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is waiting for a path. posIndex={posIndex} vehicleData.m_targetPos1={vehicleData.m_targetPos1} fwd={fwd} afterRotToTargetPos1Diff={afterRotToTargetPos1Diff} maxSpeed={maxSpeed}"); } #endif } } motionFactor = 0f; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Reset motion factor. motionFactor={motionFactor}"); } #endif } forward = VectorUtils.NormalizeXZ(fwd, out forwardLen); float curve = Mathf.PI / 2f /* 1.57079637f*/ * (1f - forward.z); // <- constant: a bit inaccurate PI/2 if (forwardLen > 1f) { curve /= forwardLen; } float targetDist = forwardLen; #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): targetDist={targetDist} fwd={fwd} curve={curve} maxSpeed={maxSpeed}"); } #endif if (vehicleData.m_targetPos1.w < 0.1f) { maxSpeed = this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve); maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos1.w, braking * 0.9f)); } else { maxSpeed = Mathf.Min(maxSpeed, this.CalculateTargetSpeed(vehicleID, ref vehicleData, 1000f, curve)); } #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [1] maxSpeed={maxSpeed}"); } #endif maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos2.w, braking * 0.9f)); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [2] maxSpeed={maxSpeed}"); } #endif targetDist += VectorUtils.LengthXZ(vehicleData.m_targetPos2 - vehicleData.m_targetPos1); maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, vehicleData.m_targetPos3.w, braking * 0.9f)); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [3] maxSpeed={maxSpeed}"); } #endif targetDist += VectorUtils.LengthXZ(vehicleData.m_targetPos3 - vehicleData.m_targetPos2); if (vehicleData.m_targetPos3.w < 0.01f) { targetDist = Mathf.Max(0f, targetDist + (this.m_info.m_generatedInfo.m_wheelBase - this.m_info.m_generatedInfo.m_size.z) * 0.5f); } maxSpeed = Mathf.Min(maxSpeed, CalculateMaxSpeed(targetDist, 0f, braking * 0.9f)); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): [4] maxSpeed={maxSpeed}"); } #endif CarAI.CheckOtherVehicles(vehicleID, ref vehicleData, ref frameData, ref maxSpeed, ref blocked, ref zero, estimatedFrameDist, braking * 0.9f, lodPhysics); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): CheckOtherVehicles finished. blocked={blocked}"); } #endif if (maxSpeed < curSpeed) { float brake = Mathf.Max(acceleration, Mathf.Min(braking, curSpeed)); targetSpeed = Mathf.Max(maxSpeed, curSpeed - brake); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): maxSpeed < curSpeed. maxSpeed={maxSpeed} curSpeed={curSpeed} brake={brake} targetSpeed={targetSpeed}"); } #endif } else { float accel = Mathf.Max(acceleration, Mathf.Min(braking, -curSpeed)); targetSpeed = Mathf.Min(maxSpeed, curSpeed + accel); #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): maxSpeed >= curSpeed. maxSpeed={maxSpeed} curSpeed={curSpeed} accel={accel} targetSpeed={targetSpeed}"); } #endif } } } else if (curSpeed < 0.1f && hasValidPathTargetPos && leaderInfo.m_vehicleAI.ArriveAtDestination(leaderID, ref leaderData)) { leaderData.Unspawn(leaderID); return; } if ((leaderData.m_flags & Vehicle.Flags.Stopped) == (Vehicle.Flags) 0 && maxSpeed < 0.1f) { #if DEBUG if (debug) { Log._Debug($"CustomTramBaseAI.SimulationStep({vehicleID}): Vehicle is not stopped but maxSpeed < 0.1. maxSpeed={maxSpeed}"); } #endif blocked = true; } if (blocked) { leaderData.m_blockCounter = (byte)Mathf.Min((int)(leaderData.m_blockCounter + 1), 255); } else { leaderData.m_blockCounter = 0; } if (forwardLen > 1f) { turnAngle = Mathf.Asin(forward.x) * Mathf.Sign(targetSpeed); targetMotion = forward * targetSpeed; } else { Vector3 vel = Vector3.ClampMagnitude(afterRotToTargetPos1Diff * 0.5f - curveTangent, braking); targetMotion = curveTangent + vel; } } bool mayBlink = (currentFrameIndex + (uint)leaderID & 16u) != 0u; Vector3 springs = targetMotion - curveTangent; Vector3 targetAfterWheelRotMotion = frameData.m_rotation * targetMotion; Vector3 targetBeforeWheelRotMotion = Vector3.Normalize((Vector3)vehicleData.m_targetPos0 - posBeforeWheelRot) * (targetMotion.magnitude * motionFactor); targetBeforeWheelRotMotion -= targetAfterWheelRotMotion * (Vector3.Dot(targetAfterWheelRotMotion, targetBeforeWheelRotMotion) / Mathf.Max(1f, targetAfterWheelRotMotion.sqrMagnitude)); posAfterWheelRot += targetAfterWheelRotMotion; posBeforeWheelRot += targetBeforeWheelRotMotion; frameData.m_rotation = Quaternion.LookRotation(posAfterWheelRot - posBeforeWheelRot); Vector3 targetPos = posAfterWheelRot - frameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f); frameData.m_velocity = targetPos - frameData.m_position; if (leadingVehicle != 0) { frameData.m_position += frameData.m_velocity * 0.6f; } else { frameData.m_position += frameData.m_velocity * 0.5f; } frameData.m_swayVelocity = frameData.m_swayVelocity * (1f - this.m_info.m_dampers) - springs * (1f - this.m_info.m_springs) - frameData.m_swayPosition * this.m_info.m_springs; frameData.m_swayPosition += frameData.m_swayVelocity * 0.5f; frameData.m_steerAngle = 0f; frameData.m_travelDistance += targetMotion.z; if (leadingVehicle != 0) { frameData.m_lightIntensity = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[(int)leaderID].GetLastFrameData().m_lightIntensity; } else { frameData.m_lightIntensity.x = 5f; frameData.m_lightIntensity.y = ((springs.z >= -0.1f) ? 0.5f : 5f); frameData.m_lightIntensity.z = ((turnAngle >= -0.1f || !mayBlink) ? 0f : 5f); frameData.m_lightIntensity.w = ((turnAngle <= 0.1f || !mayBlink) ? 0f : 5f); } frameData.m_underground = ((vehicleData.m_flags & Vehicle.Flags.Underground) != (Vehicle.Flags) 0); frameData.m_transition = ((vehicleData.m_flags & Vehicle.Flags.Transition) != (Vehicle.Flags) 0); //base.SimulationStep(vehicleID, ref vehicleData, ref frameData, leaderID, ref leaderData, lodPhysics); }
protected virtual bool ProcessOffer(ushort buildingID, ref Building data, TransferManager.TransferReason material, TransferManager.TransferOffer offer, TransferManager.TransferReason trTarget, StartTransferCallStructure tup, U instance) { if (material == trTarget) { ServiceSystemDefinition def = ServiceSystemDefinition.from(instance.m_info, tup.vehicleType); if (def == null) { SVMUtils.doLog("SSD Não definido para: {0} {1} {2} {3}", instance.m_info.m_class.m_service, instance.m_info.m_class.m_subService, tup.vehicleLevel ?? instance.m_info.m_class.m_level, tup.vehicleType); return(false); } #region District Check var ext = def.GetTransportExtension(); if (ext.GetAllowDistrictServiceRestrictions()) { var buildingDistrict = DistrictManager.instance.GetDistrict(data.m_position); var offerDistrict = DistrictManager.instance.GetDistrict(offer.Position); if (buildingDistrict != offerDistrict) { if (ServiceVehiclesManagerMod.debugMode) { SVMUtils.doLog($"Building serving different district: building {data.Info} ({buildingID} - districtId {buildingDistrict} {DistrictManager.instance.GetDistrictName(buildingDistrict)}) => offerDistrict: {offerDistrict} {DistrictManager.instance.GetDistrictName(offerDistrict)}"); } if (!ext.GetAllowOutsidersEffective(offerDistrict)) { var districtBuildings = SVMBuildingUtils.getAllBuildingsFromCity(def, offerDistrict, true, true); if (ServiceVehiclesManagerMod.debugMode) { SVMUtils.doLog($"Offer doesn't allow outsiders. Available buildings found: {districtBuildings}"); } if (districtBuildings.Count > 0) { var newBuildingId = districtBuildings[Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)districtBuildings.Count)]; return(ProcessOffer(newBuildingId, ref BuildingManager.instance.m_buildings.m_buffer[newBuildingId], material, offer, trTarget, tup, instance)); } if (ServiceVehiclesManagerMod.debugMode) { SVMUtils.doLog($"Ignoring because no buildings can handle it"); } } if (!ext.GetAllowGoOutsideEffective(buildingDistrict)) { var districtBuildings = SVMBuildingUtils.getAllBuildingsFromCity(def, offerDistrict, false, true); if (ServiceVehiclesManagerMod.debugMode) { SVMUtils.doLog($"Building district doesn't allow go out. Available buildings found: {districtBuildings}"); } if (districtBuildings.Count > 0) { var newBuildingId = districtBuildings[Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)districtBuildings.Count)]; return(ProcessOffer(newBuildingId, ref BuildingManager.instance.m_buildings.m_buffer[newBuildingId], material, offer, trTarget, tup, instance)); } if (ServiceVehiclesManagerMod.debugMode) { SVMUtils.doLog($"Ignoring because no buildings can handle it (2)"); } } } } #endregion SVMUtils.doLog("[{1}] SSD = {0}", def, material); VehicleInfo randomVehicleInfo = ServiceSystemDefinition.availableDefinitions[def].GetAModel(buildingID); SVMUtils.doLog("[{1}] Veh = {0}", randomVehicleInfo?.ToString() ?? "<NULL>", material); if (randomVehicleInfo != null) { Array16 <Vehicle> vehicles = Singleton <VehicleManager> .instance.m_vehicles; instance.CalculateSpawnPosition(buildingID, ref data, ref Singleton <SimulationManager> .instance.m_randomizer, randomVehicleInfo, out Vector3 position, out Vector3 vector2); if (Singleton <VehicleManager> .instance.CreateVehicle(out ushort num, ref Singleton <SimulationManager> .instance.m_randomizer, randomVehicleInfo, position, material, tup.tramsferToSource, tup.transferToTarget)) { randomVehicleInfo.m_vehicleAI.SetSource(num, ref vehicles.m_buffer[(int)num], buildingID); randomVehicleInfo.m_vehicleAI.StartTransfer(num, ref vehicles.m_buffer[(int)num], material, offer); return(true); } } } return(false); }
public static int spawn_vehicle(Vehicle veh, Vector3 pos) { var returnCode = veh.Spawn(pos); if (returnCode == 1) { API.Shared.SetEntityData(veh.NetHandle, "Vehicle", veh); } API.Shared.SetVehicleEngineStatus(veh.NetHandle, false); if (veh.OwnerId != 0) { API.Shared.SetVehicleLocked(veh.NetHandle, true); } if (veh.Group.CommandType == Group.CommandTypeLspd) { API.Shared.SetVehicleEnginePowerMultiplier(veh.NetHandle, 4); } //Install modifications. ModdingManager.ApplyVehicleMods(veh); //Set wheel type. GrandTheftMultiplayer.Server.API.Shared.Red.setVehicleWheelType(veh.NetHandle, VehicleInfo.Get(veh.VehModel).wheelType); return(returnCode); }
protected static bool StartPathFind(ushort segmentId, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue) { if (data.m_path != 0u) { Singleton<PathManager>.instance.ReleasePath(data.m_path); data.m_path = 0u; } NetManager instance = Singleton<NetManager>.instance; if ((instance.m_nodes.m_buffer[data.m_startNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) { for (int i = 0; i < 8; i++) { ushort segment = instance.m_nodes.m_buffer[data.m_startNode].GetSegment(i); if (segment != 0 && segment != segmentId && instance.m_segments.m_buffer[segment].m_path != 0u) { return true; } } } if ((instance.m_nodes.m_buffer[data.m_endNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) { for (int j = 0; j < 8; j++) { ushort segment2 = instance.m_nodes.m_buffer[data.m_endNode].GetSegment(j); if (segment2 != 0 && segment2 != segmentId && instance.m_segments.m_buffer[segment2].m_path != 0u) { return true; } } } var position = instance.m_nodes.m_buffer[data.m_startNode].m_position; var position2 = instance.m_nodes.m_buffer[data.m_endNode].m_position; PathUnit.Position startPosA; PathUnit.Position startPosB; float num; float num2; if (!PathManager.FindPathPosition(position, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, true, 32f, out startPosA, out startPosB, out num, out num2)) { return true; } PathUnit.Position endPosA; PathUnit.Position endPosB; float num3; float num4; if (!PathManager.FindPathPosition(position2, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, true, true, 32f, out endPosA, out endPosB, out num3, out num4)) { return true; } if ((instance.m_nodes.m_buffer[data.m_startNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) { startPosB = default(PathUnit.Position); } if ((instance.m_nodes.m_buffer[data.m_endNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) { endPosB = default(PathUnit.Position); } startPosA.m_offset = 128; startPosB.m_offset = 128; endPosA.m_offset = 128; endPosB.m_offset = 128; bool stopLane = GetStopLane(ref startPosA, vehicleType); bool stopLane2 = GetStopLane(ref startPosB, vehicleType); bool stopLane3 = GetStopLane(ref endPosA, vehicleType); bool stopLane4 = GetStopLane(ref endPosB, vehicleType); if ((!stopLane && !stopLane2) || (!stopLane3 && !stopLane4)) { return true; } uint path; if (Singleton<CustomPathManager>.instance.CreatePath(out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle, vehicleType, 20000f, false, true, true, skipQueue, ItemClass.Service.PublicTransport)) { if (startPosA.m_segment != 0 && startPosB.m_segment != 0) { var expr_2D9Cp0 = instance.m_nodes.m_buffer; var expr_2D9Cp1 = data.m_startNode; expr_2D9Cp0[expr_2D9Cp1].m_flags = (expr_2D9Cp0[expr_2D9Cp1].m_flags | NetNode.Flags.Ambiguous); } else { var expr305Cp0 = instance.m_nodes.m_buffer; var expr305Cp1 = data.m_startNode; expr305Cp0[expr305Cp1].m_flags = (expr305Cp0[expr305Cp1].m_flags & ~NetNode.Flags.Ambiguous); } if (endPosA.m_segment != 0 && endPosB.m_segment != 0) { var expr344Cp0 = instance.m_nodes.m_buffer; var expr344Cp1 = data.m_endNode; expr344Cp0[expr344Cp1].m_flags = (expr344Cp0[expr344Cp1].m_flags | NetNode.Flags.Ambiguous); } else { var expr370Cp0 = instance.m_nodes.m_buffer; var expr370Cp1 = data.m_endNode; expr370Cp0[expr370Cp1].m_flags = (expr370Cp0[expr370Cp1].m_flags & ~NetNode.Flags.Ambiguous); } data.m_path = path; data.m_flags |= NetSegment.Flags.WaitingPath; return false; } return true; }
public bool CustomStartPathFind(ushort vehicleId, ref Vehicle vehicleData, Vector3 startPos, Vector3 endPos, bool startBothWays, bool endBothWays) { VehicleInfo info = m_info; bool allowUnderground = (vehicleData.m_flags & (Vehicle.Flags.Underground | Vehicle.Flags.Transition)) != 0; if (!PathManager.FindPathPosition( startPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, allowUnderground, false, 32f, out PathUnit.Position startPosA, out PathUnit.Position startPosB, out float startDistSqrA, out float startDistSqrB) || !PathManager.FindPathPosition( endPos, ItemClass.Service.Road, NetInfo.LaneType.Vehicle, info.m_vehicleType, false, false, 32f, out PathUnit.Position endPosA, out PathUnit.Position endPosB, out float endDistSqrA, out float endDistSqrB)) { return(false); } if (!startBothWays || startDistSqrB > startDistSqrA * 1.2f) { startPosB = default(PathUnit.Position); } if (!endBothWays || endDistSqrB > endDistSqrA * 1.2f) { endPosB = default(PathUnit.Position); } // NON-STOCK CODE START PathCreationArgs args; args.extPathType = ExtPathType.None; args.extVehicleType = ExtVehicleType.Trolleybus; args.vehicleId = vehicleId; args.spawned = (vehicleData.m_flags & Vehicle.Flags.Spawned) != 0; args.buildIndex = Singleton <SimulationManager> .instance.m_currentBuildIndex; args.startPosA = startPosA; args.startPosB = startPosB; args.endPosA = endPosA; args.endPosB = endPosB; args.vehiclePosition = default; args.laneTypes = NetInfo.LaneType.Vehicle; args.vehicleTypes = info.m_vehicleType; args.maxLength = 20000f; args.isHeavyVehicle = IsHeavyVehicle(); args.hasCombustionEngine = CombustionEngine(); args.ignoreBlocked = IgnoreBlocked(vehicleId, ref vehicleData); args.ignoreFlooded = false; args.randomParking = false; args.ignoreCosts = false; args.stablePath = true; args.skipQueue = true; if (CustomPathManager._instance.CustomCreatePath( out uint path, ref Singleton <SimulationManager> .instance.m_randomizer, args)) { // NON-STOCK CODE END if (vehicleData.m_path != 0u) { Singleton <PathManager> .instance.ReleasePath(vehicleData.m_path); } vehicleData.m_path = path; vehicleData.m_flags |= Vehicle.Flags.WaitingPath; return(true); } return(false); }
public static bool CustomStartPathFind(ushort segmentID, ref NetSegment data, ItemClass.Service netService, VehicleInfo.VehicleType vehicleType, bool skipQueue) { if (data.m_path != 0u) { Singleton<PathManager>.instance.ReleasePath(data.m_path); data.m_path = 0u; } NetManager instance = Singleton<NetManager>.instance; if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) { for (int i = 0; i < 8; i++) { ushort segment = instance.m_nodes.m_buffer[(int)data.m_startNode].GetSegment(i); if (segment != 0 && segment != segmentID && instance.m_segments.m_buffer[(int)segment].m_path != 0u) { return true; } } } if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Ambiguous) != NetNode.Flags.None) { for (int j = 0; j < 8; j++) { ushort segment2 = instance.m_nodes.m_buffer[(int)data.m_endNode].GetSegment(j); if (segment2 != 0 && segment2 != segmentID && instance.m_segments.m_buffer[(int)segment2].m_path != 0u) { return true; } } } Vector3 position = instance.m_nodes.m_buffer[(int)data.m_startNode].m_position; Vector3 position2 = instance.m_nodes.m_buffer[(int)data.m_endNode].m_position; PathUnit.Position startPosA; PathUnit.Position startPosB; float num; float num2; if (!PathManager.FindPathPosition(position, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, vehicleType, true, false, 32f, out startPosA, out startPosB, out num, out num2)) { CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data); return true; } PathUnit.Position endPosA; PathUnit.Position endPosB; float num3; float num4; if (!PathManager.FindPathPosition(position2, netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, vehicleType, true, false, 32f, out endPosA, out endPosB, out num3, out num4)) { CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data); return true; } if ((instance.m_nodes.m_buffer[(int)data.m_startNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) { startPosB = default(PathUnit.Position); } if ((instance.m_nodes.m_buffer[(int)data.m_endNode].m_flags & NetNode.Flags.Fixed) != NetNode.Flags.None) { endPosB = default(PathUnit.Position); } startPosA.m_offset = 128; startPosB.m_offset = 128; endPosA.m_offset = 128; endPosB.m_offset = 128; bool stopLane = CustomTransportLineAI.GetStopLane(ref startPosA, vehicleType); bool stopLane2 = CustomTransportLineAI.GetStopLane(ref startPosB, vehicleType); bool stopLane3 = CustomTransportLineAI.GetStopLane(ref endPosA, vehicleType); bool stopLane4 = CustomTransportLineAI.GetStopLane(ref endPosB, vehicleType); if ((!stopLane && !stopLane2) || (!stopLane3 && !stopLane4)) { CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data); return true; } uint path; ExtVehicleType extVehicleType = ExtVehicleType.Bus; if ((vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None) extVehicleType = ExtVehicleType.PassengerTrain; if ((vehicleType & VehicleInfo.VehicleType.Tram) != VehicleInfo.VehicleType.None) extVehicleType = ExtVehicleType.Tram; if ((vehicleType & VehicleInfo.VehicleType.Ship) != VehicleInfo.VehicleType.None) extVehicleType = ExtVehicleType.PassengerShip; if ((vehicleType & VehicleInfo.VehicleType.Plane) != VehicleInfo.VehicleType.None) extVehicleType = ExtVehicleType.PassengerPlane; //Log._Debug($"Transport line. extVehicleType={extVehicleType}"); if (Singleton<CustomPathManager>.instance.CreatePath(extVehicleType, out path, ref Singleton<SimulationManager>.instance.m_randomizer, Singleton<SimulationManager>.instance.m_currentBuildIndex, startPosA, startPosB, endPosA, endPosB, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, vehicleType, 20000f, false, true, true, skipQueue)) { if (startPosA.m_segment != 0 && startPosB.m_segment != 0) { NetNode[] expr_2F5_cp_0 = instance.m_nodes.m_buffer; ushort expr_2F5_cp_1 = data.m_startNode; expr_2F5_cp_0[(int)expr_2F5_cp_1].m_flags = (expr_2F5_cp_0[(int)expr_2F5_cp_1].m_flags | NetNode.Flags.Ambiguous); } else { NetNode[] expr_321_cp_0 = instance.m_nodes.m_buffer; ushort expr_321_cp_1 = data.m_startNode; expr_321_cp_0[(int)expr_321_cp_1].m_flags = (expr_321_cp_0[(int)expr_321_cp_1].m_flags & ~NetNode.Flags.Ambiguous); } if (endPosA.m_segment != 0 && endPosB.m_segment != 0) { NetNode[] expr_360_cp_0 = instance.m_nodes.m_buffer; ushort expr_360_cp_1 = data.m_endNode; expr_360_cp_0[(int)expr_360_cp_1].m_flags = (expr_360_cp_0[(int)expr_360_cp_1].m_flags | NetNode.Flags.Ambiguous); } else { NetNode[] expr_38C_cp_0 = instance.m_nodes.m_buffer; ushort expr_38C_cp_1 = data.m_endNode; expr_38C_cp_0[(int)expr_38C_cp_1].m_flags = (expr_38C_cp_0[(int)expr_38C_cp_1].m_flags & ~NetNode.Flags.Ambiguous); } data.m_path = path; data.m_flags |= NetSegment.Flags.WaitingPath; return false; } CustomTransportLineAI.CheckSegmentProblems(segmentID, ref data); return true; }
public Task SetVehicleTrackingInfo(VehicleInfo info) { _vehicleInfo = info; return(TaskDone.Done); }