178 lines
6.1 KiB
GDScript
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")
|