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 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); } } }
private void DoScheduledEvacuation(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen) { schedule.Schedule(ResidentState.Unknown); ushort building = CitizenProxy.GetCurrentBuilding(ref citizen); if (building == 0) { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is trying to find a shelter from current position"); TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0)); } else { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is trying to find a shelter from {building}"); residentAI.FindEvacuationPlace(instance, citizenId, building, residentAI.GetEvacuationReason(instance, building)); } }
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 (instanceId == 0) { if (vehicleId == 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 && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating) && CitizenMgr.IsAreaEvacuating(instanceId)) { 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); schedule.DepartureTime = default; TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0)); return(true); } ushort targetBuilding = CitizenMgr.GetTargetBuilding(instanceId); bool headingToWork = targetBuilding == CitizenProxy.GetWorkBuilding(ref citizen); if (vehicleId != 0 && schedule.DepartureTime != default) { float maxTravelTime = headingToWork ? abandonCarRideToWorkDurationThreshold : abandonCarRideDurationThreshold; if ((TimeInfo.Now - schedule.DepartureTime).TotalHours > maxTravelTime) { buildingAI.RegisterReachingTrouble(targetBuilding); if (targetBuilding == CitizenProxy.GetHomeBuilding(ref citizen)) { return(true); } Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} cancels the trip because of traffic jam"); schedule.Schedule(ResidentState.Relaxing); schedule.Hint = ScheduleHint.RelaxNearbyOnly; schedule.CurrentState = ResidentState.InTransition; return(false); } } if (headingToWork) { 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); schedule.CurrentState = ResidentState.InTransition; return(false); } return(true); }
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; } bool isEvacuating = CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating); if (vehicleId == 0 && !isEvacuating && CitizenMgr.IsAreaEvacuating(instanceId)) { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Searching for a shelter."); TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, touristAI.GetEvacuationReason(instance, 0)); return; } if (isEvacuating) { return; } if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, all: true)) { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} exits the guided tour."); FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, 0); return; } ushort targetBuildingId = CitizenProxy.GetVisitBuilding(ref citizen); TouristTarget target; if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode)) { if (CitizenMgr.GetTargetNode(instanceId) != 0) { target = TouristTarget.Relaxing; } else { return; } } else { if (targetBuildingId == 0) { targetBuildingId = CitizenMgr.GetTargetBuilding(instanceId); } BuildingMgr.GetBuildingService(targetBuildingId, out ItemClass.Service targetService, out ItemClass.SubService targetSubService); switch (targetService) { // Heading to a hotel, no need to change anything case ItemClass.Service.Commercial when targetSubService == ItemClass.SubService.CommercialTourist: return; case ItemClass.Service.Commercial when targetSubService == ItemClass.SubService.CommercialLeisure: target = TouristTarget.Party; break; case ItemClass.Service.Tourism: case ItemClass.Service.Beautification: case ItemClass.Service.Monument: target = TouristTarget.Relaxing; break; case ItemClass.Service.Commercial: target = TouristTarget.Shopping; break; default: return; } } if (GetTouristGoingOutChance(ref citizen, target) > 0) { return; } ushort hotel = FindHotel(targetBuildingId); if (hotel != 0) { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} changes the target and moves to a hotel {hotel} because of time or weather"); StartMovingToVisitBuilding(instance, citizenId, ref citizen, 0, hotel); } else { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} leaves the city because of time or weather"); touristAI.FindVisitPlace(instance, citizenId, 0, touristAI.GetLeavingReason(instance, citizenId, ref citizen)); } }
private void ProcessCitizenMoving(TAI instance, uint citizenId, ref TCitizen citizen, bool mayCancel) { 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); } else { // TODO: check whether this makes sense and maybe remove/replace this logic // Don't know why the original game does this... 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, false)} was on the way, but the area evacuates. Finding an evacuation place."); TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0)); return; } bool returnHome = false; ushort targetBuilding = CitizenMgr.GetTargetBuilding(instanceId); if (targetBuilding != CitizenProxy.GetWorkBuilding(ref citizen)) { ItemClass.Service targetService = BuildingMgr.GetBuildingService(targetBuilding); if (targetService == ItemClass.Service.Beautification && IsBadWeather(citizenId)) { Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} cancels the trip to a park due to bad weather"); returnHome = true; } } if (!returnHome && CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.WaitingTransport | CitizenInstance.Flags.WaitingTaxi)) { if (mayCancel && CitizenMgr.GetInstanceWaitCounter(instanceId) == 255 && Random.ShouldOccur(AbandonTransportWaitChance)) { Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} goes back home"); returnHome = true; } } if (returnHome) { ushort home = CitizenProxy.GetHomeBuilding(ref citizen); if (home == 0) { return; } residentAI.StartMoving(instance, citizenId, ref citizen, 0, home); } }
/// <summary> /// Finds an evacuation place for the specified citizen. /// </summary> /// /// <param name="citizenId">The citizen ID to find an evacuation place for.</param> /// /// <param name="reason">The evacuation reason.</param> protected void FindEvacuationPlace(uint citizenId, TransferManager.TransferReason reason) => TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, reason);