/// <summary> /// Logs the transfer offers. /// </summary> /// <param name="direction">The direction.</param> /// <param name="offers">The offers.</param> /// <param name="count">The count.</param> /// <param name="amount">The amount.</param> /// <param name="buildings">The buildings.</param> /// <param name="material">The material.</param> private static void DebugListLog( string direction, TransferManager.TransferOffer[] offers, ushort[] count, int[] amount, Building[] buildings, TransferManager.TransferReason material) { for (int priority = 0; priority < 8; priority++) { int index = ((int)material * 8) + priority; for (int i = 0; i < count[index]; i++) { Log.InfoList info = new Log.InfoList(); TransferManager.TransferOffer offer = offers[(index * 256) + i]; info.Add("Active", offer.Active); info.Add("Amount", offer.Amount); info.Add("Priority", offer.Priority); info.Add("Vehicle", offer.Vehicle, VehicleHelper.GetVehicleName(offer.Vehicle)); info.Add("Citizen", offer.Citizen, CitizenHelper.GetCitizenName(offer.Citizen)); info.Add("TransportLine", offer.TransportLine, TransportLineHelper.GetLineName(offer.TransportLine)); info.Add("Building", offer.Building, BuildingHelper.GetBuildingName(offer.Building), BuildingHelper.GetDistrictName(offer.Building)); if (buildings != null && offer.Building > 0 && buildings[offer.Building].Info != null && (buildings[offer.Building].m_flags & Building.Flags.Created) == Building.Flags.Created) { info.Add("Garbage", buildings[offer.Building].m_garbageBuffer); info.Add("Dead", buildings[offer.Building].m_deathProblemTimer); } Log.DevDebug(typeof(TransferManagerHelper), "DebugListLog", direction, material, info); } } }
/// <summary> /// Creates a new instance of an information list with garbage vehicle info. /// </summary> /// <param name="vehicleId">The vehicle identifier.</param> /// <param name="vehicle">The vehicle.</param> /// <param name="dirtyBuildingId">The dirty building identifier.</param> /// <param name="dirtyBuilding">The dirty building.</param> /// <returns>The information list.</returns> private static Log.InfoList NewGarbageVehicleInfoList(ushort vehicleId, ref Vehicle vehicle, ushort dirtyBuildingId, ref Building dirtyBuilding) { Log.InfoList infoList = new Log.InfoList(); infoList.Add("SourceBuilding", vehicle.m_sourceBuilding, BuildingHelper.GetBuildingName(vehicle.m_sourceBuilding)); infoList.Add("Vehicle", vehicleId, VehicleHelper.GetVehicleName(vehicleId)); infoList.Add("DirtyBuilding", dirtyBuildingId, BuildingHelper.GetBuildingName(dirtyBuildingId)); infoList.Add("TargetBuilding", vehicle.m_targetBuilding, BuildingHelper.GetBuildingName(vehicle.m_targetBuilding)); return(infoList); }
/// <summary> /// Updates the specified vehicle. /// </summary> /// <param name="vehicle">The vehicle.</param> public void Update(ref Vehicle vehicle) { this.targetBuildingId = vehicle.m_targetBuilding; this.isTrailer = vehicle.m_leadingVehicle != 0; this.hasCargoParent = vehicle.m_cargoParent != 0; if (this.hasCargoParent && !Global.Settings.Experimental.AllowTrackingOfCargoChildren) { return; } if (this.isTrailer) { if (Global.Settings.Experimental.TrackLostTrailers) { this.UpdateTrailer(ref vehicle); } return; } // Check if vehicle has flag that should be checked. Vehicle.Flags flags = vehicle.m_flags & FlagsToCheck; if ((flags & VehicleHelper.VehicleAll) != ~VehicleHelper.VehicleAll) { Vector3 position = vehicle.GetLastFramePosition(); // Remember first time stamp the vehicle was seen with this flag at this position. if (this.checkFlagSinceFrame == 0 || this.checkFlagSinceTime == 0 || flags != this.checkFlags || Math.Truncate((position - this.checkFlagPosition).sqrMagnitude) > 0) { this.isFlagged = false; this.checkFlags = flags; this.checkFlagPosition = position; this.checkFlagSinceTime = Global.SimulationTime; this.checkFlagSinceFrame = Global.CurrentFrame; } else if (!this.isFlagged && this.CheckFlaggedForFrames > Global.CheckFlagStuckDelay) { // Check if stuck with flag. double delta = this.CheckFlaggedForSeconds; if (delta > Global.Settings.RecoveryCrews.DelaySeconds) { Log.Info(this, "IsFlagged", this.checkFlags, this.VehicleId, delta, VehicleHelper.GetVehicleName(this.VehicleId)); this.isFlagged = true; } } } else if ((this.checkFlags & VehicleHelper.VehicleAll) != ~VehicleHelper.VehicleAll || this.checkFlagSinceTime != 0 || this.checkFlagSinceFrame != 0) { this.isFlagged = false; this.checkFlags = ~VehicleHelper.VehicleAll; this.checkFlagSinceTime = 0; this.checkFlagSinceFrame = 0; } // Check if vehicle is confused. if (ConfusionHelper.VehicleIsConfused(ref vehicle)) { if (this.confusedDeAssignedSinceFrame == 0) { this.confusedDeAssignedSinceFrame = Global.CurrentFrame; } if (this.confusedSinceFrame == 0 || this.confusedSinceTime == 0) { if (Log.LogALot) { Log.DevDebug(this, "Update", "NewConfused", this.VehicleId, this.ConfusedForSeconds, this.ConfusedForFrames, Global.Settings.RecoveryCrews.DelaySeconds, Global.DeAssignConfusedDelay, vehicle.m_targetBuilding, vehicle.m_flags, VehicleHelper.GetVehicleName(this.VehicleId)); } this.isConfused = false; this.confusedSinceTime = Global.SimulationTime; this.confusedSinceFrame = Global.CurrentFrame; this.confusedDeAssignedSinceFrame = Global.CurrentFrame; } else if (!this.isConfused && this.ConfusedForFrames > Global.CheckFlagStuckDelay) { // Check if stuck confused. double delta = this.ConfusedForSeconds; if (delta > Global.Settings.RecoveryCrews.DelaySeconds) { Log.Info(this, "IsConfused", this.VehicleId, delta, VehicleHelper.GetVehicleName(this.VehicleId)); this.isConfused = true; } } } else if (this.confusedSinceTime != 0 || this.confusedSinceFrame != 0 || this.confusedDeAssignedSinceFrame != 0) { this.isConfused = false; this.confusedSinceTime = 0; this.confusedSinceFrame = 0; this.confusedDeAssignedSinceFrame = 0; } this.isStuck = this.isLost || this.isConfused || this.isFlagged || this.isBroken; }
/// <summary> /// Handles the vehicles problems. /// </summary> /// <returns>True if a problem was handled.</returns> public bool HandleProblem() { if (this.hasCargoParent && !((this.isFlagged || this.isLost) && Global.Settings.Experimental.AllowRemovalOfStuckCargoChildren) && !(this.isConfused && Global.Settings.Experimental.AllowRemovalOfConfusedCargoChildren)) { if (Log.LogALot) { Log.DevDebug(this, "HandleProblem", "StuckLostBroken", "IgnoreCargoChild", this.VehicleId, VehicleHelper.GetVehicleName(this.VehicleId)); } this.lastHandledStamp = Global.CurrentFrame; return(false); } if (this.isTrailer && !Global.Settings.Experimental.RemoveLostTrailers) { if (Log.LogALot) { Log.DevDebug(this, "HandleProblem", "StuckLostBroken", "IgnoreTrailer", this.VehicleId, VehicleHelper.GetVehicleName(this.VehicleId)); } this.lastHandledStamp = Global.CurrentFrame; return(false); } if (this.isStuck && this.lastHandledStamp + Global.CheckFlagStuckDelay < Global.CurrentFrame) { try { if (this.isTrailer) { // Remove trailer vehicle. Log.Debug(this, "HandleProblem", "StuckLostBroken", "DeSpawnTrailer", this.VehicleId, this.ExtraInfo, VehicleHelper.GetVehicleName(this.VehicleId)); this.DeSpawnTrailer(); } else { // Remove vehicle. Log.Debug(this, "HandleProblem", "StuckLostBroken", "DeSpawn", this.VehicleId, this.ExtraInfo, VehicleHelper.GetVehicleName(this.VehicleId)); this.DeSpawn(); } return(true); } catch (Exception ex) { Log.Error(this, "HandleProblem", ex, this.VehicleId); this.handlingErrors++; return(this.handlingErrors > 10); } finally { this.isStuck = false; this.lastHandledStamp = Global.CurrentFrame; } } if (this.ConfusedDeAssignedForFrames > Global.DeAssignConfusedDelay && !this.isTrailer && IsDispatchersResponsibility(this.dispatcherType)) { try { // De-assign vehicle. Log.Debug(this, "HandleProblem", "Confused", "DeAssign", this.VehicleId, VehicleHelper.GetVehicleName(this.VehicleId)); this.DeAssign(); } catch (Exception ex) { Log.Error(this, "HandleProblem", ex, this.VehicleId); this.handlingErrors++; return(this.handlingErrors > 10); } finally { this.confusedDeAssignedSinceFrame = Global.CurrentFrame; } } return(false); }
/// <summary> /// Updates the specified trailer vehicle. /// </summary> /// <param name="vehicle">The vehicle.</param> private void UpdateTrailer(ref Vehicle vehicle) { Vehicle[] vehicles = Singleton <VehicleManager> .instance.m_vehicles.m_buffer; LostReasons lost = LostReasons.None; ushort count = 0; ushort leadId = this.VehicleId; ushort nextId = vehicle.m_leadingVehicle; while (nextId != 0) { if (vehicles[nextId].m_trailingVehicle != leadId) { lost = LostReasons.IgnorantLead; break; } if (count >= ushort.MaxValue) { throw new Exception("Loop counter too high"); } count++; leadId = nextId; nextId = vehicles[leadId].m_leadingVehicle; } if (lost == LostReasons.None && (vehicles[leadId].Info == null || (vehicles[leadId].m_flags & Vehicle.Flags.Spawned) == ~VehicleHelper.VehicleAll)) { lost = LostReasons.NoLead; } if (lost != LostReasons.None) { if (this.lostSinceFrame == 0 || this.lostSinceTime == 0 || this.lostReason == LostReasons.None || lost != this.lostReason) { if (Log.LogALot) { Log.DevDebug(this, "UpdateTrailer", "NewLost", lost, this.VehicleId, this.LostForSeconds, this.LostForFrames, Global.Settings.RecoveryCrews.DelaySeconds, Global.CheckFlagStuckDelay, vehicle.m_leadingVehicle, vehicle.m_flags, VehicleHelper.GetVehicleName(this.VehicleId)); } this.isLost = false; this.lostReason = lost; this.lostSinceTime = Global.SimulationTime; this.lostSinceFrame = Global.CurrentFrame; } else if (!this.isLost) { double delta; if (this.lostReason != LostReasons.None && this.LostForFrames > Global.CheckFlagStuckDelay) { delta = this.LostForSeconds; if (delta > Global.Settings.RecoveryCrews.DelaySeconds) { Log.Info(this, "IsLost", lost, this.VehicleId, delta, VehicleHelper.GetVehicleName(this.VehicleId)); this.isLost = true; } } } } else { this.isLost = false; this.lostReason = LostReasons.None; this.lostSinceTime = 0; this.lostSinceFrame = 0; } this.isStuck = this.isLost || this.isConfused || this.isFlagged || this.isBroken; }
/// <summary> /// Categorizes the vehicles. /// </summary> /// <param name="firstVehicleId">The first vehicle identifier.</param> /// <param name="lastVehicleId">The last vehicle identifier.</param> private void HandleVehicles(ushort firstVehicleId, int lastVehicleId) { Vehicle[] vehicles = Singleton <VehicleManager> .instance.m_vehicles.m_buffer; Building[] buildings = Singleton <BuildingManager> .instance.m_buildings.m_buffer; for (ushort id = firstVehicleId; id < lastVehicleId; id++) { // Is the vehicle? if (vehicles[id].m_leadingVehicle != 0 || vehicles[id].m_cargoParent != 0 || vehicles[id].Info == null || (vehicles[id].m_flags & VehicleHelper.VehicleExists) == ~VehicleHelper.VehicleAll) { if (this.removedFromGrid != null && this.removedFromGrid.Contains(id)) { this.removedFromGrid.Remove(id); } if (this.StuckVehicles != null && this.StuckVehicles.ContainsKey(id)) { //if (Log.LogALot) //{ // Log.DevDebug(this, "HandleVehicles", "StuckVehicles", "Gone", id); //} this.StuckVehicles.Remove(id); } } else { // Check target assignments for service vehicles. if ((vehicles[id].m_flags & Vehicle.Flags.TransferToSource) != ~VehicleHelper.VehicleAll && (vehicles[id].m_flags & (Vehicle.Flags.TransferToTarget | Vehicle.Flags.Arriving | Vehicle.Flags.Stopped)) == ~VehicleHelper.VehicleAll && (vehicles[id].m_flags & VehicleHelper.VehicleUnavailable) == ~VehicleHelper.VehicleAll && vehicles[id].m_targetBuilding != vehicles[id].m_sourceBuilding && (buildings[vehicles[id].m_sourceBuilding].m_flags & Building.Flags.Downgrading) == Building.Flags.None) { if (Global.Settings.DeathCare.DispatchVehicles && Global.HearseDispatcher != null && vehicles[id].m_transferType == Global.HearseDispatcher.TransferType) { Global.HearseDispatcher.CheckVehicleTarget(id, ref vehicles[id]); } if (Global.Settings.Garbage.DispatchVehicles && Global.GarbageTruckDispatcher != null && vehicles[id].m_transferType == Global.GarbageTruckDispatcher.TransferType) { Global.GarbageTruckDispatcher.CheckVehicleTarget(id, ref vehicles[id]); } if (Global.Settings.HealthCare.DispatchVehicles && Global.AmbulanceDispatcher != null && vehicles[id].m_transferType == Global.AmbulanceDispatcher.TransferType) { Global.AmbulanceDispatcher.CheckVehicleTarget(id, ref vehicles[id]); } } // Handle grid removals. if (this.removedFromGrid != null) { if ((vehicles[id].m_flags & Vehicle.Flags.Stopped) == ~VehicleHelper.VehicleAll && (vehicles[id].Info.m_vehicleAI is HearseAI || vehicles[id].Info.m_vehicleAI is AmbulanceAI)) { if (this.removedFromGrid.Contains(id)) { if (Log.LogALot) { Log.Debug(this, "HandleVehicles", "Moving", id, vehicles[id].m_targetBuilding, vehicles[id].Info.name, VehicleHelper.GetVehicleName(id), vehicles[id].m_flags); } this.removedFromGrid.Remove(id); } } else if ((Global.Settings.DeathCare.RemoveFromGrid && vehicles[id].Info.m_vehicleAI is HearseAI) || (Global.Settings.HealthCare.RemoveFromGrid && vehicles[id].Info.m_vehicleAI is AmbulanceAI)) { if (!this.removedFromGrid.Contains(id)) { if (Log.LogALot) { Log.Debug(this, "HandleVehicles", "RemoveFromGrid", id, vehicles[id].m_targetBuilding, vehicles[id].Info.name, VehicleHelper.GetVehicleName(id), vehicles[id].m_flags); } Singleton <VehicleManager> .instance.RemoveFromGrid(id, ref vehicles[id], false); this.removedFromGrid.Add(id); } } } // Try to fix stuck vehicles. if (this.StuckVehicles != null) { if (StuckVehicleInfo.HasProblem(id, ref vehicles[id])) { StuckVehicleInfo stuckVehicle; if (this.StuckVehicles.TryGetValue(id, out stuckVehicle)) { stuckVehicle.Update(ref vehicles[id]); } else { stuckVehicle = new StuckVehicleInfo(id, ref vehicles[id]); this.StuckVehicles[id] = stuckVehicle; if (Log.LogALot) { Log.DevDebug(this, "HandleVehicles", "StuckVehicles", "New", id, vehicles[id].m_flags, stuckVehicle.Flagged, stuckVehicle.Lost, stuckVehicle.Confused, stuckVehicle.ExtraInfo); } } if (stuckVehicle.HandleProblem()) { if (Log.LogALot) { Log.DevDebug(this, "HandleVehicles", "StuckVehicles", "Handled", id); } this.StuckVehicles.Remove(id); } } else if (this.StuckVehicles.ContainsKey(id)) { if (Log.LogALot) { Log.DevDebug(this, "HandleVehicles", "StuckVehicles", "NoProblem", id, vehicles[id].m_flags, vehicles[id].m_flags & StuckVehicleInfo.FlagsToCheck, ConfusionHelper.VehicleIsConfused(ref vehicles[id])); } this.StuckVehicles.Remove(id); } } } } }