public void Reduceinfection()//降低感染概率 { //相关数值变动写在这里 CitizenMgr.ChangeInfectRateOverall(-0.3f); CostAndCoolingFunction(1500, 20f, "应政府宣传,人们都带上了口罩。"); }
/// <summary> /// The entry method of the custom AI. /// </summary> /// /// <param name="instance">A reference to an object instance of the original AI.</param> /// <param name="citizenId">The ID of the citizen to process.</param> /// <param name="citizen">A <typeparamref name="TCitizen"/> reference to process.</param> public void UpdateLocation(TAI instance, uint citizenId, ref TCitizen citizen) { if (!EnsureCitizenCanBeProcessed(citizenId, ref citizen)) { return; } if (CitizenProxy.IsDead(ref citizen) || CitizenProxy.IsSick(ref citizen)) { CitizenMgr.ReleaseCitizen(citizenId); return; } switch (CitizenProxy.GetLocation(ref citizen)) { case Citizen.Location.Home: case Citizen.Location.Work: CitizenMgr.ReleaseCitizen(citizenId); break; case Citizen.Location.Visit: ProcessVisit(instance, citizenId, ref citizen); break; case Citizen.Location.Moving: ProcessMoving(instance, citizenId, ref citizen); break; } }
/// <summary>Determines whether the specified citizen must be processed as a virtual citizen.</summary> /// <typeparam name="TAI">The type of the citizen's AI.</typeparam> /// <param name="humanAI">The citizen AI reference.</param> /// <param name="citizen">The citizen to check.</param> /// <param name="realizeCitizen">A callback to determine whether a virtual citizen should be realized.</param> /// <returns><c>true</c> if the citizen must be processed as a virtual citizen; otherwise, <c>false</c>.</returns> protected bool IsCitizenVirtual <TAI>(TAI humanAI, ref TCitizen citizen, Func <TAI, bool> realizeCitizen) { if (CitizenProxy.GetInstance(ref citizen) != 0) { return(false); } uint virtualChance; switch (Config.VirtualCitizens) { case VirtualCitizensLevel.None: return(false); case VirtualCitizensLevel.Few: virtualChance = FewVirtualCitizensChance; break; case VirtualCitizensLevel.Vanilla: return(!realizeCitizen(humanAI)); case VirtualCitizensLevel.Many: virtualChance = ManyVirtualCitizensChance; break; default: return(false); } return(CitizenMgr.GetInstancesCount() * 100 / CitizenInstancesMaxCount < virtualChance ? !realizeCitizen(humanAI) : Random.ShouldOccur(virtualChance)); }
private ushort MoveToCommercialBuilding(TAI instance, uint citizenId, ref TCitizen citizen, float distance, bool isVirtual) { ushort buildingId = CitizenProxy.GetCurrentBuilding(ref citizen); if (buildingId == 0) { return(0); } ushort foundBuilding = BuildingMgr.FindActiveBuilding(buildingId, distance, ItemClass.Service.Commercial); if (IsBuildingNoiseRestricted(foundBuilding)) { Log.Debug($"Citizen {citizenId} won't go to the commercial building {foundBuilding}, it has a NIMBY policy"); return(0); } if (StartMovingToVisitBuilding(instance, citizenId, ref citizen, foundBuilding, isVirtual)) { ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); uint homeUnit = BuildingMgr.GetCitizenUnit(homeBuilding); uint citizenUnit = CitizenProxy.GetContainingUnit(ref citizen, citizenId, homeUnit, CitizenUnit.Flags.Home); if (citizenUnit != 0) { CitizenMgr.ModifyUnitGoods(citizenUnit, ShoppingGoodsAmount); } } return(foundBuilding); }
private bool CitzenReturnsFromShelter(TAI instance, uint citizenId, ref TCitizen citizen) { ushort visitBuilding = CitizenProxy.GetVisitBuilding(ref citizen); if (BuildingMgr.GetBuildingService(visitBuilding) != ItemClass.Service.Disaster) { return(true); } if (!BuildingMgr.BuildingHasFlags(visitBuilding, Building.Flags.Downgrading)) { return(false); } ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); if (homeBuilding == 0) { Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen)} was in a shelter but seems to be homeless. Releasing the citizen."); CitizenMgr.ReleaseCitizen(citizenId); return(true); } Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} returning from evacuation place back home"); ReturnFromVisit(instance, citizenId, ref citizen, homeBuilding); return(true); }
private void ProcessMoving(TAI instance, uint citizenId, ref TCitizen citizen) { ushort instanceId = CitizenProxy.GetInstance(ref citizen); ushort vehicleId = CitizenProxy.GetVehicle(ref citizen); if (instanceId == 0) { if (vehicleId == 0) { CitizenMgr.ReleaseCitizen(citizenId); } return; } if (vehicleId == 0 && CitizenMgr.IsAreaEvacuating(instanceId) && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating)) { Log.Debug(TimeInfo.Now, $"Tourist {GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Leaving the city."); touristAI.FindVisitPlace(instance, citizenId, CitizenProxy.GetCurrentBuilding(ref citizen), touristAI.GetLeavingReason(instance, citizenId, ref citizen)); return; } if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, true)) { FindRandomVisitPlace(instance, citizenId, ref citizen, TouristDoNothingProbability, 0); } }
private void ProcessCitizenAtHome(TAI instance, uint citizenId, ref TCitizen citizen) { if (CitizenProxy.GetHomeBuilding(ref citizen) == 0) { Log.Debug($"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is in corrupt state: at home with no home building. Releasing the poor citizen."); CitizenMgr.ReleaseCitizen(citizenId); return; } ushort vehicle = CitizenProxy.GetVehicle(ref citizen); if (vehicle != 0) { Log.Debug(TimeInfo.Now, $"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is at home but vehicle = {vehicle}"); return; } if (CitizenGoesWorking(instance, citizenId, ref citizen)) { return; } if (IsBusyAtHomeInTheMorning(CitizenProxy.GetAge(ref citizen)) || !residentAI.DoRandomMove(instance)) { return; } if (CitizenGoesShopping(instance, citizenId, ref citizen) || CitizenGoesToEvent(instance, citizenId, ref citizen)) { return; } CitizenGoesRelaxing(instance, citizenId, ref citizen); }
public override void TransitionReason() { if (mCitizen.timeAlive > mCitizen.ToHospTimeTotal) { mFSMSystem.TransitionFSMState(FSMTransition.WantHealing); return; } else if (!mCitizen.CheckAlive()) { mFSMSystem.TransitionFSMState(FSMTransition.ToLate); CitizenMgr.IllCnt--; return; } if (mCitizen.bCheckAmbulanceKey) { mCitizen.bCheckAmbulanceKey = false; if (CitizenMgr.CheckBedsAvailable()) { mFSMSystem.TransitionFSMState(FSMTransition.TookByAmbulance); } else { mFSMSystem.TransitionFSMState(FSMTransition.CantTakeAmbulance); } return; } }
private void DoScheduledHome(ref CitizenSchedule schedule, TAI instance, uint citizenId, ref TCitizen citizen) { ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); if (homeBuilding == 0) { Log.Debug(LogCategory.State, $"WARNING: {GetCitizenDesc(citizenId, ref citizen)} is in corrupt state: want to go home with no home building. Releasing the poor citizen."); CitizenMgr.ReleaseCitizen(citizenId); schedule = default; return; } ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating); if (residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, homeBuilding)) { CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0); schedule.Schedule(ResidentState.Unknown); Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} back home"); } else { Log.Debug(LogCategory.Movement, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} wanted to go home from {currentBuilding} but can't, waiting for the next opportunity"); } }
/// <summary> /// The main method of the custom AI. /// </summary> /// /// <param name="instance">A reference to an object instance of the original AI.</param> /// <param name="citizenId">The ID of the citizen to process.</param> /// <param name="citizen">A <see cref="Citizen"/> reference to process.</param> public void UpdateLocation(TAI instance, uint citizenId, ref TCitizen citizen) { if (!EnsureCitizenValid(citizenId, ref citizen)) { return; } if (CitizenProxy.IsDead(ref citizen)) { ProcessCitizenDead(instance, citizenId, ref citizen); return; } if ((CitizenProxy.IsSick(ref citizen) && ProcessCitizenSick(instance, citizenId, ref citizen)) || (CitizenProxy.IsArrested(ref citizen) && ProcessCitizenArrested(ref citizen))) { return; } ResidentState residentState = GetResidentState(ref citizen); switch (residentState) { case ResidentState.LeftCity: CitizenMgr.ReleaseCitizen(citizenId); break; case ResidentState.MovingHome: ProcessCitizenMoving(instance, citizenId, ref citizen, false); break; case ResidentState.AtHome: ProcessCitizenAtHome(instance, citizenId, ref citizen); break; case ResidentState.MovingToTarget: ProcessCitizenMoving(instance, citizenId, ref citizen, true); break; case ResidentState.AtSchoolOrWork: ProcessCitizenAtSchoolOrWork(instance, citizenId, ref citizen); break; case ResidentState.AtLunch: case ResidentState.Shopping: case ResidentState.AtLeisureArea: case ResidentState.Visiting: ProcessCitizenVisit(instance, residentState, citizenId, ref citizen); break; case ResidentState.Evacuating: ProcessCitizenEvacuation(instance, citizenId, ref citizen); break; case ResidentState.InShelter: CitzenReturnsFromShelter(instance, citizenId, ref citizen); return; } }
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); }
public override void StateStart() { mAnimator.SetBool("Healthy", true); MoveTimerTotal = CitizenMgr.GenerateMovePeriod(); mCitizen.timeAlive = 0; mCitizen.transform.name = "Latent"; mCitizen.CitizenType = CitizenType.Latent; CitizenMgr.LatentCnt++; }
public override void StateStart() { MoveTimerTotal = CitizenMgr.GenerateMovePeriod(); mCitizen.CitizenType = CitizenType.Cured; mCitizen.ClearAllStatus(false); mCitizen.AddStatus(CitizenStatusType.Healthy); mCitizen.name = "Cured"; mAnimator.SetBool("Healthy", true); CitizenMgr.CuredCnt++; }
public override void StateStart() { mCitizen.timeAlive = 0; mAnimator.SetBool("Healthy", false); MoveTimerTotal = CitizenMgr.GenerateMovePeriod(); mCitizen.transform.name = "Ill"; mCitizen.CitizenType = CitizenType.Ill; mCitizen.AddStatus(CitizenStatusType.Ill); CitizenMgr.IllCnt++; }
public override void StateStart() { mCitizen.CitizenType = CitizenType.Healthy; mCitizen.timeAlive = 0; mCitizen.bWearingMask = false; MoveTimerTotal = CitizenMgr.GenerateMovePeriod(); mCitizen.transform.name = "Healthy"; mAnimator.SetBool("Healthy", true); CitizenMgr.HealthyCnt++; }
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); }
/// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param> /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, RealTimeEventManager eventManager, SpareTimeBehavior spareTimeBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior)); residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()]; workBehavior = new WorkBehavior(config, connections.Random, connections.BuildingManager, connections.TimeInfo, GetEstimatedTravelTime); }
public override void TransitionReason() { if (!mCitizen.CheckAlive()) { mFSMSystem.TransitionFSMState(FSMTransition.ToLate); CitizenMgr.IllCnt--; } else if (CitizenMgr.CheckBedsAvailable()) { mCitizen.bMovingToHosp = true; mFSMSystem.TransitionFSMState(FSMTransition.BedsAvailable); } }
private void ProcessCitizenMoving(TAI instance, uint citizenId, ref TCitizen citizen, bool mayCancel) { ushort instanceId = CitizenProxy.GetInstance(ref citizen); ushort vehicleId = CitizenProxy.GetVehicle(ref citizen); // TODO: implement bored of traffic jam trip abandon if (vehicleId == 0 && instanceId == 0) { if (CitizenProxy.GetVisitBuilding(ref citizen) != 0) { CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0); } Log.Debug($"Teleporting {GetCitizenDesc(citizenId, ref citizen)} back home because they are moving but no instance is specified"); CitizenProxy.SetLocation(ref citizen, Citizen.Location.Home); CitizenProxy.SetArrested(ref citizen, false); return; } if (vehicleId == 0 && CitizenMgr.IsAreaEvacuating(instanceId) && !CitizenProxy.HasFlags(ref citizen, Citizen.Flags.Evacuating)) { Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} was on the way, but the area evacuates. Finding an evacuation place."); TransferMgr.AddOutgoingOfferFromCurrentPosition(citizenId, residentAI.GetEvacuationReason(instance, 0)); return; } if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.TargetIsNode | CitizenInstance.Flags.OnTour, true)) { ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); if (IsChance(AbandonTourChance) && homeBuilding != 0) { CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating); residentAI.StartMoving(instance, citizenId, ref citizen, 0, homeBuilding); } } else if (CitizenMgr.InstanceHasFlags(instanceId, CitizenInstance.Flags.WaitingTransport | CitizenInstance.Flags.WaitingTaxi)) { if (mayCancel && CitizenMgr.GetInstanceWaitCounter(instanceId) == 255 && IsChance(AbandonTransportWaitChance)) { ushort home = CitizenProxy.GetHomeBuilding(ref citizen); if (home == 0) { return; } Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} doesn't want to wait for transport anymore, goes back home"); residentAI.StartMoving(instance, citizenId, ref citizen, 0, home); } } }
private void ProcessCitizenOnTour(TAI instance, uint citizenId, ref TCitizen citizen) { if (!CitizenMgr.InstanceHasFlags(CitizenProxy.GetInstance(ref citizen), CitizenInstance.Flags.TargetIsNode)) { return; } ushort homeBuilding = CitizenProxy.GetHomeBuilding(ref citizen); if (homeBuilding != 0) { Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen, false)} exits a guided tour and moves back home."); residentAI.StartMoving(instance, citizenId, ref citizen, 0, homeBuilding); } }
/// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param> /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param> /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param> /// <param name="travelBehavior">A behavior that provides simulation info for the citizens traveling.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, RealTimeEventManager eventManager, WorkBehavior workBehavior, SpareTimeBehavior spareTimeBehavior, TravelBehavior travelBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); this.workBehavior = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior)); this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior)); this.travelBehavior = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior)); residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()]; }
/// <summary> /// Ensures that the specified citizen is in a valid state and can be processed. /// </summary> /// /// <param name="citizenId">The citizen ID to check.</param> /// <param name="citizen">The citizen data reference.</param> /// /// <returns><c>true</c> if the specified citizen is in a valid state; otherwise, <c>false</c>.</returns> protected bool EnsureCitizenCanBeProcessed(uint citizenId, ref TCitizen citizen) { if (CitizenProxy.IsEmpty(ref citizen) || CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn) && CitizenProxy.GetLocation(ref citizen) == Citizen.Location.Home) { CitizenMgr.ReleaseCitizen(citizenId); return(false); } if (CitizenProxy.IsCollapsed(ref citizen)) { Log.Debug(LogCategory.State, $"{GetCitizenDesc(citizenId, ref citizen)} is collapsed, doing nothing..."); return(false); } return(true); }
private void ProcessCitizenDead(TAI instance, uint citizenId, ref TCitizen citizen) { ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen); switch (currentLocation) { case Citizen.Location.Home when currentBuilding != 0: CitizenProxy.SetWorkplace(ref citizen, citizenId, 0); CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0); break; case Citizen.Location.Work when currentBuilding != 0: CitizenProxy.SetHome(ref citizen, citizenId, 0); CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0); break; case Citizen.Location.Visit when currentBuilding != 0: CitizenProxy.SetHome(ref citizen, citizenId, 0); CitizenProxy.SetWorkplace(ref citizen, citizenId, 0); if (BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen)) == ItemClass.Service.HealthCare) { return; } break; case Citizen.Location.Moving when CitizenProxy.GetVehicle(ref citizen) != 0: CitizenProxy.SetHome(ref citizen, citizenId, 0); CitizenProxy.SetWorkplace(ref citizen, citizenId, 0); CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0); return; default: Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is released because of death"); residentSchedules[citizenId] = default; CitizenMgr.ReleaseCitizen(citizenId); return; } residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Dead); Log.Debug(LogCategory.State, TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is dead, body should get serviced"); }
private void ProcessCitizenDead(TAI instance, uint citizenId, ref TCitizen citizen) { ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen); Citizen.Location currentLocation = CitizenProxy.GetLocation(ref citizen); if (currentBuilding == 0 || (currentLocation == Citizen.Location.Moving && CitizenProxy.GetVehicle(ref citizen) == 0)) { Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is released"); residentSchedules[citizenId] = default; CitizenMgr.ReleaseCitizen(citizenId); return; } if (currentLocation != Citizen.Location.Home && CitizenProxy.GetHomeBuilding(ref citizen) != 0) { CitizenProxy.SetHome(ref citizen, citizenId, 0); } if (currentLocation != Citizen.Location.Work && CitizenProxy.GetWorkBuilding(ref citizen) != 0) { CitizenProxy.SetWorkplace(ref citizen, citizenId, 0); } if (currentLocation != Citizen.Location.Visit && CitizenProxy.GetVisitBuilding(ref citizen) != 0) { CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0); } if (currentLocation == Citizen.Location.Moving || CitizenProxy.GetVehicle(ref citizen) != 0) { return; } if (currentLocation == Citizen.Location.Visit && BuildingMgr.GetBuildingService(CitizenProxy.GetVisitBuilding(ref citizen)) == ItemClass.Service.HealthCare) { return; } residentAI.FindHospital(instance, citizenId, currentBuilding, TransferManager.TransferReason.Dead); Log.Debug(TimeInfo.Now, $"{GetCitizenDesc(citizenId, ref citizen)} is dead, body should get serviced"); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimeHumanAIBase{TCitizen}"/> class. /// </summary> /// /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// /// <param name="config">A configuration to use with this custom logic.</param> /// <param name="connections">An object providing the proxies that connect the method calls to the game methods.</param> /// <param name="eventManager">A reference to an <see cref="IRealTimeEventManager"/> instance.</param> protected RealTimeHumanAIBase(RealTimeConfig config, GameConnections <TCitizen> connections, IRealTimeEventManager eventManager) { Config = config ?? throw new ArgumentNullException(nameof(config)); EventMgr = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); if (connections == null) { throw new ArgumentNullException(nameof(connections)); } CitizenMgr = connections.CitizenManager; BuildingMgr = connections.BuildingManager; TransferMgr = connections.TransferManager; CitizenProxy = connections.CitizenConnection; TimeInfo = connections.TimeInfo; Random = connections.Random; WeatherInfo = connections.WeatherInfo; CitizenInstancesMaxCount = CitizenMgr.GetMaxInstancesCount(); }
void RandomMove() { currentMoveTimer += Time.fixedDeltaTime; if (currentMoveTimer > MoveTimerTotal) { currentMoveTimer = 0; MoveTimerTotal = CitizenMgr.GenerateMovePeriod(); if (mCitizen.CheckReachDest()) { int loopTimes = 0; while (loopTimes++ < 10) { if (mCitizen.TryMove(CitizenMgr.GenerateMoveDest(), 0.1f)) { break; } } } } }
void CheckInfected() { var colls = Physics.OverlapSphere(mCitizen.transform.position, CitizenMgr.MaxSafeDist); foreach (Collider co in colls) { Citizen p = co.gameObject.GetComponent <Citizen>(); if (p && (p.CitizenType == CitizenType.Ill || p.CitizenType == CitizenType.Latent)) { if (p != null && !CitizenMgr.SafeDistance(mCitizen, p)) { if (Random.Range(0.0f, 1.0f) < mCitizen.InfectRate) { mFSMSystem.TransitionFSMState(FSMTransition.Infected); return; } } } } }
protected bool EnsureCitizenValid(uint citizenId, ref TCitizen citizen) { if (CitizenProxy.GetHomeBuilding(ref citizen) == 0 && CitizenProxy.GetWorkBuilding(ref citizen) == 0 && CitizenProxy.GetVisitBuilding(ref citizen) == 0 && CitizenProxy.GetInstance(ref citizen) == 0 && CitizenProxy.GetVehicle(ref citizen) == 0) { CitizenMgr.ReleaseCitizen(citizenId); return(false); } if (CitizenProxy.IsCollapsed(ref citizen)) { Log.Debug($"{GetCitizenDesc(citizenId, ref citizen)} is collapsed, doing nothing..."); return(false); } return(true); }
/// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">An <see cref="IRealTimeEventManager"/> instance.</param> /// <param name="buildingAI">The custom building AI.</param> /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param> /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param> /// <param name="travelBehavior">A behavior that provides simulation info for the citizens traveling.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, IRealTimeEventManager eventManager, IRealTimeBuildingAI buildingAI, IWorkBehavior workBehavior, ISpareTimeBehavior spareTimeBehavior, ITravelBehavior travelBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); this.buildingAI = buildingAI ?? throw new ArgumentNullException(nameof(buildingAI)); this.workBehavior = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior)); this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior)); this.travelBehavior = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior)); residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()]; abandonCarRideDurationThreshold = Constants.MaxTravelTime * 0.8f; abandonCarRideToWorkDurationThreshold = Constants.MaxTravelTime; }
/// <summary> /// Ensures that the provided citizen is in a valid state and can be processed. /// </summary> /// /// <param name="citizenId">The citizen ID to check.</param> /// <param name="citizen">The citizen data reference.</param> /// /// <returns><c>true</c> if the provided citizen is in a valid state; otherwise, <c>false</c>.</returns> protected bool EnsureCitizenCanBeProcessed(uint citizenId, ref TCitizen citizen) { if ((CitizenProxy.GetHomeBuilding(ref citizen) == 0 && CitizenProxy.GetWorkBuilding(ref citizen) == 0 && CitizenProxy.GetVisitBuilding(ref citizen) == 0 && CitizenProxy.GetInstance(ref citizen) == 0 && CitizenProxy.GetVehicle(ref citizen) == 0) || (CitizenProxy.HasFlags(ref citizen, Citizen.Flags.MovingIn) && CitizenProxy.GetLocation(ref citizen) == Citizen.Location.Home)) { CitizenMgr.ReleaseCitizen(citizenId); return(false); } if (CitizenProxy.IsCollapsed(ref citizen)) { Log.Debug($"{GetCitizenDesc(citizenId, ref citizen, false)} is collapsed, doing nothing..."); return(false); } return(true); }