diff --git a/Assets/_Project/Audio/buildings/general/building_falling.ogg b/Assets/_Project/Audio/buildings/general/building_falling.ogg
new file mode 100644
index 0000000..859533a
--- /dev/null
+++ b/Assets/_Project/Audio/buildings/general/building_falling.ogg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e81a9e427500661a7e5f11cb61124168f9be60cbfd7164fb86eaec408ccdef3b
+size 51189
diff --git a/Assets/_Project/Audio/buildings/general/building_falling.ogg.meta b/Assets/_Project/Audio/buildings/general/building_falling.ogg.meta
new file mode 100644
index 0000000..c1849c6
--- /dev/null
+++ b/Assets/_Project/Audio/buildings/general/building_falling.ogg.meta
@@ -0,0 +1,23 @@
+fileFormatVersion: 2
+guid: 2726115fda23119cea127edb372d0f21
+AudioImporter:
+ externalObjects: {}
+ serializedVersion: 8
+ defaultSettings:
+ serializedVersion: 2
+ loadType: 0
+ sampleRateSetting: 0
+ sampleRateOverride: 44100
+ compressionFormat: 1
+ quality: 1
+ conversionMode: 0
+ preloadAudioData: 0
+ platformSettingOverrides: {}
+ forceToMono: 0
+ normalize: 1
+ loadInBackground: 0
+ ambisonic: 0
+ 3D: 1
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/_Project/Prefabs/Towers/Tower Construction Sets/BuildSiteVisual.prefab b/Assets/_Project/Prefabs/Towers/Tower Construction Sets/BuildSiteVisual.prefab
index 6d0724b..771a16c 100644
--- a/Assets/_Project/Prefabs/Towers/Tower Construction Sets/BuildSiteVisual.prefab
+++ b/Assets/_Project/Prefabs/Towers/Tower Construction Sets/BuildSiteVisual.prefab
@@ -118,6 +118,7 @@ GameObject:
- component: {fileID: 9075933591925717035}
- component: {fileID: 7845454079079718139}
- component: {fileID: 6259437393614329336}
+ - component: {fileID: 3172884111175399884}
m_Layer: 0
m_Name: BuildSiteVisual
m_TagString: Untagged
@@ -206,3 +207,21 @@ BoxCollider:
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
+--- !u!114 &3172884111175399884
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 7720770984308489338}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 5712fbfba2f64c3aa653bebe31773d54, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::TD.Combat.TowerFallingSound
+ fallingSound:
+ clip: {fileID: 8300000, guid: 2726115fda23119cea127edb372d0f21, type: 3}
+ volume: 0.67
+ minPitch: 0.95
+ maxPitch: 0.95
+ triggerSecondsBeforeCompletion: 1
diff --git a/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab b/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab
index 640d249..23c11f4 100644
--- a/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab
+++ b/Assets/_Project/Prefabs/Towers/Tower_TeslaCoil.prefab
@@ -149,7 +149,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject
- GlobalObjectIdHash: 1363936954
+ GlobalObjectIdHash: 280718094
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
diff --git a/Assets/_Project/Scripts/Combat/TowerFallingSound.cs b/Assets/_Project/Scripts/Combat/TowerFallingSound.cs
new file mode 100644
index 0000000..9333b2f
--- /dev/null
+++ b/Assets/_Project/Scripts/Combat/TowerFallingSound.cs
@@ -0,0 +1,46 @@
+// Assets/_Project/Scripts/Combat/TowerFallingSound.cs
+using TD.Audio;
+using TD.Gameplay;
+using UnityEngine;
+
+namespace TD.Combat
+{
+ ///
+ /// Local-only audio for the tower falling from the sky. Attached to
+ /// (not , which doesn't exist
+ /// yet) and polled every frame: plays a sound on every peer once construction has
+ /// seconds or less remaining, so the whoosh
+ /// leads the tower's actual fall/land animation (see ,
+ /// which starts once is replaced by the real
+ /// at construction-complete).
+ ///
+ [RequireComponent(typeof(BuildSiteVisual))]
+ public class TowerFallingSound : MonoBehaviour
+ {
+ [SerializeField] private SoundConfig fallingSound;
+
+ [Tooltip("Sound fires once remaining construction time drops to this many seconds " +
+ "or less.")]
+ [SerializeField] private float triggerSecondsBeforeCompletion = 1f;
+
+ private BuildSiteVisual buildSiteVisual;
+ private bool played;
+
+ private void Awake()
+ {
+ buildSiteVisual = GetComponent();
+ }
+
+ private void Update()
+ {
+ if (played || buildSiteVisual == null) return;
+ if (buildSiteVisual.CurrentStage != BuildStage.Constructing) return;
+
+ if (buildSiteVisual.ComputeRemainingSeconds() <= triggerSecondsBeforeCompletion)
+ {
+ played = true;
+ AudioManager.Instance?.Play(fallingSound.clip, AudioCategory.UI, fallingSound.RandomPitch(), fallingSound.volume);
+ }
+ }
+ }
+}
diff --git a/Assets/_Project/Scripts/Combat/TowerFallingSound.cs.meta b/Assets/_Project/Scripts/Combat/TowerFallingSound.cs.meta
new file mode 100644
index 0000000..0ad2579
--- /dev/null
+++ b/Assets/_Project/Scripts/Combat/TowerFallingSound.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5712fbfba2f64c3aa653bebe31773d54
+timeCreated: 1783406173
\ No newline at end of file
diff --git a/Assets/_Project/Scripts/Gameplay/BuildSiteVisual.cs b/Assets/_Project/Scripts/Gameplay/BuildSiteVisual.cs
index f51b10d..7e85cc4 100644
--- a/Assets/_Project/Scripts/Gameplay/BuildSiteVisual.cs
+++ b/Assets/_Project/Scripts/Gameplay/BuildSiteVisual.cs
@@ -184,6 +184,20 @@ namespace TD.Gameplay
return Mathf.Clamp01((currentRunElapsed + accumulatedConstructionTime.Value) / bt);
}
+ ///
+ /// Returns seconds remaining until construction completes. Safe to call on any
+ /// client. Returns 0 while Queued (no timer running yet) or once complete.
+ ///
+ public float ComputeRemainingSeconds()
+ {
+ float bt = buildTime.Value;
+ if (bt <= 0f) return 0f;
+ float currentRunElapsed = constructionStartServerTime.Value > 0f
+ ? (float)NetworkManager.Singleton.ServerTime.Time - constructionStartServerTime.Value
+ : 0f;
+ return Mathf.Max(0f, bt - (currentRunElapsed + accumulatedConstructionTime.Value));
+ }
+
// ----- ISelectable ------------------------------------------------
/// Name shown in the HUD portrait. Pulls from the resolved