/// <summary> /// Copied from original game code at game version 1.7.2-f1. /// </summary> public static void TransferManager_AddIncomingOffer_Original(TransferManager transferManager, TransferManager.TransferReason material, TransferManager.TransferOffer offer) { TransferManagerHelper.CheckInstance(transferManager); for (int priority = offer.Priority; priority >= 0; --priority) { int index = (int)material * 8 + priority; int num = (int)TransferManagerHelper.IncomingCount[index]; if (num < 256) { TransferManagerHelper.IncomingOffers[index * 256 + num] = offer; TransferManagerHelper.IncomingCount[index] = (ushort)(num + 1); TransferManagerHelper.IncomingAmount[(int)material] += offer.Amount; break; } } }
/// <summary> /// Starts the transfer. /// </summary> /// <param name="vehicleId">The vehicle identifier.</param> /// <param name="vehicle">The vehicle.</param> /// <param name="material">The material.</param> /// <param name="targetBuildingId">The target building identifier.</param> /// <param name="targetCitizenId">The target citizen identifier.</param> /// <returns>True on success.</returns> private static bool StartTransfer(ushort vehicleId, ref Vehicle vehicle, TransferManager.TransferReason material, ushort targetBuildingId, uint targetCitizenId) { TransferManager.TransferOffer offer = TransferManagerHelper.MakeOffer(targetBuildingId, targetCitizenId); vehicle.m_flags &= ~Vehicle.Flags.GoingBack; vehicle.m_flags |= Vehicle.Flags.WaitingTarget; // Cast AI as games original AI so detoured methods are called, but not methods from not replaced classes. if (Global.Settings.AssignmentCompatibilityMode == ServiceDispatcherSettings.ModCompatibilityMode.UseInstanciatedClassMethods || !Global.Settings.AllowReflection()) { vehicle.Info.m_vehicleAI.StartTransfer(vehicleId, ref vehicle, material, offer); } else if (vehicle.Info.m_vehicleAI is HearseAI) { ((HearseAI)vehicle.Info.m_vehicleAI.CastTo <HearseAI>()).StartTransfer(vehicleId, ref vehicle, material, offer); } else if (vehicle.Info.m_vehicleAI is GarbageTruckAI) { ((GarbageTruckAI)vehicle.Info.m_vehicleAI.CastTo <GarbageTruckAI>()).StartTransfer(vehicleId, ref vehicle, material, offer); } else if (vehicle.Info.m_vehicleAI is AmbulanceAI) { ((AmbulanceAI)vehicle.Info.m_vehicleAI.CastTo <AmbulanceAI>()).StartTransfer(vehicleId, ref vehicle, material, offer); } else { vehicle.Info.m_vehicleAI.StartTransfer(vehicleId, ref vehicle, material, offer); } if (vehicle.m_targetBuilding == targetBuildingId && (targetCitizenId == 0 || Singleton <CitizenManager> .instance.m_citizens.m_buffer[targetCitizenId].m_vehicle == vehicleId)) { return(true); } Log.Warning(typeof(VehicleHelper), "StartTransfer", "Target Not Assigned", vehicleId, targetBuildingId, targetCitizenId, material, vehicle.m_sourceBuilding, vehicle.m_targetBuilding, (TransferManager.TransferReason)vehicle.m_transferType, vehicle.m_flags); return(false); }
/// <summary> /// Starts the transfer. /// </summary> /// <param name="serviceBuildingId">The building identifier.</param> /// <param name="building">The building.</param> /// <param name="material">The material.</param> /// <param name="targetBuildingId">The target building identifier.</param> /// <param name="targetCitizenId">The target citizen identifier.</param> /// <param name="vehicleId">The vehicle identifier.</param> /// <returns>Vehicle info for the created vehicle.</returns> public static VehicleInfo StartTransfer(ushort serviceBuildingId, ref Building building, TransferManager.TransferReason material, ushort targetBuildingId, uint targetCitizenId, out ushort vehicleId) { if (building.Info.m_buildingAI is HospitalAI && targetCitizenId == 0) { return(VehicleHelper.CreateServiceVehicle(serviceBuildingId, material, targetBuildingId, targetCitizenId, out vehicleId)); } Vehicle[] vehicles = Singleton <VehicleManager> .instance.m_vehicles.m_buffer; Citizen[] citizens = Singleton <CitizenManager> .instance.m_citizens.m_buffer; TransferManager.TransferOffer offer = TransferManagerHelper.MakeOffer(targetBuildingId, targetCitizenId); int count; HashSet <ushort> ownVehicles = new HashSet <ushort>(); count = 0; vehicleId = building.m_ownVehicles; while (vehicleId != 0) { ownVehicles.Add(vehicleId); if (count >= ushort.MaxValue) { throw new Exception("Loop counter too high"); } count++; vehicleId = vehicles[vehicleId].m_nextOwnVehicle; } // Cast AI as games original AI so detoured methods are called, but not methods from not replaced classes. if (Global.Settings.CreationCompatibilityMode == ServiceDispatcherSettings.ModCompatibilityMode.UseInstanciatedClassMethods || !Global.Settings.AllowReflection()) { building.Info.m_buildingAI.StartTransfer(serviceBuildingId, ref building, material, offer); } else if (building.Info.m_buildingAI is CemeteryAI) { ((CemeteryAI)building.Info.m_buildingAI.CastTo <CemeteryAI>()).StartTransfer(serviceBuildingId, ref building, material, offer); } else if (building.Info.m_buildingAI is LandfillSiteAI) { ((LandfillSiteAI)building.Info.m_buildingAI.CastTo <LandfillSiteAI>()).StartTransfer(serviceBuildingId, ref building, material, offer); } else if (building.Info.m_buildingAI is HospitalAI) { ((HospitalAI)building.Info.m_buildingAI.CastTo <HospitalAI>()).StartTransfer(serviceBuildingId, ref building, material, offer); } else { building.Info.m_buildingAI.StartTransfer(serviceBuildingId, ref building, material, offer); } ushort newVehicleId = 0; ushort waitingVehicleId = 0; Vehicle.Flags findFlags = Vehicle.Flags.Created; switch (material) { case TransferManager.TransferReason.Dead: case TransferManager.TransferReason.Garbage: case TransferManager.TransferReason.Sick: findFlags |= Vehicle.Flags.TransferToSource; break; case TransferManager.TransferReason.DeadMove: case TransferManager.TransferReason.GarbageMove: case TransferManager.TransferReason.SickMove: findFlags |= Vehicle.Flags.TransferToSource; break; } count = 0; vehicleId = building.m_ownVehicles; while (vehicleId != 0) { if (!ownVehicles.Contains(vehicleId) && (vehicles[vehicleId].m_flags & findFlags) == findFlags && vehicles[vehicleId].Info != null) { if (vehicles[vehicleId].m_targetBuilding == targetBuildingId && (targetCitizenId == 0 || citizens[targetCitizenId].m_vehicle == vehicleId)) { return(vehicles[vehicleId].Info); } newVehicleId = vehicleId; if ((vehicles[vehicleId].m_flags & Vehicle.Flags.WaitingTarget) == Vehicle.Flags.WaitingTarget) { waitingVehicleId = vehicleId; } } if (count >= ushort.MaxValue) { throw new Exception("Loop counter too high"); } count++; vehicleId = vehicles[vehicleId].m_nextOwnVehicle; } if (waitingVehicleId != 0) { vehicleId = waitingVehicleId; //Log.DevDebug(typeof(BuildingHelper), "StartTransfer", "Waiting Vehicle", serviceBuildingId, targetBuildingId, targetCitizenId, material, vehicleId, vehicles[vehicleId].m_flags); } else if (newVehicleId != 0) { vehicleId = newVehicleId; //Log.DevDebug(typeof(BuildingHelper), "StartTransfer", "Guess Vehicle", serviceBuildingId, targetBuildingId, targetCitizenId, material, vehicleId, vehicles[vehicleId].m_flags); } else { vehicleId = 0; Log.Info(typeof(BuildingHelper), "StartTransfer", "Lost Vehicle", serviceBuildingId, targetBuildingId, targetCitizenId, material); return(null); } if (!VehicleHelper.AssignTarget(vehicleId, ref vehicles[vehicleId], material, targetBuildingId, targetCitizenId)) { return(null); } return(vehicles[vehicleId].Info); }
/// <summary> /// Called when game updates. /// </summary> /// <param name="realTimeDelta">The real time delta.</param> /// <param name="simulationTimeDelta">The simulation time delta.</param> public override void OnUpdate(float realTimeDelta, float simulationTimeDelta) { if (this.isBroken) { return; } try { if (this.threadingManager.simulationPaused) { if (!this.called || (Global.CurrentFrame - Log.LastFlush >= Global.LogFlushDelay)) { Log.FlushBuffer(); } return; } Global.SimulationTime += simulationTimeDelta; uint simulationFrame = this.threadingManager.simulationFrame; if (Global.CurrentFrame == simulationFrame) { return; } if (Global.CurrentFrame == 0) { Global.LogDebugLists(); } if (Global.CurrentFrame == 0 && simulationFrame > 0) { this.lastDebugListLog = simulationFrame; } if (this.started && Detours.InitNeeded) { Detours.Initialize(); } Global.CurrentFrame = simulationFrame; if (Global.ServiceProblems != null && Global.CurrentFrame - Global.ServiceProblems.LastUpdate >= Global.ProblemUpdateDelay) { Global.ServiceProblems.Update(); } if (Global.Settings.DispatchAnyVehicles || Global.Settings.AutoEmptyAnyBuildings) { // Do building stuff. if (Global.Buildings != null) { // Update buildings. Global.Buildings.Update(); } // Do vehicle based stuff. if (Global.Vehicles != null) { // Update vehicles. Global.Vehicles.Update(); } // Do building based stuff. if (Global.Buildings != null) { // Dispatch hearses. if (Global.Settings.DeathCare.DispatchVehicles && Global.HearseDispatcher != null) { Global.HearseDispatcher.Dispatch(); } // Dispatch garbage trucks; if (Global.Settings.Garbage.DispatchVehicles && Global.GarbageTruckDispatcher != null) { Global.GarbageTruckDispatcher.Dispatch(); } // Dispatch ambulances. if (Global.Settings.HealthCare.DispatchVehicles && Global.AmbulanceDispatcher != null) { Global.AmbulanceDispatcher.Dispatch(); } } if (Global.TransferOffersCleaningNeeded || Global.CurrentFrame - this.lastTransferOffersClean > Global.CleanTransferOffersDelay) { if (Global.CleanTransferOffers) { TransferManagerHelper.CleanTransferOffers(); } this.lastTransferOffersClean = Global.CurrentFrame; Global.TransferOffersCleaningNeeded = false; } } if (Global.CurrentFrame - this.lastDebugListLog >= Global.DebugListLogDelay) { this.lastDebugListLog = Global.CurrentFrame; Global.LogDebugLists(); } else if (!this.started || (Global.CurrentFrame - Log.LastFlush >= Global.LogFlushDelay)) { Log.FlushBuffer(); } this.started = true; if (this.exceptionCount > 0) { this.exceptionCount--; } } catch (Exception ex) { this.exceptionCount++; if (this.exceptionCount > MaxExceptionCount) { try { Detours.Revert(); } catch (Exception rex) { Log.Error(this, "OnUpdate", rex); } this.isBroken = true; } Log.Error(this, "OnUpdate", ex); } finally { this.called = true; base.OnUpdate(realTimeDelta, simulationTimeDelta); } }
/// <summary> /// Logs the debug lists. /// </summary> /// <param name="initializing">if set to <c>true</c> level is loading.</param> /// <param name="deInitializing">if set to <c>true</c> level is unloading.</param> private static void LogDebugLists(bool initializing, bool deInitializing) { try { bool flush = false; if (initializing) { if (Log.LogDebugLists) { Log.Debug(typeof(Global), "LogDebugLists", "Initializing"); } } else if (deInitializing) { if (Log.LogDebugLists) { Log.Debug(typeof(Global), "LogDebugLists", "DeInitializing"); } } else if (CurrentFrame == 0) { if (Log.LogDebugLists) { Log.Debug(typeof(Global), "LogDebugLists", "Started"); Detours.LogInfo(); TransferManagerHelper.LogInfo(); VehicleHelper.DebugListLog(); BuildingHelper.DebugListLog(); TransferManagerHelper.DebugListLog(); flush = true; } } else if (CurrentFrame > 0) { if (Log.LogDebugLists) { Log.Debug(typeof(Global), "LogDebugLists", "Running"); if (Global.Buildings != null) { Global.Buildings.DebugListLogBuildings(); } if (Global.Vehicles != null) { Global.Vehicles.DebugListLogVehicles(); } TransferManagerHelper.DebugListLog(); flush = true; } if (Global.ServiceProblems != null) { Global.ServiceProblems.DebugListLogServiceProblems(); flush = true; } } if (flush) { Log.FlushBuffer(); } } catch (Exception ex) { Log.Error(typeof(Global), "LogDebugLists", ex); } }
/// <summary> /// Initializes the helpers. /// </summary> public static void InitializeHelpers() { TransferManagerHelper.DeInitialize(); VehicleHelper.Initialize(); BulldozeHelper.Initialize(); }