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); }
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); }
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); }
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); }
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}"); }
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); }
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)); }
private uint AdjustRelaxChance(uint relaxChance, ref TCitizen citizen) { ushort visitBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); return((BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.BeautificationParks) ? relaxChance * 2 : relaxChance); }
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; } }
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); }
/// <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); }
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)); }
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)); }
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); }
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); }
private ushort FindHotel(ushort currentBuilding) { if (!Random.ShouldOccur(FindHotelChance)) { return(0); } return(BuildingMgr.FindActiveBuilding( currentBuilding, HotelSearchDistance, ItemClass.Service.Commercial, ItemClass.SubService.CommercialTourist)); }
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); } } }
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); }
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"); }
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); }
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"); }
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; } }