Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
150 lines
5.0 KiB
GDScript
150 lines
5.0 KiB
GDScript
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
|