Compare commits
10 Commits
44d83f30f1
...
2c3d8c7cfd
| Author | SHA1 | Date |
|---|---|---|
|
|
2c3d8c7cfd | |
|
|
35772ba2a6 | |
|
|
d5aca6bdf4 | |
|
|
dd4fcbdf2c | |
|
|
960a8612b4 | |
|
|
882d44264a | |
|
|
ac86c4371e | |
|
|
0ad1ce1ca0 | |
|
|
83c8a61f14 | |
|
|
6d1fcfce07 |
Binary file not shown.
|
|
@ -0,0 +1,24 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="wav"
|
||||||
|
type="AudioStreamWAV"
|
||||||
|
uid="uid://bdqk0x4qyk3mc"
|
||||||
|
path="res://.godot/imported/pruge_bass.wav-c5ceaea0b44c81c9961ac70c3dc5f07c.sample"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/music&sfx/sfx/pruge_bass.wav"
|
||||||
|
dest_files=["res://.godot/imported/pruge_bass.wav-c5ceaea0b44c81c9961ac70c3dc5f07c.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
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,24 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="wav"
|
||||||
|
type="AudioStreamWAV"
|
||||||
|
uid="uid://bqg3q37ugk8ja"
|
||||||
|
path="res://.godot/imported/purge_build_up.wav-478e240cc516d2308f089ccc744223fa.sample"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/music&sfx/sfx/purge_build_up.wav"
|
||||||
|
dest_files=["res://.godot/imported/purge_build_up.wav-478e240cc516d2308f089ccc744223fa.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
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,24 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="wav"
|
||||||
|
type="AudioStreamWAV"
|
||||||
|
uid="uid://bci64umwgnpjj"
|
||||||
|
path="res://.godot/imported/purge_impact_boom.wav-dc17074eb0200fae32cf877c94544e56.sample"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/music&sfx/sfx/purge_impact_boom.wav"
|
||||||
|
dest_files=["res://.godot/imported/purge_impact_boom.wav-dc17074eb0200fae32cf877c94544e56.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
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,24 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="wav"
|
||||||
|
type="AudioStreamWAV"
|
||||||
|
uid="uid://xkygjr5ewvic"
|
||||||
|
path="res://.godot/imported/purge_sustained_boom.wav-ebb185be11c79583807c007ee85b5815.sample"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/music&sfx/sfx/purge_sustained_boom.wav"
|
||||||
|
dest_files=["res://.godot/imported/purge_sustained_boom.wav-ebb185be11c79583807c007ee85b5815.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
|
||||||
|
|
@ -6,4 +6,6 @@ class_name Perk
|
||||||
@export var stats: String = ""
|
@export var stats: String = ""
|
||||||
@export var spell: String = SpellLibrary.NONE
|
@export var spell: String = SpellLibrary.NONE
|
||||||
@export var icon: Texture2D = null
|
@export var icon: Texture2D = null
|
||||||
|
@export var archetype_slot: String = ""
|
||||||
|
@export var requires_mode: String = ""
|
||||||
var effect: Callable
|
var effect: Callable
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ func _play_hit_sound() -> void:
|
||||||
ap.play()
|
ap.play()
|
||||||
|
|
||||||
func take_damage(amount: int) -> void:
|
func take_damage(amount: int) -> void:
|
||||||
if is_dying or is_hurt:
|
if is_dying:
|
||||||
return
|
return
|
||||||
hp -= amount
|
hp -= amount
|
||||||
if hp <= 0:
|
if hp <= 0:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
extends ProjectileBase
|
extends ProjectileBase
|
||||||
|
|
||||||
var fireball_aoe = false
|
|
||||||
var explosion_scene = preload("res://scenes/explosion.tscn")
|
var explosion_scene = preload("res://scenes/explosion.tscn")
|
||||||
|
var tornado_scene = preload("res://scenes/tornado.tscn")
|
||||||
@onready var perk_effects = get_node("/root/Game/PerkEffects")
|
@onready var perk_effects = get_node("/root/Game/PerkEffects")
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|
@ -9,12 +9,24 @@ func _ready() -> void:
|
||||||
damage = 10
|
damage = 10
|
||||||
|
|
||||||
func _on_body_entered(body: Node2D) -> void:
|
func _on_body_entered(body: Node2D) -> void:
|
||||||
fireball_aoe = perk_effects.fireball_aoe_enabled
|
if not body.is_in_group("enemies"):
|
||||||
if body.is_in_group("enemies"):
|
return
|
||||||
body.take_damage(damage)
|
body.take_damage(damage)
|
||||||
if fireball_aoe:
|
match perk_effects.get_mode("fireball.impact"):
|
||||||
|
"explosion":
|
||||||
|
_spawn_explosion()
|
||||||
|
"spawn_tornado":
|
||||||
|
_spawn_tornado()
|
||||||
|
queue_free()
|
||||||
|
|
||||||
|
func _spawn_explosion() -> void:
|
||||||
var boom = explosion_scene.instantiate()
|
var boom = explosion_scene.instantiate()
|
||||||
boom.global_position = global_position
|
boom.global_position = global_position
|
||||||
get_parent().call_deferred("add_child", boom)
|
get_parent().call_deferred("add_child", boom)
|
||||||
queue_free()
|
|
||||||
|
func _spawn_tornado() -> void:
|
||||||
|
var tw = tornado_scene.instantiate()
|
||||||
|
tw.global_position = global_position
|
||||||
|
tw.explosion_damage = int(round(tw.explosion_damage * 0.33))
|
||||||
|
get_parent().call_deferred("add_child", tw)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,22 @@ func _ready() -> void:
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
func _is_eligible(perk: Perk) -> bool:
|
||||||
|
if perk.requires_mode == "":
|
||||||
|
return true
|
||||||
|
var parts = perk.requires_mode.split(":")
|
||||||
|
return perk_effects.get_mode(parts[0]) == parts[1]
|
||||||
|
|
||||||
func show_perks():
|
func show_perks():
|
||||||
player.stream = level_sound
|
player.stream = level_sound
|
||||||
player.play()
|
player.play()
|
||||||
if perks.is_empty():
|
var eligible = perks.filter(_is_eligible)
|
||||||
|
if eligible.is_empty():
|
||||||
return
|
return
|
||||||
var tween = create_tween()
|
var tween = create_tween()
|
||||||
tween.tween_property($ColorRect, "color:a", 0.6, 0.3)
|
tween.tween_property($ColorRect, "color:a", 0.6, 0.3)
|
||||||
get_tree().paused = true
|
get_tree().paused = true
|
||||||
var shuffled = perks.duplicate()
|
var shuffled = eligible.duplicate()
|
||||||
shuffled.shuffle()
|
shuffled.shuffle()
|
||||||
var chosen = shuffled.slice(0, 3)
|
var chosen = shuffled.slice(0, 3)
|
||||||
await get_tree().create_timer(0.4).timeout
|
await get_tree().create_timer(0.4).timeout
|
||||||
|
|
@ -54,6 +61,9 @@ func select_perk(perk):
|
||||||
_spawn_level_up_particles(get_node("/root/Game/World/Witch").global_position)
|
_spawn_level_up_particles(get_node("/root/Game/World/Witch").global_position)
|
||||||
_spawn_level_up_particles(get_node("/root/Game/World/Player").global_position)
|
_spawn_level_up_particles(get_node("/root/Game/World/Player").global_position)
|
||||||
perks.erase(perk)
|
perks.erase(perk)
|
||||||
|
if perk.archetype_slot != "":
|
||||||
|
for p in perks.filter(func(p): return p.archetype_slot == perk.archetype_slot):
|
||||||
|
perks.erase(p)
|
||||||
for child in $HBoxContainer.get_children():
|
for child in $HBoxContainer.get_children():
|
||||||
child.animate_out()
|
child.animate_out()
|
||||||
var tween = create_tween()
|
var tween = create_tween()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ var fireball = preload("res://scenes/fireball.tscn")
|
||||||
var throwing_knife = preload("res://scenes/throwing_knive.tscn")
|
var throwing_knife = preload("res://scenes/throwing_knive.tscn")
|
||||||
var cauldron
|
var cauldron
|
||||||
var available_perks: Array[Perk] = []
|
var available_perks: Array[Perk] = []
|
||||||
var fireball_aoe_enabled = false
|
var spell_modes: Dictionary = {}
|
||||||
var laser_retarget_enabled = false
|
var laser_retarget_enabled = false
|
||||||
var throwing_knife_enabled = false
|
var throwing_knife_enabled = false
|
||||||
var throwing_knife_cooldown: float = 2.0
|
var throwing_knife_cooldown: float = 2.0
|
||||||
|
|
@ -39,6 +39,12 @@ func _stat_new(label: String, val: String) -> String:
|
||||||
func _stat_toggle(label: String) -> String:
|
func _stat_toggle(label: String) -> String:
|
||||||
return "[color=#aaaaaa]" + label + "[/color]\n[color=#888888]OFF[/color] → [color=#77dd77]ON[/color]"
|
return "[color=#aaaaaa]" + label + "[/color]\n[color=#888888]OFF[/color] → [color=#77dd77]ON[/color]"
|
||||||
|
|
||||||
|
func get_mode(slot: String) -> String:
|
||||||
|
return spell_modes.get(slot, "base")
|
||||||
|
|
||||||
|
func set_mode(slot: String, mode: String) -> void:
|
||||||
|
spell_modes[slot] = mode
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
cauldron = witch.get_node("CauldronBar")
|
cauldron = witch.get_node("CauldronBar")
|
||||||
|
|
||||||
|
|
@ -78,19 +84,71 @@ func _ready() -> void:
|
||||||
|
|
||||||
var faoe = Perk.new()
|
var faoe = Perk.new()
|
||||||
faoe.name = "AOE Fireball"
|
faoe.name = "AOE Fireball"
|
||||||
faoe.description = "Fireballs explode on impact"
|
faoe.description = "Fireballs explode on impact instead of hitting a single enemy"
|
||||||
faoe.stats = _stat_toggle("AOE")
|
faoe.stats = _stat_toggle("AOE")
|
||||||
faoe.spell = SpellLibrary.FIREBALL
|
faoe.spell = SpellLibrary.FIREBALL
|
||||||
faoe.icon = _icon_fireball
|
faoe.icon = _icon_fireball
|
||||||
faoe.effect = fireball_aoe
|
faoe.archetype_slot = "fireball.impact"
|
||||||
|
faoe.effect = fireball_set_impact_explosion
|
||||||
available_perks.append(faoe)
|
available_perks.append(faoe)
|
||||||
|
|
||||||
|
var ftor = Perk.new()
|
||||||
|
ftor.name = "Fireball: Spawn Tornado"
|
||||||
|
ftor.description = "Fireballs spawn a tornado on impact instead of exploding"
|
||||||
|
ftor.stats = _stat_toggle("Tornado")
|
||||||
|
ftor.spell = SpellLibrary.FIREBALL
|
||||||
|
ftor.icon = _icon_fireball
|
||||||
|
ftor.archetype_slot = "fireball.impact"
|
||||||
|
ftor.effect = fireball_set_impact_tornado
|
||||||
|
available_perks.append(ftor)
|
||||||
|
|
||||||
|
var fsg = Perk.new()
|
||||||
|
fsg.name = "Fireball: Shotgun"
|
||||||
|
fsg.description = "Fireball fires a spread of pellets in front of you instead of homing shots"
|
||||||
|
fsg.stats = _stat_toggle("Shotgun")
|
||||||
|
fsg.spell = SpellLibrary.FIREBALL
|
||||||
|
fsg.icon = _icon_fireball
|
||||||
|
fsg.archetype_slot = "fireball.cast"
|
||||||
|
fsg.effect = fireball_set_cast_shotgun
|
||||||
|
available_perks.append(fsg)
|
||||||
|
|
||||||
|
var fmg = Perk.new()
|
||||||
|
fmg.name = "Fireball: Minigun"
|
||||||
|
fmg.description = "Fireball rapid-fires at the nearest enemy instead of one burst"
|
||||||
|
fmg.stats = _stat_toggle("Minigun")
|
||||||
|
fmg.spell = SpellLibrary.FIREBALL
|
||||||
|
fmg.icon = _icon_fireball
|
||||||
|
fmg.archetype_slot = "fireball.cast"
|
||||||
|
fmg.effect = fireball_set_cast_minigun
|
||||||
|
available_perks.append(fmg)
|
||||||
|
|
||||||
|
var smp = Perk.new()
|
||||||
|
smp.name = "Shotgun: More Pellets"
|
||||||
|
smp.description = "Fire more pellets per shotgun blast"
|
||||||
|
smp.stats = _stat("Pellets", str(witch.fireball_pellet_count), str(witch.fireball_pellet_count + 2))
|
||||||
|
smp.spell = SpellLibrary.FIREBALL
|
||||||
|
smp.icon = _icon_fireball
|
||||||
|
smp.requires_mode = "fireball.cast:shotgun"
|
||||||
|
smp.effect = shotgun_more_pellets
|
||||||
|
available_perks.append(smp)
|
||||||
|
|
||||||
|
var msu = Perk.new()
|
||||||
|
msu.name = "Minigun: Spin-Up"
|
||||||
|
msu.description = "Fire fireballs faster in minigun mode"
|
||||||
|
msu.stats = _stat("Interval", "%.3fs" % witch.fireball_minigun_interval, "%.3fs" % maxf(0.03, witch.fireball_minigun_interval - 0.015))
|
||||||
|
msu.spell = SpellLibrary.FIREBALL
|
||||||
|
msu.icon = _icon_fireball
|
||||||
|
msu.requires_mode = "fireball.cast:minigun"
|
||||||
|
msu.effect = minigun_spin_up
|
||||||
|
available_perks.append(msu)
|
||||||
|
|
||||||
var fsp = Perk.new()
|
var fsp = Perk.new()
|
||||||
fsp.name = "Fireball Spread"
|
fsp.name = "Fireball Spread"
|
||||||
fsp.description = "Fireballs target more enemies"
|
fsp.description = "Fireballs target more enemies"
|
||||||
fsp.stats = _stat("Targets", str(witch.fireball_max_targets), str(witch.fireball_max_targets + 3))
|
fsp.stats = _stat("Targets", str(witch.fireball_max_targets), str(witch.fireball_max_targets + 3))
|
||||||
fsp.spell = SpellLibrary.FIREBALL
|
fsp.spell = SpellLibrary.FIREBALL
|
||||||
fsp.icon = _icon_fireball
|
fsp.icon = _icon_fireball
|
||||||
|
fsp.requires_mode = "fireball.cast:base"
|
||||||
fsp.effect = fireball_spread
|
fsp.effect = fireball_spread
|
||||||
available_perks.append(fsp)
|
available_perks.append(fsp)
|
||||||
|
|
||||||
|
|
@ -166,8 +224,17 @@ func laser_retarget():
|
||||||
func double_shuriken():
|
func double_shuriken():
|
||||||
witch.shuriken_count += 2
|
witch.shuriken_count += 2
|
||||||
|
|
||||||
func fireball_aoe():
|
func fireball_set_impact_explosion() -> void:
|
||||||
fireball_aoe_enabled = true
|
set_mode("fireball.impact", "explosion")
|
||||||
|
|
||||||
|
func fireball_set_impact_tornado() -> void:
|
||||||
|
set_mode("fireball.impact", "spawn_tornado")
|
||||||
|
|
||||||
|
func fireball_set_cast_shotgun() -> void:
|
||||||
|
set_mode("fireball.cast", "shotgun")
|
||||||
|
|
||||||
|
func fireball_set_cast_minigun() -> void:
|
||||||
|
set_mode("fireball.cast", "minigun")
|
||||||
|
|
||||||
func fireball_spread():
|
func fireball_spread():
|
||||||
witch.fireball_max_targets = witch.fireball_max_targets * 1.5
|
witch.fireball_max_targets = witch.fireball_max_targets * 1.5
|
||||||
|
|
@ -177,9 +244,35 @@ func fireball_spread():
|
||||||
fsp.stats = _stat("Targets", str(witch.fireball_max_targets), str(witch.fireball_max_targets * 1.5))
|
fsp.stats = _stat("Targets", str(witch.fireball_max_targets), str(witch.fireball_max_targets * 1.5))
|
||||||
fsp.spell = SpellLibrary.FIREBALL
|
fsp.spell = SpellLibrary.FIREBALL
|
||||||
fsp.icon = _icon_fireball
|
fsp.icon = _icon_fireball
|
||||||
|
fsp.requires_mode = "fireball.cast:base"
|
||||||
fsp.effect = fireball_spread
|
fsp.effect = fireball_spread
|
||||||
available_perks.append(fsp)
|
available_perks.append(fsp)
|
||||||
|
|
||||||
|
func shotgun_more_pellets() -> void:
|
||||||
|
witch.fireball_pellet_count += 2
|
||||||
|
var smp = Perk.new()
|
||||||
|
smp.name = "Shotgun: More Pellets"
|
||||||
|
smp.description = "Fire more pellets per shotgun blast"
|
||||||
|
smp.stats = _stat("Pellets", str(witch.fireball_pellet_count), str(witch.fireball_pellet_count + 2))
|
||||||
|
smp.spell = SpellLibrary.FIREBALL
|
||||||
|
smp.icon = _icon_fireball
|
||||||
|
smp.requires_mode = "fireball.cast:shotgun"
|
||||||
|
smp.effect = shotgun_more_pellets
|
||||||
|
available_perks.append(smp)
|
||||||
|
|
||||||
|
func minigun_spin_up() -> void:
|
||||||
|
witch.fireball_minigun_interval = maxf(0.03, witch.fireball_minigun_interval - 0.015)
|
||||||
|
if witch.fireball_minigun_interval > 0.03:
|
||||||
|
var msu = Perk.new()
|
||||||
|
msu.name = "Minigun: Spin-Up"
|
||||||
|
msu.description = "Fire fireballs faster in minigun mode"
|
||||||
|
msu.stats = _stat("Interval", "%.3fs" % (witch.fireball_minigun_interval + 0.015), "%.3fs" % witch.fireball_minigun_interval)
|
||||||
|
msu.spell = SpellLibrary.FIREBALL
|
||||||
|
msu.icon = _icon_fireball
|
||||||
|
msu.requires_mode = "fireball.cast:minigun"
|
||||||
|
msu.effect = minigun_spin_up
|
||||||
|
available_perks.append(msu)
|
||||||
|
|
||||||
func brew_explosion():
|
func brew_explosion():
|
||||||
cauldron.brew_explosion = true
|
cauldron.brew_explosion = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ signal health_changed(current_hp: int, max_hp: int)
|
||||||
signal died(attacker)
|
signal died(attacker)
|
||||||
|
|
||||||
var camera
|
var camera
|
||||||
|
@onready var perk_effects = get_node("/root/Game/PerkEffects")
|
||||||
var is_casting = false
|
var is_casting = false
|
||||||
var fireball = preload("res://scenes/fireball.tscn")
|
var fireball = preload("res://scenes/fireball.tscn")
|
||||||
var shuriken = preload("res://scenes/shuriken.tscn")
|
var shuriken = preload("res://scenes/shuriken.tscn")
|
||||||
|
|
@ -19,6 +20,9 @@ var max_hp: int = 50
|
||||||
var current_hp: int = 50
|
var current_hp: int = 50
|
||||||
var is_invincible: bool = false
|
var is_invincible: bool = false
|
||||||
var fireball_max_targets: int = 5
|
var fireball_max_targets: int = 5
|
||||||
|
var fireball_pellet_count: int = 6
|
||||||
|
var fireball_minigun_shots: int = 6
|
||||||
|
var fireball_minigun_interval: float = 0.08
|
||||||
|
|
||||||
const HP_BAR_WIDTH = 20
|
const HP_BAR_WIDTH = 20
|
||||||
const HP_BAR_HEIGHT = 3
|
const HP_BAR_HEIGHT = 3
|
||||||
|
|
@ -55,6 +59,15 @@ func _on_collect(DropsBase):
|
||||||
|
|
||||||
|
|
||||||
func shoot_fireballs():
|
func shoot_fireballs():
|
||||||
|
match perk_effects.get_mode("fireball.cast"):
|
||||||
|
"shotgun":
|
||||||
|
await _cast_fireball_shotgun()
|
||||||
|
"minigun":
|
||||||
|
await _cast_fireball_minigun()
|
||||||
|
_:
|
||||||
|
await _cast_fireball_base()
|
||||||
|
|
||||||
|
func _cast_fireball_base() -> void:
|
||||||
var enemies = get_tree().get_nodes_in_group("enemies")
|
var enemies = get_tree().get_nodes_in_group("enemies")
|
||||||
enemies = enemies.filter(func(e): return is_instance_valid(e))
|
enemies = enemies.filter(func(e): return is_instance_valid(e))
|
||||||
enemies.sort_custom(func(a, b): return global_position.distance_to(a.global_position) < global_position.distance_to(b.global_position))
|
enemies.sort_custom(func(a, b): return global_position.distance_to(a.global_position) < global_position.distance_to(b.global_position))
|
||||||
|
|
@ -64,15 +77,46 @@ func shoot_fireballs():
|
||||||
continue
|
continue
|
||||||
var dir = global_position.direction_to(enemy.global_position)
|
var dir = global_position.direction_to(enemy.global_position)
|
||||||
_face_direction(dir)
|
_face_direction(dir)
|
||||||
var fb = fireball.instantiate()
|
_spawn_fireball_toward(enemy.global_position)
|
||||||
fb.global_position = global_position
|
|
||||||
get_parent().add_child(fb)
|
|
||||||
fb.launch(enemy.global_position)
|
|
||||||
_play_fire_sfx()
|
_play_fire_sfx()
|
||||||
camera.shake(0.15, 0.5)
|
camera.shake(0.15, 0.5)
|
||||||
await get_tree().create_timer(0.12).timeout
|
await get_tree().create_timer(0.12).timeout
|
||||||
$AnimatedSprite2D.play("south")
|
$AnimatedSprite2D.play("south")
|
||||||
|
|
||||||
|
func _cast_fireball_shotgun() -> void:
|
||||||
|
var target = get_nearest_enemy(global_position)
|
||||||
|
var aim_pos = target.global_position if target != null else global_position + Vector2.DOWN * 100.0
|
||||||
|
var base_dir = global_position.direction_to(aim_pos)
|
||||||
|
_face_direction(base_dir)
|
||||||
|
var spread_deg = 40.0
|
||||||
|
for i in range(fireball_pellet_count):
|
||||||
|
var t = float(i) / float(max(1, fireball_pellet_count - 1))
|
||||||
|
var angle_offset = deg_to_rad(lerp(-spread_deg / 2.0, spread_deg / 2.0, t))
|
||||||
|
var dir = base_dir.rotated(angle_offset)
|
||||||
|
_spawn_fireball_toward(global_position + dir * 300.0)
|
||||||
|
_play_fire_sfx()
|
||||||
|
camera.shake(0.2, 0.6)
|
||||||
|
$AnimatedSprite2D.play("south")
|
||||||
|
|
||||||
|
func _cast_fireball_minigun() -> void:
|
||||||
|
for i in range(fireball_minigun_shots):
|
||||||
|
var target = get_nearest_enemy(global_position)
|
||||||
|
if target == null:
|
||||||
|
break
|
||||||
|
var dir = global_position.direction_to(target.global_position)
|
||||||
|
_face_direction(dir)
|
||||||
|
_spawn_fireball_toward(target.global_position)
|
||||||
|
_play_fire_sfx()
|
||||||
|
camera.shake(0.08, 0.3)
|
||||||
|
await get_tree().create_timer(fireball_minigun_interval).timeout
|
||||||
|
$AnimatedSprite2D.play("south")
|
||||||
|
|
||||||
|
func _spawn_fireball_toward(target_pos: Vector2) -> void:
|
||||||
|
var fb = fireball.instantiate()
|
||||||
|
fb.global_position = global_position
|
||||||
|
get_parent().add_child(fb)
|
||||||
|
fb.launch(target_pos)
|
||||||
|
|
||||||
func _face_direction(dir: Vector2) -> void:
|
func _face_direction(dir: Vector2) -> void:
|
||||||
if abs(dir.x) >= abs(dir.y):
|
if abs(dir.x) >= abs(dir.y):
|
||||||
$AnimatedSprite2D.play("east" if dir.x > 0 else "west")
|
$AnimatedSprite2D.play("east" if dir.x > 0 else "west")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue