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 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 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 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 bool ProcessCitizenSick(TAI instance, uint citizenId, ref TCitizen citizen) { var 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) { ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen); switch (BuildingMgr.GetBuildingService(visitBuilding)) { case ItemClass.Service.HealthCare: UpdateSickStateOnVisitingHealthcare(citizenId, visitBuilding, ref citizen); return(true); case ItemClass.Service.Disaster when !BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading): 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 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)) { FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding); } return; // Tourist is sleeping in a hotel case ItemClass.Service.Commercial when TimeInfo.IsNightTime && BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.CommercialTourist: return; } if (Random.ShouldOccur(TouristEventChance) && !IsBadWeather()) { ICityEvent cityEvent = GetUpcomingEventToAttend(citizenId, ref citizen); if (cityEvent != null) { StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), cityEvent.BuildingId); Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} attending an event at {cityEvent.BuildingId}"); return; } } int doNothingChance; switch (EventMgr.GetEventState(visitBuilding, DateTime.MaxValue)) { case CityEventState.Ongoing: if (Random.ShouldOccur(TouristShoppingChance)) { BuildingMgr.ModifyMaterialBuffer(visitBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount); } return; case CityEventState.Finished: doNothingChance = 0; break; default: doNothingChance = TouristDoNothingProbability; break; } FindRandomVisitPlace(instance, citizenId, ref citizen, doNothingChance, visitBuilding); }
private ScheduleAction UpdateCitizenState(ref TCitizen citizen, ref CitizenSchedule schedule) { if (schedule.CurrentState == ResidentState.Ignored) { return(ScheduleAction.Ignore); } if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.DummyTraffic)) { schedule.CurrentState = ResidentState.Ignored; return(ScheduleAction.Ignore); } Citizen.Location location = CitizenProxy.GetLocation(ref citizen); if (location == Citizen.Location.Moving) { if (CitizenMgr.InstanceHasFlags( CitizenProxy.GetInstance(ref citizen), CitizenInstance.Flags.OnTour | CitizenInstance.Flags.TargetIsNode, true)) { // Guided tours are treated as visits schedule.CurrentState = ResidentState.Visiting; schedule.Hint = ScheduleHint.OnTour; return(ScheduleAction.ProcessState); } return(ScheduleAction.ProcessTransition); } ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); if (currentBuilding == 0) { schedule.CurrentState = ResidentState.Unknown; return(ScheduleAction.ProcessState); } ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding); if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating) && buildingService != ItemClass.Service.Disaster) { schedule.CurrentState = ResidentState.Evacuation; schedule.Schedule(ResidentState.InShelter); return(ScheduleAction.ProcessState); } switch (location) { case Citizen.Location.Home: schedule.CurrentState = ResidentState.AtHome; return(ScheduleAction.ProcessState); case Citizen.Location.Work: if (buildingService == ItemClass.Service.Disaster && CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating)) { schedule.CurrentState = ResidentState.InShelter; return(ScheduleAction.ProcessState); } if (CitizenProxy.GetVisitBuilding(ref citizen) == currentBuilding && schedule.WorkStatus != WorkStatus.Working) { // A citizen may visit their own work building (e.g. shopping), // but the game sets the location to 'work' even if the citizen visits the building. goto case Citizen.Location.Visit; } schedule.CurrentState = ResidentState.AtSchoolOrWork; return(ScheduleAction.ProcessState); case Citizen.Location.Visit: switch (buildingService) { case ItemClass.Service.Beautification: case ItemClass.Service.Monument: case ItemClass.Service.Tourism: case ItemClass.Service.Commercial when BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure && schedule.WorkStatus != WorkStatus.Working: schedule.CurrentState = ResidentState.Relaxing; return(ScheduleAction.ProcessState); case ItemClass.Service.Commercial: schedule.CurrentState = ResidentState.Shopping; return(ScheduleAction.ProcessState); case ItemClass.Service.Disaster when CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating): schedule.CurrentState = ResidentState.InShelter; return(ScheduleAction.ProcessState); } schedule.CurrentState = ResidentState.Visiting; return(ScheduleAction.ProcessState); } return(ScheduleAction.Ignore); }
private ResidentState GetResidentState(ref TCitizen citizen) { if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.DummyTraffic)) { return(ResidentState.Ignored); } ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding); if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating) && buildingService != ItemClass.Service.Disaster) { return(ResidentState.Evacuating); } switch (CitizenProxy.GetLocation(ref citizen)) { case Citizen.Location.Home: return(currentBuilding != 0 ? ResidentState.AtHome : ResidentState.Unknown); case Citizen.Location.Work: if (buildingService == ItemClass.Service.Disaster && CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating)) { return(ResidentState.InShelter); } if (CitizenProxy.GetVisitBuilding(ref citizen) == currentBuilding) { // A citizen may visit their own work building (e.g. shopping) goto case Citizen.Location.Visit; } return(currentBuilding != 0 ? ResidentState.AtSchoolOrWork : ResidentState.Unknown); case Citizen.Location.Visit: if (currentBuilding == 0) { return(ResidentState.Unknown); } switch (buildingService) { case ItemClass.Service.Commercial: if (CitizenProxy.GetWorkBuilding(ref citizen) != 0 && IsWorkDay && TimeInfo.CurrentHour > Config.LunchBegin && TimeInfo.CurrentHour < GetSpareTimeBeginHour(CitizenProxy.GetAge(ref citizen))) { return(ResidentState.AtLunch); } if (BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure) { return(ResidentState.AtLeisureArea); } return(ResidentState.Shopping); case ItemClass.Service.Beautification: return(ResidentState.AtLeisureArea); case ItemClass.Service.Disaster: return(ResidentState.InShelter); } return(ResidentState.Visiting); case Citizen.Location.Moving: ushort instanceId = CitizenProxy.GetInstance(ref citizen); if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.OnTour | CitizenInstance.Flags.TargetIsNode, true)) { return(ResidentState.OnTour); } ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); return(homeBuilding != 0 && CitizenMgr.GetTargetBuilding(instanceId) == homeBuilding ? ResidentState.MovingHome : ResidentState.MovingToTarget); default: return(ResidentState.Unknown); } }
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)) { FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding); } return; // Tourist is sleeping in a hotel case ItemClass.Service.Commercial when TimeInfo.IsNightTime && BuildingMgr.GetBuildingSubService(visitBuilding) == ItemClass.SubService.CommercialTourist: return; } if (IsChance(TouristEventChance) && AttendUpcomingEvent(citizenId, ref citizen, out ushort eventBuilding)) { StartMovingToVisitBuilding(instance, citizenId, ref citizen, CitizenProxy.GetCurrentBuilding(ref citizen), eventBuilding); touristAI.AddTouristVisit(instance, citizenId, eventBuilding); Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} attending an event at {eventBuilding}"); return; } bool doShopping; switch (EventMgr.GetEventState(visitBuilding, DateTime.MaxValue)) { case CityEventState.Ongoing: doShopping = IsChance(TouristShoppingChance); break; case CityEventState.Finished: doShopping = !FindRandomVisitPlace(instance, citizenId, ref citizen, 0, visitBuilding); break; default: doShopping = false; break; } if (doShopping || !FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, visitBuilding)) { BuildingMgr.ModifyMaterialBuffer(visitBuilding, TransferManager.TransferReason.Shopping, -ShoppingGoodsAmount); touristAI.AddTouristVisit(instance, citizenId, visitBuilding); } }
private ResidentState GetResidentState(ref TCitizen citizen) { ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); ItemClass.Service buildingService = BuildingMgr.GetBuildingService(currentBuilding); if (BuildingMgr.BuildingHasFlags(currentBuilding, Building.Flags.Evacuating) && buildingService != ItemClass.Service.Disaster) { return(ResidentState.Evacuating); } switch (CitizenProxy.GetLocation(ref citizen)) { case Citizen.Location.Home: if (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn)) { return(ResidentState.LeftCity); } if (currentBuilding != 0) { return(ResidentState.AtHome); } return(ResidentState.Unknown); case Citizen.Location.Work: if (buildingService == ItemClass.Service.Disaster && CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating)) { return(ResidentState.InShelter); } return(currentBuilding != 0 ? ResidentState.AtSchoolOrWork : ResidentState.Unknown); case Citizen.Location.Visit: if (currentBuilding == 0) { return(ResidentState.Unknown); } switch (buildingService) { case ItemClass.Service.Commercial: if (CitizenProxy.GetWorkBuilding(ref citizen) != 0 && IsWorkDay && TimeInfo.CurrentHour > Config.LunchBegin && TimeInfo.CurrentHour < GetSpareTimeBeginHour(CitizenProxy.GetAge(ref citizen))) { return(ResidentState.AtLunch); } if (BuildingMgr.GetBuildingSubService(currentBuilding) == ItemClass.SubService.CommercialLeisure) { return(ResidentState.AtLeisureArea); } return(ResidentState.Shopping); case ItemClass.Service.Beautification: return(ResidentState.AtLeisureArea); case ItemClass.Service.Disaster: return(ResidentState.InShelter); } return(ResidentState.Visiting); case Citizen.Location.Moving: ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); return(homeBuilding != 0 && CitizenMgr.GetTargetBuilding(CitizenProxy.GetInstance(ref citizen)) == homeBuilding ? ResidentState.MovingHome : ResidentState.MovingToTarget); default: return(ResidentState.Unknown); } }