MIF_E31230535/sniper_mode.gd

178 lines
6.1 KiB
GDScript

extends Node2D
@onready var crosshair = $Crosshair
# 🎬 Ambil referensi ke AnimationPlayer transisi
@onready var anim_player = $TransitionLayer/fade_to_black
# ==============================================================================
# 🎛️ SETELAN AUDIO MANUAL MINIGAME SNIPER (UBAH DI SINI)
# ==============================================================================
# Nilai volume dasar dalam desibel (dB) untuk musik sniper
var VOLUME_DASAR_BGM: float = -5.0
# Durasi efek transisi suara masuk dan keluar (dalam detik)
var DURASI_FADE_IN: float = 3.0
var DURASI_FADE_OUT: float = 1.5
# ==============================================================================
# 🎵 AMBIL REFERENSI NODE AUDIO TUNGGAL (Sesuai nama bawaan di scene)
@onready var audio_player = $AudioStreamPlayer
# 🔊 BARU: REFERENSI NODE AUDIO KEDUA UNTUK SFX TEMBAKAN SNIPER
@onready var sfx_tembak = $AudioStreamPlayer2
# --- REFERENSI LANGSUNG KE KEDUA TENTARA ---
@onready var soldier_1 = $Soldier
@onready var soldier_2 = $Soldier2
var is_finishing = false
# --- VARIABEL UNTUK COUNTER ---
var total_target = 0
var target_tereliminasi = 0
# --- STRUKTUR DATA PATROLI UNTUK MULTI-MUSUH ---
enum StatePatroli { JALAN_KANAN, DIAM_KANAN, JALAN_KIRI, DIAM_KIRI }
# Kita buatkan konfigurasi terpisah menggunakan Dictionary agar gerakannya tidak seragam/kaku
var data_patroli = {}
@export var kecepatan_patroli = 100.0
@export var durasi_diam = 2.0
@export var jarak_patroli = 150.0 # Jarak bolak-balik dari titik awal masing-masing
# --- 🎯 VARIABEL SENSITIVITAS SLIDE ANDROID ---
@export var sensitivitas_sentuhan : float = 1.2
func _ready():
# 🎬 1. JALANKAN ANIMASI FADE IN SAAT SCENE SNIPER BARU DIMUAT
if anim_player and anim_player.has_animation("fadein"):
anim_player.play("fadein")
print("🎬 Sniper Stage Dimulai: Memutar animasi fadein...")
# 2. Inisialisasi posisi awal dan state untuk masing-masing soldier
inisialisasi_musuh(soldier_1)
inisialisasi_musuh(soldier_2)
# 3. Hitung berapa banyak musuh yang ada di awal permainan
total_target = get_tree().get_nodes_in_group("musuh").size()
print("Misi Sniper Dimulai! Total target: ", total_target)
# 🎵 SISTEM FADE IN OTOMATIS AUDIO TUNGGAL
if audio_player:
if audio_player.stream and audio_player.stream is AudioStreamOggVorbis:
audio_player.stream.loop = true
audio_player.volume_db = -80.0 # Mulai dari senyap total
audio_player.play()
var tween = create_tween()
tween.tween_property(audio_player, "volume_db", VOLUME_DASAR_BGM, DURASI_FADE_IN)\
.set_trans(Tween.TRANS_QUAD)\
.set_ease(Tween.EASE_OUT)
print("🎵 Musik Sniper mulai berputar dengan efek Fade-In ke ", VOLUME_DASAR_BGM, " dB!")
func inisialisasi_musuh(node_musuh):
if is_instance_valid(node_musuh):
data_patroli[node_musuh] = {
"titik_awal_x": node_musuh.global_position.x,
"status_sekarang": StatePatroli.JALAN_KANAN,
"timer_patroli": 0.0
}
func _physics_process(delta):
# Jalankan pergerakan untuk semua musuh yang terdaftar jika mereka masih valid
for musuh in data_patroli.keys():
if is_instance_valid(musuh) and not musuh.is_dead and not musuh.is_chasing:
logika_kontrol_patroli(musuh, delta)
func _input(event):
if is_finishing: return
# 📲 LOGIKA MULTI-PLATFORM UNTUK ANDROID (SLIDE LAYAR)
if event is InputEventScreenDrag:
crosshair.global_position += event.relative * sensitivitas_sentuhan
# 💻 LOGIKA MULTI-PLATFORM UNTUK PC (IKUTI MOUSE)
elif event is InputEventMouseMotion and OS.get_name() != "Android":
crosshair.global_position = get_global_mouse_position()
# 💥 LOGIKA MENEMBAK (Mendukung Klik Kiri PC ATAU Tombol UI Android)
if event.is_action_pressed("click_kiri"):
tembak()
# --- MESIN PENGGERAK OTOMATIS MULTI-MUSUH ---
func logika_kontrol_patroli(musuh, delta):
var data = data_patroli[musuh]
match data["status_sekarang"]:
StatePatroli.JALAN_KANAN:
musuh.velocity.x = kecepatan_patroli
if musuh.global_position.x >= (data["titik_awal_x"] + jarak_patroli):
musuh.velocity.x = 0
data["status_sekarang"] = StatePatroli.DIAM_KANAN
data["timer_patroli"] = 0.0
StatePatroli.DIAM_KANAN:
data["timer_patroli"] += delta
if data["timer_patroli"] >= durasi_diam:
data["status_sekarang"] = StatePatroli.JALAN_KIRI
StatePatroli.JALAN_KIRI:
musuh.velocity.x = -kecepatan_patroli
if musuh.global_position.x <= (data["titik_awal_x"] - jarak_patroli):
musuh.velocity.x = 0
data["status_sekarang"] = StatePatroli.DIAM_KIRI
data["timer_patroli"] = 0.0
StatePatroli.DIAM_KIRI:
data["timer_patroli"] += delta
if data["timer_patroli"] >= durasi_diam:
data["status_sekarang"] = StatePatroli.JALAN_KANAN
func tembak():
print("DOR!")
# 🔊 BARU: MAINKAN SFX TEMBAKAN SETIAP KALI TOMBOL INTERAKSI DILEPAS
if sfx_tembak:
sfx_tembak.play()
print("🔊 SFX: Suara tembakan sniper senapan rifle bergelegar!")
if has_node("Camera2D"):
$Camera2D.apply_shake(10.0)
var target = crosshair.get_target_terbidik()
if target and target.has_method("stealth_assassination"):
target.stealth_assassination()
target_tereliminasi += 1
print("Target kena! Progress: ", target_tereliminasi, "/", total_target)
cek_progres_misi()
func cek_progres_misi():
if target_tereliminasi >= total_target and not is_finishing:
is_finishing = true
mulai_transisi_kembali()
func mulai_transisi_kembali():
print("Semua target tumbang! Menunggu jeda sejenak...")
await get_tree().create_timer(1.5).timeout
# 🎵 TURUNKAN VOLUME AUDIO PERLAHAN (FADE-OUT) SEBELUM PINDAH SCENE
if audio_player and audio_player.is_playing():
var tween_out = create_tween()
tween_out.tween_property(audio_player, "volume_db", -80.0, DURASI_FADE_OUT)\
.set_trans(Tween.TRANS_QUAD)\
.set_ease(Tween.EASE_IN)
print("🎵 Menurunkan volume musik sniper secara sinematik (Fade-Out)...")
if anim_player and anim_player.has_animation("fadeout"):
anim_player.play("fadeout")
await anim_player.animation_finished
# 🎵 Matikan audio secara total demi menghemat memori setelah layar hitam
if audio_player:
audio_player.stop()
print("🚀 Kembali ke perjalanan utama...")
get_tree().change_scene_to_file("res://stage1_2.tscn")