This commit is contained in:
2026-07-04 16:57:40 -07:00
parent 16e396841e
commit c6b7890212
47 changed files with 1713 additions and 209 deletions
@@ -27,6 +27,12 @@ namespace ProjectM.Client
byte _lastPhase;
bool _phaseInit;
AudioClip _stingCoreHit;
int _lastCore = -1;
float _coreStingCooldown;
AudioClip _stingBeep, _stingRoar;
int _lastCountdownSec = -1;
bool _bossRoared;
const float AmbientBaseVolume = 0.10f; // low bed; Defend eases up to ~1.7x
@@ -36,6 +42,9 @@ namespace ProjectM.Client
_stingExpedition = MakeSting(520f, 880f, 0.45f, 0.30f); // airy rising "deploy"
_stingDefend = MakeSting(300f, 140f, 0.55f, 0.42f); // tense falling "wave incoming"
_stingBuild = MakeSting(440f, 660f, 0.40f, 0.26f); // soft confirm
_stingCoreHit = MakeSting(240f, 70f, 0.30f, 0.55f); // harsh falling "Core hit" alarm
_stingBeep = MakeSting(880f, 880f, 0.09f, 0.30f); // countdown tick
_stingRoar = MakeSting(90f, 38f, 0.90f, 0.60f); // boss-arrival roar (low falling growl)
}
protected override void OnStartRunning()
@@ -76,6 +85,50 @@ namespace ProjectM.Client
// Ease the drone intensity toward the phase target (tenser during Defend).
float target = phase == CyclePhase.Siege ? AmbientBaseVolume * 1.7f : AmbientBaseVolume;
_ambient.volume = Mathf.MoveTowards(_ambient.volume, target * GameVolume.Music, SystemAPI.Time.DeltaTime * 0.25f);
// Core-under-attack alarm: a falling sting on each CoreIntegrity drop (rate-limited) so a base
// breach is AUDIBLE even when the fight has the player's eyes elsewhere.
_coreStingCooldown -= SystemAPI.Time.DeltaTime;
if (SystemAPI.TryGetSingleton<CoreIntegrity>(out var core))
{
if (_lastCore >= 0 && core.Current < _lastCore && _coreStingCooldown <= 0f)
{
_ambient.PlayOneShot(_stingCoreHit, 0.8f * GameVolume.Sfx);
_coreStingCooldown = 0.7f;
}
_lastCore = core.Current;
}
// Launch countdown beeps (3-2-1) + the boss-arrival roar — replicated-state observations only.
if (SystemAPI.TryGetSingleton<RunInfo>(out var runAudio))
{
int sec = -1;
if (runAudio.Lifecycle == RunLifecycle.Launching && runAudio.LaunchTick != 0
&& SystemAPI.TryGetSingleton<NetworkTime>(out var antime) && antime.ServerTick.IsValid)
{
int tl = new NetworkTick(runAudio.LaunchTick).TicksSince(antime.ServerTick);
if (tl > 0) sec = tl / 60 + 1;
}
if (sec > 0 && sec != _lastCountdownSec && sec <= 3)
_ambient.PlayOneShot(_stingBeep, 0.5f * GameVolume.Sfx);
_lastCountdownSec = sec;
bool inBossRoom = runAudio.Lifecycle == RunLifecycle.InRoom
&& runAudio.CurrentRoomType == RoomTypeId.Boss;
if (!inBossRoom)
{
_bossRoared = false; // re-arm for the next boss room
}
else if (!_bossRoared)
{
foreach (var _ in SystemAPI.Query<RefRO<Health>>().WithAll<EnemyTag>())
{
_ambient.PlayOneShot(_stingRoar, 0.9f * GameVolume.Sfx);
_bossRoared = true;
break;
}
}
}
}
void PlaySting(byte phase)