Wire the crowd variants into per-role pools and verify every seed resolves
Full build / Import + headless tests (push) Successful in 55s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-04 11:03:01 +01:00
1 parent 4e8665e25b
commit 6052ea391b
3 files changed
+35 -28

No files matched your search

+19 -23
View File
@@ -195,32 +195,28 @@ const GEAR_ATTACH := {
}
## Character variants from tools/blender_assets.py. The manifest is the source
## of truth; this mapping keeps selection deterministic and testable offline.
const CHARACTER_MODELS := {
Rules.NpcType.TOURIST: "npc_casual",
Rules.NpcType.CONFUSED_VISITOR: "npc_casual",
Rules.NpcType.INTOXICATED: "npc_casual",
Rules.NpcType.AUTHORIZED_GUEST: "npc_jacket",
Rules.NpcType.AUTHORIZED_STAFF: "npc_jacket",
Rules.NpcType.PROTESTER: "npc_jacket",
Rules.NpcType.INFLUENCER: "npc_coat",
Rules.NpcType.TRESPASSER: "npc_coat",
Rules.NpcType.VIOLENT_THREAT: "npc_hoodie",
Rules.NpcType.MENTAL_CRISIS: "npc_hoodie",
Rules.NpcType.PERFORMER: "npc_dress",
Rules.NpcType.DELIVERY: "npc_vest",
Rules.NpcType.RESPONDER: "npc_firefighter",
const CHARACTER_POOLS := {
Rules.NpcType.TOURIST: ["npc_casual", "npc_crowd_a", "npc_crowd_d"],
Rules.NpcType.CONFUSED_VISITOR: ["npc_casual", "npc_crowd_b"],
Rules.NpcType.INTOXICATED: ["npc_casual", "npc_crowd_c"],
Rules.NpcType.AUTHORIZED_GUEST: ["npc_jacket", "npc_casual", "npc_casual"],
Rules.NpcType.AUTHORIZED_STAFF: ["npc_jacket"],
Rules.NpcType.PROTESTER: ["npc_jacket"],
Rules.NpcType.INFLUENCER: ["npc_coat"],
Rules.NpcType.TRESPASSER: ["npc_hoodie", "npc_coat"],
Rules.NpcType.VIOLENT_THREAT: ["npc_hoodie", "npc_coat"],
Rules.NpcType.MENTAL_CRISIS: ["npc_hoodie"],
Rules.NpcType.PERFORMER: ["npc_dress"],
Rules.NpcType.DELIVERY: ["npc_vest"],
Rules.NpcType.RESPONDER: ["npc_firefighter"],
}
## Which library character represents this profile. Pure and seed-stable; some
## roles alternate between two silhouettes so crowds do not clone.
## Which library character represents this profile. Pure and seed-stable; a role
## picks from its pool by seed so crowds vary without cloning, and every pool
## entry resolves to a committed library GLB.
static func character_model_for(npc_type: int, seed_value: int) -> String:
match npc_type:
Rules.NpcType.AUTHORIZED_GUEST:
return "npc_jacket" if seed_value % 3 == 0 else "npc_casual"
Rules.NpcType.TRESPASSER, Rules.NpcType.VIOLENT_THREAT:
return "npc_hoodie" if seed_value % 2 == 0 else "npc_coat"
_:
return str(CHARACTER_MODELS.get(npc_type, "npc_casual"))
var pool: Array = CHARACTER_POOLS.get(npc_type, ["npc_casual"])
return str(pool[absi(seed_value) % pool.size()])
const HAIR_STYLES := ["short", "long", "bun", "beard", "bald", "short"]
const HAND_ITEMS := ["phone", "cup", "clipboard", "umbrella", "camera", "none"]