MIF_E31230535/mobilmusuhboss.gd

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)