Game.City.CityUtils
Assembly: Assembly-CSharp
Namespace: Game.City
Type: public static class
Base: (static utility class — no instance/base type)
Summary:
CityUtils is a small helper/utility class used by the game to read/apply city options and city modifiers and to compute workplace capacity for city service buildings. It contains pure/static helpers that operate on City-related bitmasks, DynamicBuffer
Fields
- None
This type declares no fields.
Properties
- None
This type declares no properties.
Constructors
- None (static utility class)
There is no instance constructor. No static constructor is declared.
Methods
public static bool CheckOption(City city, CityOption option)
Returns true if the given City has the specified option enabled. It checks city.m_OptionMask using (city.m_OptionMask & (1 << (int)option)) != 0. Use this to quickly test a city-level option bit.
Notes: - Safe to call with any City value; relies on City.m_OptionMask bitmask. - Equivalent to HasOption when you only have CityOptionData vs City.
public static void ApplyModifier(ref float value, DynamicBuffer<CityModifier> modifiers, CityModifierType type)
Applies a modifier specified by type from the supplied DynamicBufferto the provided value (passed by ref). The modifier is a float2 delta where: - delta.x is an additive offset applied first (value += delta.x)
- delta.y is a multiplicative delta applied second (value += value * delta.y)
Behavior: - If modifiers.Length <= (int)type, no change is made. - The method modifies the supplied value in place.
Example behavior: - If value = 100, delta = (10, 0.1) -> value becomes 100 + 10 = 110, then 110 + 110 * 0.1 = 121.
Notes: - Ordering matters: additive applied before multiplicative. - Use when applying city-wide modifiers (tax, demand, etc.) stored in buffers.
-
public static float2 GetModifier(DynamicBuffer<CityModifier> modifiers, CityModifierType type)
Returns the float2 delta for the specified modifier type, or default(float2) (0,0) if the buffer does not contain that index. Useful to read a modifier without applying it directly. -
public static bool HasOption(CityOptionData optionData, CityOption option)
Checks whether the provided CityOptionData has a given option bit set. Similar to CheckOption but operates on CityOptionData.m_OptionMask.
Notes: - Both this and CheckOption use a 1 << (int)option bit test on an uint mask.
public static int GetCityServiceWorkplaceMaxWorkers(Entity ownerEntity, ref ComponentLookup<PrefabRef> prefabRefs, ref BufferLookup<InstalledUpgrade> installedUpgrades, ref ComponentLookup<Deleted> deleteds, ref ComponentLookup<WorkplaceData> workplaceDatas, ref ComponentLookup<SchoolData> schoolDatas, ref BufferLookup<Student> studentBufs)
Computes and returns the maximum number of workers for a city service workplace instance (ownerEntity). The computation accounts for:- The base workplace data from the prefab referenced by the owner's PrefabRef.
- Installed upgrades on the instance (each upgrade may add minimum and maximum worker counts).
- The Deleted component: if the owner entity is marked Deleted the result is 0.
- If the prefab is a school (SchoolData present) the returned max worker count is adjusted based on current student load (studentBufs length vs school student capacity) using Mathf.Lerp: result is max(minimumAllowed, Lerp(0, result, studentCount / studentCapacity)).
Detailed logic: 1. If deleteds.HasComponent(ownerEntity) => return 0. 2. Resolve the prefab entity: entity = prefabRefs[ownerEntity]; if that prefab entity does not have WorkplaceData => return 0. 3. Start result = workplaceDatas[entity].m_MaxWorkers. 4. If no installedUpgrades buffer exists on owner, return the current result. 5. num = (workplaceDatas[entity].m_MinimumWorkersLimit == 0) ? result : workplaceDatas[entity].m_MinimumWorkersLimit - This num is the running minimum allowed number of workers (base or explicitly configured minimum). 6. For each InstalledUpgrade in installedUpgrades[ownerEntity]: - If prefabRefs.HasComponent(upgradeEntity) && !deleteds.HasComponent(upgradeEntity): - Resolve upgrade prefab entity2 = prefabRefs[item.m_Upgrade] - If workplaceDatas.HasComponent(entity2), then add workplaceDatas[entity2].m_MinimumWorkersLimit to num and workplaceDatas[entity2].m_MaxWorkers to result. 7. If the base prefab has SchoolData: - studentCapacity = schoolDatas[entity].m_StudentCapacity - length = studentBufs[ownerEntity].Length (current students) - result = math.max(num, (int)Mathf.Lerp(0f, result, 1f * length / (float)studentCapacity)) 8. Return result.
Notes and pitfalls: - The method expects properly populated ComponentLookup/BufferLookup objects (typically created via System.Stateful lookups in a SystemBase/System). - PrefabRef lookup must exist for the ownerEntity and for each installed upgrade to include their workplace data. - Ensure you call BufferLookup.HasBuffer/ComponentLookup.HasComponent checks where appropriate (the method itself calls HasBuffer and HasComponent internally in places). - The school capacity adjustment uses Mathf.Lerp with integer cast; if studentCapacity is 0 this will be a divide-by-zero—however in normal data school studentCapacity should be > 0. Still, callers should ensure valid data. - This method uses math.max to ensure the returned number is at least the computed minimum limit.
Usage Example
// Example: checking options and applying modifiers inside a SystemBase
protected override void OnUpdate()
{
// Example: Check city option
City city = ...; // obtain City struct (from some singleton/context)
bool enabled = CityUtils.CheckOption(city, CityOption.SomeOption);
// Example: apply a city modifier stored in a DynamicBuffer<CityModifier>
Entity cityEntity = ...;
DynamicBuffer<CityModifier> modifiers = SystemAPI.GetBuffer<CityModifier>(cityEntity);
float taxRate = 10f;
CityUtils.ApplyModifier(ref taxRate, modifiers, CityModifierType.TaxRate);
// taxRate is now changed according to additive and multiplicative deltas.
// Example: compute service workplace capacity inside a system using lookups
var prefabRefs = GetComponentLookup<PrefabRef>(true);
var installedUpgrades = GetBufferLookup<InstalledUpgrade>(true);
var deleteds = GetComponentLookup<Deleted>(true);
var workplaceDatas = GetComponentLookup<WorkplaceData>(true);
var schoolDatas = GetComponentLookup<SchoolData>(true);
var studentBufs = GetBufferLookup<Student>(true);
Entity ownerEntity = ...; // building instance
int maxWorkers = CityUtils.GetCityServiceWorkplaceMaxWorkers(ownerEntity,
ref prefabRefs, ref installedUpgrades, ref deleteds, ref workplaceDatas, ref schoolDatas, ref studentBufs);
}
Additional tips:
- Use CheckOption / HasOption to quickly read option bitmasks; these are simple bit tests and very cheap.
- When working with DynamicBuffer