From 9a82e74e419309d574fe1202bd06cd55f1e248c5 Mon Sep 17 00:00:00 2001 From: 3002102 <3002102@stud.hs-mannheim.de> Date: Wed, 15 Apr 2026 19:09:21 +0200 Subject: [PATCH] add a knive perk where the witch initally throws a knive every 2 seconds with subsequent upgrades until the cooldown is 1s between throws (#10) Reviewed-on: https://gitty.informatik.hs-mannheim.de/3002102/gae_wild_jam/pulls/10 Co-authored-by: 3002102 <3002102@stud.hs-mannheim.de> Co-committed-by: 3002102 <3002102@stud.hs-mannheim.de> --- assets/weapons/knive.ase | Bin 0 -> 647 bytes assets/weapons/knvie.png | Bin 0 -> 263 bytes assets/weapons/knvie.png.import | 40 +++++++++++++++++++++++++++ scenes/throwing_knive.tscn | 33 +++++++++++++++++++++++ scripts/perk_effects.gd | 46 ++++++++++++++++++++++++++------ scripts/throwing_knive.gd | 24 +++++++++++++++++ scripts/throwing_knive.gd.uid | 1 + scripts/witch.gd | 4 ++- 8 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 assets/weapons/knive.ase create mode 100644 assets/weapons/knvie.png create mode 100644 assets/weapons/knvie.png.import create mode 100644 scenes/throwing_knive.tscn create mode 100644 scripts/throwing_knive.gd create mode 100644 scripts/throwing_knive.gd.uid diff --git a/assets/weapons/knive.ase b/assets/weapons/knive.ase new file mode 100644 index 0000000000000000000000000000000000000000..7d602fa4223a8e5b85e19cbf5420c5ac9228558e GIT binary patch literal 647 zcmcJLO-NKx7(hRDVh9Z+Tv!P6a3Wj?KA%G(J{%^pg$9WWV-R$PDZxh=mZ%XpsDUtn zV>%#ei#F|ap(T<*6eA*t8!h}ptf++$f+j-qtm_%Yg!X=qcerxaQVqJj1E@7$OBzj?BWn!IJq24umSnB6HYbB^b$)c znKTke9cgqCMG-m47Nw{l0Y7rgXmKLMhRT&RX=(6eND!yo3O>H~P%DgaIj4!7mvm7) z|M6sUZ+{UAd~gi;{mPg9EXya0ZHawXU){uB_g<%rC+zsBdS|U1+0y?Tkofoi|Nr?~dB$v6pwAdQUHx3vIVCg! E0NB)YCjbBd literal 0 HcmV?d00001 diff --git a/assets/weapons/knvie.png.import b/assets/weapons/knvie.png.import new file mode 100644 index 0000000..0b8ebf7 --- /dev/null +++ b/assets/weapons/knvie.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://pot4k8a6lxd0" +path="res://.godot/imported/knvie.png-6e2c57d6850f97653fad709f2c5186b5.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/weapons/knvie.png" +dest_files=["res://.godot/imported/knvie.png-6e2c57d6850f97653fad709f2c5186b5.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/scenes/throwing_knive.tscn b/scenes/throwing_knive.tscn new file mode 100644 index 0000000..86f1197 --- /dev/null +++ b/scenes/throwing_knive.tscn @@ -0,0 +1,33 @@ +[gd_scene format=3 uid="uid://oegpflgwf17e"] + +[ext_resource type="Script" uid="uid://dpj26ryawjq02" path="res://scripts/throwing_knive.gd" id="2_knive"] +[ext_resource type="Texture2D" uid="uid://pot4k8a6lxd0" path="res://assets/weapons/knvie.png" id="2_tyd64"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_frs86"] +atlas = ExtResource("2_tyd64") +region = Rect2(0, 0, 32, 32) + +[sub_resource type="SpriteFrames" id="SpriteFrames_t4gbw"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_frs86") +}], +"loop": true, +"name": &"default", +"speed": 5.0 +}] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_1ss1s"] +size = Vector2(15, 7) + +[node name="ThrowingKnive" type="Area2D" unique_id=882877238] +script = ExtResource("2_knive") + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="." unique_id=164559800] +texture_filter = 1 +sprite_frames = SubResource("SpriteFrames_t4gbw") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=886320879] +position = Vector2(0.5, -0.5) +shape = SubResource("RectangleShape2D_1ss1s") diff --git a/scripts/perk_effects.gd b/scripts/perk_effects.gd index ce9005d..9c37670 100644 --- a/scripts/perk_effects.gd +++ b/scripts/perk_effects.gd @@ -3,10 +3,13 @@ extends Node2D @onready var witch = get_node("/root/Game/Witch") @onready var player = get_node("/root/Game/Player") var fireball = preload("res://scenes/fireball.tscn") +var throwing_knife = preload("res://scenes/throwing_knive.tscn") var cauldron var available_perks: Array[Perk] = [] var fireball_aoe_enabled = false -# Called when the node enters the scene tree for the first time. +var throwing_knife_enabled = false +var throwing_knife_cooldown: float = 2.0 +var _knife_timer: float = 0.0 func _ready() -> void: cauldron = witch.get_node("CauldronBar") @@ -25,20 +28,47 @@ func _ready() -> void: bexp.description = "The Witch casts an explosion on finishing a brew" bexp.effect = brew_explosion available_perks.append(bexp) - - pass # Replace with function body. + var tk = Perk.new() + tk.name = "Throwing Knife" + tk.description = "Automatically throw a knife at the nearest enemy every second" + tk.effect = enable_throwing_knife + available_perks.append(tk) - -# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: - pass + if throwing_knife_enabled: + _knife_timer += delta + if _knife_timer >= throwing_knife_cooldown: + _knife_timer = 0.0 + _shoot_throwing_knife() func double_shuriken(): witch.shuriken_count = 2 - + func fireball_aoe(): fireball_aoe_enabled = true - + func brew_explosion(): cauldron.brew_explosion = true + +func enable_throwing_knife(): + throwing_knife_enabled = true + var upg = Perk.new() + upg.name = "Knife Cooldown" + upg.description = "Reduce throwing knife cooldown by 0.2s (min 1s)" + upg.effect = knife_cooldown_upgrade + available_perks.append(upg) + +func knife_cooldown_upgrade(): + throwing_knife_cooldown = maxf(1.0, throwing_knife_cooldown - 0.2) + if throwing_knife_cooldown > 1.0: + var upg = Perk.new() + upg.name = "Knife Cooldown" + upg.description = "Reduce throwing knife cooldown by 0.2s (min 1s)" + upg.effect = knife_cooldown_upgrade + available_perks.append(upg) + +func _shoot_throwing_knife() -> void: + var knife = throwing_knife.instantiate() + knife.global_position = witch.global_position + witch.get_parent().add_child(knife) diff --git a/scripts/throwing_knive.gd b/scripts/throwing_knive.gd new file mode 100644 index 0000000..f7029be --- /dev/null +++ b/scripts/throwing_knive.gd @@ -0,0 +1,24 @@ +extends ProjectileBase + +var _target_enemy: Node = null + +func _ready() -> void: + super() + speed = 400.0 + var witch = get_node("/root/Game/Witch") + _target_enemy = witch.get_nearest_enemy(witch.global_position, _knife_filter) + if _target_enemy == null: + queue_free() + return + _target_enemy.add_to_group("knife_targeted") + tree_exiting.connect(_on_knife_exiting) + var dir = global_position.direction_to(_target_enemy.global_position) + rotation = dir.angle() + launch(_target_enemy.global_position) + +func _knife_filter(enemy: Node) -> bool: + return not enemy.is_dying and not enemy.is_hurt and not enemy.is_in_group("knife_targeted") + +func _on_knife_exiting() -> void: + if is_instance_valid(_target_enemy) and _target_enemy.is_in_group("knife_targeted"): + _target_enemy.remove_from_group("knife_targeted") diff --git a/scripts/throwing_knive.gd.uid b/scripts/throwing_knive.gd.uid new file mode 100644 index 0000000..702c511 --- /dev/null +++ b/scripts/throwing_knive.gd.uid @@ -0,0 +1 @@ +uid://dpj26ryawjq02 diff --git a/scripts/witch.gd b/scripts/witch.gd index 8366fb4..f792f42 100644 --- a/scripts/witch.gd +++ b/scripts/witch.gd @@ -43,10 +43,12 @@ func shoot_shuriken(): get_parent().add_child(sh) await get_tree().create_timer(0.2).timeout -func get_nearest_enemy(from: Vector2) -> Node: +func get_nearest_enemy(from: Vector2, filter: Callable = Callable()) -> Node: var nearest = null var min_distance = INF for enemy in get_tree().get_nodes_in_group("enemies"): + if filter.is_valid() and not filter.call(enemy): + continue var dist = from.distance_to(enemy.global_position) if dist < min_distance: min_distance = dist