Ejemplo n.º 1
0
        /// <summary>
        /// Sets the target and updates the games vehicle object.
        /// </summary>
        /// <param name="targetBuildingId">The target building identifier.</param>
        /// <param name="vehicle">The vehicle.</param>
        /// <param name="material">The material.</param>
        /// <returns>The result of the action.</returns>
        public VehicleResult SetTarget(ushort targetBuildingId, ref Vehicle vehicle, TransferManager.TransferReason?material)
        {
            if (targetBuildingId == 0)
            {
                if (this.Target == 0 && vehicle.m_targetBuilding == 0)
                {
                    return(new VehicleResult(true));
                }

                return(this.DeAssign(ref vehicle, true, "SetTarget"));
            }

            if (Log.LogALot)
            {
                Log.DevDebug(this, "SetTarget", this.VehicleId, targetBuildingId, this.Target, vehicle.m_targetBuilding, vehicle.m_flags);
            }

            VehicleResult result = VehicleHelper.AssignTarget(this.VehicleId, ref vehicle, material, targetBuildingId, 0);

            if (result)
            {
                this.LastAssigned  = Global.CurrentFrame;
                this.FreeToCollect = false;
                this.Target        = targetBuildingId;
            }
            else
            {
                Log.Debug(this, "SetTarget", "Failed", this.VehicleId, targetBuildingId, this.Target, vehicle.m_targetBuilding, vehicle.m_flags);

                this.LastAssigned  = 0;
                this.FreeToCollect = false;
                this.Target        = 0;
            }

            return(result);
        }
        /// <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);
        }