Commit f631e2c2 authored by Gavin An's avatar Gavin An

투사체 속성 넣을 수 있도록

parent 71d60e4a
class_name MageUnit
extends BaseUnit
## Mage 유닛 고유 동작 및 비주얼 제어 클래스
## Mage (마법사) 유닛 고유 동작 및 비주얼 제어 클래스
## - BaseUnit을 상속받아 마법사 모델 스킨 적용, 애니메이션 라이브러리 로드 및
## 불덩이(Fireball) 특수 효과 발사체 생성을 처리합니다.
## 유닛의 3D 비주얼 모델, 스킨 텍스처, 무기 및 애니메이션 플레이어 연동 설정
func _setup_unit_visuals() -> void:
# 자식 노드 중 메이지 모델 노드 명시적 확보
# 자식 노드 중 메이지(Mage) 3D 모델 노드 이름을 명시하여 인스턴스를 확보합니다.
var m_name: String = "mage"
var node: Node3D = get_node_or_null(m_name) as Node3D
# 모델 노드가 씬 트리 아래에 존재하지 않을 경우 에러를 출력하고 함수를 종료합니다.
if not node:
push_error("MageUnit: Model node '" + m_name + "' not found under children.")
return
_model_instance = node
# 메이지 스킨 및 무기 결합
# UnitHelper를 활용해 마법사 전용 스킨 이미지와 무기 메쉬를 결합합니다.
UnitHelper.apply_skin(_model_instance, "res://assets/models/units/mage/mage_0.png")
UnitHelper.attach_weapon(_model_instance, unit_data)
# 애니메이션 플레이어 및 라이브러리 연동
# 모델 씬 내부에 구성되어 있는 AnimationPlayer 노드를 탐색하여 변수에 캐싱합니다.
_model_anim_player = UnitHelper.find_animation_player(_model_instance)
if _model_anim_player:
print("MageUnit: Linked pre-configured model & AnimationPlayer: ", m_name)
# 마법사 유닛 전용으로 추출된 애니메이션 라이브러리 리소스 경로를 지정합니다.
var anim_lib_path: String = "res://assets/models/units/" + m_name + "/" + m_name + "_animations.tres"
if ResourceLoader.exists(anim_lib_path):
var lib: AnimationLibrary = load(anim_lib_path) as AnimationLibrary
if lib:
# 기존 기본 빈 라이브러리가 존재하면 충돌 방지를 위해 제거합니다.
if _model_anim_player.has_animation_library(""):
_model_anim_player.remove_animation_library("")
# 마법사 전용 애니메이션 라이브러리가 등록되어 있지 않다면 라이브러리를 추가합니다.
if not _model_anim_player.has_animation_library(m_name):
_model_anim_player.add_animation_library(m_name, lib)
print("MageUnit: Loaded and registered ", m_name, " animations library successfully.")
# 트랙 내 불필요한 루트 모션 경로 정리를 수행합니다.
UnitHelper.clean_root_animation_tracks(_model_anim_player)
## 메이지 애니메이션 갱신 제어
## 매 프레임 물리에 맞추어 마법사 유닛의 애니메이션 상태를 제어하는 함수
func _update_animations() -> void:
if not _model_anim_player:
return
var m_name: String = "mage"
var library_prefix: String = m_name + "/"
# 전용 애니메이션 라이브러리 내에 기본 대기 상태(Idle) 애니메이션이 있는지 식별합니다.
var has_custom_anims: bool = _model_anim_player.has_animation(library_prefix + "Idle")
var target_anim: String = ""
......@@ -46,30 +57,36 @@ func _update_animations() -> void:
var blend_time: float = 0.2
if has_custom_anims:
# Mage용 애니메이션 매핑 (Attack, Running, Idle, Casting)
# Mage용 애니메이션 이름 매핑 (Attack, Running, Idle, Casting)
var attack_anim: String = library_prefix + "Attack"
var run_anim: String = library_prefix + "Running"
var idle_anim: String = library_prefix + "Idle"
var cast_anim: String = library_prefix + "Casting"
# 1. 공격 중일 때 (공격 선딜/모션 락 타이머가 작동 중인 경우)
if _attack_lock_timer > 0.0:
var base_speed: float = 1.2
var base_speed: float = 1.5
# 유닛 쿨다운에 맞춘 애니메이션 속도 보정
if unit_data.cooldown < 0.6:
base_speed = 0.6 / unit_data.cooldown
play_speed = clampf(base_speed, 1.0, 3.0)
# 마법을 시전하는 모션(Casting)을 재생합니다.
target_anim = cast_anim
# 2. 이동 중일 때 (속도 벡터 크기가 0.1보다 클 경우)
elif velocity.length() > 0.1:
target_anim = run_anim
play_speed = 1.1
# 3. 그 외 기본 대기 상태일 때
else:
target_anim = idle_anim
play_speed = 1.0
# 타겟 애니메이션이 정해졌고, 현재 재생 중인 애니메이션과 다를 경우 크로스페이드 재생합니다.
if target_anim != "" and _model_anim_player.current_animation != target_anim:
_last_anim_state = target_anim.replace(library_prefix, "")
_model_anim_player.play(target_anim, blend_time, play_speed)
else:
# Fallback 처리
# 전용 애니메이션이 없을 때의 예외 처리 (기본 Fallback 점프 애니메이션 루프 적용)
var fallback_anim: String = "Armature|Armature|Basic_Jump|baselayer"
if not _model_anim_player.has_animation(fallback_anim):
return
......@@ -87,16 +104,22 @@ func _update_animations() -> void:
if target_anim != "" and _model_anim_player.current_animation != target_anim:
_model_anim_player.play(target_anim, blend_time, play_speed)
## 메이지 전용 발사체 생성 및 스폰
## 마법사(Mage) 전용 화염 불덩이(Fireball) 발사체를 월드에 스폰하는 함수
func _spawn_projectile(fire_position: Vector3) -> void:
# 공통 Projectile 스크립트를 로드하여 발사체 인스턴스를 동적 생성합니다.
var projectile_script = preload("res://src/entities/units/projectile.gd")
var proj: Node3D = projectile_script.new() as Node3D
# 발사체의 능력치 및 비행 속성 주입 (공격력, 유도 대상, 비행 속도, 이펙트 색상)
proj.set("damage", unit_data.damage)
proj.set("target", _target_monster)
proj.set("speed", 18.0) # 불덩이는 크고 묵직하므로 조금 느린 속도(18.0m/s)로 날아가게 설정
proj.set("color", Color(1.0, 0.35, 0.1, 1.0)) # 붉은 주황색 계열의 색상 지정
# 불덩이 비주얼 효과 씬 장착
# 셰이더 및 GPUParticles3D가 사전 구성된 불덩이 비주얼 효과 씬(.tscn)을 전달합니다.
var fb_effect = preload("res://src/entities/projectiles/fireball/fireball_effect.tscn")
proj.set("custom_visual_scene", fb_effect)
# 발사체를 씬 트리에 등록하고 설정된 발사 좌표(fire_position)를 부여합니다.
get_tree().current_scene.add_child(proj)
proj.global_position = fire_position
......@@ -89,8 +89,12 @@ func _update_animations() -> void:
func _spawn_projectile(fire_position: Vector3) -> void:
var projectile_script = preload("res://src/entities/units/projectile.gd")
var proj: Node3D = projectile_script.new() as Node3D
# 발사체의 속성들을 설정합니다. (공격력, 유도 대상, 비행 속도, 이펙트 색상)
proj.set("damage", unit_data.damage)
proj.set("target", _target_monster)
proj.set("speed", 28.0) # 화살은 매우 날렵하므로 빠른 속도(28.0m/s)로 비행하게 설정
proj.set("color", unit_data.unit_color) # 레인저 고유의 유닛 컬러 지정
# 레인저 화살 비주얼 씬 장착
var arrow_effect = preload("res://src/entities/projectiles/arrow/arrow_effect.tscn")
......
class_name UnitData
extends Resource
## 유닛의 기획 능력치를 정의하는 커스텀 리소스 (UnitData)
## 유닛의 기획 능력치(스펙) 데이터를 정의하는 커스텀 리소스 클래스 (UnitData)
## - Godot의 Resource 클래스를 상속받아 유닛 데이터 템플릿을 생성 및 직렬화하기에 용이합니다.
## - DataManager에서 각 유닛의 기본 능력치를 정의하고 생성할 때 템플릿 데이터로 활용됩니다.
## 유닛 고유 식별자 ID (예: "Unit_Striker", "Unit_Mage")
@export var unit_id: String = ""
## UI 및 로그에 출력할 유닛 이름 (예: "Striker", "Mage")
@export var unit_name: String = ""
## 유닛의 기본 공격력 (적에게 가하는 데미지 수치)
@export var damage: float = 10.0
## 공격 주기/쿨다운 시간 (초 단위, 낮을수록 공격 속도가 빠름)
@export var cooldown: float = 1.0
## 유닛의 전장 내 기본 이동 속도
@export var move_speed: float = 4.0
## 공격 가능 사거리 (단위: 미터, 근접 유닛은 보통 1.5, 원거리는 8.0~10.0)
@export var attack_range: float = 1.5
## 원거리 유닛 여부 (true일 경우 투사체를 발사하고, false일 경우 근접 타격을 가함)
@export var is_ranged: bool = false
## 유닛 선택 링(Selection Ring) 및 발사체 색상 연출 등에 쓰이는 유닛 고유 색상
@export var unit_color: Color = Color.WHITE
......@@ -56,8 +56,8 @@ alignment = 1
[node name="Portrait" type="TextureRect" parent="VBoxContainer/CardsHBox/MageCard" unique_id=947627767]
custom_minimum_size = Vector2(240, 240)
layout_mode = 2
expand_mode = 1
stretch_mode = 6
expand_mode = 4
stretch_mode = 4
[node name="Name" type="Label" parent="VBoxContainer/CardsHBox/MageCard" unique_id=594177406]
layout_mode = 2
......@@ -88,8 +88,8 @@ alignment = 1
[node name="Portrait" type="TextureRect" parent="VBoxContainer/CardsHBox/WarriorCard" unique_id=1881168350]
custom_minimum_size = Vector2(240, 240)
layout_mode = 2
expand_mode = 1
stretch_mode = 6
expand_mode = 4
stretch_mode = 4
[node name="Name" type="Label" parent="VBoxContainer/CardsHBox/WarriorCard" unique_id=1845912094]
layout_mode = 2
......
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