game: add weapon base and sword
This commit is contained in:
@@ -18,6 +18,7 @@ const GROUP_DAMAGEABLE = "damagable"
|
|||||||
const GROUP_PLAYER = "player"
|
const GROUP_PLAYER = "player"
|
||||||
const GROUP_XP_ORB = "xp_orb"
|
const GROUP_XP_ORB = "xp_orb"
|
||||||
const GROUP_PICKUP = "pickup"
|
const GROUP_PICKUP = "pickup"
|
||||||
|
const GROUP_PROJ_MANAGER = "proj_manager"
|
||||||
|
|
||||||
enum ModRarity { LEGENDARY, EPIC, RARE, NORMAL }
|
enum ModRarity { LEGENDARY, EPIC, RARE, NORMAL }
|
||||||
|
|
||||||
|
@@ -33,6 +33,7 @@ enemy="Group containing all enemies"
|
|||||||
damagable="Can be damaged using take_damage"
|
damagable="Can be damaged using take_damage"
|
||||||
xp_orb="Experience orbs"
|
xp_orb="Experience orbs"
|
||||||
pickup="Items that can be picked up"
|
pickup="Items that can be picked up"
|
||||||
|
proj_manager="Parent node for all projectiles"
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
|
@@ -1,102 +0,0 @@
|
|||||||
extends Node2D
|
|
||||||
|
|
||||||
@export var default_attack_time: float = 0.5
|
|
||||||
@export var player: Player = null
|
|
||||||
|
|
||||||
@onready var trigger_area: Area2D = $TriggerArea
|
|
||||||
@onready var trigger_collision: CollisionShape2D = $TriggerArea/TriggerCollision
|
|
||||||
@onready var timer: Timer = $Timer
|
|
||||||
@onready var attack_path: Path2D = $AttackPath
|
|
||||||
@onready var path_follow_2d: PathFollow2D = $AttackPath/PathFollow2D
|
|
||||||
@onready var attack_area: Area2D = $AttackPath/PathFollow2D/Sprite2D/AttackArea
|
|
||||||
|
|
||||||
var base_damage: float = 5.0
|
|
||||||
var current_target: Node2D = null
|
|
||||||
var current_progress: float = 0.0
|
|
||||||
var damaged_this_attack: Array = []
|
|
||||||
var is_attacking: bool = false
|
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
|
||||||
attack_path.visible = false
|
|
||||||
|
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
|
||||||
if timer.is_stopped() and current_progress == 0.0:
|
|
||||||
timer.start()
|
|
||||||
if current_progress > 0.95:
|
|
||||||
reset_attack()
|
|
||||||
if (
|
|
||||||
current_target
|
|
||||||
and is_instance_valid(current_target)
|
|
||||||
and not current_target.is_queued_for_deletion()
|
|
||||||
):
|
|
||||||
track_target(current_target)
|
|
||||||
is_attacking = true
|
|
||||||
attack_path.visible = true
|
|
||||||
|
|
||||||
if is_attacking:
|
|
||||||
# Do attack animation
|
|
||||||
current_progress += delta / default_attack_time
|
|
||||||
current_progress = clampf(current_progress, 0.0, 1.0)
|
|
||||||
path_follow_2d.progress_ratio = current_progress
|
|
||||||
|
|
||||||
|
|
||||||
func reset_attack() -> void:
|
|
||||||
current_target = null
|
|
||||||
attack_path.visible = false
|
|
||||||
current_progress = 0.0
|
|
||||||
damaged_this_attack = []
|
|
||||||
is_attacking = false
|
|
||||||
position = Vector2.ZERO
|
|
||||||
rotation = 0.0
|
|
||||||
|
|
||||||
|
|
||||||
func set_target(body: Node2D):
|
|
||||||
current_target = body
|
|
||||||
is_attacking = true
|
|
||||||
|
|
||||||
|
|
||||||
func track_target(body: Node2D):
|
|
||||||
var mid_distance = attack_path.curve.get_baked_length() / 2
|
|
||||||
var mid_point: Vector2 = attack_path.curve.sample_baked(mid_distance)
|
|
||||||
var offset = body.global_position - to_global(mid_point)
|
|
||||||
|
|
||||||
var desired_dir = (body.global_position - to_global(mid_point)).normalized()
|
|
||||||
var start_point_global = attack_path.to_global(attack_path.curve.sample_baked(0))
|
|
||||||
var end_point_global = attack_path.to_global(
|
|
||||||
attack_path.curve.sample_baked(attack_path.curve.get_baked_length())
|
|
||||||
)
|
|
||||||
var curve_dir = (start_point_global - end_point_global).normalized()
|
|
||||||
var angle_diff = curve_dir.angle_to(desired_dir)
|
|
||||||
if rotation == 0.0:
|
|
||||||
rotation = curve_dir.angle_to(desired_dir)
|
|
||||||
position += offset
|
|
||||||
|
|
||||||
|
|
||||||
func _on_timer_timeout() -> void:
|
|
||||||
if current_target:
|
|
||||||
if trigger_area.has_overlapping_areas():
|
|
||||||
if current_target not in trigger_area.get_overlapping_bodies():
|
|
||||||
current_target = null
|
|
||||||
return
|
|
||||||
if trigger_area.has_overlapping_bodies():
|
|
||||||
for body in trigger_area.get_overlapping_bodies():
|
|
||||||
if body.is_in_group(GlobalConst.GROUP_ENEMY):
|
|
||||||
set_target(body)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_attack_area_body_entered(body: Node2D) -> void:
|
|
||||||
if not attack_path.visible:
|
|
||||||
return
|
|
||||||
if body in damaged_this_attack:
|
|
||||||
return
|
|
||||||
if body.is_in_group(GlobalConst.GROUP_ENEMY) and body.is_in_group(GlobalConst.GROUP_DAMAGEABLE):
|
|
||||||
var crit_chance = player.player_stats.get_final("crit_chance", player.modifiers)
|
|
||||||
var damage_dealt = base_damage
|
|
||||||
var is_crit = randf() >= 1 - crit_chance
|
|
||||||
if is_crit:
|
|
||||||
damage_dealt *= player.player_stats.get_final("crit_multiplier", player.modifiers)
|
|
||||||
|
|
||||||
body.take_damage(damage_dealt, is_crit)
|
|
||||||
damaged_this_attack.append(body)
|
|
@@ -1 +0,0 @@
|
|||||||
uid://db326gu8abue5
|
|
@@ -1,53 +0,0 @@
|
|||||||
[gd_scene load_steps=6 format=3 uid="uid://cdojqe2m4kxx1"]
|
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://dycw7c3484dir" path="res://assets/sprites/sword.png" id="1_3fwwl"]
|
|
||||||
[ext_resource type="Script" uid="uid://db326gu8abue5" path="res://scenes/attacks/attack_sword.gd" id="1_frsqi"]
|
|
||||||
|
|
||||||
[sub_resource type="Curve2D" id="Curve2D_frsqi"]
|
|
||||||
bake_interval = 2.0
|
|
||||||
_data = {
|
|
||||||
"points": PackedVector2Array(0, 0, 0, 0, 0, 0, 0, 0, 25, 10, 200, 0)
|
|
||||||
}
|
|
||||||
point_count = 2
|
|
||||||
|
|
||||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_frsqi"]
|
|
||||||
size = Vector2(13.9997, 46.999)
|
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_3fwwl"]
|
|
||||||
radius = 267.002
|
|
||||||
|
|
||||||
[node name="AttackSword" type="Node2D"]
|
|
||||||
script = ExtResource("1_frsqi")
|
|
||||||
|
|
||||||
[node name="AttackPath" type="Path2D" parent="."]
|
|
||||||
curve = SubResource("Curve2D_frsqi")
|
|
||||||
|
|
||||||
[node name="PathFollow2D" type="PathFollow2D" parent="AttackPath"]
|
|
||||||
loop = false
|
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="AttackPath/PathFollow2D"]
|
|
||||||
position = Vector2(0.322462, -0.946582)
|
|
||||||
rotation = 0.328329
|
|
||||||
texture = ExtResource("1_3fwwl")
|
|
||||||
|
|
||||||
[node name="AttackArea" type="Area2D" parent="AttackPath/PathFollow2D/Sprite2D"]
|
|
||||||
collision_layer = 0
|
|
||||||
collision_mask = 2
|
|
||||||
|
|
||||||
[node name="AttackCollision" type="CollisionShape2D" parent="AttackPath/PathFollow2D/Sprite2D/AttackArea"]
|
|
||||||
position = Vector2(-0.0328934, -4.50646)
|
|
||||||
shape = SubResource("RectangleShape2D_frsqi")
|
|
||||||
|
|
||||||
[node name="TriggerArea" type="Area2D" parent="."]
|
|
||||||
visible = false
|
|
||||||
collision_layer = 0
|
|
||||||
collision_mask = 2
|
|
||||||
|
|
||||||
[node name="TriggerCollision" type="CollisionShape2D" parent="TriggerArea"]
|
|
||||||
shape = SubResource("CircleShape2D_3fwwl")
|
|
||||||
|
|
||||||
[node name="Timer" type="Timer" parent="."]
|
|
||||||
one_shot = true
|
|
||||||
|
|
||||||
[connection signal="body_entered" from="AttackPath/PathFollow2D/Sprite2D/AttackArea" to="." method="_on_attack_area_body_entered"]
|
|
||||||
[connection signal="timeout" from="Timer" to="." method="_on_timer_timeout"]
|
|
@@ -55,6 +55,7 @@ func do_movement(delta: float) -> void:
|
|||||||
else:
|
else:
|
||||||
_do_nav_agent_movement()
|
_do_nav_agent_movement()
|
||||||
|
|
||||||
|
|
||||||
func _has_direct_path():
|
func _has_direct_path():
|
||||||
target_cast.target_position = to_local(target.global_position)
|
target_cast.target_position = to_local(target.global_position)
|
||||||
target_cast.enabled = true
|
target_cast.enabled = true
|
||||||
|
@@ -14,6 +14,7 @@ func _process(delta: float) -> void:
|
|||||||
elapsed_time += delta
|
elapsed_time += delta
|
||||||
main_ui.player_ui.set_elapsed_time(elapsed_time)
|
main_ui.player_ui.set_elapsed_time(elapsed_time)
|
||||||
|
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
if event.is_action_pressed("ui_cancel"):
|
if event.is_action_pressed("ui_cancel"):
|
||||||
main_ui.pause_ui.toggle_pause_ui()
|
main_ui.pause_ui.toggle_pause_ui()
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=8 format=3 uid="uid://bjg50n7aab3ng"]
|
[gd_scene load_steps=9 format=3 uid="uid://bjg50n7aab3ng"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://brb4ssksmtq8k" path="res://scenes/main.gd" id="1_jyhfs"]
|
[ext_resource type="Script" uid="uid://brb4ssksmtq8k" path="res://scenes/main.gd" id="1_jyhfs"]
|
||||||
[ext_resource type="PackedScene" uid="uid://4xha2nhf8fya" path="res://scenes/test_level.tscn" id="1_o5qli"]
|
[ext_resource type="PackedScene" uid="uid://4xha2nhf8fya" path="res://scenes/test_level.tscn" id="1_o5qli"]
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
[ext_resource type="PackedScene" uid="uid://dy73qrxcgrwg3" path="res://scenes/managers/enemy_manager.tscn" id="5_tbgi4"]
|
[ext_resource type="PackedScene" uid="uid://dy73qrxcgrwg3" path="res://scenes/managers/enemy_manager.tscn" id="5_tbgi4"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bbev8m5g0p3a3" path="res://scenes/pickups/pickup_magnet.tscn" id="6_tefeu"]
|
[ext_resource type="PackedScene" uid="uid://bbev8m5g0p3a3" path="res://scenes/pickups/pickup_magnet.tscn" id="6_tefeu"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cr8gj1dlloamp" path="res://scenes/pickups/pickup_hp.tscn" id="7_o6xl0"]
|
[ext_resource type="PackedScene" uid="uid://cr8gj1dlloamp" path="res://scenes/pickups/pickup_hp.tscn" id="7_o6xl0"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c2o1lpm4pimpr" path="res://scenes/managers/projectile_manager.tscn" id="8_tipki"]
|
||||||
|
|
||||||
[node name="Main" type="Node2D"]
|
[node name="Main" type="Node2D"]
|
||||||
script = ExtResource("1_jyhfs")
|
script = ExtResource("1_jyhfs")
|
||||||
@@ -32,3 +33,5 @@ position = Vector2(1697, 414)
|
|||||||
|
|
||||||
[node name="PickupHP" parent="." instance=ExtResource("7_o6xl0")]
|
[node name="PickupHP" parent="." instance=ExtResource("7_o6xl0")]
|
||||||
position = Vector2(1678, 939)
|
position = Vector2(1678, 939)
|
||||||
|
|
||||||
|
[node name="ProjectileManager" parent="." instance=ExtResource("8_tipki")]
|
||||||
|
@@ -26,11 +26,13 @@ func _on_timer_timeout() -> void:
|
|||||||
new_enemy.target = target
|
new_enemy.target = target
|
||||||
add_child(new_enemy)
|
add_child(new_enemy)
|
||||||
|
|
||||||
|
|
||||||
func _on_stop_spawning(val: bool):
|
func _on_stop_spawning(val: bool):
|
||||||
if val:
|
if val:
|
||||||
timer.stop()
|
timer.stop()
|
||||||
elif timer.is_stopped():
|
elif timer.is_stopped():
|
||||||
timer.start()
|
timer.start()
|
||||||
|
|
||||||
|
|
||||||
func _on_set_spawn_rate(val: float):
|
func _on_set_spawn_rate(val: float):
|
||||||
timer.wait_time = 1 / val
|
timer.wait_time = 1 / val
|
||||||
|
3
scenes/managers/projectile_manager.tscn
Normal file
3
scenes/managers/projectile_manager.tscn
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[gd_scene format=3 uid="uid://c2o1lpm4pimpr"]
|
||||||
|
|
||||||
|
[node name="ProjectileManager" type="Node2D"]
|
@@ -5,7 +5,6 @@ extends CharacterBody2D
|
|||||||
@export var main_ui: MainUI
|
@export var main_ui: MainUI
|
||||||
|
|
||||||
@onready var sprite_2d: Sprite2D = $Sprite2D
|
@onready var sprite_2d: Sprite2D = $Sprite2D
|
||||||
@onready var attack_sword: Node2D = $AttackSword
|
|
||||||
|
|
||||||
var player_stats: PlayerStats = PlayerStats.new()
|
var player_stats: PlayerStats = PlayerStats.new()
|
||||||
var modifiers: Array[PlayerStatsModifier] = []
|
var modifiers: Array[PlayerStatsModifier] = []
|
||||||
@@ -61,7 +60,6 @@ func die():
|
|||||||
dead = true
|
dead = true
|
||||||
remove_from_group("damagable")
|
remove_from_group("damagable")
|
||||||
get_tree().call_group("enemy", "cheer")
|
get_tree().call_group("enemy", "cheer")
|
||||||
attack_sword.queue_free()
|
|
||||||
GlobalConst.sig_stop_spawning.emit(true)
|
GlobalConst.sig_stop_spawning.emit(true)
|
||||||
sprite_2d.z_index += 10
|
sprite_2d.z_index += 10
|
||||||
get_taunted()
|
get_taunted()
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://5x5wimok8uw2" path="res://assets/sprites/roguelikeChar_transparent.png" id="1_3vyb7"]
|
[ext_resource type="Texture2D" uid="uid://5x5wimok8uw2" path="res://assets/sprites/roguelikeChar_transparent.png" id="1_3vyb7"]
|
||||||
[ext_resource type="Script" uid="uid://cvqaxckx4num3" path="res://scenes/player.gd" id="1_g2els"]
|
[ext_resource type="Script" uid="uid://cvqaxckx4num3" path="res://scenes/player.gd" id="1_g2els"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cdojqe2m4kxx1" path="res://scenes/attacks/attack_sword.tscn" id="3_qhqgy"]
|
[ext_resource type="PackedScene" uid="uid://dfikvj27k01tu" path="res://scenes/weapons/weapon_sword.tscn" id="3_qhqgy"]
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id="CircleShape2D_3vyb7"]
|
[sub_resource type="CircleShape2D" id="CircleShape2D_3vyb7"]
|
||||||
radius = 8.0
|
radius = 8.0
|
||||||
@@ -22,9 +22,6 @@ region_rect = Rect2(0, 104, 16, 14)
|
|||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||||
shape = SubResource("CircleShape2D_3vyb7")
|
shape = SubResource("CircleShape2D_3vyb7")
|
||||||
|
|
||||||
[node name="AttackSword" parent="." node_paths=PackedStringArray("player") instance=ExtResource("3_qhqgy")]
|
|
||||||
player = NodePath("..")
|
|
||||||
|
|
||||||
[node name="PickupArea" type="Area2D" parent="."]
|
[node name="PickupArea" type="Area2D" parent="."]
|
||||||
collision_layer = 0
|
collision_layer = 0
|
||||||
collision_mask = 24
|
collision_mask = 24
|
||||||
@@ -33,4 +30,6 @@ monitorable = false
|
|||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="PickupArea"]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="PickupArea"]
|
||||||
shape = SubResource("CircleShape2D_qhqgy")
|
shape = SubResource("CircleShape2D_qhqgy")
|
||||||
|
|
||||||
|
[node name="WeaponSword" parent="." instance=ExtResource("3_qhqgy")]
|
||||||
|
|
||||||
[connection signal="area_entered" from="PickupArea" to="." method="_on_pickup_area_area_entered"]
|
[connection signal="area_entered" from="PickupArea" to="." method="_on_pickup_area_area_entered"]
|
||||||
|
42
scenes/weapons/weapon_base.gd
Normal file
42
scenes/weapons/weapon_base.gd
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
class_name WeaponBase
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
@export var attack_cd: float
|
||||||
|
@export var attack_damage: float
|
||||||
|
@export var attack_aoe: float
|
||||||
|
@export var attack_duration: float
|
||||||
|
@export var attack_range: float
|
||||||
|
|
||||||
|
|
||||||
|
func _on_attack_cd_timer_timeout() -> void:
|
||||||
|
do_attack()
|
||||||
|
|
||||||
|
|
||||||
|
func do_attack() -> void:
|
||||||
|
push_error("%s does not implement do_attack" % self)
|
||||||
|
|
||||||
|
|
||||||
|
func find_target_in_radius() -> EnemyBase:
|
||||||
|
var space_state: PhysicsDirectSpaceState2D = get_world_2d().direct_space_state
|
||||||
|
var shape := CircleShape2D.new()
|
||||||
|
shape.radius = attack_range
|
||||||
|
|
||||||
|
var query := PhysicsShapeQueryParameters2D.new()
|
||||||
|
query.shape = shape
|
||||||
|
query.transform = Transform2D(0, global_position)
|
||||||
|
query.collision_mask = 2
|
||||||
|
query.collide_with_bodies = true
|
||||||
|
var results := space_state.intersect_shape(query)
|
||||||
|
if len(results) < 1:
|
||||||
|
return null
|
||||||
|
var closest: PhysicsBody2D = results[0]["collider"]
|
||||||
|
for r in results:
|
||||||
|
var c: PhysicsBody2D = r["collider"]
|
||||||
|
if not c.is_in_group(GlobalConst.GROUP_ENEMY):
|
||||||
|
continue
|
||||||
|
if (
|
||||||
|
c.global_position.distance_to(global_position)
|
||||||
|
< closest.global_position.distance_to(global_position)
|
||||||
|
):
|
||||||
|
closest = c
|
||||||
|
return closest
|
1
scenes/weapons/weapon_base.gd.uid
Normal file
1
scenes/weapons/weapon_base.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://d6nwfhyethdw
|
11
scenes/weapons/weapon_base.tscn
Normal file
11
scenes/weapons/weapon_base.tscn
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://i8mtky2req41"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://d6nwfhyethdw" path="res://scenes/weapons/weapon_base.gd" id="1_v4xn6"]
|
||||||
|
|
||||||
|
[node name="WeaponBase" type="Node2D"]
|
||||||
|
script = ExtResource("1_v4xn6")
|
||||||
|
|
||||||
|
[node name="AttackCDTimer" type="Timer" parent="."]
|
||||||
|
autostart = true
|
||||||
|
|
||||||
|
[connection signal="timeout" from="AttackCDTimer" to="." method="_on_attack_cd_timer_timeout"]
|
42
scenes/weapons/weapon_sword.gd
Normal file
42
scenes/weapons/weapon_sword.gd
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
class_name WeaponSword
|
||||||
|
extends WeaponBase
|
||||||
|
|
||||||
|
const WEAPON_SWORD_PROJECTILE = preload("res://scenes/weapons/weapon_sword_projectile.tscn")
|
||||||
|
|
||||||
|
@onready var targeting_range: Area2D = $TargetingRange
|
||||||
|
@onready var targeting_range_shape: CollisionShape2D = $TargetingRange/CollisionShape2D
|
||||||
|
|
||||||
|
signal projectile_hit(projectile: WeaponSwordProjectile, enemy: EnemyBase)
|
||||||
|
|
||||||
|
var _player: Player
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
targeting_range_shape.shape.radius = attack_range
|
||||||
|
projectile_hit.connect(_on_projectile_hit)
|
||||||
|
_player = get_tree().get_first_node_in_group(GlobalConst.GROUP_PLAYER)
|
||||||
|
|
||||||
|
|
||||||
|
func do_attack() -> void:
|
||||||
|
var target: EnemyBase = find_target_in_radius()
|
||||||
|
if not target:
|
||||||
|
return
|
||||||
|
|
||||||
|
var projectile = WEAPON_SWORD_PROJECTILE.instantiate()
|
||||||
|
projectile.damage = attack_damage
|
||||||
|
projectile.target = target
|
||||||
|
projectile.on_hit_sig = projectile_hit
|
||||||
|
add_child(projectile)
|
||||||
|
|
||||||
|
|
||||||
|
func deal_damage(enemy: EnemyBase):
|
||||||
|
var crit_chance = _player.player_stats.get_final("crit_chance", _player.modifiers)
|
||||||
|
var damage_dealt = attack_damage
|
||||||
|
var is_crit = randf() >= 1 - crit_chance
|
||||||
|
if is_crit:
|
||||||
|
damage_dealt *= _player.player_stats.get_final("crit_multiplier", _player.modifiers)
|
||||||
|
enemy.take_damage(damage_dealt, is_crit)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_projectile_hit(projectile: WeaponSwordProjectile, enemy: EnemyBase):
|
||||||
|
deal_damage(enemy)
|
1
scenes/weapons/weapon_sword.gd.uid
Normal file
1
scenes/weapons/weapon_sword.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b072d866r4usq
|
22
scenes/weapons/weapon_sword.tscn
Normal file
22
scenes/weapons/weapon_sword.tscn
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dfikvj27k01tu"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://i8mtky2req41" path="res://scenes/weapons/weapon_base.tscn" id="1_2dti5"]
|
||||||
|
[ext_resource type="Script" uid="uid://b072d866r4usq" path="res://scenes/weapons/weapon_sword.gd" id="2_ruf80"]
|
||||||
|
|
||||||
|
[sub_resource type="CircleShape2D" id="CircleShape2D_ruf80"]
|
||||||
|
|
||||||
|
[node name="WeaponSword" instance=ExtResource("1_2dti5")]
|
||||||
|
script = ExtResource("2_ruf80")
|
||||||
|
attack_cd = 1.0
|
||||||
|
attack_damage = 5.0
|
||||||
|
attack_aoe = 1.0
|
||||||
|
attack_duration = 1.0
|
||||||
|
attack_range = 150.0
|
||||||
|
|
||||||
|
[node name="TargetingRange" type="Area2D" parent="." index="1"]
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 2
|
||||||
|
monitorable = false
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetingRange" index="0"]
|
||||||
|
shape = SubResource("CircleShape2D_ruf80")
|
40
scenes/weapons/weapon_sword_projectile.gd
Normal file
40
scenes/weapons/weapon_sword_projectile.gd
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
class_name WeaponSwordProjectile
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
@export var speed: float = 500.0
|
||||||
|
@export var range: float = 200.0
|
||||||
|
@export var target: Node2D
|
||||||
|
@export var damage: float
|
||||||
|
@export var on_hit_sig: Signal
|
||||||
|
|
||||||
|
var _direction: Vector2
|
||||||
|
var _traveled: float = 0.0
|
||||||
|
var _already_hit: Array[PhysicsBody2D] = []
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_direction = global_position.direction_to(target.global_position).normalized()
|
||||||
|
_traveled = 0.0
|
||||||
|
rotation = _direction.angle()
|
||||||
|
if _direction.x < 0:
|
||||||
|
rotation += PI
|
||||||
|
var proj_manager = get_tree().get_first_node_in_group(GlobalConst.GROUP_PROJ_MANAGER)
|
||||||
|
if not proj_manager:
|
||||||
|
return
|
||||||
|
reparent(proj_manager, true)
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
|
var step = _direction * speed * delta
|
||||||
|
global_position += step
|
||||||
|
_traveled += step.length()
|
||||||
|
|
||||||
|
if _traveled >= range:
|
||||||
|
queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_area_2d_body_entered(body: Node2D) -> void:
|
||||||
|
if body in _already_hit:
|
||||||
|
return
|
||||||
|
on_hit_sig.emit(self, body)
|
||||||
|
_already_hit.append(body)
|
1
scenes/weapons/weapon_sword_projectile.gd.uid
Normal file
1
scenes/weapons/weapon_sword_projectile.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c40iaqdubwl0p
|
24
scenes/weapons/weapon_sword_projectile.tscn
Normal file
24
scenes/weapons/weapon_sword_projectile.tscn
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[gd_scene load_steps=4 format=3 uid="uid://bv5f47x3ishmf"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://c40iaqdubwl0p" path="res://scenes/weapons/weapon_sword_projectile.gd" id="1_asuu4"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dycw7c3484dir" path="res://assets/sprites/sword.png" id="2_pxap4"]
|
||||||
|
|
||||||
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ygc1t"]
|
||||||
|
size = Vector2(16, 46)
|
||||||
|
|
||||||
|
[node name="WeaponSwordProjectile" type="Node2D"]
|
||||||
|
script = ExtResource("1_asuu4")
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
texture = ExtResource("2_pxap4")
|
||||||
|
|
||||||
|
[node name="Area2D" type="Area2D" parent="."]
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 2
|
||||||
|
monitorable = false
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||||
|
position = Vector2(0, -5)
|
||||||
|
shape = SubResource("RectangleShape2D_ygc1t")
|
||||||
|
|
||||||
|
[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]
|
Reference in New Issue
Block a user