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);
        }
Esempio n. 2
0
        private bool ShouldMoveToSchoolOrWork(ushort currentBuilding, ushort workBuilding, float workBeginHour, float workEndHour, float overtime)
        {
            float gotoHour = workBeginHour - overtime - MaxHoursOnTheWay;

            if (gotoHour < 0)
            {
                gotoHour += 24f;
            }

            float leaveHour = workEndHour + overtime;

            if (leaveHour >= 24f)
            {
                leaveHour -= 24f;
            }

            float currentHour = TimeInfo.CurrentHour;

            if (!IsWorkHour(currentHour, gotoHour, leaveHour))
            {
                return(false);
            }

            float distance = BuildingMgr.GetDistanceBetweenBuildings(currentBuilding, workBuilding);
            float onTheWay = Mathf.Clamp(distance / OnTheWayDistancePerHour, MinHoursOnTheWay, MaxHoursOnTheWay);

            gotoHour = workBeginHour - overtime - onTheWay;
            if (gotoHour < 0)
            {
                gotoHour += 24f;
            }

            return(IsWorkHour(currentHour, gotoHour, leaveHour));
        }
        private bool ProcessCitizenSick(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen);
            if (currentLocation == Citizen.Location.Moving)
            {
                return(false);
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (currentLocation != Citizen.Location.Home && currentBuilding == 0)
            {
                Log.Debug(LogCategory.State, $"Teleporting {GetCitizenDesc(citizenId, ref citizen)} back home because they are sick but no building is specified");
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                return(true);
            }

            if (currentLocation != Citizen.Location.Home && CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return(true);
            }

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

            Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is sick, trying to get to a hospital");
            residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Sick);
            return(true);
        }
Esempio n. 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 IsBuildingNoiseRestricted(ushort targetBuilding, ushort currentBuilding)
        {
            if (BuildingMgr.GetBuildingSubService(targetBuilding) != ItemClass.SubService.CommercialLeisure)
            {
                return(false);
            }

            float currentHour = TimeInfo.CurrentHour;

            if (currentHour >= Config.GoToSleepUpHour || currentHour <= Config.WakeupHour)
            {
                return(BuildingMgr.IsBuildingNoiseRestricted(targetBuilding));
            }

            float travelTime = GetEstimatedTravelTime(currentBuilding, targetBuilding);

            if (travelTime == 0)
            {
                return(false);
            }

            float arriveHour = (float)TimeInfo.Now.AddHours(travelTime).TimeOfDay.TotalHours;

            if (arriveHour >= Config.GoToSleepUpHour || arriveHour <= Config.WakeupHour)
            {
                return(BuildingMgr.IsBuildingNoiseRestricted(targetBuilding));
            }

            return(false);
        }
Esempio n. 6
0
        private bool CitizenReturnsHomeFromVisit(TAI instance, uint citizenId, ref TCitizen citizen, bool isVirtual)
        {
            ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen);

            if (homeBuilding == 0 || CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return(false);
            }

            ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            switch (EventMgr.GetEventState(visitBuilding, TimeInfo.Now.AddHours(MaxHoursOnTheWay)))
            {
            case CityEventState.Upcoming:
            case CityEventState.Ongoing:
                return(false);

            case CityEventState.Finished:
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} returning from an event at {visitBuilding} back home to {homeBuilding}");
                ReturnFromVisit(instance, citizenId, ref citizen, homeBuilding, Citizen.Location.Home, isVirtual);
                return(true);
            }

            ItemClass.SubService visitedSubService = BuildingMgr.GetBuildingSubService(visitBuilding);
            if (Random.ShouldOccur(ReturnFromVisitChance) ||
                (visitedSubService == ItemClass.SubService.CommercialLeisure && TimeInfo.IsNightTime && BuildingMgr.IsBuildingNoiseRestricted(visitBuilding)))
            {
                Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} returning from visit back home");
                ReturnFromVisit(instance, citizenId, ref citizen, homeBuilding, Citizen.Location.Home, isVirtual);
                return(true);
            }

            return(false);
        }
Esempio n. 7
0
        private void FindHotel(TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (!Random.ShouldOccur(FindHotelChance))
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} didn't want to stay in a hotel, leaving the city");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            ushort hotel = BuildingMgr.FindActiveBuilding(
                currentBuilding,
                FullSearchDistance,
                ItemClass.Service.Commercial,
                ItemClass.SubService.CommercialTourist);

            if (hotel == 0)
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} didn't find a hotel, leaving the city");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            StartMovingToVisitBuilding(instance, citizenId, ref citizen, currentBuilding, hotel);
            Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} stays in a hotel {hotel}");
        }
Esempio n. 8
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);
        }
Esempio n. 9
0
        private bool IsBuildingNoiseRestricted(ushort building)
        {
            float arriveHour = (float)TimeInfo.Now.AddHours(MaxHoursOnTheWay).TimeOfDay.TotalHours;

            return((arriveHour >= TimeInfo.SunsetHour || TimeInfo.CurrentHour >= TimeInfo.SunsetHour ||
                    arriveHour <= TimeInfo.SunriseHour || TimeInfo.CurrentHour <= TimeInfo.SunriseHour) &&
                   BuildingMgr.IsBuildingNoiseRestricted(building));
        }
Esempio n. 10
0
        private uint AdjustRelaxChance(uint relaxChance, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            return((BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.BeautificationParks)
                ? relaxChance * 2
                : relaxChance);
        }
Esempio n. 11
0
        private void ProcessCitizenVisit(TAI instance, ResidentState citizenState, uint citizenId, ref TCitizen citizen, bool isVirtual)
        {
            ushort currentBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (currentBuilding == 0)
            {
                Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen, isVirtual)} is in corrupt state: visiting with no visit building. Teleporting home.");
                CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home);
                return;
            }

            switch (citizenState)
            {
            case ResidentState.AtLunch:
                CitizenReturnsFromLunch(instance, citizenId, ref citizen, isVirtual);

                return;

            case ResidentState.AtLeisureArea:
                if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.NeedGoods) &&
                    BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure)
                {
                    // No Citizen.Flags.NeedGoods flag reset here, because we only bought 'beer' or 'champagne' in a leisure building.
                    BuildingMgr.ModifyMaterialBuffer(CitizenProxy.GetVisitBuilding(ref citizen), TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                }

                goto case ResidentState.Visiting;

            case ResidentState.Visiting:
                if (!CitizenGoesWorking(instance, citizenId, ref citizen, isVirtual))
                {
                    CitizenReturnsHomeFromVisit(instance, citizenId, ref citizen, isVirtual);
                }

                return;

            case ResidentState.Shopping:
                if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.NeedGoods))
                {
                    BuildingMgr.ModifyMaterialBuffer(CitizenProxy.GetVisitBuilding(ref citizen), TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                    CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.NeedGoods);
                }

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

                if (Random.ShouldOccur(ReturnFromShoppingChance) || IsWorkDayMorning(CitizenProxy.GetAge(ref citizen)))
                {
                    Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, isVirtual)} returning from shopping at {currentBuilding} back home");
                    ReturnFromVisit(instance, citizenId, ref citizen, CitizenProxy.GetHomeBuilding(ref citizen), Citizen.Location.Home, isVirtual);
                }

                return;
            }
        }
Esempio n. 12
0
        private bool ShouldMoveToSchoolOrWork(ushort workBuilding, ushort currentBuilding, Citizen.AgeGroup citizenAge)
        {
            if (workBuilding == 0 || IsWeekend)
            {
                return(false);
            }

            float currentHour = TimeInfo.CurrentHour;
            float gotoWorkHour;
            float leaveWorkHour;
            bool  overtime;

            switch (citizenAge)
            {
            case Citizen.AgeGroup.Child:
            case Citizen.AgeGroup.Teen:
                gotoWorkHour  = Config.SchoolBegin;
                leaveWorkHour = Config.SchoolEnd;
                overtime      = false;
                break;

            case Citizen.AgeGroup.Young:
            case Citizen.AgeGroup.Adult:
                gotoWorkHour  = Config.WorkBegin;
                leaveWorkHour = Config.WorkEnd;
                overtime      = IsChance(Config.OnTimeQuota);
                break;

            default:
                return(false);
            }

            // Performance optimization:
            // If the current hour is far away from the working hours, don't even calculate the overtime and on the way time
            if (overtime &&
                (currentHour < gotoWorkHour - MaxHoursOnTheWay - Config.MaxOvertime || currentHour > leaveWorkHour + Config.MaxOvertime))
            {
                return(false);
            }
            else if (currentHour < gotoWorkHour - MaxHoursOnTheWay || currentHour > leaveWorkHour)
            {
                return(false);
            }

            if (overtime)
            {
                gotoWorkHour  -= Config.MaxOvertime * Randomizer.Int32(100) / 200f;
                leaveWorkHour += Config.MaxOvertime;
            }

            float distance = BuildingMgr.GetDistanceBetweenBuildings(currentBuilding, workBuilding);
            float onTheWay = Mathf.Clamp(distance / OnTheWayDistancePerHour, MinHoursOnTheWay, MaxHoursOnTheWay);

            gotoWorkHour -= onTheWay;

            return(currentHour >= gotoWorkHour && currentHour < leaveWorkHour);
        }
Esempio n. 13
0
        /// <summary>Gets an estimated travel time (in hours) between two specified buildings.</summary>
        /// <param name="building1">The ID of the first building.</param>
        /// <param name="building2">The ID of the second building.</param>
        /// <returns>An estimated travel time in hours.</returns>
        protected float GetEstimatedTravelTime(ushort building1, ushort building2)
        {
            if (building1 == 0 || building2 == 0 || building1 == building2)
            {
                return(0);
            }

            float distance = BuildingMgr.GetDistanceBetweenBuildings(building1, building2);

            return(RealTimeMath.Clamp(distance / OnTheWayDistancePerHour, MinTravelTime, MaxTravelTime));
        }
        private bool ProcessCitizenInShelter(ref CitizenSchedule schedule, ref TCitizen citizen)
        {
            ushort shelter = CitizenProxy.GetVisitBuilding(ref citizen);

            if (BuildingMgr.BuildingHasFlags(shelter, Building.Flags.Downgrading))
            {
                schedule.Schedule(ResidentState.Unknown, default);
                return(true);
            }

            return(false);
        }
Esempio n. 15
0
        private bool ProcessCitizenVisit(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding        = CitizenProxy.GetVisitBuilding(ref citizen);
            var    currentBuildingService = BuildingMgr.GetBuildingService(currentBuilding);

            if (currentBuildingService == ItemClass.Service.Education)
            {
                residentAI.AttemptAutodidact(instance, ref citizen, currentBuildingService);
            }

            return(RescheduleVisit(ref schedule, citizenId, ref citizen, currentBuilding));
        }
Esempio n. 16
0
        private bool ProcessCitizenShopping(ref CitizenSchedule schedule, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.NeedGoods) && currentBuilding != 0)
            {
                BuildingMgr.ModifyMaterialBuffer(currentBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.NeedGoods);
            }

            return(RescheduleVisit(ref schedule, citizenId, ref citizen, currentBuilding));
        }
Esempio n. 17
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);
        }
Esempio n. 18
0
        private bool ProcessCitizenRelaxing(ref CitizenSchedule schedule, uint citizenId, ref TCitizen citizen)
        {
            ushort currentBuilding = CitizenProxy.GetVisitBuilding(ref citizen);

            if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.NeedGoods) &&
                BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure)
            {
                // No Citizen.Flags.NeedGoods flag reset here, because we only bought 'beer' or 'champagne' in a leisure building.
                BuildingMgr.ModifyMaterialBuffer(currentBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
            }

            return(RescheduleVisit(ref schedule, citizenId, ref citizen, currentBuilding));
        }
        private bool ProcessCitizenInShelter(ref CitizenSchedule schedule, ref TCitizen citizen)
        {
            ushort shelter = CitizenProxy.GetVisitBuilding(ref citizen);

            if (BuildingMgr.BuildingHasFlags(shelter, Building.Flags.Downgrading) && schedule.ScheduledState == ResidentState.InShelter)
            {
                CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
                schedule.Schedule(ResidentState.Unknown);
                return(true);
            }

            return(false);
        }
Esempio n. 20
0
        private ushort FindHotel(ushort currentBuilding)
        {
            if (!Random.ShouldOccur(FindHotelChance))
            {
                return(0);
            }

            return(BuildingMgr.FindActiveBuilding(
                       currentBuilding,
                       HotelSearchDistance,
                       ItemClass.Service.Commercial,
                       ItemClass.SubService.CommercialTourist));
        }
Esempio n. 21
0
        private void UpdateSickStateOnVisitingHealthcare(uint citizenId, ushort buildingId, ref TCitizen citizen)
        {
            var citizenAge = CitizenProxy.GetAge(ref citizen);

            if ((citizenAge == Citizen.AgeGroup.Child || citizenAge == Citizen.AgeGroup.Teen) && BuildingMgr.IsBuildingAIOfType <ChildcareAI>(buildingId) ||
                citizenAge == Citizen.AgeGroup.Senior && BuildingMgr.IsBuildingAIOfType <EldercareAI>(buildingId))
            {
                if (CitizenProxy.GetHealth(ref citizen) > Random.GetRandomValue(100u))
                {
                    Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} was sick, but got healed in a child or elder care building");
                    CitizenProxy.SetSick(ref citizen, isSick: false);
                }
            }
        }
Esempio n. 22
0
        private void FindRandomVisitPlace(TAI instance, uint citizenId, ref TCitizen citizen, int doNothingProbability, ushort currentBuilding)
        {
            var target = (TouristTarget)touristAI.GetRandomTargetType(instance, doNothingProbability);

            target = AdjustTargetToTimeAndWeather(ref citizen, target);

            switch (target)
            {
            case TouristTarget.LeaveCity:
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} decides to leave the city");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                break;

            case TouristTarget.Shopping:
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetShoppingReason(instance));
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} stays in the city, goes shopping");
                break;

            case TouristTarget.Relaxing:
                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} stays in the city, goes relaxing");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetEntertainmentReason(instance));
                break;

            case TouristTarget.Party:
                ushort leisureBuilding = BuildingMgr.FindActiveBuilding(
                    currentBuilding,
                    LeisureSearchDistance,
                    ItemClass.Service.Commercial,
                    ItemClass.SubService.CommercialLeisure);
                if (leisureBuilding == 0)
                {
                    goto case TouristTarget.Hotel;
                }

                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} want to party in {leisureBuilding}");
                StartMovingToVisitBuilding(instance, citizenId, ref citizen, currentBuilding, leisureBuilding);
                break;

            case TouristTarget.Hotel:
                ushort hotel = FindHotel(currentBuilding);
                if (hotel == 0)
                {
                    goto case TouristTarget.LeaveCity;
                }

                Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} want to stay in a hotel {hotel}");
                StartMovingToVisitBuilding(instance, citizenId, ref citizen, currentBuilding, hotel);
                break;
            }
        }
        private ushort MoveToLeisure(TAI instance, uint citizenId, ref TCitizen citizen, ushort buildingId)
        {
            ushort leisureBuilding = BuildingMgr.FindActiveBuilding(
                buildingId,
                LeisureSearchDistance,
                ItemClass.Service.Commercial,
                ItemClass.SubService.CommercialLeisure);

            if (leisureBuilding == CitizenProxy.GetWorkBuilding(ref citizen))
            {
                return(0);
            }

            StartMovingToVisitBuilding(instance, citizenId, ref citizen, leisureBuilding);
            return(leisureBuilding);
        }
Esempio n. 24
0
        private ushort MoveToLeisure(TAI instance, uint citizenId, ref TCitizen citizen, ushort buildingId, bool isVirtual)
        {
            ushort leisureBuilding = BuildingMgr.FindActiveBuilding(
                buildingId,
                LeisureSearchDistance,
                ItemClass.Service.Commercial,
                ItemClass.SubService.CommercialLeisure);

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

            StartMovingToVisitBuilding(instance, citizenId, ref citizen, leisureBuilding, isVirtual);
            return(leisureBuilding);
        }
        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");
        }
Esempio n. 26
0
        private ushort MoveToLeisureBuilding(TAI instance, uint citizenId, ref TCitizen citizen, ushort currentBuilding)
        {
            ushort leisureBuilding = BuildingMgr.FindActiveBuilding(
                currentBuilding,
                LeisureSearchDistance,
                ItemClass.Service.Commercial,
                ItemClass.SubService.CommercialLeisure);

            if (buildingAI.IsNoiseRestricted(leisureBuilding, currentBuilding))
            {
                Log.Debug(LogCategory.Movement, $"Citizen {citizenId} won't go to the leisure building {leisureBuilding}, it has a NIMBY policy");
                return(0);
            }

            return(StartMovingToVisitBuilding(instance, citizenId, ref citizen, leisureBuilding)
                ? leisureBuilding
                : (ushort)0);
        }
Esempio n. 27
0
        private uint AdjustRelaxChance(uint relaxChance, ref TCitizen citizen)
        {
            ushort visitBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            if (BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.BeautificationParks)
            {
                return(relaxChance * 2);
            }
            else if (CitizenProxy.GetAge(ref citizen) == Citizen.AgeGroup.Senior &&
                     BuildingMgr.IsBuildingServiceLevel(visitBuilding, ItemClass.Service.HealthCare, ItemClass.Level.Level3))
            {
                return(relaxChance * 4);
            }
            else
            {
                return(relaxChance);
            }
        }
        private ushort MoveToCommercialBuilding(TAI instance, uint citizenId, ref TCitizen citizen, float distance)
        {
            ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen);

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

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

            if (foundBuilding == CitizenProxy.GetWorkBuilding(ref citizen))
            {
                return(0);
            }

            StartMovingToVisitBuilding(instance, citizenId, ref citizen, foundBuilding);
            return(foundBuilding);
        }
        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");
        }
Esempio n. 30
0
        private void FindRandomVisitPlace(TAI instance, uint citizenId, ref TCitizen citizen, int doNothingProbability, ushort currentBuilding, bool isVirtual)
        {
            int targetType = touristAI.GetRandomTargetType(instance, doNothingProbability);

            if (targetType == 1)
            {
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen, isVirtual)} decides to leave the city");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetLeavingReason(instance, citizenId, ref citizen));
                return;
            }

            if (!Random.ShouldOccur(GetGoOutChance(CitizenProxy.GetAge(ref citizen))) || IsBadWeather(citizenId))
            {
                FindHotel(instance, citizenId, ref citizen, isVirtual);
                return;
            }

            if (isVirtual)
            {
                if (Random.ShouldOccur(TouristShoppingChance) && BuildingMgr.GetBuildingService(currentBuilding) == ItemClass.Service.Commercial)
                {
                    BuildingMgr.ModifyMaterialBuffer(currentBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount);
                }

                touristAI.AddTouristVisit(instance, citizenId, currentBuilding);

                return;
            }

            switch (targetType)
            {
            case 2:
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetShoppingReason(instance));
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen, isVirtual)} stays in the city, goes shopping");
                break;

            case 3:
                Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen, isVirtual)} stays in the city, goes relaxing");
                touristAI.FindVisitPlace(instance, citizenId, currentBuilding, touristAI.GetEntertainmentReason(instance));
                break;
            }
        }