class_name FacilityDefinition extends Resource const LEGACY_SCHEMA_VERSION := 1 const DETAILED_SCHEMA_VERSION := 2 enum MapZone { ANY, ABOVE_GROUND, BOUNDARY, UNDERGROUND, } enum ViewLayer { FRONT, BACK, } @export_group("Identity") @export_range(LEGACY_SCHEMA_VERSION, DETAILED_SCHEMA_VERSION, 1) var definition_schema_version := LEGACY_SCHEMA_VERSION @export var id: StringName @export var display_name := "" @export_multiline var description := "" @export var category: StringName = &"uncategorized" @export var service_types: Array[StringName] = [] @export var default_service_type: StringName = &"" @export var service_profiles: Dictionary = {} @export_group("Placement") @export var zone := MapZone.ANY @export var layer := ViewLayer.FRONT @export var footprint := Vector2i.ONE @export var allowed_rotations: Array[int] = [0, 90, 180, 270] @export var guest_access_offsets: Array[Vector2i] = [] @export var staff_access_offsets: Array[Vector2i] = [] @export var required_connection_tags: Array[StringName] = [] @export var preferred_adjacency_tags: Array[StringName] = [] @export var forbidden_adjacency_tags: Array[StringName] = [] @export_group("Construction") @export var construction_cost := {&"gold": 100, &"materials": 1} @export var build_minutes := 60 @export_range(1, 3, 1) var weight_per_cell := 1 @export var pass_through := false @export_range(0, 100, 1) var demolition_refund_percent := 25 @export_range(1, 5, 1) var max_level := 3 @export var upgrade_costs: Array[Dictionary] = [] @export_group("Upkeep and Power") @export var maintenance_gold := 0 @export var maintenance_mana := 0 @export_range(0, 100, 1) var power_priority := 50 @export_group("Staffing") @export var staff_min := 0 @export var staff_max := 0 @export var required_roles: Array[StringName] = [] @export var primary_skill: StringName = &"service" @export_group("Service") @export var customer_capacity := -1 @export var service_attribute: StringName = &"" @export var capacity := 0 @export var queue_capacity := 0 @export var base_service_minutes := 1 @export var base_quality := 50 @export var base_price := 0 @export var inventory_inputs: Dictionary = {} @export var inventory_outputs: Dictionary = {} @export var opening_schedule := {&"morning": true, &"day": true, &"night": true} @export var policy_schema: Dictionary = {} @export_group("Environment and Risk") @export_range(0, 100, 1) var cleanliness_decay_per_service := 0 @export_range(0, 100, 1) var noise_per_service := 0 @export_range(-100, 100, 1) var beauty_effect := 0 @export_range(-100, 100, 1) var security_effect := 0 @export_range(-100, 100, 1) var concealment_effect := 0 @export_range(0, 100, 1) var heat_per_service := 0 @export var incident_weights: Dictionary = {} @export_group("Audience and Content") @export var allowed_guest_tags: Array[StringName] = [] @export var forbidden_guest_tags: Array[StringName] = [] @export var adult_content := false @export var content_replacement_id: StringName = &"" @export_group("Progression") @export var faith_per_service := 0 @export_range(1, 7, 1) var unlock_rank := 1 @export var research_requirements: Array[StringName] = [] @export_group("Analytics") @export var statistics_keys: Array[StringName] = [] @export_group("Classification") @export var tags: Array[StringName] = [] func is_valid() -> bool: return not id.is_empty() \ and not display_name.is_empty() \ and footprint.x > 0 \ and footprint.y > 0 \ and build_minutes > 0 \ and weight_per_cell in [1, 2, 3] \ and not allowed_rotations.is_empty() \ and maintenance_gold >= 0 \ and maintenance_mana >= 0 \ and staff_min >= 0 \ and staff_max >= staff_min \ and customer_capacity >= -1 \ and service_attribute in [&"", &"appetite", &"relaxation", &"sexual", &"gambling"] \ and capacity >= 0 \ and queue_capacity >= 0 \ and base_service_minutes > 0 \ and base_price >= 0 \ and faith_per_service >= 0 \ and detailed_profile_is_valid() func has_detailed_profile() -> bool: return definition_schema_version == DETAILED_SCHEMA_VERSION func detailed_profile_is_valid() -> bool: if definition_schema_version == LEGACY_SCHEMA_VERSION: return true if definition_schema_version != DETAILED_SCHEMA_VERSION: return false if category.is_empty() or service_types.is_empty() or default_service_type.is_empty(): return false if not service_types.has(default_service_type) or not service_profiles.has(default_service_type): return false if guest_access_offsets.is_empty() and staff_access_offsets.is_empty() and not pass_through: return false if demolition_refund_percent < 0 or demolition_refund_percent > 100: return false if max_level < 1 or max_level > 5 or upgrade_costs.size() != max_level - 1: return false if unlock_rank < 1 or unlock_rank > 7: return false for time_band: StringName in [&"morning", &"day", &"night"]: if not opening_schedule.has(time_band) or not opening_schedule[time_band] is bool: return false if opening_schedule.size() != 3: return false if adult_content and (not tags.has(&"adult_only") or content_replacement_id.is_empty()): return false return true