Files
tekton/scripts/portal_door.gd
T

105 lines
3.2 KiB
GDScript

extends StaticBody3D
# PortalDoor.gd
# Specialized door for "Tekton Doors" mode.
# Teleports players to a target room/door when they step into it.
signal player_entered_portal(player_node, door_node)
@export var room_id: int = 0
@export var door_id: int = 0 # 0: North, 1: South, 2: East, 3: West
# State synced by PortalModeManager
var target_room_id: int = -1
var target_door_id: int = -1
var is_active: bool = true
var portal_color: Color = Color.WHITE: set = set_portal_color
func set_portal_color(value: Color):
portal_color = value
_update_visuals()
@onready var detection_area: Area3D = $Area3D
func _ready():
add_to_group("PortalDoors")
if detection_area:
detection_area.body_entered.connect(_on_body_entered)
# Visual feedback: indicate door is active
_update_visuals()
func _on_body_entered(body: Node3D):
if not is_active: return
if body.is_in_group("Players") or body.get("is_bot"):
var current_time = Time.get_ticks_msec()
if body.has_meta("last_portal_time"):
# Reduce cooldown to 200ms to match manager logic and allow fast re-entry
if current_time - body.get_meta("last_portal_time") < 200:
return
body.set_meta("last_portal_time", current_time)
print("[PortalDoor] Player %s entered Door %d in Room %d" % [body.name, door_id, room_id])
emit_signal("player_entered_portal", body, self )
var _materials_initialized: bool = false
func _update_visuals():
# Removed is_node_ready() check to allow early setter calls to prepare variables,
# but we still need the nodes to exist to apply them.
if not is_inside_tree(): return
var vortex = get_node_or_null("Vortex")
var frame_left = get_node_or_null("Frame_Left")
# If children aren't there yet, we can't update visuals.
# This usually happens if called before or during early _ready.
if not vortex or not frame_left: return
if not _materials_initialized:
_initialize_unique_materials()
_materials_initialized = true
if vortex:
var mat = vortex.get_surface_override_material(0)
if mat:
mat.albedo_color = portal_color
mat.albedo_color.a = 0.5
if mat.has_method("set_emission"):
mat.set("emission", portal_color)
for part_name in ["Frame_Left", "Frame_Right", "Frame_Top"]:
var frame = get_node_or_null(part_name)
if frame:
var mat = frame.get_surface_override_material(0)
if mat:
mat.albedo_color = portal_color.lerp(Color.BLACK, 0.4)
func _initialize_unique_materials():
var vortex = get_node_or_null("Vortex")
if vortex:
var mat = vortex.get_surface_override_material(0)
if not mat:
mat = vortex.mesh.surface_get_material(0)
if mat:
vortex.set_surface_override_material(0, mat.duplicate())
for part_name in ["Frame_Left", "Frame_Right", "Frame_Top"]:
var frame = get_node_or_null(part_name)
if frame:
var mat = frame.get_surface_override_material(0)
if not mat:
mat = frame.mesh.surface_get_material(0)
if mat:
frame.set_surface_override_material(0, mat.duplicate())
func get_teleport_target_position() -> Vector2i:
# This function will be called by the manager to determine WHERE the player spawns
# usually just outside the target door's position.
# For now, let's just return a placeholder that the manager will override.
return Vector2i.ZERO