using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using Engine.Models; using SUISS.Scheduling; using UnityEngine; namespace SUISSEngine { [RequireComponent(typeof(Serializing), typeof(Builder))] public class Destroyer : MonoBehaviour { protected virtual void OnSerialize(Dictionary values) { } protected virtual void OnDeserialize(Dictionary values) { } //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event Destroyer.QueueChangedEventHandler QueueChangedEvent; protected virtual void FireQueueChangedEvent() { if (this.QueueChangedEvent != null) { this.QueueChangedEvent(); } } public bool isSelecting { get; private set; } public bool isDestroying { get { return this.currentlyDestroying != null; } } public void ClickedBuilding(Building building) { if (building.state != BuildingState.Normal) { return; } if (!building.CanDemolish) { return; } if (this.selectedBuildings.Contains(building)) { Destroyer.Deselect(building.gameObject); this.selectedBuildings.Remove(building); } else { Destroyer.Select(building.gameObject); this.selectedBuildings.Add(building); } } public void ClickedRoad(Road road) { if (this.selectedRoads.Contains(road)) { Destroyer.Deselect(road.gameObject); this.selectedRoads.Remove(road); } else { Destroyer.Select(road.gameObject); this.selectedRoads.Add(road); } } protected static void SetColor(GameObject obj, Color color) { SpriteRenderer component = obj.GetComponent(); if (component != null) { component.color = color; } } protected static void Select(GameObject obj) { Destroyer.SetColor(obj, Color.red); } protected static void Deselect(GameObject obj) { Destroyer.SetColor(obj, Color.white); } protected void ResetSelection(bool destroy) { foreach (Building building in this.selectedBuildings) { Destroyer.Deselect(building.gameObject); } foreach (Road road in this.selectedRoads) { Destroyer.Deselect(road.gameObject); } if (destroy) { this.StartDestroyingSelection(); } this.selectedBuildings.Clear(); this.selectedRoads.Clear(); } public void StartSelecting() { if (this.isSelecting) { UnityEngine.Debug.LogWarning("Cant start selecting when already selecting"); return; } this.isSelecting = true; } public void CancelSelecting() { if (!this.isSelecting) { UnityEngine.Debug.LogWarning("Cant cancel selecting when not selecting"); return; } this.isSelecting = false; this.ResetSelection(false); } public Building[] SelectedBuildings { get { return this.selectedBuildings.ToArray(); } } public void DestroySelection() { if (!this.isSelecting) { UnityEngine.Debug.LogWarning("Cant start destroying when not selecting"); return; } this.isSelecting = false; this.ResetSelection(true); } private Building GetLastInDestroyQueue() { if (this.destroyQueue.Count != 0) { return this.destroyQueue.List[this.destroyQueue.Count - 1]; } return this.currentlyDestroying; } public double GetTimeTillDestroyed(Building b) { if (!(this.currentlyDestroying == b) && !this.destroyQueue.List.Contains(b)) { UnityEngine.Debug.LogError("The Building is not in the destroyQueue"); return 0.0; } if (this.currentlyDestroying == b) { return this.currentlyDestroying.DemolishTimeLeft; } double num = this.currentlyDestroying.DemolishTimeLeft; for (int i = 0; i < this.destroyQueue.Count; i++) { num += (double)this.destroyQueue.List[i].demolishTime; if (this.destroyQueue.List[i] == b) { break; } } return num; } public double GetTimeTillFinished() { return this.GetTimeTillDestroyed(this.GetLastInDestroyQueue()); } private void StartDestroyingSelection() { this.DestroyRoads(); this.QueueDestroyBuildings(); } private void EndCurrentDestroyAction(double endedAtTime) { if (this.currentlyDestroying != null) { this.currentlyDestroying.DestroyedEvent -= this.EndCurrentDestroyAction; this.currentlyDestroying = null; } if (this.destroyQueue != null && this.destroyQueue.Count > 0) { if ((int)(Timing.time - endedAtTime) > 0) { this.FastForward(Timing.time - endedAtTime); } else { this.DestroyNext(Timing.time); } } else { this.UpdateNotification(); } } public void DestroyNext(double startTime) { if (this.isDestroying || this.destroyQueue.Count == 0) { UnityEngine.Debug.LogWarning("Cant destroy next building. " + ((!this.isDestroying) ? "Queue is empty!" : "The destroyer hasnt finished destroying yet")); return; } this.currentlyDestroying = this.destroyQueue.Dequeue(); this.FireQueueChangedEvent(); this.currentlyDestroying.StartDemolishing(startTime); this.currentlyDestroying.DestroyedEvent += this.EndCurrentDestroyAction; this.FireQueueChangedEvent(); this.UpdateNotification(); } private void DestroyRoads() { foreach (Road road in this.selectedRoads) { this.builder.DestroyTile(road.GetComponent()); } } private void QueueDestroyBuildings() { foreach (Building building in this.selectedBuildings) { this.DestroyBuilding(building); } } public void DestroyBuilding(Building building) { if (building.CanDemolish && building.state == BuildingState.Normal) { building.SetInDemolishingState((!this.isDestroying) ? 1 : (this.GetLastInDestroyQueue().SpotInDestroyQueue + 1)); this.EnqueueBuilding(building, true); } } public void EnqueueBuilding(Building building, bool startDestroyingIfPossible) { this.destroyQueue.Enqueue(building); this.FireQueueChangedEvent(); if (!this.isDestroying && startDestroyingIfPossible) { this.DestroyNext(Timing.time); } else { this.UpdateNotification(); } } public void CancelDestroyBuilding(Building building) { if (this.currentlyDestroying == building) { this.EndCurrentDestroyAction(Timing.time); } else { this.destroyQueue.Remove(building); } this.UpdateNotification(); } public void SetCurrentlyDestroying(Building building) { if (this.isDestroying) { UnityEngine.Debug.LogWarning("Cant set a new building to be destroyed. The destroyer is already destroying another building"); return; } this.currentlyDestroying = building; this.currentlyDestroying.DestroyedEvent += this.EndCurrentDestroyAction; } private void FastForward(double time) { if (this.isDestroying || this.destroyQueue.Count == 0) { UnityEngine.Debug.LogWarning("Cant fastforward since " + ((!this.isDestroying) ? "the destroyqueue is empty" : "there is a destroyment in progress!!")); return; } this.DestroyNext(Timing.time - time); } private void UpdateNotification() { HUDView hudview = UnityEngine.Object.FindObjectOfType(); if (hudview != null) { hudview.UpdateDemolishQueueButton(); } } private void OnGridDeserialized() { this.UpdateNotification(); } public void FinishAll() { if (this.isDestroying) { this.currentlyDestroying.FinishDemolishing(); } IEnumerator enumerator = this.destroyQueue.GetEnumerator(); try { while (enumerator.MoveNext()) { object obj = enumerator.Current; Building building = (Building)obj; building.StartDemolishing(Timing.time); building.FinishDemolishing(); } } finally { IDisposable disposable; if ((disposable = (enumerator as IDisposable)) != null) { disposable.Dispose(); } } } public List DemolishList { get { List list = new List(); if (this.currentlyDestroying != null) { list.Add(this.currentlyDestroying); } list.AddRange(this.destroyQueue.List); return list; } } [SelfReference] public Builder builder; [SelfReference] public Serializing serializing; private List selectedBuildings = new List(); private List selectedRoads = new List(); private Building currentlyDestroying; private PriorityQueue destroyQueue = new PriorityQueue(new Destroyer.DestroyBuildingComparer()); public delegate void QueueChangedEventHandler(); private class DestroyBuildingComparer : IComparer { public int Compare(Building x, Building y) { return x.SpotInDestroyQueue.CompareTo(y.SpotInDestroyQueue); } } } }