137 lines
3.7 KiB
GDScript
137 lines
3.7 KiB
GDScript
class_name ActivitySite
|
|
extends Node3D
|
|
|
|
static var _all: Array = []
|
|
|
|
@export var site_id: StringName
|
|
@export var action_id: StringName = SimulationIds.ACTION_REST
|
|
@export var display_name := "Activity Site"
|
|
@export_range(1, 12, 1) var capacity := 1
|
|
@export_range(0.1, 100.0, 0.1, "or_greater") var interaction_range := 3.0
|
|
@export var debug_label_enabled := true
|
|
|
|
@onready var interaction_point: Marker3D = $InteractionPoint
|
|
|
|
var _last_label_text := ""
|
|
var _active_world_adapter: ActiveWorldAdapter
|
|
|
|
|
|
func _ready() -> void:
|
|
if site_id.is_empty():
|
|
push_error("ActivitySite at %s has empty site_id" % get_path())
|
|
_update_presentation()
|
|
return
|
|
if not is_interaction_range_valid():
|
|
push_error("ActivitySite '%s' must have a positive finite interaction_range" % site_id)
|
|
_update_presentation()
|
|
return
|
|
_active_world_adapter = ActiveWorldAdapter.find_for_node(self)
|
|
var existing: ActivitySite = get_by_id_in_context(site_id, _active_world_adapter)
|
|
if existing != null:
|
|
push_error(
|
|
(
|
|
"Duplicate ActivitySite site_id '%s' at %s; first registered at %s"
|
|
% [site_id, get_path(), existing.get_path()]
|
|
)
|
|
)
|
|
_update_presentation()
|
|
return
|
|
_all.append(self)
|
|
add_to_group("activity_sites")
|
|
set_notify_transform(true)
|
|
_notify_world_adapter()
|
|
_update_presentation()
|
|
set_process(false)
|
|
|
|
|
|
func _exit_tree() -> void:
|
|
_unregister_from_world_adapter()
|
|
_all.erase(self)
|
|
|
|
|
|
func get_interaction_position() -> Vector3:
|
|
return interaction_point.global_position if interaction_point != null else global_position
|
|
|
|
|
|
func supports_action(candidate_action_id: StringName) -> bool:
|
|
if action_id == candidate_action_id:
|
|
return true
|
|
return (
|
|
action_id == SimulationIds.ACTION_PATROL
|
|
and candidate_action_id == SimulationIds.ACTION_DEFEND
|
|
)
|
|
|
|
|
|
func is_interaction_range_valid() -> bool:
|
|
return is_finite(interaction_range) and interaction_range > 0.0
|
|
|
|
|
|
func _notification(what: int) -> void:
|
|
if what == NOTIFICATION_TRANSFORM_CHANGED and is_node_ready():
|
|
if is_instance_valid(_active_world_adapter):
|
|
_active_world_adapter.refresh_world_target_position(self)
|
|
|
|
|
|
func _notify_world_adapter() -> void:
|
|
if not is_inside_tree():
|
|
return
|
|
if (
|
|
not is_instance_valid(_active_world_adapter)
|
|
or not _active_world_adapter.owns_target_node(self)
|
|
):
|
|
_active_world_adapter = ActiveWorldAdapter.find_for_node(self)
|
|
if _active_world_adapter != null:
|
|
_active_world_adapter.register_world_target(self)
|
|
|
|
|
|
func _bind_active_world_adapter(adapter: ActiveWorldAdapter) -> void:
|
|
if adapter != null and adapter.owns_target_node(self):
|
|
_active_world_adapter = adapter
|
|
|
|
|
|
func _unregister_from_world_adapter() -> void:
|
|
if not is_instance_valid(_active_world_adapter):
|
|
_active_world_adapter = ActiveWorldAdapter.find_for_node(self)
|
|
if is_instance_valid(_active_world_adapter):
|
|
_active_world_adapter.unregister_world_target(self)
|
|
_active_world_adapter = null
|
|
|
|
|
|
func _update_presentation() -> void:
|
|
if not has_node("DebugLabel"):
|
|
return
|
|
var label := $DebugLabel as Label3D
|
|
label.visible = debug_label_enabled
|
|
if not debug_label_enabled:
|
|
return
|
|
var text := "%s\n%s\ncap:%d" % [display_name, action_id, capacity]
|
|
if text == _last_label_text:
|
|
return
|
|
_last_label_text = text
|
|
label.text = text
|
|
|
|
|
|
func set_debug_label_enabled(is_enabled: bool) -> void:
|
|
debug_label_enabled = is_enabled
|
|
_update_presentation()
|
|
|
|
|
|
static func get_by_id(search_id: StringName):
|
|
for node in _all:
|
|
if node.site_id == search_id:
|
|
return node
|
|
return null
|
|
|
|
|
|
static func get_by_id_in_context(
|
|
search_id: StringName, adapter: ActiveWorldAdapter
|
|
) -> ActivitySite:
|
|
for node in _all:
|
|
if node.site_id == search_id and ActiveWorldAdapter.find_for_node(node) == adapter:
|
|
return node as ActivitySite
|
|
return null
|
|
|
|
|
|
static func get_all() -> Array:
|
|
return _all.duplicate()
|