Beispiel #1
0
        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");
            }
        }
Beispiel #2
0
        private void ReturnFromVisit(
            TAI instance,
            uint citizenId,
            ref TCitizen citizen,
            ushort targetBuilding,
            Citizen.Location targetLocation,
            bool isVirtual)
        {
            if (targetBuilding == 0 || targetLocation == Citizen.Location.Visit || CitizenProxy.GetVehicle(ref citizen) != 0)
            {
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
            CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);

            if (isVirtual || targetBuilding == currentBuilding)
            {
                CitizenProxy.SetLocation(ref citizen, targetLocation);
            }
            else
            {
                residentAI.StartMoving(instance, citizenId, ref citizen, currentBuilding, targetBuilding);
            }
        }
Beispiel #3
0
        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, $"{GetCitizenDesc(citizenId, ref citizen)} is currently homeless. Cannot move home, waiting for the next opportunity");
                return;
            }

            ushort currentBuilding = CitizenProxy.GetCurrentBuilding(ref citizen);

            CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);

#if DEBUG
            string logEntry = $"{GetCitizenDesc(citizenId, ref citizen)} is going from {currentBuilding} back home";
#else
            const string logEntry = null;
#endif

            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, logEntry);
            }
            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");
            }
        }
Beispiel #4
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);
        }
Beispiel #5
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;
            }
        }
 private void ReturnFromVisit(TAI instance, uint citizenId, ref TCitizen citizen, ushort targetBuilding)
 {
     if (targetBuilding != 0 && CitizenProxy.GetVehicle(ref citizen) == 0)
     {
         CitizenProxy.RemoveFlags(ref citizen, Citizen.Flags.Evacuating);
         residentAI.StartMoving(instance, citizenId, ref citizen, CitizenProxy.GetVisitBuilding(ref citizen), targetBuilding);
         CitizenProxy.SetVisitPlace(ref citizen, citizenId, 0);
     }
 }
Beispiel #7
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));
        }
        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 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);
                }
            }
        }