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 var throwing_knife_enabled = false var throwing_knife_cooldown: float = 2.0 var throwing_knife_count: int = 1 var _knife_timer: float = 0.0 var spellbook_scene = preload("res://scenes/spellbook.tscn") var spellbook_count: int = 0 var spellbook_damage: int = 12 var spellbook_speed: float = 1.5 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 var _icon_player: 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) _icon_player = AtlasTexture.new() _icon_player.atlas = preload("res://assets/Swordsman_lvl1/Without_shadow/Swordsman_lvl1_Idle_without_shadow.png") _icon_player.region = Rect2(0, 0, 64, 64) var dsh = Perk.new() dsh.name = "Double Shuriken" 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 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 = "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 = "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 = "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) var sf = Perk.new() sf.name = "Swift Feet" sf.description = "Move faster" sf.stats = _stat("Speed", str(player.speed), str(player.speed + 10)) sf.spell = SpellLibrary.NONE sf.icon = _icon_player sf.effect = swift_feet available_perks.append(sf) var bh = Perk.new() bh.name = "Battle Hardened" bh.description = "Hit harder" bh.stats = _stat("Strength", str(player.strength), str(player.strength + 2)) bh.spell = SpellLibrary.NONE bh.icon = _icon_player bh.effect = battle_hardened available_perks.append(bh) var ss = Perk.new() ss.name = "Swift Strike" ss.description = "Attack more often" ss.stats = _stat("Attack CD", "%.2fs" % player.get_node("AttackSpeed").wait_time, "%.2fs" % maxf(0.2, player.get_node("AttackSpeed").wait_time - 0.1)) ss.spell = SpellLibrary.NONE ss.icon = _icon_player ss.effect = swift_strike available_perks.append(ss) func _process(delta: float) -> void: if throwing_knife_enabled: _knife_timer += delta if _knife_timer >= throwing_knife_cooldown: _knife_timer = 0.0 _shoot_throwing_knife() if spellbook_count > 0: _spellbook_angle += spellbook_speed * delta for i in range(_spellbooks.size()): var offset = (TAU / _spellbooks.size()) * i _spellbooks[i].global_position = witch.global_position + Vector2(cos(_spellbook_angle + offset), sin(_spellbook_angle + offset)) * SPELLBOOK_RADIUS 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 = "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 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) func extra_knife(): throwing_knife_count = min(throwing_knife_count + 1, 3) if throwing_knife_count < 3: var ek = Perk.new() ek.name = "Extra Knife" 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) 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 = "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) func _shoot_throwing_knife() -> void: for i in range(throwing_knife_count): var knife = throwing_knife.instantiate() knife.global_position = witch.global_position witch.get_parent().add_child(knife) func unlock_spellbook() -> void: spellbook_count = 1 _rebuild_spellbooks() var eb = Perk.new() eb.name = "Extra Book" 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 = "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 = "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) func extra_book() -> void: spellbook_count = min(spellbook_count + 1, 5) _rebuild_spellbooks() if spellbook_count < 5: var eb = Perk.new() eb.name = "Extra Book" 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) func faster_orbit() -> void: spellbook_speed += 0.5 var fo = Perk.new() fo.name = "Faster Orbit" 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) func book_damage() -> void: spellbook_damage += 4 for book in _spellbooks: book.damage = spellbook_damage var bd = Perk.new() bd.name = "Book 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) func _rebuild_spellbooks() -> void: for book in _spellbooks: book.queue_free() _spellbooks.clear() for i in range(spellbook_count): var book = spellbook_scene.instantiate() book.damage = spellbook_damage witch.get_parent().add_child(book) _spellbooks.append(book) func swift_feet() -> void: player.speed += 10 var sf = Perk.new() sf.name = "Swift Feet" sf.description = "Move faster" sf.stats = _stat("Speed", str(player.speed), str(player.speed + 10)) sf.spell = SpellLibrary.NONE sf.icon = _icon_player sf.effect = swift_feet available_perks.append(sf) func battle_hardened() -> void: player.strength += 2 var bh = Perk.new() bh.name = "Battle Hardened" bh.description = "Hit harder" bh.stats = _stat("Strength", str(player.strength), str(player.strength + 2)) bh.spell = SpellLibrary.NONE bh.icon = _icon_player bh.effect = battle_hardened available_perks.append(bh) func swift_strike() -> void: var timer = player.get_node("AttackSpeed") timer.wait_time = maxf(0.2, timer.wait_time - 0.1) if timer.wait_time > 0.2: var ss = Perk.new() ss.name = "Swift Strike" ss.description = "Attack more often" ss.stats = _stat("Attack CD", "%.2fs" % timer.wait_time, "%.2fs" % maxf(0.2, timer.wait_time - 0.1)) ss.spell = SpellLibrary.NONE ss.icon = _icon_player ss.effect = swift_strike available_perks.append(ss)