/// <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;
                }
            }
        }
Пример #2
0
        /// <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);
        }
Пример #4
0
        /// <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);
            }
        }
Пример #5
0
        /// <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);
            }
        }
Пример #6
0
 /// <summary>
 /// Initializes the helpers.
 /// </summary>
 public static void InitializeHelpers()
 {
     TransferManagerHelper.DeInitialize();
     VehicleHelper.Initialize();
     BulldozeHelper.Initialize();
 }