예제 #1
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);
        }