using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using CIG; using CIG.Translation; using CIG3.ExtensionMethods; using CIGEnums; using SUISS.Core; using SUISS.Scheduling; using UnityEngine; namespace SUISSEngine { [RequireComponent(typeof(GridTile), typeof(Serializing))] public class Building : MonoBehaviour { //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event Building.TimedBuildingEventHandler ConstructionCompletedEvent; protected virtual void FireConstructionCompletedEvent(double constructionCompletedTime) { if (this.ConstructionCompletedEvent != null) { this.ConstructionCompletedEvent(constructionCompletedTime); } } //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event Building.TimedBuildingEventHandler DestroyedEvent; protected virtual void FireDestroyedEvent(double destroyedTime) { if (this.DestroyedEvent != null) { this.DestroyedEvent(destroyedTime); } } public virtual Currencies PurchasePrice { get { return this.initialPurchasePrice; } } public virtual bool IsUnlocked { get { return true; } } public virtual List ShownProperties { get { return new List(); } } public virtual bool InfoRequiresFrequentRefresh { get { return false; } } public virtual bool CanSpeedup { get { return false; } } public virtual ILocalizedString InfoText() { UnityEngine.Debug.LogWarning("InfoText should have an override"); return Localization.EmptyLocalizedString; } protected virtual void ClickHandler(GameObject target) { if (this._state == BuildingState.Demolishing || this._state == BuildingState.WaitingForDemolishing) { SingletonMonobehaviour.Instance.RequestFirstPopup(delegate(State state) { ((BuildDemolishPopupState)state).SwitchTab(BuildDemolishTabs.Demolish); }); } } public BuildingState state { get { return this._state; } protected set { if (this._state != value) { this._state = value; } } } public string LocalizationKey { get { return (!string.IsNullOrEmpty(this.stringReference)) ? this.stringReference : base.name; } } public ILocalizedString LocalName { get { return Localization.Key(this.LocalizationKey); } } public string CachedName { get { if (string.IsNullOrEmpty(this.cachedName)) { this.cachedName = base.name; } return this.cachedName; } } public virtual bool HasRoad { get { return this.hasRoad; } protected set { if (this.hasRoad != value) { this.hasRoad = value; this.serializing.Serialize(); } } } public int SpotInDestroyQueue { get { return this.spotInDestroyQueue; } } private Renderer TileRenderer { get { if (this._tileRenderer == null) { this._tileRenderer = this.tile.GetComponent(); } return this._tileRenderer; } } private Collider2D TileCollider2D { get { if (this._tileCollider2D == null) { this._tileCollider2D = this.tile.GetComponent(); } return this._tileCollider2D; } } protected virtual void Awake() { this._renderer = base.GetComponent(); this._currencyAnimationSource.Init(this._currencyAnimationObject); } protected virtual void OnDestroy() { if (SingletonMonobehaviour.IsAvailable) { if (this._defaultBehaviourRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._defaultBehaviourRoutine); this._defaultBehaviourRoutine = null; } if (this._demolishBehaviourRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._demolishBehaviourRoutine); this._demolishBehaviourRoutine = null; } } } protected virtual void OnSerialize(Dictionary values) { values["state"] = (int)this.state; values["hasRoad"] = this.HasRoad; if (this.state == BuildingState.Constructing) { if (this.constructionEnumerator != null) { values["constructed"] = (double)this.constructionEnumerator.Current; } else if (this.constructionTime > 0) { values["constructed"] = Timing.time + (double)this.constructionTime; } } else if (this.state == BuildingState.WaitingForDemolishing) { if (this.spotInDestroyQueue > 0) { values["destroyQueueSpot"] = this.spotInDestroyQueue; } } else if (this.state == BuildingState.Demolishing) { if (this.demolishEnumerator != null) { values["demolished"] = (double)this.demolishEnumerator.Current; } else if (this.demolishTime > 0) { values["demolished"] = Timing.time + (double)this.demolishTime; } } } protected virtual void OnDeserialize(Dictionary values) { if (values.ContainsKey("state")) { this._state = (BuildingState)((int)values["state"]); if (this._state == BuildingState.Constructing && values.ContainsKey("constructed")) { this.constructedTime = (double)values["constructed"]; } else if (this._state == BuildingState.WaitingForDemolishing && values.ContainsKey("destroyQueueSpot")) { this.spotInDestroyQueue = (int)values["destroyQueueSpot"]; } else if (this._state == BuildingState.Demolishing && values.ContainsKey("demolished")) { this.demolishedTime = (double)values["demolished"]; } } if (values.ContainsKey("hasRoad")) { this.hasRoad = (bool)values["hasRoad"]; } } protected virtual void OnDeserialized() { if (this == null) { return; } if (this.state == BuildingState.Demolishing) { Destroyer componentInParent = base.GetComponentInParent(); componentInParent.SetCurrentlyDestroying(this); Clickable component = base.GetComponent(); if (component != null) { component.OnClickEvent += this.ClickHandler; } ButtonGridTileIcon buttonGridTileIcon = this._gridTileIconManager.SetIcon(GridTileIconType.Demolish); buttonGridTileIcon.Init(delegate { this.ClickHandler(base.gameObject); }); if (this._demolishBehaviourRoutine == null) { SingletonMonobehaviour.Instance.StartRoutine(this._demolishBehaviourRoutine = this.DemolishBehaviour(0.0), base.gameObject); } } else { if (this.state == BuildingState.WaitingForDemolishing) { Destroyer componentInParent2 = base.GetComponentInParent(); componentInParent2.EnqueueBuilding(this, false); } if (this._defaultBehaviourRoutine == null) { SingletonMonobehaviour.Instance.StartRoutine(this._defaultBehaviourRoutine = this.DefaultBehaviour(), base.gameObject); } if (this.state == BuildingState.Constructing) { this.SetProgressBar(this.ConstructionTimeLeft, (double)this.constructionTime); } } } protected virtual void OnGridTileStatusChanged(GridTile.Status oldStatus) { if (this == null) { return; } GridTile.Status status = this.tile.status; if (status != GridTile.Status.Created) { if (status == GridTile.Status.Moving || status == GridTile.Status.Preview) { this._gridTileIconManager.HideIcon(); } } else { if (oldStatus != GridTile.Status.Preview) { if (oldStatus == GridTile.Status.Moving) { this.OnAdjacentRoadsChanged(null); } } else { SingletonMonobehaviour.Instance.PlayClip(Clip.Build); if (this.checkForRoad) { this.hasRoad = this.CheckForRoad(); } if (this._defaultBehaviourRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._defaultBehaviourRoutine); } SingletonMonobehaviour.Instance.StartRoutine(this._defaultBehaviourRoutine = this.DefaultBehaviour(), base.gameObject); } this._gridTileIconManager.ShowIcon(); } } protected virtual void OnGridTileHiddenChanged() { if (this._constructionGameObject != null) { if (this.tile.hidden) { if (this._constructionGameObjectRenderer != null) { this._constructionGameObjectRenderer.enabled = false; } if (this._constructionGameObjectCollider2D != null) { this._constructionGameObjectCollider2D.enabled = false; } } else { if (this._constructionGameObjectRenderer != null) { this._constructionGameObjectRenderer.enabled = true; } if (this._constructionGameObjectCollider2D != null) { this._constructionGameObjectCollider2D.enabled = true; } if (this.TileRenderer != null) { this.TileRenderer.enabled = false; } if (this.TileCollider2D != null) { this.TileCollider2D.enabled = false; } } } } protected virtual void OnConstructionStarted() { this.SetProgressBar((double)this.constructionTime, (double)this.constructionTime); } protected virtual void OnConstructionCompleted() { this.UpdateMissingRoadIcon(); this.FireConstructionCompletedEvent(Timing.time); this.HideProgressBar(); } protected virtual void OnDemolishStarted() { this.SetProgressBar((double)this.demolishTime, (double)this.demolishTime); } protected virtual void OnDemolishCompleted() { this.FireDestroyedEvent(this.demolishedTime); } protected virtual void OnDemolishCancelled() { } public virtual bool CanDemolish { get { return this.destructible; } } public bool CheckForRoad() { if (this == null || this.tile == null || this.tile.element == null || this.tile.element.Grid == null) { return false; } foreach (GridTile gridTile in this.tile.element.Grid.GetNeighbourTiles(this.tile)) { if (gridTile.GetComponent() != null) { return true; } } return false; } public bool IsConstructed { get { return this.state == BuildingState.Normal || this.state == BuildingState.Moving || this.state == BuildingState.WaitingForDemolishing || this.state == BuildingState.Demolishing; } } public virtual void StartDemolishing(double startTime) { if (this.state != BuildingState.WaitingForDemolishing) { UnityEngine.Debug.LogWarning(string.Format("{0}: Cannot demolish in state {1}", base.name, this.state)); return; } SingletonMonobehaviour.Instance.PlayClip(Clip.Demolish, true); Scheduler instance = SingletonMonobehaviour.Instance; if (instance != null) { if (this._demolishBehaviourRoutine != null) { instance.StopRoutine(this._demolishBehaviourRoutine); this._demolishBehaviourRoutine = null; } instance.StartRoutine(this._demolishBehaviourRoutine = this.DemolishBehaviour(startTime), base.gameObject); } } public void FinishDemolishing() { if (this.demolishEnumerator != null) { SingletonMonobehaviour.Instance.PlayClip(Clip.Fairy); SingletonMonobehaviour.Instance.StopRoutine(this.demolishEnumerator); this.demolishEnumerator = null; base.BroadcastMessage("OnSpeedupPurchased", SendMessageOptions.DontRequireReceiver); } } public void FinishConstruction() { if (this.constructionEnumerator != null) { SingletonMonobehaviour.Instance.PlayClip(Clip.Fairy); SingletonMonobehaviour.Instance.StopRoutine(this.constructionEnumerator); this.constructionEnumerator = null; base.BroadcastMessage("OnSpeedupPurchased", SendMessageOptions.DontRequireReceiver); } } public double ConstructionTimeLeft { get { if (this.constructionEnumerator != null) { return Scheduler.TimeLeft(this.constructionEnumerator); } return 0.0; } } public double DemolishTimeLeft { get { if (this.demolishEnumerator != null) { return Scheduler.TimeLeft(this.demolishEnumerator); } if (this.state == BuildingState.WaitingForDemolishing) { return (double)this.demolishTime; } return 0.0; } } public virtual void OnAdjacentRoadsChanged(GridTile road) { if (this.checkForRoad) { this.HasRoad = this.CheckForRoad(); } this.UpdateMissingRoadIcon(); } private void UpdateMissingRoadIcon() { if (this.checkForRoad && !this.HasRoad) { ButtonGridTileIcon buttonGridTileIcon = this._gridTileIconManager.SetIcon(GridTileIconType.MissingRoad); buttonGridTileIcon.Init(delegate { this.ClickHandler(base.gameObject); }); } else { this._gridTileIconManager.RemoveIcon(GridTileIconType.MissingRoad); } } protected void HideProgressBar() { if (this._progressOverlay != null) { UnityEngine.Object.Destroy(this._progressOverlay.gameObject); this._gridTileIconManager.RemoveIcon(GridTileIconType.UpgradeArrow); } } protected void SetProgressBar(double time, double totalTime) { if (this._progressOverlay == null) { this._progressOverlay = OverlayProgress.Get(base.gameObject); } this._progressOverlay.Initialize(Timing.Instance.GameTime + time, totalTime); this.ProgressTimeChanged(); } protected virtual void ProgressTimeChanged() { } private IEnumerator WaitForConstruction() { double finishTime; if (this.constructedTime < 0.0) { finishTime = Timing.time + (double)this.constructionTime; } else { finishTime = this.constructedTime; } yield return finishTime; yield break; } private IEnumerator ConstructionBehaviour() { if (this.constructionTime <= 0 || SingletonMonobehaviour.Instance.IsSpeedupped(this)) { yield break; } this.SetConstructionSprite(); yield return this.constructionEnumerator = this.WaitForConstruction(); this.constructionEnumerator = null; this.SetOriginalSprite(); yield break; } private IEnumerator DefaultBehaviour() { switch (this.state) { case BuildingState.Preview: this.state = BuildingState.Constructing; SingletonMonobehaviour.Instance.AddBuildingAction(); base.BroadcastMessage("OnConstructionStarted", SendMessageOptions.DontRequireReceiver); this.serializing.Serialize(); SingletonMonobehaviour.Instance.StartTracking(this, Timing.time + (double)this.constructionTime); break; case BuildingState.Constructing: break; case BuildingState.Normal: goto IL_125; case BuildingState.Moving: goto IL_1A7; case BuildingState.WaitingForDemolishing: { ButtonGridTileIcon icon = this._gridTileIconManager.SetIcon(GridTileIconType.Demolish); icon.Init(delegate { this.ClickHandler(base.gameObject); }); goto IL_125; } default: goto IL_1A7; } yield return this.ConstructionBehaviour(); this.state = BuildingState.Normal; base.BroadcastMessage("OnConstructionCompleted", SendMessageOptions.DontRequireReceiver); this.serializing.Serialize(); SingletonMonobehaviour.Instance.FinishTracking(this); IL_125: Clickable clicker = base.GetComponent(); if (clicker != null) { clicker.OnClickEvent += this.ClickHandler; } this.UpdateMissingRoadIcon(); goto IL_1CB; IL_1A7: UnityEngine.Debug.LogWarning(string.Format("Building is in weird state {0}.", this.state)); IL_1CB: this._defaultBehaviourRoutine = null; yield break; } private IEnumerator WaitForDemolish(double startTime) { if (this.demolishedTime < 0.0) { yield return this.demolishedTime = startTime + (double)this.demolishTime; } else { yield return this.demolishedTime; } yield break; } public void SetInDemolishingState(int spotInDestroyQueue) { if (this.state != BuildingState.Normal) { UnityEngine.Debug.Log(string.Format("Cant demolish building from state {0}", this.state)); return; } this.spotInDestroyQueue = spotInDestroyQueue; this.state = BuildingState.WaitingForDemolishing; this.serializing.Serialize(); ButtonGridTileIcon buttonGridTileIcon = this._gridTileIconManager.SetIcon(GridTileIconType.Demolish); buttonGridTileIcon.Init(delegate { this.ClickHandler(base.gameObject); }); } public void CancelDemolishment() { if (this.state != BuildingState.WaitingForDemolishing && this.state != BuildingState.Demolishing) { UnityEngine.Debug.Log(string.Format("Cant cancel demolishment from state {0}", this.state)); return; } base.GetComponentInParent().CancelDestroyBuilding(this); BuildingState state = this.state; this.state = BuildingState.Normal; if (state == BuildingState.Demolishing) { SingletonMonobehaviour.Instance.StopRoutine(this.demolishEnumerator); this.demolishedTime = -1.0; } this.serializing.Serialize(); this._gridTileIconManager.RemoveIcon(GridTileIconType.Demolish); this.UpdateMissingRoadIcon(); } private IEnumerator DemolishBehaviour(double startTime) { this.state = BuildingState.Demolishing; base.BroadcastMessage("OnDemolishStarted", SendMessageOptions.DontRequireReceiver); this.serializing.Serialize(); yield return this.demolishEnumerator = this.WaitForDemolish(startTime); this.HideProgressBar(); this.demolishEnumerator = null; if (this.state != BuildingState.Demolishing) { base.BroadcastMessage("OnDemolishCancelled", SendMessageOptions.DontRequireReceiver); this.serializing.Serialize(); this._demolishBehaviourRoutine = null; yield break; } this._gridTileIconManager.RemoveIcon(GridTileIconType.Demolish); SingletonMonobehaviour.Instance.AddBuildingAction(); base.BroadcastMessage("OnDemolishCompleted", SendMessageOptions.DontRequireReceiver); IsometricIsland.GetParent(this).builder.DestroyTile(this.tile); this._demolishBehaviourRoutine = null; yield break; } private void SetConstructionSprite() { if (this.constructionPrefab == null) { UnityEngine.Debug.LogWarning(string.Format("Building {0} has constructionPrefab null", base.name)); return; } this._constructionGameObject = UnityEngine.Object.Instantiate(this.constructionPrefab); this._constructionGameObjectRenderer = this._constructionGameObject.GetComponent(); this._constructionGameObjectCollider2D = this._constructionGameObject.GetComponent(); base.gameObject.AttachChildTransform(this._constructionGameObject, SpriteAlignment.Custom); Clickable.Instance(this._constructionGameObject).OnClickEvent += this.ClickHandler; if (this.tile.hidden) { if (this._constructionGameObjectRenderer != null) { this._constructionGameObjectRenderer.enabled = false; } if (this._constructionGameObjectRenderer != null) { this._constructionGameObjectRenderer.enabled = false; } } this.savedGridTileOffset = this.tile.offset; GridTile component = this._constructionGameObject.GetComponent(); if (component != null) { this.tile.offset = component.offset; } this.tile.UpdateTransform(); component.spriteRenderer.sortingOrder = this.tile.spriteRenderer.sortingOrder; if (this.TileRenderer != null) { this.TileRenderer.enabled = false; } if (this.TileCollider2D != null) { this.TileCollider2D.enabled = false; } } private void SetOriginalSprite() { if (this._constructionGameObject != null) { if (!this.tile.hidden) { if (this.TileRenderer != null) { this.TileRenderer.enabled = true; } if (this.TileCollider2D != null) { this.TileCollider2D.enabled = true; } } this.tile.offset = this.savedGridTileOffset; this.tile.UpdateTransform(); Clickable.Instance(this._constructionGameObject).OnClickEvent -= this.ClickHandler; this._constructionGameObject.transform.parent = null; UnityEngine.Object.Destroy(this._constructionGameObject); this._constructionGameObject = null; this._constructionGameObjectRenderer = null; this._constructionGameObjectCollider2D = null; } } public Bounds RendererBounds() { if (this._constructionGameObject != null && this._constructionGameObjectRenderer.enabled) { return this._constructionGameObjectRenderer.bounds; } return this._renderer.bounds; } [SerializeField] protected GridTileIconManager _gridTileIconManager; [SerializeField] protected PlingManager _plingManager; [SerializeField] protected CurrencyAnimationSource _currencyAnimationSource; public GameObject constructionPrefab; public Currencies initialPurchasePrice; public int goldCostAtMax; public int constructionTime; public int demolishTime; public bool checkForRoad; public bool movable; public bool destructible; public string stringReference; [SelfReference] public Serializing serializing; [SelfReference] public GridTile tile; protected object _currencyAnimationObject = new object(); private string cachedName = string.Empty; private OverlayProgress _progressOverlay; private BuildingState _state; protected double constructedTime = -1.0; protected double demolishedTime = -1.0; private GameObject _constructionGameObject; private Renderer _constructionGameObjectRenderer; private Collider2D _constructionGameObjectCollider2D; private bool hasRoad; private Vector3 savedGridTileOffset; private int spotInDestroyQueue = -1; private IEnumerator _defaultBehaviourRoutine; private IEnumerator _demolishBehaviourRoutine; private Renderer _tileRenderer; private Collider2D _tileCollider2D; protected Renderer _renderer; private IEnumerator constructionEnumerator; private IEnumerator demolishEnumerator; public delegate void TimedBuildingEventHandler(double time); } }