Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display homelessness count #17

Open
kendallroth opened this issue Aug 15, 2024 · 6 comments
Open

Display homelessness count #17

kendallroth opened this issue Aug 15, 2024 · 6 comments
Labels
feature New functionality or workflow

Comments

@kendallroth
Copy link
Owner

kendallroth commented Aug 15, 2024

With the current issues with homelessness, it could be nice to show a homeless count/percentage. However, this data is not currently exposed to the UI, and may not even be calculated behind the scenes? Once implemented, the displayed value will also need to be determined, as a percentage of entire population may not be super beneficial at massive populations (then again, it is a very similar idea to unemployment, and could benefit from #16).

This will require some additional ECS work, particularly with Queries, but may also require a Job (depending on approach).

Note that unemployment does not necessarily indicate homeless (due to temporary unemployment allowance), but might help pare down list of citizens?

There are several mods that are already calculating this, including ByeByeHomeless and CimCensus. However, both of these mods seem a little bit overkill for simply calculating the number of homeless in the city, but they may be the only viable options...

@kendallroth kendallroth added the feature New functionality or workflow label Aug 15, 2024
@kendallroth
Copy link
Owner Author

kendallroth commented Aug 22, 2024

"Scene Explorer" mod is useful in-game for selecting an entity and viewing its components. From investigations there are a couple of potential options:

  • Query for entities with Game.Creatures.Human component, then check for m_Flags=Homeless (bit comparison, likely?)
  • Query for Game.Citizens.HomelessHousehold component, then get household members
    • Entities with Game.Citizens.HomelessHousehold likely have a Game.Citizens.Household component, as well as a Game.Citizens.HouseholdCitizen buffer (length of people in homeless household?) 🎉
    • Querying by HomelessHousehold does return the same value/amount as searching for that component in-game (Scene Explorer)
    • Update: HomelessHousehold apparently only exists for homeless currently living in a park!
    • Uncertain how this would work, as the chain seems to be an entity with Game.Citizens.HouseholdMember, which has m_Household sub-entity, which in turn has Game.Citizens.HomelessHousehold component. m_Household sub-entity also has a prefab ref "component" (DynamicHousehold) with a household data prefab containing the counts of children, students, adults, elders (not sure about teens?).

Warning

Some information about HomelessHousehold has been adjusted!

@kendallroth
Copy link
Owner Author

kendallroth commented Aug 22, 2024

Game.UI.InGame.CitizenUIUtils.cs has an example (GetCitizenConditions()) of indicating whether a citizen is homeless (for selected citizen info screen).

// From 'StatusSection', which inherits 'InfoSectionBase', which inherits 'UISystemBase'
Entity selectedEntity;  // From 'InfoSectionBase' property

EntityManager entityManager = ((ComponentSystemBase)this).EntityManager;
Citizen componentData = ((EntityManager)(ref entityManager)).GetComponentData<Citizen>(selectedEntity);
entityManager = ((ComponentSystemBase)this).EntityManager;
HouseholdMember componentData2 = ((EntityManager)(ref entityManager)).GetComponentData<HouseholdMember>(selectedEntity);
conditions = CitizenUIUtils.GetCitizenConditions(((ComponentSystemBase)this).EntityManager, selectedEntity, componentData, componentData2, conditions);
public static NativeList<CitizenCondition> GetCitizenConditions(
    EntityManager entityManager,
    Entity entity,
    Citizen citizen,
    HouseholdMember householdMember,
    NativeList<CitizenCondition> conditions
)
{
    PropertyRenter propertyRenter = default(PropertyRenter);
    if (
        !((EntityManager)(ref entityManager)).HasComponent<CommuterHousehold>(householdMember.m_Household) &&
        !((EntityManager)(ref entityManager)).HasComponent<TouristHousehold>(householdMember.m_Household) &&
        (
            !EntitiesExtensions.TryGetComponent<PropertyRenter>(entityManager, householdMember.m_Household, ref propertyRenter) ||
            ((EntityManager)(ref entityManager)).HasComponent<Game.Buildings.Park>(propertyRenter.m_Property))
        )
    {
        CitizenCondition citizenCondition = new CitizenCondition(CitizenConditionKey.Homeless);
        conditions.Add(ref citizenCondition);
    }
}

@kendallroth
Copy link
Owner Author

kendallroth commented Aug 22, 2024

Game.Creatures.CreatureUtils.cs has an example (GetConditions) of checking if a human is homeless. However, this does not necessarily correspond with whether the game considers them homeless, as even with this flag some citizens do not display the "Homeless" condition when selected (due to having PropertyRenter component?).

public static ActivityCondition GetConditions(Human human)
{
    if ((human.m_Flags & HumanFlags.Homeless) != 0)
    { ... }
}

Game.Debug.DebugSystem.cs has an example (RemoveAllHomeless) of querying for homeless households (and adding a Deleted component).

private void RemoveAllHomeless()
{
    EntityManager entityManager = ((ComponentSystemBase)this).EntityManager;
    EntityQuery val = ((EntityManager)(ref entityManager)).CreateEntityQuery((ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<HomelessHousehold>() });
    entityManager = ((ComponentSystemBase)this).EntityManager;
    ((EntityManager)(ref entityManager)).AddComponent<Deleted>(val);
}

Game.Simulation.CountHouseholdDataSystem.cs has an example (Accumulate) of counting homeless households via iteration in job.

Game.UI.InGame.DeveloperInfoUISystem.cs has an example appearing to reference a homeless count, but unfortunately it was only counting homeless within selected park (in debug mode) 🤷.

@kendallroth
Copy link
Owner Author

kendallroth commented Aug 22, 2024

Ran some queries in Scene Explorer to compare with in-game (population 12,127)

Component Value
Citizen 12,709
HouseholdMember 12,709
Household 5,837
HouseholdCitizen 5,837
PropertyRenter 5,613
Human 3,112
HomelessHousehold 52
TouristHousehold 4
CommuterHousehold 0
Renter 897
Resident 3,112

less useful stats

Component Value
Temp 0
Deleted 0
Criminal 10 ✔️
Creature 4,107
HouseholdPet 3,223
Pet 981

@kendallroth
Copy link
Owner Author

kendallroth commented Aug 23, 2024

Old code comments during experimentation

            // Homeless Person
            //   Components:
            //      - Game.Creatures.Human [m_Flags=Homeless]
            //      - Game.Creatures.Resident [m_Flags=Arrive,Hangaround,IgnoreBenches]
            //        - m_Citizen: Entity(78485:1 - Citizen Male)
            //          - Components:
            //            - Game.Citizens.HouseholdMember (single household)
            //              - m_Household: Entity(95261:1 - Single Household)
            //                - Components:
            //                  - Game.Prefabs.PrefabRef - DynamicHousehold
            //                  - Game.Buildings.PropertyRenter
            //                    - m_Rent: 0
            //                  - Game.Citizens.HomelessHousehold
            //                    - m_TempHome (park entity)
            //                  - Game.Citizens.Household [m_Flags=MovedIn]
            //            - Game.Citizens.Citizen
            //              - m_UnemploymentCounter: 0 (not helpful?)
            //            - Game.Citizens.Arrived (tag)
            //       - Game.Prefabs.PrefabRef - Elderly_Male
            //         - Game.Prefabs.ResidentData
            //           - m_Age: Elderly

@kendallroth
Copy link
Owner Author

kendallroth commented Aug 23, 2024

It turns out that HomelessHousehold component is only for homeless households living in parks... Any homeless not living in parks (which could be even more, likely) will not be included in this query! Parks appear to have a maximum amount of homeless slots, which would explain why the homeless households count was remaining steady (even with Bye Bye Homeless active).

The most reliable option appears to be iterating over Human flag and checking for m_Flags indicating homelessness... However, this is assuming that all Human component entities are always available in simulation 🤷‍♂️ (which might not be the case for performance (see above in have queries), although households do have a list of members...).


Should check whether HomelessHouseholds are associated with renting process, even if living temporarily in park?

It does appear that HomelessHousehold entities are associated with renting process (ie. have Game.Buildings.PropertyRenter component) when living in a park (albeit with m_Rent=0). This PropertyRenter component is associated with the same entity as HomelessHousehold (ie. HouseholdMember.m_Household.[HomelessHousehold | PropertyRenter | PropertySeeker]).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New functionality or workflow
Projects
None yet
Development

No branches or pull requests

1 participant