142 lines
4.2 KiB
GDScript
142 lines
4.2 KiB
GDScript
extends Node2D
|
|
|
|
# 🛠️ BARU: Sinyal untuk memberi tahu Stage kalau boss masuk Fase 2
|
|
signal fase_dua_dimulai
|
|
|
|
@export var roda_berputar : bool = true
|
|
@export var sprite_rusak_tahap1 : Texture2D
|
|
@export var sprite_rusak_tahap2 : Texture2D
|
|
@export var sprite_hancur_total : Texture2D
|
|
|
|
@export var peluru_fase1 : PackedScene = preload("res://pelururiflemusuh.tscn")
|
|
@export var peluru_fase2 : PackedScene = preload("res://pelurumusuhfase_2.tscn")
|
|
|
|
# 🎛️ SETELAN VOLUME AUDIO FASE 2 (+10 dB)
|
|
@export var VOLUME_TEMBAKAN_KUAT: float = 10.0
|
|
|
|
var health = 100
|
|
var is_destroyed = false
|
|
|
|
# 🛠️ BARU: Pengaman agar sinyal tutorial Fase 2 hanya dikirim sekali saja
|
|
var tutorial_fase2_sudah_dikirim: bool = false
|
|
|
|
@onready var body_sprite = $StaticBody2D/body
|
|
@onready var anim_player = $AnimationPlayer
|
|
@onready var titik_tembak = $TitikTembak
|
|
|
|
# 🎵 AUDIO STREAM 1: Tembakan Biasa (Fase 1)
|
|
@onready var audio_tembakan = $AudioStreamPlayer
|
|
# 🎵 AUDIO STREAM 2: Tembakan Diperkuat / Meriam (Fase 2)
|
|
@onready var audio_tembakan_kuat = $AudioStreamPlayer2
|
|
|
|
# Variabel untuk referensi player agar bisa diincar
|
|
var player_ref = null
|
|
|
|
func _ready():
|
|
if roda_berputar and anim_player:
|
|
anim_player.play("berputar")
|
|
|
|
# Cari player di dalam scene
|
|
player_ref = get_tree().current_scene.find_child("Player", true, false)
|
|
|
|
func mulai_menembak():
|
|
if is_destroyed: return
|
|
await get_tree().create_timer(5.0).timeout
|
|
_loop_tembakan()
|
|
|
|
func _loop_tembakan():
|
|
while not is_destroyed and visible:
|
|
if health > 50:
|
|
for i in range(5):
|
|
if is_destroyed or health <= 50: break
|
|
_eksekusi_tembak_bertarget(peluru_fase1, 5)
|
|
await get_tree().create_timer(0.15).timeout
|
|
await get_tree().create_timer(5.0).timeout
|
|
else:
|
|
if is_destroyed: break
|
|
_eksekusi_tembak_bertarget(peluru_fase2, 40.0)
|
|
await get_tree().create_timer(7.0).timeout
|
|
|
|
func _eksekusi_tembak_bertarget(scene_peluru, nilai_damage):
|
|
if scene_peluru and titik_tembak:
|
|
|
|
# 🎵 MAINKAN AUDIO BERDASARKAN FASE NYAWA BOSS
|
|
if health > 50:
|
|
if audio_tembakan:
|
|
audio_tembakan.play()
|
|
else:
|
|
if audio_tembakan_kuat:
|
|
audio_tembakan_kuat.volume_db = VOLUME_TEMBAKAN_KUAT
|
|
audio_tembakan_kuat.play()
|
|
|
|
var peluru = scene_peluru.instantiate()
|
|
|
|
# 1. Tentukan posisi muncul peluru
|
|
var spawn_pos = titik_tembak.global_position
|
|
peluru.global_position = spawn_pos
|
|
peluru.damage = nilai_damage
|
|
|
|
# --- Atur Kecepatan Peluru ---
|
|
if "speed" in peluru:
|
|
if health > 50:
|
|
peluru.speed = 600.0 # Kecepatan peluru Fase 1
|
|
else:
|
|
peluru.speed = 1000.0 # Kecepatan peluru Fase 2 (lebih ngebut!)
|
|
|
|
# 2. Tentukan target (Default ke kiri jauh)
|
|
var target_pos = spawn_pos + Vector2(-1000, 0)
|
|
|
|
if is_instance_valid(player_ref):
|
|
target_pos = player_ref.global_position
|
|
|
|
if player_ref.get("is_menunduk") == true:
|
|
target_pos.y -= 220 # Meleset ke atas
|
|
else:
|
|
target_pos.y -= 50 # Bidik badan
|
|
|
|
# 3. Hitung Arah
|
|
var diff = target_pos - spawn_pos
|
|
if diff.x > 0: diff.x = -100 # Paksa arah tetap ke kiri
|
|
var arah = diff.normalized()
|
|
|
|
# 4. Terapkan Arah dan Rotasi
|
|
if "direction" in peluru:
|
|
peluru.direction = arah
|
|
|
|
peluru.rotation = arah.angle()
|
|
|
|
get_tree().current_scene.add_child(peluru)
|
|
|
|
func kurangi_nyawa(_jumlah):
|
|
if is_destroyed: return
|
|
if health <= 50: health -= 1.5
|
|
else: health -= 0.5
|
|
|
|
print("HP Boss: ", health)
|
|
|
|
# 🛠️ BARU: Deteksi Transisi ke HP <= 50 untuk memicu Sinyal Tutorial
|
|
if health <= 50 and not tutorial_fase2_sudah_dikirim and not is_destroyed:
|
|
tutorial_fase2_sudah_dikirim = true
|
|
emit_signal("fase_dua_dimulai") # Ledakkan sinyal ke skrip Stage!
|
|
|
|
if health <= 0: hancurkan_mobil()
|
|
elif health <= 25:
|
|
body_sprite.texture = sprite_rusak_tahap2
|
|
body_sprite.scale = Vector2(1.79, 2.022)
|
|
elif health <= 50:
|
|
body_sprite.texture = sprite_rusak_tahap1
|
|
body_sprite.scale = Vector2(1.79, 2.022)
|
|
|
|
func hancurkan_mobil():
|
|
is_destroyed = true
|
|
if anim_player: anim_player.stop()
|
|
if sprite_hancur_total:
|
|
body_sprite.texture = sprite_hancur_total
|
|
body_sprite.scale = Vector2(1.79, 2.022)
|
|
|
|
var body = get_node_or_null("StaticBody2D")
|
|
if body:
|
|
for child in body.get_children():
|
|
if child is CollisionPolygon2D or child is CollisionShape2D:
|
|
child.set_deferred("disabled", true)
|