186 lines
6.5 KiB
GDScript
186 lines
6.5 KiB
GDScript
class_name WorkZone
|
|
extends Node2D
|
|
|
|
# ============================================================================
|
|
# WorkZone.gd - 打工区场景控制器
|
|
# ============================================================================
|
|
# 承载赛博打工区概念地图,负责玩家出生点和相机边界配置。
|
|
# ============================================================================
|
|
|
|
const CAMERA_ZOOM: Vector2 = Vector2(2.0, 2.0)
|
|
const CAMERA_LIMIT_LEFT: int = -1280
|
|
const CAMERA_LIMIT_TOP: int = -960
|
|
const CAMERA_LIMIT_RIGHT: int = 1280
|
|
const CAMERA_LIMIT_BOTTOM: int = 960
|
|
const MALL_PANEL_SCENE: PackedScene = preload("res://scenes/ui/mall/MallPanel.tscn")
|
|
const COURSE_BOARD_PANEL_SCENE: PackedScene = preload("res://scenes/ui/CourseBoardPanel.tscn")
|
|
const MALL_ENTRANCE_POSITION: Vector2 = Vector2(-4, -418)
|
|
const MALL_ENTRANCE_SIZE: Vector2 = Vector2(112, 34)
|
|
const MALL_EXIT_POSITION: Vector2 = Vector2(-4, -310)
|
|
const MALL_EXIT_REOPEN_COOLDOWN: float = 0.45
|
|
const PLAYER_COLLISION_LAYER: int = 1
|
|
|
|
@onready var player: PlayerController = $YSortWorld/Characters/Players/Player
|
|
@onready var playerCamera: Camera2D = $YSortWorld/Characters/Players/Player/Camera2D
|
|
@onready var uiLayer: CanvasLayer = $UILayer
|
|
|
|
var _mallPanel: Control
|
|
var _courseBoardPanel: Control
|
|
var _mallEntranceArea: Area2D
|
|
var _isInsideMall: bool = false
|
|
var _mallCanEnter: bool = true
|
|
|
|
func _ready() -> void:
|
|
add_to_group("whaletown_interactable")
|
|
_apply_spawn_point()
|
|
_configure_camera()
|
|
_ensure_mall_panel()
|
|
_ensure_course_board_panel()
|
|
_ensure_mall_entrance_area()
|
|
EventSystem.connect_event(EventNames.OBJECT_INTERACTED, _on_object_interacted, self)
|
|
EventSystem.connect_event(EventNames.MALL_CLOSED, _on_mall_closed, self)
|
|
_discover_destination()
|
|
|
|
func _discover_destination() -> void:
|
|
var destination_id := SceneManager.get_next_destination_id()
|
|
if destination_id.is_empty():
|
|
destination_id = "work_entrance"
|
|
var socialManager := get_node_or_null("/root/SocialManager")
|
|
if socialManager != null and socialManager.has_method("discover_destination"):
|
|
socialManager.call("discover_destination", destination_id)
|
|
|
|
func _exit_tree() -> void:
|
|
EventSystem.disconnect_event(EventNames.OBJECT_INTERACTED, _on_object_interacted, self)
|
|
EventSystem.disconnect_event(EventNames.MALL_CLOSED, _on_mall_closed, self)
|
|
|
|
func _apply_spawn_point() -> void:
|
|
if player.has_scene_position_override:
|
|
return
|
|
var spawnName: String = SceneManager.get_next_spawn_name()
|
|
var markerName: String = spawnName if not spawnName.is_empty() else "DefaultSpawn"
|
|
var marker := $Markers.get_node_or_null(markerName) as Marker2D
|
|
if marker == null:
|
|
marker = $Markers/DefaultSpawn
|
|
player.global_position = marker.global_position
|
|
|
|
func _configure_camera() -> void:
|
|
playerCamera.zoom = CAMERA_ZOOM
|
|
playerCamera.position_smoothing_enabled = true
|
|
playerCamera.limit_left = CAMERA_LIMIT_LEFT
|
|
playerCamera.limit_top = CAMERA_LIMIT_TOP
|
|
playerCamera.limit_right = CAMERA_LIMIT_RIGHT
|
|
playerCamera.limit_bottom = CAMERA_LIMIT_BOTTOM
|
|
playerCamera.limit_smoothed = true
|
|
|
|
func _ensure_mall_panel() -> void:
|
|
var existingPanel := uiLayer.get_node_or_null("MallPanel") as Control
|
|
if existingPanel != null:
|
|
_mallPanel = existingPanel
|
|
return
|
|
_mallPanel = MALL_PANEL_SCENE.instantiate() as Control
|
|
_mallPanel.name = "MallPanel"
|
|
uiLayer.add_child(_mallPanel)
|
|
|
|
func _ensure_course_board_panel() -> void:
|
|
var existingPanel := uiLayer.get_node_or_null("CourseBoardPanel") as Control
|
|
if existingPanel != null:
|
|
_courseBoardPanel = existingPanel
|
|
return
|
|
_courseBoardPanel = COURSE_BOARD_PANEL_SCENE.instantiate() as Control
|
|
_courseBoardPanel.name = "CourseBoardPanel"
|
|
uiLayer.add_child(_courseBoardPanel)
|
|
|
|
func _ensure_mall_entrance_area() -> void:
|
|
var areas := get_node_or_null("InteractionAreas") as Node2D
|
|
if areas == null:
|
|
areas = Node2D.new()
|
|
areas.name = "InteractionAreas"
|
|
add_child(areas)
|
|
|
|
var entrance := areas.get_node_or_null("MallEntranceArea") as WorkZoneBuildingArea
|
|
if entrance == null:
|
|
entrance = WorkZoneBuildingArea.new()
|
|
entrance.name = "MallEntranceArea"
|
|
areas.add_child(entrance)
|
|
|
|
entrance.buildingId = "whale_super_mall"
|
|
entrance.buildingTitle = "鲸鱼商城"
|
|
entrance.buildingRole = "mall"
|
|
entrance.position = MALL_ENTRANCE_POSITION
|
|
|
|
var shape := entrance.get_node_or_null("CollisionShape2D") as CollisionShape2D
|
|
if shape == null:
|
|
shape = CollisionShape2D.new()
|
|
shape.name = "CollisionShape2D"
|
|
entrance.add_child(shape)
|
|
|
|
var rectangle := shape.shape as RectangleShape2D
|
|
if rectangle == null:
|
|
rectangle = RectangleShape2D.new()
|
|
shape.shape = rectangle
|
|
shape.position = Vector2.ZERO
|
|
rectangle.size = MALL_ENTRANCE_SIZE
|
|
_setup_mall_entrance_trigger(entrance)
|
|
|
|
func _setup_mall_entrance_trigger(entrance: Area2D) -> void:
|
|
_mallEntranceArea = entrance
|
|
_mallEntranceArea.collision_mask = 0
|
|
|
|
func _on_object_interacted(data: Dictionary) -> void:
|
|
var buildingId := str(data.get("buildingId", ""))
|
|
if buildingId.is_empty():
|
|
return
|
|
if buildingId == "whale_super_mall":
|
|
_enter_mall()
|
|
return
|
|
if buildingId == "virtual_whale_recruitment_board":
|
|
_open_course_board()
|
|
return
|
|
if not [
|
|
"whale_job_center",
|
|
"ai_service_station",
|
|
"whale_coin_exchange",
|
|
"virtual_whale_recruitment_board",
|
|
].has(buildingId):
|
|
return
|
|
|
|
var title := str(data.get("title", buildingId))
|
|
var role := str(data.get("role", ""))
|
|
print("WorkZone interaction ready: %s (%s)" % [title, role])
|
|
|
|
func _open_course_board() -> void:
|
|
if is_instance_valid(_courseBoardPanel) and _courseBoardPanel.has_method("show_panel"):
|
|
_courseBoardPanel.call("show_panel")
|
|
|
|
func _on_mall_entrance_body_entered(body: Node2D) -> void:
|
|
return
|
|
|
|
func _enter_mall() -> void:
|
|
if _isInsideMall:
|
|
return
|
|
_isInsideMall = true
|
|
_set_player_mall_transition_state(true)
|
|
if is_instance_valid(_mallPanel) and _mallPanel.has_method("show_panel"):
|
|
_mallPanel.call("show_panel")
|
|
|
|
func _on_mall_closed(_data: Dictionary = {}) -> void:
|
|
if not _isInsideMall:
|
|
return
|
|
_isInsideMall = false
|
|
_mallCanEnter = false
|
|
player.global_position = MALL_EXIT_POSITION
|
|
if player.has_method("_reset_movement_input_state"):
|
|
player.call("_reset_movement_input_state")
|
|
_set_player_mall_transition_state(false)
|
|
await get_tree().create_timer(MALL_EXIT_REOPEN_COOLDOWN).timeout
|
|
_mallCanEnter = true
|
|
|
|
func _set_player_mall_transition_state(isInsideMall: bool) -> void:
|
|
if not is_instance_valid(player):
|
|
return
|
|
player.visible = not isInsideMall
|
|
player.set_physics_process(not isInsideMall)
|
|
player.velocity = Vector2.ZERO
|
|
if player.has_method("_reset_movement_input_state"):
|
|
player.call("_reset_movement_input_state")
|