Commit 312e1e41 authored by Gavin An's avatar Gavin An

스크립트 정리

parent 33596b43
## 3d MeshLibrary / GridMap 에는 커스텀 메타 데이터를 넣을 수 없음.
## 따라서, 스크립트를 통해 타일마다 메타데이터를 넣어줘야 함.
## 쓰이는 메타데이터가 있으면 여기다가 넣어야 함.
* 'unit_place_blocked': 해당 타일에 유닛을 설치못하는가
\ No newline at end of file
This diff is collapsed.
[gd_scene format=3 uid="uid://doj12ce3mmosn"]
[ext_resource type="MeshLibrary" uid="uid://bh17fgvq0gpu4" path="res://assets/tile/desert/scenes/desert_mesh_library.tres" id="1_byiru"]
[ext_resource type="MeshLibrary" uid="uid://dh2qv7hjdu846" path="res://assets/tile/desert/scenes/desert_mesh_library.tres" id="1_byiru"]
[node name="Stage1Map" type="GridMap" unique_id=875122487]
mesh_library = ExtResource("1_byiru")
......
......@@ -12,6 +12,7 @@ const MAGE_SCENE: PackedScene = preload("res://src/entities/units/mage/mage_unit
const WARRIOR_LV1_SCENE: PackedScene = preload("res://src/entities/units/warrior/lv1/warrior_unit.tscn")
const PLACEMENT_TILE_OVERLAY_SCENE: PackedScene = preload("res://src/ui/unit_placement/placement_tile_overlay.tscn")
const OVERLAY_POOL_WARMUP_BATCH_SIZE: int = 16
const UNIT_PLACE_BLOCKED_METADATA_KEY: String = "unit_place_blocked"
## MonsterPath와 가까운 타일을 "몬스터 길"로 판정할 때 추가로 더해 주는 여유 폭입니다.
## 실제 판정 거리는 `타일 반폭 + 타일 크기 * 이 비율`입니다.
......@@ -35,6 +36,7 @@ var _overlay_pool: Array[Node] = []
var _active_overlays: Array[Node] = []
var _overlay_pool_parent: Node = null
var _is_overlay_pool_warming_up: bool = false
var _overlay_ignored_unit: Node = null
var _monster_path_tile_cache_grid_map: GridMap = null
var _monster_path_tile_cache: Dictionary = {}
......@@ -58,6 +60,34 @@ func setup(hud: Control, unit_spawn_button: Button, base_unit_scene: PackedScene
_base_unit_scene = base_unit_scene
_spawn_button_default_text = _unit_spawn_button.text
## UnitController처럼 HUD 버튼 없이 타일 선택/오버레이 기능만 필요한 코드에서 사용하는 간단한 초기화입니다.
## 이 파일이 타일 레이캐스트, GridMap 탐색, 몬스터 길 캐시, 오버레이 풀을 한곳에서 관리하게 만들어
## 유닛 생성 배치와 선택 유닛 재배치가 같은 판정을 공유하도록 합니다.
func setup_tile_helper(owner_control: Control) -> void:
_hud = owner_control
## 외부 컨트롤러가 화면 좌표를 GridMap 셀 정보로 바꿀 때 사용하는 공개 wrapper입니다.
## 내부 구현은 HUD의 유닛 생성 배치와 동일한 `_get_tile_info_from_screen()`을 그대로 사용합니다.
func get_tile_info_from_screen(screen_pos: Vector2) -> Dictionary:
return _get_tile_info_from_screen(screen_pos)
## 외부 컨트롤러가 타일 배치 가능 여부를 검사할 때 사용하는 공개 wrapper입니다.
## ignored_unit은 재배치 중인 자기 자신을 점유 검사에서 제외하기 위한 값입니다.
func is_tile_occupied(tile_cell: Vector3i, ignored_unit: Node=null) -> bool:
return _is_tile_occupied(tile_cell, ignored_unit)
## 외부 컨트롤러가 선택 유닛 재배치 모드에 들어갈 때 사용하는 공개 wrapper입니다.
## ignored_unit은 현재 움직이려는 유닛이며, 자기 기존 타일이 빨간색 점유 타일로 표시되지 않게 합니다.
func show_placement_tile_overlays(ignored_unit: Node=null) -> void:
_overlay_ignored_unit = ignored_unit
_show_placement_tile_overlays()
## 외부 컨트롤러가 재배치 모드를 끝낼 때 사용하는 공개 wrapper입니다.
## 오버레이 노드는 삭제하지 않고 풀에 반납해 다음 유닛 생성/이동 배치 때 끊김 없이 재사용합니다.
func clear_placement_tile_overlays() -> void:
_overlay_ignored_unit = null
_clear_placement_tile_overlays()
## 전장 진입 직후 타일 오버레이 풀을 미리 준비합니다.
## HUD _ready()에서 호출되며, 한 프레임 뒤 StageMap/GridMap이 준비된 시점에 사용 타일 수만큼 씬 인스턴스를 만들어 둡니다.
func warmup_overlay_pool_deferred() -> void:
......@@ -326,21 +356,48 @@ func _find_grid_map(node: Node) -> GridMap:
return null
## 이미 타일에 고정 배치된 유닛이 해당 셀을 점유 중인지 확인합니다.
## - MeshLibrary 타일 Mesh에 unit_place_blocked=true metadata가 있으면 "점유됨"으로 취급해 배치를 막습니다.
## - 몬스터가 지나다니는 길 타일은 유닛이 없어도 "점유됨"으로 취급해 배치를 막습니다.
## - BaseUnit.place_on_tile()에서 기록한 occupied_tile_cell을 기준으로 중복 배치를 막습니다.
func _is_tile_occupied(tile_cell: Vector3i) -> bool:
func _is_tile_occupied(tile_cell: Vector3i, ignored_unit: Node=null) -> bool:
var grid_map: GridMap = _get_stage_grid_map()
if grid_map and _is_monster_path_tile(grid_map, tile_cell):
return true
if grid_map:
if _is_tile_unit_place_blocked(grid_map, tile_cell):
return true
if _is_monster_path_tile(grid_map, tile_cell):
return true
var units: Array[Node] = _hud.get_tree().get_nodes_in_group("units")
for unit_node: Node in units:
if unit_node == ignored_unit:
continue
if unit_node is BaseUnit:
var unit: BaseUnit = unit_node as BaseUnit
if unit.is_tile_bound and unit.occupied_tile_cell == tile_cell:
return true
return false
## GridMap 셀에 배치된 MeshLibrary item의 Mesh metadata를 읽어 배치 금지 타일인지 확인합니다.
## MeshLibrary item 자체에는 Godot API로 노출되는 metadata 슬롯이 없어서,
## desert_mesh_library.tres 작업 시 각 item이 참조하는 ArrayMesh에 unit_place_blocked 값을 저장해 둡니다.
## metadata가 없거나 MeshLibrary/item/mesh를 찾지 못하면 기본값은 false로 두어 기존 타일 동작을 보존합니다.
func _is_tile_unit_place_blocked(grid_map: GridMap, tile_cell: Vector3i) -> bool:
var item_id: int = grid_map.get_cell_item(tile_cell)
if item_id == -1:
return false
var mesh_library: MeshLibrary = grid_map.mesh_library
if mesh_library == null:
return false
var item_mesh: Mesh = mesh_library.get_item_mesh(item_id)
if item_mesh == null:
return false
return item_mesh.get_meta(UNIT_PLACE_BLOCKED_METADATA_KEY, false) == true
## 몬스터 이동 경로로 판단되는 타일인지 확인합니다.
## 길 타일은 "이미 유닛이 있다"는 의미의 점유와는 성격이 다르지만, 최종 배치 가능 여부에서는 똑같이 막혀야 합니다.
func _is_monster_path_tile(grid_map: GridMap, tile_cell: Vector3i) -> bool:
......@@ -460,8 +517,9 @@ func _clear_placement_tile_overlays() -> void:
func _add_placement_tile_overlay(grid_map: GridMap, tile_cell: Vector3i) -> void:
if _is_monster_path_tile(grid_map, tile_cell):
return
var is_occupied: bool = _is_tile_occupied(tile_cell)
if _is_tile_unit_place_blocked(grid_map, tile_cell):
return
var is_occupied: bool = _is_tile_occupied(tile_cell, _overlay_ignored_unit)
var overlay: Node = _take_overlay_from_pool()
if not overlay:
return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment