diff --git a/assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3 b/assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3 new file mode 100644 index 0000000..971ebb4 Binary files /dev/null and b/assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3 differ diff --git a/assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3.import b/assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3.import new file mode 100644 index 0000000..6d1ac96 --- /dev/null +++ b/assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://b27862pnesv4a" +path="res://.godot/imported/47313572-experimental-8-bit-sound-270302.mp3-c4341312242ec2d6d5bacb1c4c433fda.mp3str" + +[deps] + +source_file="res://assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3" +dest_files=["res://.godot/imported/47313572-experimental-8-bit-sound-270302.mp3-c4341312242ec2d6d5bacb1c4c433fda.mp3str"] + +[params] + +loop=false +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/music&sfx/sfx/card_shuffle.wav b/assets/music&sfx/sfx/card_shuffle.wav new file mode 100644 index 0000000..64c19c1 Binary files /dev/null and b/assets/music&sfx/sfx/card_shuffle.wav differ diff --git a/assets/music&sfx/sfx/card_shuffle.wav.import b/assets/music&sfx/sfx/card_shuffle.wav.import new file mode 100644 index 0000000..34ad2b6 --- /dev/null +++ b/assets/music&sfx/sfx/card_shuffle.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://3ubacx6k21aq" +path="res://.godot/imported/card_shuffle.wav-2df5de9a976f5727aeeddc7f5f41163e.sample" + +[deps] + +source_file="res://assets/music&sfx/sfx/card_shuffle.wav" +dest_files=["res://.godot/imported/card_shuffle.wav-2df5de9a976f5727aeeddc7f5f41163e.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3 b/assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3 new file mode 100644 index 0000000..5e3477f Binary files /dev/null and b/assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3 differ diff --git a/assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3.import b/assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3.import new file mode 100644 index 0000000..410c8da --- /dev/null +++ b/assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://o81j4w2j1p16" +path="res://.godot/imported/data_pion-sfx9-fwoosh-324525.mp3-aae109eab17a5ca7e7981c978d3c52e3.mp3str" + +[deps] + +source_file="res://assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3" +dest_files=["res://.godot/imported/data_pion-sfx9-fwoosh-324525.mp3-aae109eab17a5ca7e7981c978d3c52e3.mp3str"] + +[params] + +loop=false +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/assets/music&sfx/sfx/fire.wav b/assets/music&sfx/sfx/fire.wav new file mode 100644 index 0000000..e70de04 Binary files /dev/null and b/assets/music&sfx/sfx/fire.wav differ diff --git a/assets/music&sfx/sfx/fire.wav.import b/assets/music&sfx/sfx/fire.wav.import new file mode 100644 index 0000000..fad481d --- /dev/null +++ b/assets/music&sfx/sfx/fire.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://buxdyhc4ih63f" +path="res://.godot/imported/fire.wav-a8c495294a82be1272b8f8a56ccb40f5.sample" + +[deps] + +source_file="res://assets/music&sfx/sfx/fire.wav" +dest_files=["res://.godot/imported/fire.wav-a8c495294a82be1272b8f8a56ccb40f5.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3 b/assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3 new file mode 100644 index 0000000..d3233b2 Binary files /dev/null and b/assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3 differ diff --git a/assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3.import b/assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3.import new file mode 100644 index 0000000..e30a1e1 --- /dev/null +++ b/assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://bh8o5pk2cco1a" +path="res://.godot/imported/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3-0a5ea69aced7938e6b9174c8f11f81d9.mp3str" + +[deps] + +source_file="res://assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3" +dest_files=["res://.godot/imported/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3-0a5ea69aced7938e6b9174c8f11f81d9.mp3str"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3 b/assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3 new file mode 100644 index 0000000..70295e1 Binary files /dev/null and b/assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3 differ diff --git a/assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3.import b/assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3.import new file mode 100644 index 0000000..3d0dc1e --- /dev/null +++ b/assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://bjyttcuhiidrq" +path="res://.godot/imported/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3-a2556229ce18ac544b49cfbc2bd40be8.mp3str" + +[deps] + +source_file="res://assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3" +dest_files=["res://.godot/imported/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3-a2556229ce18ac544b49cfbc2bd40be8.mp3str"] + +[params] + +loop=false +loop_offset=0.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/project.godot b/project.godot index 39e1713..d1985a5 100644 --- a/project.godot +++ b/project.godot @@ -22,6 +22,7 @@ buses/default_bus_layout="uid://5oswo22yvmtg" [autoload] MusicManager="*uid://dmu7041wi1upt" +SpellLibrary="*res://scripts/SpellLibrary.gd" [display] diff --git a/scenes/PerkCard.tscn b/scenes/PerkCard.tscn index 502a9a5..71406bd 100644 --- a/scenes/PerkCard.tscn +++ b/scenes/PerkCard.tscn @@ -13,25 +13,30 @@ region = Rect2(561, 17, 46, 62) [sub_resource type="LabelSettings" id="LabelSettings_qag4p"] line_spacing = 5.0 font = ExtResource("3_n4umd") -font_size = 12 +font_size = 16 +outline_size = 2 +outline_color = Color(0, 0, 0, 1) [sub_resource type="AtlasTexture" id="AtlasTexture_n4umd"] atlas = ExtResource("4_nlhlf") region = Rect2(258, 241, 25, 14) [sub_resource type="LabelSettings" id="LabelSettings_ni87r"] -font = ExtResource("4_40ty6") -font_size = 11 +line_spacing = 6.0 +font = ExtResource("3_n4umd") +font_size = 17 +outline_size = 2 +outline_color = Color(0, 0, 0, 1) [node name="PerkCard" type="Control" unique_id=1471811151] -custom_minimum_size = Vector2(200, 300) +custom_minimum_size = Vector2(240, 360) layout_mode = 3 anchors_preset = 0 script = ExtResource("1_t8gqh") [node name="Card" type="TextureRect" parent="." unique_id=1832247473] texture_filter = 1 -custom_minimum_size = Vector2(200, 300) +custom_minimum_size = Vector2(240, 360) layout_mode = 0 offset_right = 40.0 offset_bottom = 40.0 @@ -42,10 +47,10 @@ layout_mode = 1 anchors_preset = 5 anchor_left = 0.5 anchor_right = 0.5 -offset_left = -50.5 +offset_left = -65.0 offset_top = 43.0 -offset_right = 50.5 -offset_bottom = 92.0 +offset_right = 65.0 +offset_bottom = 100.0 grow_horizontal = 2 text = "Zweizeilige Überschrift @@ -54,6 +59,7 @@ label_settings = SubResource("LabelSettings_qag4p") horizontal_alignment = 1 [node name="TextureRect" type="TextureRect" parent="Card/Name" unique_id=2128840891] +texture_filter = 1 layout_mode = 1 anchors_preset = 7 anchor_left = 0.5 @@ -67,35 +73,33 @@ offset_bottom = 19.0 grow_horizontal = 2 grow_vertical = 0 texture = SubResource("AtlasTexture_n4umd") +stretch_mode = 5 -[node name="Description" type="Label" parent="Card" unique_id=859816848] +[node name="Description" type="RichTextLabel" parent="Card" unique_id=859816848] layout_mode = 1 anchors_preset = 7 anchor_left = 0.5 anchor_top = 1.0 anchor_right = 0.5 anchor_bottom = 1.0 -offset_left = -65.0 -offset_top = -176.0 -offset_right = 69.0 -offset_bottom = -43.0 +offset_left = -100.0 +offset_top = -215.0 +offset_right = 100.0 +offset_bottom = -36.0 grow_horizontal = 2 grow_vertical = 0 -text = "Text in Zeile Eins -Text in Zeile Eins -Text in Zeile Eins -Text in Zeile Eins -Text in Zeile Zwei -Text in Zeile Drei -Text in Zeile Vier -Text in Zeile Fünf" -label_settings = SubResource("LabelSettings_ni87r") -horizontal_alignment = 1 -autowrap_mode = 2 +theme_override_fonts/normal_font = ExtResource("3_n4umd") +theme_override_font_sizes/normal_font_size = 17 +theme_override_constants/outline_size = 2 +theme_override_colors/default_color = Color(1, 1, 1, 1) +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +bbcode_enabled = true +scroll_active = false +text = "" [node name="Button" type="Button" parent="." unique_id=1274377333] layout_mode = 0 -offset_right = 200.0 -offset_bottom = 300.0 +offset_right = 240.0 +offset_bottom = 360.0 [connection signal="pressed" from="Button" to="." method="_on_button_pressed"] diff --git a/scenes/fireball.tscn b/scenes/fireball.tscn index 17dd868..c3877e8 100644 --- a/scenes/fireball.tscn +++ b/scenes/fireball.tscn @@ -39,7 +39,7 @@ animations = [{ }], "loop": true, "name": &"default", -"speed": 10.0 +"speed": 35.0 }] [node name="Fireball" type="Area2D" unique_id=2100779306] diff --git a/scenes/game.tscn b/scenes/game.tscn index 8405eb7..4ea837c 100644 --- a/scenes/game.tscn +++ b/scenes/game.tscn @@ -15,9 +15,9 @@ [ext_resource type="Script" uid="uid://pmmc7tivuuo4" path="res://scripts/perk_effects.gd" id="16_ca42v"] [ext_resource type="Script" uid="uid://dm1sntwjrv3vl" path="res://scripts/level_up_manager.gd" id="16_rysoc"] [ext_resource type="Texture2D" uid="uid://dp8o40ssuh8ip" path="res://assets/Tiny RPG Mana Soul GUI v1.0/20250421barB-Sheet.png" id="16_ssvqc"] -[ext_resource type="Script" path="res://scripts/pause_menu.gd" id="18_264po"] +[ext_resource type="Script" uid="uid://duauc778wc3hd" path="res://scripts/pause_menu.gd" id="18_264po"] [ext_resource type="FontFile" uid="uid://8v71dcws4q6o" path="res://assets/fonts/slkscre.ttf" id="19_1kice"] -[ext_resource type="Script" path="res://scripts/options_menu_ingame.gd" id="20_1kice"] +[ext_resource type="Script" uid="uid://586y330mhx8" path="res://scripts/options_menu_ingame.gd" id="20_1kice"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_vtaks"] texture = ExtResource("7_gee14") diff --git a/scripts/DropsBase.gd b/scripts/DropsBase.gd index 8bccbbf..0e8fc68 100644 --- a/scripts/DropsBase.gd +++ b/scripts/DropsBase.gd @@ -5,14 +5,20 @@ var witch var player var is_spawning = true signal collected -# Called when the node enters the scene tree for the first time. + +var _collect_sfx = preload("res://assets/music&sfx/sfx/lesiakower-coin-collect-retro-8-bit-sound-effect-145251.mp3") +var _sfx_player: AudioStreamPlayer + func _ready() -> void: body_entered.connect(_on_body_entered) witch = get_node("/root/Game/Witch") collected.connect(witch._on_collect) player = get_node("/root/Game/Player") + _sfx_player = AudioStreamPlayer.new() + _sfx_player.stream = _collect_sfx + _sfx_player.volume_db = -18 + add_child(_sfx_player) _animate_spawn() - pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. @@ -43,6 +49,8 @@ func _on_body_entered(body: Node2D) -> void: pass func collect(): + _sfx_player.pitch_scale = randf_range(0.85, 1.15) + _sfx_player.play() is_spawning = true var position_drop = create_tween() var target = witch.global_position diff --git a/scripts/Perk.gd b/scripts/Perk.gd index d656bb3..849db65 100644 --- a/scripts/Perk.gd +++ b/scripts/Perk.gd @@ -3,5 +3,7 @@ class_name Perk @export var name: String @export var description: String +@export var stats: String = "" +@export var spell: String = SpellLibrary.NONE @export var icon: Texture2D = null var effect: Callable diff --git a/scripts/SpellLibrary.gd b/scripts/SpellLibrary.gd new file mode 100644 index 0000000..88d06b0 --- /dev/null +++ b/scripts/SpellLibrary.gd @@ -0,0 +1,32 @@ +extends Node + +const APPLE = 0 +const GRAPE = 1 + +const NONE = "NONE" +const SHURIKEN = "SHURIKEN" +const FIREBALL = "FIREBALL" +const FIRE_SWIRL = "FIRE_SWIRL" +const TORNADO = "TORNADO" + +# Each spell's display recipe: sorted apples-first, grapes-last +var recipes: Dictionary = { + SHURIKEN: [APPLE, GRAPE, GRAPE], + FIREBALL: [APPLE, APPLE, APPLE], + FIRE_SWIRL: [APPLE, APPLE, GRAPE], + TORNADO: [GRAPE, GRAPE, GRAPE], +} + +# Takes cauldron slot_states (uses texture indices: 2 = apple, 4 = grape) +# and returns which spell that combination brews. +func identify(cauldron_slots: Array) -> String: + var apples = cauldron_slots.count(2) + var grapes = cauldron_slots.count(4) + for spell_id in recipes: + var r: Array = recipes[spell_id] + if r.count(APPLE) == apples and r.count(GRAPE) == grapes: + return spell_id + return NONE + +func get_recipe(spell: String) -> Array: + return recipes.get(spell, []) diff --git a/scripts/SpellLibrary.gd.uid b/scripts/SpellLibrary.gd.uid new file mode 100644 index 0000000..ebdaabf --- /dev/null +++ b/scripts/SpellLibrary.gd.uid @@ -0,0 +1 @@ +uid://dpn7aoem55ptp diff --git a/scripts/cauldron_bar.gd b/scripts/cauldron_bar.gd index 726235a..0bfca95 100644 --- a/scripts/cauldron_bar.gd +++ b/scripts/cauldron_bar.gd @@ -12,8 +12,10 @@ var slot_states = [0, 0, 0] var progres_index = 0 var is_brewing var brew_explosion = true -@onready var witch = get_parent() -var explosion_scene = preload("res://scenes/explosion.tscn")# Called when the node enters the scene tree for the first time. +@onready var witch = get_parent() +var explosion_scene = preload("res://scenes/explosion.tscn") +var _ignite_sfx = preload("res://assets/music&sfx/sfx/data_pion-sfx9-fwoosh-324525.mp3") +var _ignite_player: AudioStreamPlayer# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -31,7 +33,10 @@ func _ready() -> void: slots = [$Empty1, $Empty2, $Empty3] colors = [base, yellow, red, orange, purple] enrich_burning_colors() - pass # Replace with function body. + _ignite_player = AudioStreamPlayer.new() + _ignite_player.stream = _ignite_sfx + _ignite_player.volume_db = -15 + add_child(_ignite_player) # Called every frame. 'delta' is the elapsed time since the previous frame. @@ -51,6 +56,8 @@ func reset_texture(): func ignite_cauldrons(): for i in slots.size(): slots[i].texture = burning_colors[slot_states[i]] + _ignite_player.pitch_scale = randf_range(0.8, 1.2) + _ignite_player.play() await get_tree().create_timer(0.4).timeout if brew_explosion: var boom = explosion_scene.instantiate() @@ -83,16 +90,11 @@ func progres_bar(fruit): func brew(fruits): is_brewing = true await ignite_cauldrons() - var apple_count = fruits.count(2) - var grape_count = fruits.count(4) - if apple_count == 2 and grape_count == 1: - witch.shoot_fire_swirl() - elif apple_count == 3: - witch.shoot_fireballs() - elif grape_count == 3: - witch.shoot_tornado() - elif apple_count == 1 and grape_count == 2: - witch.shoot_shuriken() + match SpellLibrary.identify(fruits): + SpellLibrary.SHURIKEN: witch.shoot_shuriken() + SpellLibrary.FIREBALL: witch.shoot_fireballs() + SpellLibrary.FIRE_SWIRL: witch.shoot_fire_swirl() + SpellLibrary.TORNADO: witch.shoot_tornado() reset_texture() is_brewing = false diff --git a/scripts/level_up_manager.gd b/scripts/level_up_manager.gd index a04db52..1bda3f2 100644 --- a/scripts/level_up_manager.gd +++ b/scripts/level_up_manager.gd @@ -2,21 +2,34 @@ extends Control @onready var perk_effects = get_node("/root/Game/PerkEffects") - +var level_sound = preload("res://assets/music&sfx/sfx/lesiakower-level-up-enhancement-8-bit-retro-sound-effect-153002.mp3") +var select_sound = preload("res://assets/music&sfx/sfx/47313572-experimental-8-bit-sound-270302.mp3") +var card_shuffle_sound = preload("res://assets/music&sfx/sfx/card_shuffle.wav") var perks +var player = AudioStreamPlayer.new() +var select_player = AudioStreamPlayer.new() +var shuffle_player = AudioStreamPlayer.new() @onready var perkCard = preload("res://scenes/PerkCard.tscn") -# Called when the node enters the scene tree for the first time. + func _ready() -> void: perks = perk_effects.available_perks get_node("/root/Game/DropManager").leveled_up.connect(show_perks) - pass # Replace with function body. + add_child(player) + add_child(select_player) + add_child(shuffle_player) + player.volume_db = -10 + select_player.volume_db = -10 + shuffle_player.volume_db = -10 + select_player.stream = select_sound + shuffle_player.stream = card_shuffle_sound -# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass func show_perks(): + player.stream = level_sound + player.play() if perks.is_empty(): return var tween = create_tween() @@ -25,11 +38,14 @@ func show_perks(): var shuffled = perks.duplicate() shuffled.shuffle() var chosen = shuffled.slice(0, 3) + await get_tree().create_timer(0.4).timeout for x in chosen: var card = perkCard.instantiate() $HBoxContainer.add_child(card) - card.setup(x, func(): select_perk(x)) - + card.setup(x, func(): select_perk(x), func(): select_player.play()) + shuffle_player.play() + await get_tree().create_timer(0.25).timeout + func select_perk(perk): perk.effect.call() diff --git a/scripts/perk_card.gd b/scripts/perk_card.gd index cb622da..62def9d 100644 --- a/scripts/perk_card.gd +++ b/scripts/perk_card.gd @@ -1,42 +1,155 @@ extends Control @export var icon: Texture2D -# Called when the node enters the scene tree for the first time. var on_select: Callable +var play_sound: Callable + +var _recipe_panel: Control = null +var _panel_tween: Tween = null +const _PANEL_REST_Y = 18 + +const _FRUIT_ATLAS = preload("res://assets/16x16 Pixelart Food Icons/Pixel_Foods(ARTLİNE).png") +const _FONT_BOLD = preload("res://assets/fonts/slkscrb.ttf") - -func setup(perk: Perk, select: Callable): +func setup(perk: Perk, select: Callable, sound: Callable): + $Button.button_down.connect(_on_button_down) $Button.modulate.a = 0 $Card/Name.text = perk.name - $Card/Description.text = perk.description + var content = perk.description + if perk.stats != "": + content += "\n\n" + perk.stats + $Card/Description.text = "[center]" + content + "[/center]" if perk.icon != null: $Card/Name/TextureRect.texture = perk.icon + _build_recipe_panel(perk) animate_in() - $Button.modulate.a = 0.3 - $Button.mouse_entered.connect(func(): $Button.modulate.a = 0.6) - $Button.mouse_exited.connect(func(): $Button.modulate.a = 0.3) + $Button.mouse_entered.connect(_on_hover_enter) + $Button.mouse_exited.connect(_on_hover_exit) on_select = select + play_sound = sound - -func _on_button_pressed() -> void: +func _build_recipe_panel(perk: Perk) -> void: + var is_brewed = perk.spell != SpellLibrary.NONE + var panel_w := 240 + var panel_h := 74 if is_brewed else 38 + + _recipe_panel = Control.new() + _recipe_panel.position = Vector2(0, _PANEL_REST_Y) + _recipe_panel.size = Vector2(panel_w, panel_h) + _recipe_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE + + var border := ColorRect.new() + border.mouse_filter = Control.MOUSE_FILTER_IGNORE + border.color = Color(0.55, 0.4, 0.1, 1.0) + border.size = Vector2(panel_w, panel_h) + _recipe_panel.add_child(border) + + var bg := ColorRect.new() + bg.mouse_filter = Control.MOUSE_FILTER_IGNORE + bg.color = Color(0.08, 0.04, 0.14, 0.96) + bg.position = Vector2(2, 2) + bg.size = Vector2(panel_w - 4, panel_h - 4) + _recipe_panel.add_child(bg) + + var header := Label.new() + header.mouse_filter = Control.MOUSE_FILTER_IGNORE + header.add_theme_font_override("font", _FONT_BOLD) + header.add_theme_font_size_override("font_size", 13) + header.add_theme_color_override("font_color", Color(0.85, 0.72, 0.45, 1.0)) + header.add_theme_constant_override("outline_size", 2) + header.add_theme_color_override("font_outline_color", Color(0, 0, 0, 1)) + header.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + header.size = Vector2(panel_w, 22) + + if is_brewed: + header.text = "BREW RECIPE" + header.position = Vector2(0, 6) + _recipe_panel.add_child(header) + + var hbox := HBoxContainer.new() + hbox.mouse_filter = Control.MOUSE_FILTER_IGNORE + hbox.add_theme_constant_override("separation", 4) + hbox.alignment = BoxContainer.ALIGNMENT_CENTER + hbox.size = Vector2(panel_w, 36) + hbox.position = Vector2(0, 32) + + var recipe := SpellLibrary.get_recipe(perk.spell) + for i in recipe.size(): + if i > 0: + var plus := Label.new() + plus.mouse_filter = Control.MOUSE_FILTER_IGNORE + plus.text = "+" + plus.add_theme_font_override("font", _FONT_BOLD) + plus.add_theme_font_size_override("font_size", 14) + plus.add_theme_color_override("font_color", Color(1, 1, 1, 0.6)) + plus.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + hbox.add_child(plus) + + var fruit := TextureRect.new() + fruit.mouse_filter = Control.MOUSE_FILTER_IGNORE + var atlas := AtlasTexture.new() + atlas.atlas = _FRUIT_ATLAS + atlas.region = Rect2(1, 2, 16, 15) if recipe[i] == SpellLibrary.APPLE else Rect2(55, 19, 15, 16) + fruit.texture = atlas + fruit.custom_minimum_size = Vector2(32, 32) + fruit.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + fruit.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST + hbox.add_child(fruit) + + _recipe_panel.add_child(hbox) + else: + header.text = "AUTO / PASSIVE" + header.position = Vector2(0, panel_h / 2 - 11) + _recipe_panel.add_child(header) + + add_child(_recipe_panel) + move_child(_recipe_panel, 0) + + +func _on_hover_enter(): + if _panel_tween: + _panel_tween.kill() + _panel_tween = create_tween().set_parallel() + _panel_tween.tween_property(self, "scale", Vector2(0.93, 0.93), 0.1).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUAD) + _panel_tween.tween_property(_recipe_panel, "position:y", -float(_recipe_panel.size.y), 0.22).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CUBIC) + + +func _on_hover_exit(): + if _panel_tween: + _panel_tween.kill() + _panel_tween = create_tween().set_parallel() + _panel_tween.tween_property(self, "scale", Vector2(1.0, 1.0), 0.1).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUAD) + _panel_tween.tween_property(_recipe_panel, "position:y", float(_PANEL_REST_Y), 0.15).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_QUAD) + + +func _on_button_down() -> void: + if _recipe_panel: + _recipe_panel.visible = false + play_sound.call() await animate_out() on_select.call() - pass # Replace with function body. + func animate_in(): await get_tree().process_frame + pivot_offset = size / 2 + var icon_node = $Card/Name/TextureRect + icon_node.pivot_offset = icon_node.size / 2 + var pulse = create_tween().set_loops() + pulse.tween_property(icon_node, "scale", Vector2(1.12, 1.12), 0.9).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE) + pulse.tween_property(icon_node, "scale", Vector2(1.0, 1.0), 0.9).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE) var start_y = global_position.y + 500 var end_y = global_position.y global_position.y = start_y var tween = create_tween() tween.tween_property(self, "global_position:y", end_y, 0.3).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUAD) - + + func animate_out(): - var start_y = global_position.y + var start_y = global_position.y var end_y = global_position.y - 500 global_position.y = start_y var tween = create_tween() tween.tween_property(self, "global_position:y", end_y, 0.3).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_QUAD) await tween.finished - diff --git a/scripts/perk_effects.gd b/scripts/perk_effects.gd index ab9504e..7dcc530 100644 --- a/scripts/perk_effects.gd +++ b/scripts/perk_effects.gd @@ -20,31 +20,74 @@ const SPELLBOOK_RADIUS: float = 60.0 var _spellbook_angle: float = 0.0 var _spellbooks: Array = [] +var _icon_knife = preload("res://assets/weapons/knvie.png") +var _icon_book = preload("res://assets/books_set_2/books_pentagram.png") +var _icon_brew = preload("res://assets/books_set_2/books_health_potion.png") +var _icon_shuriken: AtlasTexture +var _icon_fireball: AtlasTexture + +func _stat(label: String, from: String, to: String) -> String: + return "[color=#aaaaaa]" + label + "[/color]\n[color=#888888]" + from + "[/color] → [color=#77dd77]" + to + "[/color]" + +func _stat_new(label: String, val: String) -> String: + return "[color=#aaaaaa]" + label + "[/color]\n[color=#77dd77]" + val + "[/color]" + +func _stat_toggle(label: String) -> String: + return "[color=#aaaaaa]" + label + "[/color]\n[color=#888888]OFF[/color] → [color=#77dd77]ON[/color]" + func _ready() -> void: cauldron = witch.get_node("CauldronBar") + + _icon_shuriken = AtlasTexture.new() + _icon_shuriken.atlas = preload("res://assets/Fire Pixel Bullet 16x16/All_Fire_Bullet_Pixel_16x16_02.png") + _icon_shuriken.region = Rect2(496, 32, 16, 16) + + _icon_fireball = AtlasTexture.new() + _icon_fireball.atlas = preload("res://assets/Fire Pixel Bullet 16x16/All_Fire_Bullet_Pixel_16x16_00.png") + _icon_fireball.region = Rect2(576, 1, 16, 16) + var dsh = Perk.new() dsh.name = "Double Shuriken" - dsh.description = "Throw two shurikens instead of one" + dsh.description = "Fire two shurikens at once" + dsh.stats = _stat("Shurikens", "1", "2") + dsh.spell = SpellLibrary.SHURIKEN + dsh.icon = _icon_shuriken dsh.effect = double_shuriken available_perks.append(dsh) + var faoe = Perk.new() faoe.name = "AOE Fireball" - faoe.description = "Fireballs spawn an explosion on contact" + faoe.description = "Fireballs explode on impact" + faoe.stats = _stat_toggle("AOE") + faoe.spell = SpellLibrary.FIREBALL + faoe.icon = _icon_fireball faoe.effect = fireball_aoe available_perks.append(faoe) + var bexp = Perk.new() bexp.name = "Brew Explosion" - bexp.description = "The Witch casts an explosion on finishing a brew" + bexp.description = "Trigger an explosion on brew" + bexp.stats = _stat_toggle("Explosion") + bexp.spell = SpellLibrary.NONE + bexp.icon = _icon_brew bexp.effect = brew_explosion available_perks.append(bexp) + var tk = Perk.new() tk.name = "Throwing Knife" - tk.description = "Automatically throw a knife at the nearest enemy every second" + tk.description = "Auto-throw at nearby enemies" + tk.stats = _stat_new("Cooldown", "%.1fs" % throwing_knife_cooldown) + tk.spell = SpellLibrary.NONE + tk.icon = _icon_knife tk.effect = enable_throwing_knife available_perks.append(tk) + var sb = Perk.new() sb.name = "Spellbook" - sb.description = "A spellbook orbits the witch, dealing 12 damage to enemies it touches" + sb.description = "An orbiting book hits enemies" + sb.stats = "[color=#aaaaaa]Damage Count[/color]\n[color=#77dd77]" + str(spellbook_damage) + " 1[/color]" + sb.spell = SpellLibrary.NONE + sb.icon = _icon_book sb.effect = unlock_spellbook available_perks.append(sb) @@ -73,12 +116,16 @@ 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.description = "Throw knives more often" + upg.stats = _stat("Cooldown", "%.1fs" % throwing_knife_cooldown, "%.1fs" % maxf(1.0, throwing_knife_cooldown - 0.2)) + upg.icon = _icon_knife upg.effect = knife_cooldown_upgrade available_perks.append(upg) var ek = Perk.new() ek.name = "Extra Knife" - ek.description = "Throw one additional knife per attack (max 3)" + ek.description = "Throw one more knife" + ek.stats = _stat("Knives", str(throwing_knife_count), str(throwing_knife_count + 1)) + ek.icon = _icon_knife ek.effect = extra_knife available_perks.append(ek) @@ -87,7 +134,9 @@ func extra_knife(): if throwing_knife_count < 3: var ek = Perk.new() ek.name = "Extra Knife" - ek.description = "Throw one additional knife per attack (max 3)" + ek.description = "Throw one more knife" + ek.stats = _stat("Knives", str(throwing_knife_count), str(throwing_knife_count + 1)) + ek.icon = _icon_knife ek.effect = extra_knife available_perks.append(ek) @@ -96,7 +145,9 @@ func knife_cooldown_upgrade(): 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.description = "Throw knives more often" + upg.stats = _stat("Cooldown", "%.1fs" % throwing_knife_cooldown, "%.1fs" % maxf(1.0, throwing_knife_cooldown - 0.2)) + upg.icon = _icon_knife upg.effect = knife_cooldown_upgrade available_perks.append(upg) @@ -111,17 +162,23 @@ func unlock_spellbook() -> void: _rebuild_spellbooks() var eb = Perk.new() eb.name = "Extra Book" - eb.description = "Add another spellbook (max 5)" + eb.description = "Add one more orbiting book" + eb.stats = _stat("Books", str(spellbook_count), str(spellbook_count + 1)) + eb.icon = _icon_book eb.effect = extra_book available_perks.append(eb) var fo = Perk.new() fo.name = "Faster Orbit" - fo.description = "Spellbooks orbit the witch faster" + fo.description = "Books orbit faster" + fo.stats = _stat("Speed", "%.1f" % spellbook_speed, "%.1f" % (spellbook_speed + 0.5)) + fo.icon = _icon_book fo.effect = faster_orbit available_perks.append(fo) var bd = Perk.new() bd.name = "Book Damage" - bd.description = "Spellbooks deal 4 more damage" + bd.description = "Books hit harder" + bd.stats = _stat("Damage", str(spellbook_damage), str(spellbook_damage + 4)) + bd.icon = _icon_book bd.effect = book_damage available_perks.append(bd) @@ -131,7 +188,9 @@ func extra_book() -> void: if spellbook_count < 5: var eb = Perk.new() eb.name = "Extra Book" - eb.description = "Add another spellbook (max 5)" + eb.description = "Add one more orbiting book" + eb.stats = _stat("Books", str(spellbook_count), str(spellbook_count + 1)) + eb.icon = _icon_book eb.effect = extra_book available_perks.append(eb) @@ -139,7 +198,9 @@ func faster_orbit() -> void: spellbook_speed += 0.5 var fo = Perk.new() fo.name = "Faster Orbit" - fo.description = "Spellbooks orbit the witch faster" + fo.description = "Books orbit faster" + fo.stats = _stat("Speed", "%.1f" % spellbook_speed, "%.1f" % (spellbook_speed + 0.5)) + fo.icon = _icon_book fo.effect = faster_orbit available_perks.append(fo) @@ -149,7 +210,9 @@ func book_damage() -> void: book.damage = spellbook_damage var bd = Perk.new() bd.name = "Book Damage" - bd.description = "Spellbooks deal 4 more damage" + bd.description = "Books hit harder" + bd.stats = _stat("Damage", str(spellbook_damage), str(spellbook_damage + 4)) + bd.icon = _icon_book bd.effect = book_damage available_perks.append(bd) @@ -162,4 +225,3 @@ func _rebuild_spellbooks() -> void: book.damage = spellbook_damage witch.get_parent().add_child(book) _spellbooks.append(book) - diff --git a/scripts/witch.gd b/scripts/witch.gd index 45ee3ff..435d3fb 100644 --- a/scripts/witch.gd +++ b/scripts/witch.gd @@ -9,6 +9,7 @@ var shuriken = preload("res://scenes/shuriken.tscn") var fire_swirl = preload("res://scenes/fire_swirl.tscn") var tornado = preload("res://scenes/tornado.tscn") var shuriken_count = 1 +var _fire_sfx = preload("res://assets/music&sfx/sfx/fire.wav") var max_hp: int = 100 var current_hp: int = 100 @@ -51,11 +52,33 @@ func _on_collect(DropsBase): func shoot_fireballs(): var enemies = get_tree().get_nodes_in_group("enemies") for enemy in enemies: + if not is_instance_valid(enemy): + continue + var dir = global_position.direction_to(enemy.global_position) + _face_direction(dir) var fb = fireball.instantiate() fb.global_position = global_position get_parent().add_child(fb) fb.launch(enemy.global_position) - camera.shake(0.3,0.8) + _play_fire_sfx() + camera.shake(0.15, 0.5) + await get_tree().create_timer(0.12).timeout + $AnimatedSprite2D.play("south") + +func _face_direction(dir: Vector2) -> void: + if abs(dir.x) >= abs(dir.y): + $AnimatedSprite2D.play("east" if dir.x > 0 else "west") + else: + $AnimatedSprite2D.play("south" if dir.y > 0 else "north") + +func _play_fire_sfx() -> void: + var asp = AudioStreamPlayer.new() + asp.stream = _fire_sfx + asp.volume_db = -10 + asp.pitch_scale = randf_range(0.9, 1.1) + get_parent().add_child(asp) + asp.play() + asp.finished.connect(asp.queue_free) func shoot_fire_swirl(): var fs = fire_swirl.instantiate()