Example #1
0
    public void Reduceinfection()//降低感染概率
    {
        //相关数值变动写在这里
        CitizenMgr.ChangeInfectRateOverall(-0.3f);

        CostAndCoolingFunction(1500, 20f, "应政府宣传,人们都带上了口罩。");
    }
Example #2
0
        /// <summary>
        /// The entry method of the custom AI.
        /// </summary>
        ///
        /// <param name="instance">A reference to an object instance of the original AI.</param>
        /// <param name="citizenId">The ID of the citizen to process.</param>
        /// <param name="citizen">A <typeparamref name="TCitizen"/> reference to process.</param>
        public void UpdateLocation(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            if (!EnsureCitizenCanBeProcessed(citizenId, ref citizen))
            {
                return;
            }

            if (CitizenProxy.IsDead(ref citizen) || CitizenProxy.IsSick(ref citizen))
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            switch (CitizenProxy.GetLocation(ref citizen))
            {
            case Citizen.Location.Home:
            case Citizen.Location.Work:
                CitizenMgr.ReleaseCitizen(citizenId);
                break;

            case Citizen.Location.Visit:
                ProcessVisit(instance, citizenId, ref citizen);
                break;

            case Citizen.Location.Moving:
                ProcessMoving(instance, citizenId, ref citizen);
                break;
            }
        }
Example #3
0
        /// <summary>Determines whether the specified citizen must be processed as a virtual citizen.</summary>
        /// <typeparam name="TAI">The type of the citizen's AI.</typeparam>
        /// <param name="humanAI">The citizen AI reference.</param>
        /// <param name="citizen">The citizen to check.</param>
        /// <param name="realizeCitizen">A callback to determine whether a virtual citizen should be realized.</param>
        /// <returns><c>true</c> if the citizen must be processed as a virtual citizen; otherwise, <c>false</c>.</returns>
        protected bool IsCitizenVirtual <TAI>(TAI humanAI, ref TCitizen citizen, Func <TAI, bool> realizeCitizen)
        {
            if (CitizenProxy.GetInstance(ref citizen) != 0)
            {
                return(false);
            }

            uint virtualChance;

            switch (Config.VirtualCitizens)
            {
            case VirtualCitizensLevel.None:
                return(false);

            case VirtualCitizensLevel.Few:
                virtualChance = FewVirtualCitizensChance;
                break;

            case VirtualCitizensLevel.Vanilla:
                return(!realizeCitizen(humanAI));

            case VirtualCitizensLevel.Many:
                virtualChance = ManyVirtualCitizensChance;
                break;

            default:
                return(false);
            }

            return(CitizenMgr.GetInstancesCount() * 100 / CitizenInstancesMaxCount < virtualChance
                ? !realizeCitizen(humanAI)
                : Random.ShouldOccur(virtualChance));
        }
Example #4
0
        private ushort MoveToCommercialBuilding(TAI instance, uint citizenId, ref TCitizen citizen, float distance, bool isVirtual)
        {
            ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (buildingId == 0)
            {
                return(0);
            }

            ushort foundBuilding = BuildingMgr.FindActiveBuilding(buildingId, distance, ItemClass.Service.Commercial);

            if (IsBuildingNoiseRestricted(foundBuilding))
            {
                Log.Debug($"Citizen {citizenId} won't go to the commercial building {foundBuilding}, it has a NIMBY policy");
                return(0);
            }

            if (StartMovingToVisitBuilding(instance, citizenId, ref citizen, foundBuilding, isVirtual))
            {
                ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);
                uint   homeUnit     = BuildingMgr.GetCitizenUnit(homeBuilding);
                uint   citizenUnit  = CitizenProxy.GetContainingUnit(ref citizen, citizenId, homeUnit, CitizenUnit.Flags.Home);
                if (citizenUnit != 0)
                {
                    CitizenMgr.ModifyUnitGoods(citizenUnit, ShoppingGoodsAmount);
                }
            }

            return(foundBuilding);
        }
        private bool CitzenReturnsFromShelter(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (BuildingMgr.GetBuildingService(visitBuilding) != ItemClass.Service.Disaster)
            {
                return(true);
            }

            if (!BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading))
            {
                return(false);
            }

            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding == 0)
            {
                Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen)} was in a shelter but seems to be homeless. Releasing the citizen.");
                CitizenMgr.ReleaseCitizen(citizenId);
                return(true);
            }

            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} returning from evacuation place back home");
            ReturnFromVisit(instance, citizenId, ref citizen, homeBuilding);
            return(true);
        }
Example #6
0
        private void ProcessMoving(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort instanceId = CitizenProxy.GetInstance(ref citizen);
            ushort vehicleId  = CitizenProxy.GetVehicle(ref citizen);

            if (instanceId == 0)
            {
                if (vehicleId == 0)
                {
                    CitizenMgr.ReleaseCitizen(citizenId);
                }

                return;
            }

            if (vehicleId == 0 && CitizenMgr.IsAreaEvacuating(instanceId) && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Leaving the city.");
                touristAI.FindVisitPlace(instance, citizenId, CitizenProxy.GetCurrentBuilding(ref citizen), touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, true))
            {
                FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, 0);
            }
        }
        private void ProcessCitizenAtHome(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            if (CitizenProxy.GetHomeBuilding(ref citizen) == 0)
            {
                Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is in corrupt state: at home with no home building. Releasing the poor citizen.");
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            ushort vehicle = CitizenProxy.GetVehicle(ref citizen);

            if (vehicle != 0)
            {
                Log.Debug(TimeInfo.Now, $"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is at home but vehicle = {vehicle}");
                return;
            }

            if (CitizenGoesWorking(instance, citizenId, ref citizen))
            {
                return;
            }

            if (IsBusyAtHomeInTheMorning(CitizenProxy.GetAge(ref citizen)) || !residentAI.DoRandomMove(instance))
            {
                return;
            }

            if (CitizenGoesShopping(instance, citizenId, ref citizen) || CitizenGoesToEvent(instance, citizenId, ref citizen))
            {
                return;
            }

            CitizenGoesRelaxing(instance, citizenId, ref citizen);
        }
Example #8
0
 public override void TransitionReason()
 {
     if (mCitizen.timeAlive > mCitizen.ToHospTimeTotal)
     {
         mFSMSystem.TransitionFSMState(FSMTransition.WantHealing);
         return;
     }
     else if (!mCitizen.CheckAlive())
     {
         mFSMSystem.TransitionFSMState(FSMTransition.ToLate);
         CitizenMgr.IllCnt--;
         return;
     }
     if (mCitizen.bCheckAmbulanceKey)
     {
         mCitizen.bCheckAmbulanceKey = false;
         if (CitizenMgr.CheckBedsAvailable())
         {
             mFSMSystem.TransitionFSMState(FSMTransition.TookByAmbulance);
         }
         else
         {
             mFSMSystem.TransitionFSMState(FSMTransition.CantTakeAmbulance);
         }
         return;
     }
 }
Example #9
0
        private void DoScheduledHome(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding == 0)
            {
                Log.Debug(LogCategory.State, $"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is in corrupt state: want to go home with no home building. Releasing the poor citizen.");
                CitizenMgr.ReleaseCitizen(citizenId);
                schedule = default;
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);

            if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, homeBuilding))
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                schedule.Schedule(ResidentState.Unknown);
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} back home");
            }
            else
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted to go home from {currentBuilding} but can't, waiting for the next opportunity");
            }
        }
Example #10
0
        /// <summary>
        /// The main method of the custom AI.
        /// </summary>
        ///
        /// <param name="instance">A reference to an object instance of the original AI.</param>
        /// <param name="citizenId">The ID of the citizen to process.</param>
        /// <param name="citizen">A <see cref="Citizen"/> reference to process.</param>
        public void UpdateLocation(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            if (!EnsureCitizenValid(citizenId, ref citizen))
            {
                return;
            }

            if (CitizenProxy.IsDead(ref citizen))
            {
                ProcessCitizenDead(instance, citizenId, ref citizen);
                return;
            }

            if ((CitizenProxy.IsSick(ref citizen) && ProcessCitizenSick(instance, citizenId, ref citizen)) ||
                (CitizenProxy.IsArrested(ref citizen) && ProcessCitizenArrested(ref citizen)))
            {
                return;
            }

            ResidentState residentState = GetResidentState(ref citizen);

            switch (residentState)
            {
            case ResidentState.LeftCity:
                CitizenMgr.ReleaseCitizen(citizenId);
                break;

            case ResidentState.MovingHome:
                ProcessCitizenMoving(instance, citizenId, ref citizen, false);
                break;

            case ResidentState.AtHome:
                ProcessCitizenAtHome(instance, citizenId, ref citizen);
                break;

            case ResidentState.MovingToTarget:
                ProcessCitizenMoving(instance, citizenId, ref citizen, true);
                break;

            case ResidentState.AtSchoolOrWork:
                ProcessCitizenAtSchoolOrWork(instance, citizenId, ref citizen);
                break;

            case ResidentState.AtLunch:
            case ResidentState.Shopping:
            case ResidentState.AtLeisureArea:
            case ResidentState.Visiting:
                ProcessCitizenVisit(instance, residentState, citizenId, ref citizen);
                break;

            case ResidentState.Evacuating:
                ProcessCitizenEvacuation(instance, citizenId, ref citizen);
                break;

            case ResidentState.InShelter:
                CitzenReturnsFromShelter(instance, citizenId, ref citizen);
                return;
            }
        }
Example #11
0
        private void ProcessVisit(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (visitBuilding == 0)
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Evacuating))
            {
                touristAI.FindEvacuationPlace(instance, citizenId, visitBuilding, touristAI.GetEvacuationReason(instance, visitBuilding));
                return;
            }

            switch (BuildingMgr.GetBuildingService(visitBuilding))
            {
            case ItemClass.Service.Disaster:
                if (BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading))
                {
                    CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
                    FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
                }

                return;

            // Tourist is sleeping in a hotel
            case ItemClass.Service.Commercial
                when BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.CommercialTourist &&
                !Random.ShouldOccur(GetHotelLeaveChance()):
                return;
            }

            ICityEvent currentEvent = EventMgr.GetCityEvent(visitBuilding);

            if (currentEvent != null && currentEvent.StartTime < TimeInfo.Now)
            {
                if (Random.ShouldOccur(TouristShoppingChance))
                {
                    BuildingMgr.ModifyMaterialBuffer(visitBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                }

                return;
            }

            if (Random.ShouldOccur(TouristEventChance) && !WeatherInfo.IsBadWeather)
            {
                ICityEvent cityEvent = GetUpcomingEventToAttend(citizenId, ref citizen);
                if (cityEvent != null &&
                    StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), cityEvent.BuildingId))
                {
                    Log.Debug(LogCategory.Events, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} attending an event at {cityEvent.BuildingId}");
                    return;
                }
            }

            FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding);
        }
Example #12
0
    public override void StateStart()
    {
        mAnimator.SetBool("Healthy", true);
        MoveTimerTotal          = CitizenMgr.GenerateMovePeriod();
        mCitizen.timeAlive      = 0;
        mCitizen.transform.name = "Latent";
        mCitizen.CitizenType    = CitizenType.Latent;

        CitizenMgr.LatentCnt++;
    }
Example #13
0
    public override void StateStart()
    {
        MoveTimerTotal       = CitizenMgr.GenerateMovePeriod();
        mCitizen.CitizenType = CitizenType.Cured;
        mCitizen.ClearAllStatus(false);
        mCitizen.AddStatus(CitizenStatusType.Healthy);
        mCitizen.name = "Cured";
        mAnimator.SetBool("Healthy", true);

        CitizenMgr.CuredCnt++;
    }
Example #14
0
    public override void StateStart()
    {
        mCitizen.timeAlive = 0;
        mAnimator.SetBool("Healthy", false);
        MoveTimerTotal          = CitizenMgr.GenerateMovePeriod();
        mCitizen.transform.name = "Ill";
        mCitizen.CitizenType    = CitizenType.Ill;
        mCitizen.AddStatus(CitizenStatusType.Ill);

        CitizenMgr.IllCnt++;
    }
Example #15
0
    public override void StateStart()
    {
        mCitizen.CitizenType    = CitizenType.Healthy;
        mCitizen.timeAlive      = 0;
        mCitizen.bWearingMask   = false;
        MoveTimerTotal          = CitizenMgr.GenerateMovePeriod();
        mCitizen.transform.name = "Healthy";

        mAnimator.SetBool("Healthy", true);

        CitizenMgr.HealthyCnt++;
    }
Example #16
0
        private bool ProcessCitizenMoving(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort instanceId = CitizenProxy.GetInstance(ref citizen);
            ushort vehicleId  = CitizenProxy.GetVehicle(ref citizen);

            if (vehicleId == 0 && instanceId == 0)
            {
                if (CitizenProxy.GetVisitBuilding(ref citizen) != 0)
                {
                    CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                }

                if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn))
                {
                    CitizenMgr.ReleaseCitizen(citizenId);
                    schedule = default;
                }
                else
                {
                    CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                    CitizenProxy.SetArrested(ref citizen, false);
                    schedule.Schedule(ResidentState.Unknown);
                }

                return(true);
            }

            if (vehicleId == 0 && CitizenMgr.IsAreaEvacuating(instanceId) && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Finding an evacuation place.");
                schedule.Schedule(ResidentState.Unknown);
                TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0));
                return(true);
            }

            ushort targetBuilding = CitizenMgr.GetTargetBuilding(instanceId);

            if (targetBuilding == CitizenProxy.GetWorkBuilding(ref citizen))
            {
                return(true);
            }

            ItemClass.Service targetService = BuildingMgr.GetBuildingService(targetBuilding);
            if (targetService == ItemClass.Service.Beautification && WeatherInfo.IsBadWeather)
            {
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} cancels the trip to a park due to bad weather");
                schedule.Schedule(ResidentState.AtHome);
                return(false);
            }

            return(true);
        }
Example #17
0
 /// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary>
 /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception>
 /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param>
 /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param>
 /// <param name="residentAI">A connection to the game's resident AI.</param>
 /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param>
 /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param>
 public RealTimeResidentAI(
     RealTimeConfig config,
     GameConnections <TCitizen> connections,
     ResidentAIConnection <TAI, TCitizen> residentAI,
     RealTimeEventManager eventManager,
     SpareTimeBehavior spareTimeBehavior)
     : base(config, connections, eventManager)
 {
     this.residentAI        = residentAI ?? throw new ArgumentNullException(nameof(residentAI));
     this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior));
     residentSchedules      = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()];
     workBehavior           = new WorkBehavior(config, connections.Random, connections.BuildingManager, connections.TimeInfo, GetEstimatedTravelTime);
 }
Example #18
0
 public override void TransitionReason()
 {
     if (!mCitizen.CheckAlive())
     {
         mFSMSystem.TransitionFSMState(FSMTransition.ToLate);
         CitizenMgr.IllCnt--;
     }
     else if (CitizenMgr.CheckBedsAvailable())
     {
         mCitizen.bMovingToHosp = true;
         mFSMSystem.TransitionFSMState(FSMTransition.BedsAvailable);
     }
 }
        private void ProcessCitizenMoving(TAI instance, uint citizenId, ref TCitizen citizen, bool mayCancel)
        {
            ushort instanceId = CitizenProxy.GetInstance(ref citizen);
            ushort vehicleId  = CitizenProxy.GetVehicle(ref citizen);

            // TODO: implement bored of traffic jam trip abandon
            if (vehicleId == 0 && instanceId == 0)
            {
                if (CitizenProxy.GetVisitBuilding(ref citizen) != 0)
                {
                    CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                }

                Log.Debug($"Teleporting {GetCitizenDesc(citizenId, ref citizen)} back home because they are moving but no instance is specified");
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                CitizenProxy.SetArrested(ref citizen, false);

                return;
            }

            if (vehicleId == 0 && CitizenMgr.IsAreaEvacuating(instanceId) && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating))
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Finding an evacuation place.");
                TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0));
                return;
            }

            if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, true))
            {
                ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);
                if (IsChance(AbandonTourChance) && homeBuilding != 0)
                {
                    CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
                    residentAI.StartMoving(instance, citizenId, ref citizen, 0, homeBuilding);
                }
            }
            else if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.WaitingTransport | CitizenInstance.Flags.WaitingTaxi))
            {
                if (mayCancel && CitizenMgr.GetInstanceWaitCounter(instanceId) == 255 && IsChance(AbandonTransportWaitChance))
                {
                    ushort home = CitizenProxy.GetHomeBuilding(ref citizen);
                    if (home == 0)
                    {
                        return;
                    }

                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} doesn't want to wait for transport anymore, goes back home");
                    residentAI.StartMoving(instance, citizenId, ref citizen, 0, home);
                }
            }
        }
Example #20
0
        private void ProcessCitizenOnTour(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            if (!CitizenMgr.InstanceHasFlags(CitizenProxy.GetInstance(ref citizen), CitizenInstance.Flags.TargetIsNode))
            {
                return;
            }

            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding != 0)
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} exits a guided tour and moves back home.");
                residentAI.StartMoving(instance, citizenId, ref citizen, 0, homeBuilding);
            }
        }
Example #21
0
        /// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary>
        /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception>
        /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param>
        /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param>
        /// <param name="residentAI">A connection to the game's resident AI.</param>
        /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param>
        /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param>
        /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param>
        /// <param name="travelBehavior">A behavior that provides simulation info for the citizens traveling.</param>
        public RealTimeResidentAI(
            RealTimeConfig config,
            GameConnections <TCitizen> connections,
            ResidentAIConnection <TAI, TCitizen> residentAI,
            RealTimeEventManager eventManager,
            WorkBehavior workBehavior,
            SpareTimeBehavior spareTimeBehavior,
            TravelBehavior travelBehavior)
            : base(config, connections, eventManager)
        {
            this.residentAI        = residentAI ?? throw new ArgumentNullException(nameof(residentAI));
            this.workBehavior      = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior));
            this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior));
            this.travelBehavior    = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior));

            residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()];
        }
Example #22
0
        /// <summary>
        /// Ensures that the specified citizen is in a valid state and can be processed.
        /// </summary>
        ///
        /// <param name="citizenId">The citizen ID to check.</param>
        /// <param name="citizen">The citizen data reference.</param>
        ///
        /// <returns><c>true</c> if the specified citizen is in a valid state; otherwise, <c>false</c>.</returns>
        protected bool EnsureCitizenCanBeProcessed(uint citizenId, ref TCitizen citizen)
        {
            if (CitizenProxy.IsEmpty(ref citizen) ||
                CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn) && CitizenProxy.GetLocation(ref citizen) == Citizen.Location.Home)
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return(false);
            }

            if (CitizenProxy.IsCollapsed(ref citizen))
            {
                Log.Debug(LogCategory.State, $"{GetCitizenDesc(citizenId, ref citizen)} is collapsed, doing nothing...");
                return(false);
            }

            return(true);
        }
        private void ProcessCitizenDead(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen);
            switch (currentLocation)
            {
            case Citizen.Location.Home when currentBuilding != 0:
                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                break;

            case Citizen.Location.Work when currentBuilding != 0:
                CitizenProxy.SetHome(ref citizen, citizenId, 0);
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                break;

            case Citizen.Location.Visit when currentBuilding != 0:
                CitizenProxy.SetHome(ref citizen, citizenId, 0);
                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);

                if (BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen)) == ItemClass.Service.HealthCare)
                {
                    return;
                }

                break;

            case Citizen.Location.Moving when CitizenProxy.GetVehicle(ref citizen) != 0:
                CitizenProxy.SetHome(ref citizen, citizenId, 0);

                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
                return;

            default:
                Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is released because of death");
                residentSchedules[citizenId] = default;
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Dead);
            Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is dead, body should get serviced");
        }
        private void ProcessCitizenDead(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen);

            if (currentBuilding == 0 || (currentLocation == Citizen.Location.Moving && CitizenProxy.GetVehicle(ref citizen) == 0))
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is released");
                residentSchedules[citizenId] = default;
                CitizenMgr.ReleaseCitizen(citizenId);
                return;
            }

            if (currentLocation != Citizen.Location.Home && CitizenProxy.GetHomeBuilding(ref citizen) != 0)
            {
                CitizenProxy.SetHome(ref citizen, citizenId, 0);
            }

            if (currentLocation != Citizen.Location.Work && CitizenProxy.GetWorkBuilding(ref citizen) != 0)
            {
                CitizenProxy.SetWorkplace(ref citizen, citizenId, 0);
            }

            if (currentLocation != Citizen.Location.Visit && CitizenProxy.GetVisitBuilding(ref citizen) != 0)
            {
                CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
            }

            if (currentLocation == Citizen.Location.Moving || CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return;
            }

            if (currentLocation == Citizen.Location.Visit &&
                BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen)) == ItemClass.Service.HealthCare)
            {
                return;
            }

            residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Dead);
            Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is dead, body should get serviced");
        }
Example #25
0
        /// <summary>
        /// Initializes a new instance of the <see cref="RealTimeHumanAIBase{TCitizen}"/> class.
        /// </summary>
        ///
        /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception>
        ///
        /// <param name="config">A configuration to use with this custom logic.</param>
        /// <param name="connections">An object providing the proxies that connect the method calls to the game methods.</param>
        /// <param name="eventManager">A reference to an <see cref="IRealTimeEventManager"/> instance.</param>
        protected RealTimeHumanAIBase(RealTimeConfig config, GameConnections <TCitizen> connections, IRealTimeEventManager eventManager)
        {
            Config   = config ?? throw new ArgumentNullException(nameof(config));
            EventMgr = eventManager ?? throw new ArgumentNullException(nameof(eventManager));

            if (connections == null)
            {
                throw new ArgumentNullException(nameof(connections));
            }

            CitizenMgr   = connections.CitizenManager;
            BuildingMgr  = connections.BuildingManager;
            TransferMgr  = connections.TransferManager;
            CitizenProxy = connections.CitizenConnection;
            TimeInfo     = connections.TimeInfo;
            Random       = connections.Random;
            WeatherInfo  = connections.WeatherInfo;

            CitizenInstancesMaxCount = CitizenMgr.GetMaxInstancesCount();
        }
Example #26
0
 void RandomMove()
 {
     currentMoveTimer += Time.fixedDeltaTime;
     if (currentMoveTimer > MoveTimerTotal)
     {
         currentMoveTimer = 0;
         MoveTimerTotal   = CitizenMgr.GenerateMovePeriod();
         if (mCitizen.CheckReachDest())
         {
             int loopTimes = 0;
             while (loopTimes++ < 10)
             {
                 if (mCitizen.TryMove(CitizenMgr.GenerateMoveDest(), 0.1f))
                 {
                     break;
                 }
             }
         }
     }
 }
Example #27
0
    void CheckInfected()
    {
        var colls = Physics.OverlapSphere(mCitizen.transform.position, CitizenMgr.MaxSafeDist);

        foreach (Collider co in colls)
        {
            Citizen p = co.gameObject.GetComponent <Citizen>();
            if (p && (p.CitizenType == CitizenType.Ill || p.CitizenType == CitizenType.Latent))
            {
                if (p != null && !CitizenMgr.SafeDistance(mCitizen, p))
                {
                    if (Random.Range(0.0f, 1.0f) < mCitizen.InfectRate)
                    {
                        mFSMSystem.TransitionFSMState(FSMTransition.Infected);
                        return;
                    }
                }
            }
        }
    }
Example #28
0
        protected bool EnsureCitizenValid(uint citizenId, ref TCitizen citizen)
        {
            if (CitizenProxy.GetHomeBuilding(ref citizen) == 0 &&
                CitizenProxy.GetWorkBuilding(ref citizen) == 0 &&
                CitizenProxy.GetVisitBuilding(ref citizen) == 0 &&
                CitizenProxy.GetInstance(ref citizen) == 0 &&
                CitizenProxy.GetVehicle(ref citizen) == 0)
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return(false);
            }

            if (CitizenProxy.IsCollapsed(ref citizen))
            {
                Log.Debug($"{GetCitizenDesc(citizenId, ref citizen)} is collapsed, doing nothing...");
                return(false);
            }

            return(true);
        }
Example #29
0
        /// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary>
        /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception>
        /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param>
        /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param>
        /// <param name="residentAI">A connection to the game's resident AI.</param>
        /// <param name="eventManager">An <see cref="IRealTimeEventManager"/> instance.</param>
        /// <param name="buildingAI">The custom building AI.</param>
        /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param>
        /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param>
        /// <param name="travelBehavior">A behavior that provides simulation info for the citizens traveling.</param>
        public RealTimeResidentAI(
            RealTimeConfig config,
            GameConnections <TCitizen> connections,
            ResidentAIConnection <TAI, TCitizen> residentAI,
            IRealTimeEventManager eventManager,
            IRealTimeBuildingAI buildingAI,
            IWorkBehavior workBehavior,
            ISpareTimeBehavior spareTimeBehavior,
            ITravelBehavior travelBehavior)
            : base(config, connections, eventManager)
        {
            this.residentAI        = residentAI ?? throw new ArgumentNullException(nameof(residentAI));
            this.buildingAI        = buildingAI ?? throw new ArgumentNullException(nameof(buildingAI));
            this.workBehavior      = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior));
            this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior));
            this.travelBehavior    = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior));

            residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()];
            abandonCarRideDurationThreshold       = Constants.MaxTravelTime * 0.8f;
            abandonCarRideToWorkDurationThreshold = Constants.MaxTravelTime;
        }
Example #30
0
        /// <summary>
        /// Ensures that the provided citizen is in a valid state and can be processed.
        /// </summary>
        ///
        /// <param name="citizenId">The citizen ID to check.</param>
        /// <param name="citizen">The citizen data reference.</param>
        ///
        /// <returns><c>true</c> if the provided citizen is in a valid state; otherwise, <c>false</c>.</returns>
        protected bool EnsureCitizenCanBeProcessed(uint citizenId, ref TCitizen citizen)
        {
            if ((CitizenProxy.GetHomeBuilding(ref citizen) == 0 &&
                 CitizenProxy.GetWorkBuilding(ref citizen) == 0 &&
                 CitizenProxy.GetVisitBuilding(ref citizen) == 0 &&
                 CitizenProxy.GetInstance(ref citizen) == 0 &&
                 CitizenProxy.GetVehicle(ref citizen) == 0)
                ||
                (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn) && CitizenProxy.GetLocation(ref citizen) == Citizen.Location.Home))
            {
                CitizenMgr.ReleaseCitizen(citizenId);
                return(false);
            }

            if (CitizenProxy.IsCollapsed(ref citizen))
            {
                Log.Debug($"{GetCitizenDesc(citizenId, ref citizen, false)} is collapsed, doing nothing...");
                return(false);
            }

            return(true);
        }