using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Unity.Mathematics; using Unity.VisualScripting; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class TowerPlacementManager : MonoBehaviour { public static TowerPlacementManager Instance; // Spawning grid events public static event Action OnSpawnGridRequested; public static event Action OnGridDeleteRequested; // Placing tower public static event Action OnTowerPlaced; [Header("Debug")] [SerializeField] private bool RebuildGrid = false; // Section: Mouse private SlotManager CurrentSelectedSlot; private int CurrentRotation = 0; // 0, 1, 2, 3 private GameObject SilhouettedObject; private TowerInfo SelectedTowerInfo; private GameObject SelectedTowerPrefab => SelectedTowerInfo.prefab; private void Start() { if (Instance != this) Destroy(Instance); Instance = this; OnSpawnGridRequested?.Invoke(this); } private void Update() { if (Input.GetKeyDown(KeyCode.R) && Input.GetKey(KeyCode.LeftShift)) { CurrentRotation--; CurrentRotation = CurrentRotation % 4; } else if (Input.GetKeyDown(KeyCode.R)) { CurrentRotation++; CurrentRotation = CurrentRotation % 4; } if (RebuildGrid) { RebuildGrid = false; OnGridDeleteRequested?.Invoke(this); OnSpawnGridRequested?.Invoke(this); } } private void OnEnable() { OnTowerPlaced += PlayPlaceSfx; MoneyManager.OnShopSelected += OnShopSelected; } private void OnDisable() { OnTowerPlaced -= PlayPlaceSfx; MoneyManager.OnShopSelected -= OnShopSelected; } private void PlayPlaceSfx(TowerInfo info) { AudioManager.PlaySound("Build Tower", Vector3.zero); } private void OnShopSelected(TowerInfo info) { SelectedTowerInfo = info; Destroy(SilhouettedObject); } public void OnSlotClicked(SlotManager slot, GridManager grid, int x, int y) { if (GameManager.Instance.Balance.Value < SelectedTowerInfo.price) return; // cant afford // slot.gameObject.GetComponentInChildren().material.color = Color.blue; OnSelectSlot(slot); SpawnTowerAtSelected(slot, SelectedTowerPrefab); GameManager.Instance.Balance.Value -= SelectedTowerInfo.price; } // Called when a slot is selected public void OnSelectSlot(SlotManager slot) { // Detects if the selected slot is new if (CurrentSelectedSlot != null && CurrentSelectedSlot != slot) OnDeselectSlot(CurrentSelectedSlot, slot); CurrentSelectedSlot = slot; slot.gameObject.GetComponentInChildren().material.color = Color.blue; } // Called when another slot is getting selected public void OnDeselectSlot(SlotManager prevSlot, SlotManager newSlot) { prevSlot.gameObject.GetComponentInChildren().material.color = Color.white; } public void SpawnTowerAtSelected(SlotManager slotRef, GameObject towerPrefab) { var spawnedTower = Instantiate(towerPrefab, CurrentSelectedSlot.transform); Quaternion newRotation = Quaternion.AngleAxis(CurrentRotation * 90f, transform.up); spawnedTower.transform.localRotation = newRotation; Tower towerScript = spawnedTower.GetComponent(); slotRef.TowerHealth = towerScript.GetComponent(); towerScript.Placed(); FinishBuild(); } public void OnSlotHovered(SlotManager slot, GridManager grid, int x, int y) { if (SilhouettedObject == null) SilhouettedObject = ToSilhouette(SelectedTowerPrefab); // Sets tower rotation Quaternion newRotation = Quaternion.AngleAxis(CurrentRotation * 90f, transform.up); SilhouettedObject.transform.localRotation = newRotation; Vector3 offset = SelectedTowerPrefab.transform.position; //SilhouettedObject.SetActive(true); SilhouettedObject.transform.parent = slot.TowerSpawnPoint.transform; SilhouettedObject.transform.localPosition = offset; } public void OnSlotUnHovered(SlotManager slot, GridManager grid, int x, int y) { Destroy(SilhouettedObject); } public void FinishBuild() { Destroy(SilhouettedObject); OnTowerPlaced?.Invoke(SelectedTowerInfo); } [Space(10)] public Material SilhouetteMaterial; public GameObject ToSilhouette(GameObject obj) { // if prefab, then spawn it if (obj.scene.name == null) obj = Instantiate(obj); Component[] objScripts = obj.GetComponents(); objScripts = objScripts.Concat(obj.GetComponentsInChildren()).ToArray(); for (int i = 0; i < objScripts.Length; i++) { var comp = objScripts[i]; if (comp is not Renderer && comp is not Transform && comp is not MeshFilter && comp is not UIBehaviour) { Destroy(comp); } else if (typeof(Renderer).IsAssignableFrom(comp)) { var renderer = comp as Renderer; renderer.materials = new Material[] { SilhouetteMaterial , SilhouetteMaterial , SilhouetteMaterial , SilhouetteMaterial , SilhouetteMaterial }; } } return obj; } }