Commit 3c907192 authored by Gavin An's avatar Gavin An

근접 유닛은 스플래시가 기본

parent 1e5019bd
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://bpbiksphmyw04"
path="res://.godot/imported/bow.glb-1784fd364296aebc0cced3fd64035baa.scn"
[deps]
source_file="res://assets/models/items/weapons/azure_bow/bow.glb"
dest_files=["res://.godot/imported/bow.glb-1784fd364296aebc0cced3fd64035baa.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
gltf/texture_map_mode=0
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
importer="scene" importer="scene"
importer_version=1 importer_version=1
type="PackedScene" type="PackedScene"
uid="uid://dcb3y3h3xmxlf" uid="uid://ddyh6wdryiymj"
path="res://.godot/imported/azure_blade.glb-a19870aae22080a3ea6f42eec3138dfe.scn" path="res://.godot/imported/old_sword.glb-75f3b315ed25f8d3a820f35bc47f754d.scn"
[deps] [deps]
source_file="res://assets/models/items/weapons/azure_blade/azure_blade.glb" source_file="res://assets/models/items/weapons/old_sword/old_sword.glb"
dest_files=["res://.godot/imported/azure_blade.glb-a19870aae22080a3ea6f42eec3138dfe.scn"] dest_files=["res://.godot/imported/old_sword.glb-75f3b315ed25f8d3a820f35bc47f754d.scn"]
[params] [params]
...@@ -17,6 +17,7 @@ nodes/root_type="" ...@@ -17,6 +17,7 @@ nodes/root_type=""
nodes/root_name="" nodes/root_name=""
nodes/root_script=null nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false mesh_library/use_node_names_as_mesh_names=false
mesh_library/create_categories_from_hierarchy=false
array_mesh/deduplicate_surfaces=true array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true nodes/apply_root_scale=true
nodes/root_scale=1.0 nodes/root_scale=1.0
...@@ -42,4 +43,4 @@ materials/extract_path="" ...@@ -42,4 +43,4 @@ materials/extract_path=""
_subresources={} _subresources={}
gltf/naming_version=2 gltf/naming_version=2
gltf/embedded_image_handling=1 gltf/embedded_image_handling=1
gltf/texture_map_mode=0 gltf/texture_map_mode=1
[gd_scene format=3 uid="uid://o4bsh40353h2"]
[ext_resource type="PackedScene" uid="uid://ddyh6wdryiymj" path="res://assets/models/items/weapons/old_sword/old_sword.glb" id="1_n03i5"]
[node name="old_sword" unique_id=811983829 instance=ExtResource("1_n03i5")]
transform = Transform3D(0.24104536, -0.2565151, 0.6622666, -0.7047695, -3.080645e-08, 0.2565151, -0.08773329, -0.7047695, -0.24104534, 0, 0.085, -0.035)
[node name="Mesh" parent="." index="0" unique_id=1964212149]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.7, 0)
...@@ -2,21 +2,21 @@ ...@@ -2,21 +2,21 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://byow3khisasa" uid="uid://be42p4a48j321"
path.s3tc="res://.godot/imported/bow_0.jpg-7f9db53893217b91e458f6561b73405a.s3tc.ctex" path.s3tc="res://.godot/imported/old_sword_0.png-48e2afd6355d671c9ae554a5b691a225.s3tc.ctex"
path.etc2="res://.godot/imported/bow_0.jpg-7f9db53893217b91e458f6561b73405a.etc2.ctex" path.etc2="res://.godot/imported/old_sword_0.png-48e2afd6355d671c9ae554a5b691a225.etc2.ctex"
metadata={ metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"], "imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true "vram_texture": true
} }
generator_parameters={ generator_parameters={
"md5": "04380a0e0b68e8030ba518cede60b7c1" "md5": "c3340516098eab9b8dda79e74f63b157"
} }
[deps] [deps]
source_file="res://assets/models/items/weapons/azure_bow/bow_0.jpg" source_file="res://assets/models/items/weapons/old_sword/old_sword_0.png"
dest_files=["res://.godot/imported/bow_0.jpg-7f9db53893217b91e458f6561b73405a.s3tc.ctex", "res://.godot/imported/bow_0.jpg-7f9db53893217b91e458f6561b73405a.etc2.ctex"] dest_files=["res://.godot/imported/old_sword_0.png-48e2afd6355d671c9ae554a5b691a225.s3tc.ctex", "res://.godot/imported/old_sword_0.png-48e2afd6355d671c9ae554a5b691a225.etc2.ctex"]
[params] [params]
......
...@@ -2,21 +2,21 @@ ...@@ -2,21 +2,21 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://d2jeadmacnycs" uid="uid://ckd88mfdajrk5"
path.s3tc="res://.godot/imported/azure_blade_Image_0.jpg-ab1c8111925f30b0e35664f4f69b0b2a.s3tc.ctex" path.s3tc="res://.godot/imported/old_sword_1.png-ff00b792a10b306a4797326af60166c4.s3tc.ctex"
path.etc2="res://.godot/imported/azure_blade_Image_0.jpg-ab1c8111925f30b0e35664f4f69b0b2a.etc2.ctex" path.etc2="res://.godot/imported/old_sword_1.png-ff00b792a10b306a4797326af60166c4.etc2.ctex"
metadata={ metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"], "imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true "vram_texture": true
} }
generator_parameters={ generator_parameters={
"md5": "7632a7275d12e7d54a8291642fe0ee63" "md5": "678b9b295cb0a19300759e9ac58a716e"
} }
[deps] [deps]
source_file="res://assets/models/items/weapons/azure_blade/azure_blade_Image_0.jpg" source_file="res://assets/models/items/weapons/old_sword/old_sword_1.png"
dest_files=["res://.godot/imported/azure_blade_Image_0.jpg-ab1c8111925f30b0e35664f4f69b0b2a.s3tc.ctex", "res://.godot/imported/azure_blade_Image_0.jpg-ab1c8111925f30b0e35664f4f69b0b2a.etc2.ctex"] dest_files=["res://.godot/imported/old_sword_1.png-ff00b792a10b306a4797326af60166c4.s3tc.ctex", "res://.godot/imported/old_sword_1.png-ff00b792a10b306a4797326af60166c4.etc2.ctex"]
[params] [params]
......
...@@ -2,21 +2,21 @@ ...@@ -2,21 +2,21 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://1qtyym2i641x" uid="uid://dto53v4gvarfh"
path.s3tc="res://.godot/imported/azure_blade_Image_2.jpg-707b3bcc521334be70ec57a6e4e9a221.s3tc.ctex" path.s3tc="res://.godot/imported/old_sword_2.png-f8913ad5328a78e4f13dfda8b56e2296.s3tc.ctex"
path.etc2="res://.godot/imported/azure_blade_Image_2.jpg-707b3bcc521334be70ec57a6e4e9a221.etc2.ctex" path.etc2="res://.godot/imported/old_sword_2.png-f8913ad5328a78e4f13dfda8b56e2296.etc2.ctex"
metadata={ metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"], "imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true "vram_texture": true
} }
generator_parameters={ generator_parameters={
"md5": "40c6fd3e4a271bacfc2f002cc1b6de20" "md5": "5f8e33b002298d2d3f89aaa570b38e17"
} }
[deps] [deps]
source_file="res://assets/models/items/weapons/azure_blade/azure_blade_Image_2.jpg" source_file="res://assets/models/items/weapons/old_sword/old_sword_2.png"
dest_files=["res://.godot/imported/azure_blade_Image_2.jpg-707b3bcc521334be70ec57a6e4e9a221.s3tc.ctex", "res://.godot/imported/azure_blade_Image_2.jpg-707b3bcc521334be70ec57a6e4e9a221.etc2.ctex"] dest_files=["res://.godot/imported/old_sword_2.png-f8913ad5328a78e4f13dfda8b56e2296.s3tc.ctex", "res://.godot/imported/old_sword_2.png-f8913ad5328a78e4f13dfda8b56e2296.etc2.ctex"]
[params] [params]
...@@ -32,7 +32,7 @@ compress/channel_pack=0 ...@@ -32,7 +32,7 @@ compress/channel_pack=0
mipmaps/generate=true mipmaps/generate=true
mipmaps/limit=-1 mipmaps/limit=-1
roughness/mode=1 roughness/mode=1
roughness/src_normal="res://assets/models/items/weapons/azure_blade/azure_blade_Image_2.jpg" roughness/src_normal="res://assets/models/items/weapons/old_sword/old_sword_2.png"
process/channel_remap/red=0 process/channel_remap/red=0
process/channel_remap/green=1 process/channel_remap/green=1
process/channel_remap/blue=2 process/channel_remap/blue=2
......
...@@ -43,9 +43,9 @@ rendering_device/driver.windows="d3d12" ...@@ -43,9 +43,9 @@ rendering_device/driver.windows="d3d12"
renderer/rendering_method="mobile" renderer/rendering_method="mobile"
textures/vram_compression/import_s3tc_bptc=true textures/vram_compression/import_s3tc_bptc=true
textures/vram_compression/import_etc2_astc=true textures/vram_compression/import_etc2_astc=true
lights_and_shadows/directional_shadow/size=1024 lights_and_shadows/directional_shadow/size=512
lights_and_shadows/directional_shadow/size.mobile=512 lights_and_shadows/directional_shadow/size.mobile=512
lights_and_shadows/directional_shadow/soft_shadow_filter_quality=0 lights_and_shadows/directional_shadow/soft_shadow_filter_quality=0
lights_and_shadows/positional_shadow/soft_shadow_filter_quality=0 lights_and_shadows/positional_shadow/soft_shadow_filter_quality=0
lights_and_shadows/positional_shadow/atlas_size=1024 lights_and_shadows/positional_shadow/atlas_size=512
lights_and_shadows/positional_shadow/atlas_size.mobile=512 lights_and_shadows/positional_shadow/atlas_size.mobile=512
[gd_scene format=3 uid="uid://cftdvlslaqab"] [gd_scene format=3 uid="uid://cftdvlslaqab"]
[ext_resource type="PackedScene" uid="uid://c6wju2s7ey11q" path="res://src/entities/units/warrior/lv1/warrior.tscn" id="1_gy7ce"] [ext_resource type="PackedScene" uid="uid://c6wju2s7ey11q" path="res://src/entities/units/warrior/lv1/warrior.tscn" id="1_gy7ce"]
[ext_resource type="PackedScene" uid="uid://c7ena3jinf4qc" path="res://assets/models/items/weapons/rapier/rapier.tscn" id="2_gy7ce"] [ext_resource type="PackedScene" uid="uid://o4bsh40353h2" path="res://assets/models/items/weapons/old_sword/old_sword.tscn" id="2_gy7ce"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_gy7ce"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_gy7ce"]
radius = 0.4 radius = 0.4
...@@ -41,12 +41,37 @@ mesh = SubResource("TorusMesh_dx6da") ...@@ -41,12 +41,37 @@ mesh = SubResource("TorusMesh_dx6da")
[node name="warrior" parent="." unique_id=1583845935 instance=ExtResource("1_gy7ce")] [node name="warrior" parent="." unique_id=1583845935 instance=ExtResource("1_gy7ce")]
[node name="BoneAttachment3D" type="BoneAttachment3D" parent="warrior/Armature/Skeleton3D" parent_id_path=PackedInt32Array(1583845935, 1756619771) index="1" unique_id=275485168] [node name="Skeleton3D" parent="warrior/Armature" parent_id_path=PackedInt32Array(1583845935, 1122658972) index="0" unique_id=1756619771]
transform = Transform3D(0.9017347, -0.23595689, -0.36221126, 0.4235169, 0.31427628, 0.8496252, -0.08664024, -0.91953963, 0.38332614, -0.24779537, -0.013620254, 0.54939604) bones/0/position = Vector3(0.008906826, -0.016679727, 0.43917266)
bones/0/rotation = Quaternion(0.5769956, -0.6211797, -0.5235334, 0.08440762)
bones/1/rotation = Quaternion(0.3405336, 0.50771105, -0.69530636, 0.37790936)
bones/2/rotation = Quaternion(0.6037263, 0.2845332, 0.26035553, 0.6976894)
bones/3/rotation = Quaternion(-0.58000565, -0.13442044, 0.031176709, 0.80284035)
bones/4/rotation = Quaternion(-0.4466983, -0.10617086, 0.00024005448, 0.8883628)
bones/5/rotation = Quaternion(0.60905373, 0.28895423, 0.43019533, 0.60040903)
bones/6/rotation = Quaternion(0.37091663, -0.0070300167, 0.33285922, 0.8669349)
bones/7/rotation = Quaternion(-0.2209062, 0.06417928, -0.046449788, 0.972072)
bones/8/rotation = Quaternion(-0.45842803, 0.1347912, 0.014290656, 0.8783341)
bones/9/rotation = Quaternion(-0.25834036, 0.20522211, 0.11844286, 0.9365444)
bones/10/rotation = Quaternion(0.022619344, 0.08164339, -0.010146947, 0.9963533)
bones/11/rotation = Quaternion(-0.04387128, 0.042346712, -0.037475266, 0.9974356)
bones/12/rotation = Quaternion(0.47878474, 0.6548964, -0.2680936, 0.51961696)
bones/13/rotation = Quaternion(0.45065325, 0.38060609, 0.33229527, 0.7359556)
bones/14/rotation = Quaternion(-0.64165676, -0.21268447, 0.33198053, 0.6578989)
bones/16/rotation = Quaternion(-0.5172855, 0.5582187, -0.3922586, -0.5166631)
bones/17/rotation = Quaternion(0.537166, -0.20910145, -0.24741791, 0.7787899)
bones/18/rotation = Quaternion(-0.27791968, 0.023365224, -0.5383427, 0.795237)
bones/20/rotation = Quaternion(0.25569445, 0.07016864, 0.0060589095, 0.9641889)
bones/21/rotation = Quaternion(0.17097658, 0.2306515, -0.1883551, 0.93919605)
bones/22/rotation = Quaternion(-0.15805918, -2.3112833e-08, 0.0019670601, 0.9874277)
bones/23/rotation = Quaternion(0.5403607, 5.8547363e-09, -0.0067247013, 0.84140664)
[node name="BoneAttachment3D" type="BoneAttachment3D" parent="warrior/Armature/Skeleton3D" index="1" unique_id=275485168]
transform = Transform3D(0.5152335, -0.8477933, 0.12561765, -0.62911963, -0.27458957, 0.7271914, -0.58201486, -0.45370203, -0.6748423, -0.23612644, 0.20563285, 0.57239693)
bone_name = "RightHand" bone_name = "RightHand"
bone_idx = 19 bone_idx = 19
[node name="rapier" parent="warrior/Armature/Skeleton3D/BoneAttachment3D" unique_id=795567087 instance=ExtResource("2_gy7ce")] [node name="old_sword" parent="warrior/Armature/Skeleton3D/BoneAttachment3D" unique_id=811983829 instance=ExtResource("2_gy7ce")]
transform = Transform3D(-0.1736482, -0.9848077, 0, 0.9848077, -0.1736482, 0, 0, 0, 1, -0.6, 0, 0) transform = Transform3D(0.24104542, -0.25651523, 0.662267, -0.7047696, -3.080647e-08, 0.25651523, -0.08773331, -0.70476985, -0.24104548, 0, 0.085, -0.035)
[editable path="warrior"] [editable path="warrior"]
...@@ -277,6 +277,9 @@ func _try_attack() -> void: ...@@ -277,6 +277,9 @@ func _try_attack() -> void:
else: else:
# 근접 유닛: 공격 애니메이션 중간 즈음(락아웃 시간의 50% 지점)에 데미지 지연 적용 # 근접 유닛: 공격 애니메이션 중간 즈음(락아웃 시간의 50% 지점)에 데미지 지연 적용
var target_ref: Node3D = _target_monster var target_ref: Node3D = _target_monster
# 자식 유닛이 범위 공격을 지원하면 공격 시작 순간의 피격 대상 목록을 반환합니다.
# 기본 구현은 현재 타겟 하나만 반환하므로 기존 근접 유닛의 동작은 그대로 유지됩니다.
var melee_targets: Array[Node3D] = _get_melee_attack_targets(target_ref)
var damage_amount: float = unit_data.damage var damage_amount: float = unit_data.damage
var damage_delay: float = _get_attack_damage_delay(_attack_lock_timer) var damage_delay: float = _get_attack_damage_delay(_attack_lock_timer)
_set_melee_move_lock_until_hit(damage_delay) _set_melee_move_lock_until_hit(damage_delay)
...@@ -284,13 +287,29 @@ func _try_attack() -> void: ...@@ -284,13 +287,29 @@ func _try_attack() -> void:
if damage_delay > 0.0: if damage_delay > 0.0:
get_tree().create_timer(damage_delay).timeout.connect( get_tree().create_timer(damage_delay).timeout.connect(
func() -> void: func() -> void:
if is_instance_valid(target_ref) and not target_ref.get("is_dead"): _apply_melee_attack_damage(melee_targets, damage_amount)
if target_ref.has_method("take_damage"):
target_ref.call("take_damage", damage_amount)
) )
else: else:
if target_ref.has_method("take_damage"): _apply_melee_attack_damage(melee_targets, damage_amount)
target_ref.call("take_damage", damage_amount)
## 이번 근접 공격으로 피해를 받을 몬스터 목록을 반환합니다.
## - 기본 근접 유닛은 자동 조준된 주 대상 하나만 공격합니다.
## - 워리어처럼 범위 공격이 필요한 자식 클래스는 이 메서드를 재정의해 여러 대상을 반환할 수 있습니다.
## - 공격 모션이 시작될 때 목록을 확정하므로, 데미지 지연 중 유닛이 회전해도 공격 방향이 바뀌지 않습니다.
func _get_melee_attack_targets(primary_target: Node3D) -> Array[Node3D]:
var targets: Array[Node3D] = []
if is_instance_valid(primary_target):
targets.append(primary_target)
return targets
## 공격 시작 시 확정한 근접 피격 대상들에게 피해를 적용합니다.
## 데미지 타이머가 끝나기 전에 죽거나 삭제된 몬스터는 건너뛰어 잘못된 인스턴스 접근을 방지합니다.
func _apply_melee_attack_damage(targets: Array[Node3D], damage_amount: float) -> void:
for target: Node3D in targets:
if not is_instance_valid(target) or target.get("is_dead") == true:
continue
if target.has_method("take_damage"):
target.call("take_damage", damage_amount)
## 공격 애니메이션 길이를 계산합니다. ## 공격 애니메이션 길이를 계산합니다.
## - 자식 클래스는 애니메이션 이름 훅만 바꾸면 공통 공격 로직을 그대로 사용할 수 있습니다. ## - 자식 클래스는 애니메이션 이름 훅만 바꾸면 공통 공격 로직을 그대로 사용할 수 있습니다.
......
...@@ -7,31 +7,30 @@ ...@@ -7,31 +7,30 @@
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0) transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0)
[node name="Skeleton3D" parent="Armature" parent_id_path=PackedInt32Array(1122658972) index="0" unique_id=1756619771] [node name="Skeleton3D" parent="Armature" parent_id_path=PackedInt32Array(1122658972) index="0" unique_id=1756619771]
bones/0/position = Vector3(-0.0042122453, -0.08830176, 0.626378) bones/0/rotation = Quaternion(0.77211255, -0.32861972, -0.39244667, 0.3766126)
bones/0/rotation = Quaternion(0.85872275, -0.08392143, -0.26641637, 0.42962164) bones/1/rotation = Quaternion(0.75794494, 0.21279207, -0.39043227, 0.47728586)
bones/1/rotation = Quaternion(0.77490896, 0.20032243, -0.4231632, 0.4246412) bones/2/rotation = Quaternion(0.36515447, 0.09661304, 0.06416007, 0.9236946)
bones/2/rotation = Quaternion(0.29141474, 0.100757435, 0.06735114, 0.94888836) bones/3/rotation = Quaternion(-0.44689593, -0.10568743, -0.06612381, 0.8858566)
bones/3/rotation = Quaternion(-0.45503718, -0.14945994, -0.05290419, 0.87624425) bones/4/rotation = Quaternion(-0.4466983, -0.10617086, 0.00024005913, 0.8883628)
bones/4/rotation = Quaternion(-0.46250498, -0.14293629, 0.009365743, 0.874969) bones/5/rotation = Quaternion(0.9525083, 0.043601416, 0.16173382, 0.25430116)
bones/5/rotation = Quaternion(0.92503315, 0.14065711, 0.12639615, 0.32947415) bones/6/rotation = Quaternion(0.37124047, -0.12221774, -0.084734604, 0.9165498)
bones/6/rotation = Quaternion(0.29527205, -0.11466962, -0.0835156, 0.94482297) bones/7/rotation = Quaternion(-0.6027679, 0.1532908, -0.01661504, 0.7828772)
bones/7/rotation = Quaternion(-0.5243528, 0.10898508, 0.071843565, 0.84143627) bones/8/rotation = Quaternion(-0.45842803, 0.1347912, 0.014290654, 0.8783341)
bones/8/rotation = Quaternion(-0.47703573, 0.14649285, -0.016162159, 0.8664384) bones/9/rotation = Quaternion(-0.25834066, 0.20522228, 0.11844309, 0.9365443)
bones/9/rotation = Quaternion(-0.2180815, 0.17500709, 0.14091109, 0.94971424) bones/10/rotation = Quaternion(0.022618964, 0.081643246, -0.010147069, 0.99635327)
bones/10/rotation = Quaternion(-0.045494687, 0.032769445, 0.011077983, 0.9983655) bones/11/rotation = Quaternion(-0.08385007, 0.0072866958, 0.00797267, 0.9964199)
bones/11/rotation = Quaternion(-0.07905474, 0.011545275, -0.0020301344, 0.9968014) bones/12/rotation = Quaternion(0.49577588, 0.62461483, -0.38751596, 0.46248677)
bones/12/rotation = Quaternion(0.5524608, 0.5694922, -0.40452987, 0.45477608) bones/13/rotation = Quaternion(0.67199486, 0.41072702, 0.19313905, 0.5851696)
bones/13/rotation = Quaternion(0.6395657, 0.3777125, 0.26244292, 0.61596483) bones/14/rotation = Quaternion(-0.31836405, -0.012108725, 0.14181627, 0.93722254)
bones/14/rotation = Quaternion(-0.055958077, -0.030247174, 0.02641047, 0.99762535) bones/15/rotation = Quaternion(-0.0009877216, 0.24114296, -0.086359695, 0.9666391)
bones/15/rotation = Quaternion(0.09356525, 0.2024164, 0.12004779, 0.96739954) bones/16/rotation = Quaternion(-0.635021, 0.45945278, -0.3177428, -0.53356445)
bones/16/rotation = Quaternion(-0.60885024, 0.5101509, -0.40538743, -0.4524473) bones/17/rotation = Quaternion(0.7112564, -0.41147092, 0.01572414, 0.56970066)
bones/17/rotation = Quaternion(0.5945567, -0.4030331, -0.2623887, 0.6443748) bones/18/rotation = Quaternion(-0.25303727, -0.0018723977, -0.11099208, 0.9610669)
bones/18/rotation = Quaternion(-0.079526834, 0.017640848, -0.03761267, 0.9959667) bones/19/rotation = Quaternion(0.0024361685, -0.54337037, -0.022761738, 0.83918095)
bones/19/rotation = Quaternion(0.09758278, -0.45935866, 0.070185356, 0.88008034) bones/20/rotation = Quaternion(0.25569457, 0.0701687, 0.006059007, 0.9641888)
bones/20/rotation = Quaternion(0.08377819, 0.015401736, 0.027466234, 0.9959868) bones/21/rotation = Quaternion(0.2485067, -0.00918251, 0.0027086218, 0.96858287)
bones/21/rotation = Quaternion(0.25044242, 0.0030668462, -0.042835645, 0.9671786) bones/22/rotation = Quaternion(-0.15805918, -2.3142073e-08, 0.0019670601, 0.9874277)
bones/22/rotation = Quaternion(-0.15805925, -1.314033e-08, 0.0019670653, 0.98742765) bones/23/rotation = Quaternion(0.5403607, 5.8879426e-09, -0.0067247017, 0.84140664)
bones/23/rotation = Quaternion(0.5403607, -6.557056e-09, -0.006724717, 0.84140664)
[node name="AnimationPlayer" parent="." index="1" unique_id=189824221] [node name="AnimationPlayer" parent="." index="1" unique_id=189824221]
libraries/ = ExtResource("2_warrior_anim") libraries/ = ExtResource("2_warrior_anim")
...@@ -7,6 +7,12 @@ const WARRIOR_ATTACK_ANIM: String = "Attack" ...@@ -7,6 +7,12 @@ const WARRIOR_ATTACK_ANIM: String = "Attack"
const WARRIOR_RUN_ANIM: String = "Run" const WARRIOR_RUN_ANIM: String = "Run"
const WARRIOR_IDLE_ANIM: String = "Idle" const WARRIOR_IDLE_ANIM: String = "Idle"
# 드워프 영웅의 전방 부채꼴 공격 방식을 워리어의 자동 공격에 맞게 사용합니다.
# 워리어가 자동으로 선택한 주 대상을 바라본 뒤 공격하므로, 해당 방향을 중심으로
# 좌우 절반 각도 안에 있고 반경 안에 있는 모든 몬스터가 같은 피해를 받습니다.
@export var area_attack_distance: float = 2.5
@export_range(1.0, 360.0, 1.0) var area_attack_angle_degrees: float = 115.0
func _setup_unit_visuals() -> void: func _setup_unit_visuals() -> void:
var node: Node3D = get_node_or_null(MODEL_NAME) as Node3D var node: Node3D = get_node_or_null(MODEL_NAME) as Node3D
if not node: if not node:
...@@ -32,14 +38,70 @@ func _setup_unit_visuals() -> void: ...@@ -32,14 +38,70 @@ func _setup_unit_visuals() -> void:
func _get_attack_animation_name(_model_name: String) -> String: func _get_attack_animation_name(_model_name: String) -> String:
return MODEL_NAME + "/" + WARRIOR_ATTACK_ANIM return MODEL_NAME + "/" + WARRIOR_ATTACK_ANIM
## 워리어의 공격 시작 순간 정면 부채꼴 안에 있는 모든 몬스터를 피격 대상으로 확정합니다.
## BaseUnit이 공격 모션의 실제 타격 시점까지 이 목록을 보관하므로, 애니메이션과 피해 타이밍은
## 기존 단일 대상 근접 공격과 동일하면서 한 번의 검 휘두르기로 여러 몬스터를 공격할 수 있습니다.
func _get_melee_attack_targets(primary_target: Node3D) -> Array[Node3D]:
var attack_origin: Vector3 = global_position
var attack_forward: Vector3 = -global_transform.basis.z
attack_forward.y = 0.0
# 모델의 Basis가 비정상적으로 축소되어 정면 벡터를 구할 수 없는 경우에도
# 월드 기본 정면을 사용해 범위 판정이 중단되지 않도록 보호합니다.
if attack_forward.length_squared() <= 0.0001:
attack_forward = Vector3.FORWARD
else:
attack_forward = attack_forward.normalized()
var hit_monsters: Array[Node3D] = []
var half_angle_radians: float = deg_to_rad(area_attack_angle_degrees * 0.5)
var minimum_forward_dot: float = cos(half_angle_radians)
for monster: Node in get_tree().get_nodes_in_group("monsters"):
if not is_instance_valid(monster) or not monster is Node3D:
continue
if monster.get("is_dead") == true:
continue
var monster_3d: Node3D = monster as Node3D
var direction_from_warrior: Vector3 = monster_3d.global_position - attack_origin
direction_from_warrior.y = 0.0
var horizontal_distance: float = direction_from_warrior.length()
if horizontal_distance > area_attack_distance:
continue
if horizontal_distance <= 0.01:
hit_monsters.append(monster_3d)
continue
var direction_to_monster: Vector3 = direction_from_warrior / horizontal_distance
if attack_forward.dot(direction_to_monster) >= minimum_forward_dot:
hit_monsters.append(monster_3d)
# 자동 조준된 주 대상은 공격 직전에 워리어가 정확히 바라보므로 일반적으로 부채꼴에 포함됩니다.
# 부동소수점 경계 오차로 주 대상만 빠지는 경우를 막아 기본 공격이 허공에 적용되는 상황을 방지합니다.
if is_instance_valid(primary_target) and not hit_monsters.has(primary_target):
var primary_offset: Vector3 = primary_target.global_position - attack_origin
primary_offset.y = 0.0
if primary_offset.length() <= area_attack_distance:
hit_monsters.append(primary_target)
# 거리순 정렬은 피해량에는 영향을 주지 않지만, 이후 타격 이펙트나 연쇄 효과가 추가되더라도
# 항상 가까운 몬스터부터 처리되는 결정적인 순서를 보장합니다.
hit_monsters.sort_custom(func(a: Node3D, b: Node3D) -> bool:
return attack_origin.distance_squared_to(a.global_position) < attack_origin.distance_squared_to(b.global_position)
)
return hit_monsters
func _get_weapon_config() -> Dictionary: func _get_weapon_config() -> Dictionary:
return { return {
"bone_name": "RightHand", "bone_name": "RightHand",
"attachment_name": "RightHandAttachment", "attachment_name": "RightHandAttachment",
"weapon_scene_path": "res://assets/models/items/weapons/rapier/rapier.tscn", "weapon_scene_path": "res://assets/models/items/weapons/old_sword/old_sword.tscn",
"texture_path": "res://assets/models/items/weapons/rapier/rapier_Baked_BaseColor.png", "texture_path": "res://assets/models/items/weapons/old_sword/old_sword_0.png",
"weapon_position": Vector3(-0.6, 0.0, 0), "weapon_position": Vector3(0, 0.085, -0.035),
"weapon_rotation": Vector3(0, 0, 100) "weapon_rotation": Vector3(-20, 110, -90),
"weapon_scale": Vector3(0.75, 0.75, 0.75),
} }
func _update_animations() -> void: func _update_animations() -> void:
......
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