using System; using System.Collections; using System.Collections.Generic; using CIG.Translation; using CIGEnums; using SUISS.Core; using SUISS.Scheduling; using SUISSEngine; using UnityEngine; public class CIGCommercialBuilding : CIGBuilding { public Currencies Profit { get { if (this.currentMaxEmployees == 0) { return new Currencies(); } return this.currentEmployees * this.currentProfit / this.currentMaxEmployees * SingletonMonobehaviour.Instance.Multipliers.CommercialBuildingProfitMultiplier; } } public Currencies ProfitPerHour { get { if (this.profitTime == 0) { return Currencies.Zero; } return 3600m * this.currentProfit / this.profitTime; } } public int MaxEmployees { get { return this.currentMaxEmployees; } protected set { int num = value - this.currentMaxEmployees; this.currentMaxEmployees = value; if (num != 0) { base.IslandState.AddJobs(num); } } } public int Employees { get { return this.currentEmployees; } protected set { int num = value - this.currentEmployees; this.currentEmployees = value; if (num != 0) { base.IslandState.AddEmployees(num); this.OnEmployeesChanged(); } } } public int ProfitTimeLeft { get { if (this._waitForProfitRoutine != null) { return (int)(Scheduler.TimeLeft(this._waitForProfitRoutine) + 0.5); } return 0; } } protected override void OnDestroy() { if (SingletonMonobehaviour.IsAvailable) { this.StopRoutines(); if (this._delayedPlingEnumerator != null) { SingletonMonobehaviour.Instance.StopRoutine(this._delayedPlingEnumerator); this._delayedPlingEnumerator = null; } } base.OnDestroy(); } public override bool CanUpgrade { get { if (this.activatable && !this.Activated) { CIGExpansions.ExpansionBlock blockForIndex = this._expansions.reference.GetBlockForIndex(this.tile.index); if (blockForIndex != null && !blockForIndex.Unlocked) { return false; } } return base.CanUpgrade; } } public void ShowCommercialTimerProgress() { base.SetProgressBar((double)this.ProfitTimeLeft, (double)this.profitTime); } public void HideCommercialTimerProgress() { if (this._showingCommercialProgressTimer) { this._showingCommercialProgressTimer = false; base.HideProgressBar(); } } protected override void ProgressTimeChanged() { this._showingCommercialProgressTimer = false; } public override ILocalizedString ReasonWhyCantUpgrade(out ILocalizedString title) { if (this.activatable && !this.Activated) { CIGExpansions reference = this._expansions.reference; if (reference != null) { CIGExpansions.ExpansionBlock blockForIndex = reference.GetBlockForIndex(this.tile.index); if (blockForIndex != null && !blockForIndex.Unlocked) { title = ((!this.Activated) ? Localization.Key("steps_to_complete_to_activate_this_building") : Localization.Key("steps_to_complete_to_be_able_to_upgrade_this_building")); return Localization.Key("buy_expansion_first"); } } } return base.ReasonWhyCantUpgrade(out title); } public override bool InfoRequiresFrequentRefresh { get { if (base.state == BuildingState.Preview || base.state != BuildingState.Normal || base.IsUpgrading || (this.activatable && !this.Activated)) { return base.InfoRequiresFrequentRefresh; } return (!this.checkForRoad || base.CheckForRoad()) && this.HasTimeLeft; } } public override bool CanSpeedup { get { return (base.state == BuildingState.Preview || base.state != BuildingState.Normal || base.IsUpgrading || (this.activatable && !this.Activated)) && base.CanSpeedup; } } public override ILocalizedString InfoText() { ILocalizedString localizedString; if (base.state == BuildingState.Preview) { localizedString = Localization.Concat(new ILocalizedString[] { base.InfoText(), Localization.LiteralNewLineString, Localization.Format(Localization.Key("profit_within"), new ILocalizedString[] { this.baseProfitCurrencies.WithoutXPCurrency().LocalizedString(), Localization.TimeSpan(TimeSpan.FromSeconds((double)this.profitTime), false) }), Localization.LiteralNewLineString, Localization.Key("jobs"), Localization.LiteralSemiColonSpaceString, Localization.Integer(this.maxEmployeesBaseValue), Localization.LiteralNewLineString, Localization.Key("construction_time"), Localization.LiteralSemiColonSpaceString, Localization.TimeSpan(TimeSpan.FromSeconds((double)this.constructionTime), false) }); if (this.maxFacilities > 0) { int num = SingletonMonobehaviour.Instance.NumberOf(base.CachedName); if (this.PurchasePrice.Contains("Cash")) { localizedString = Localization.Concat(new ILocalizedString[] { localizedString, Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_max_facilities"), new ILocalizedString[] { Localization.Integer(this.maxFacilities) }) }); } else if (num > 0) { localizedString = Localization.Concat(new ILocalizedString[] { localizedString, Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_costs_gold_max_facilities"), new ILocalizedString[] { Localization.Integer(num) }) }); } } return localizedString; } if (base.state != BuildingState.Normal || base.IsUpgrading) { return base.InfoText(); } if (this.activatable && !this.Activated) { return Localization.Concat(new ILocalizedString[] { base.InfoText(), Localization.LiteralNewLineString, Localization.Key("profit"), Localization.LiteralSemiColonSpaceString, this.baseProfitCurrencies.WithoutXPCurrency().LocalizedString(), Localization.LiteralNewLineString, Localization.Key("jobs"), Localization.LiteralSemiColonSpaceString, Localization.Integer(this.maxEmployeesBaseValue) }); } if (this.checkForRoad && !base.CheckForRoad()) { return Localization.Key("building_needs_road"); } int p = 0; if (this.MaxEmployees > 0) { p = 100 * this.Employees / this.MaxEmployees; } int num2 = (!this.activatable) ? 0 : -1; localizedString = Localization.Concat(new ILocalizedString[] { Localization.Format(Localization.Key("current_profit"), new ILocalizedString[] { this.Profit.WithoutXPCurrency().LocalizedString(), Localization.Percentage(p) }), Localization.LiteralNewLineString, Localization.Format(Localization.Key("current_employees"), new ILocalizedString[] { Localization.Integer(this.Employees), Localization.Integer(this.MaxEmployees) }), Localization.LiteralNewLineString, Localization.Format(Localization.Key("time_until_profit"), new ILocalizedString[] { this.TimeLeftString() }), Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_current_upgrade_level"), new ILocalizedString[] { Localization.Integer(base.CurrentLevel + num2), Localization.Integer(base.GetMaxLevel() + num2) }) }); if (this.CanUpgrade) { localizedString = Localization.Concat(new ILocalizedString[] { localizedString, Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_upgrade_option"), new ILocalizedString[] { Localization.Integer(base.CurrentLevel + 1 + num2), this.UpgradeCost.LocalizedString() }), Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_upgrade_option_commercial"), new ILocalizedString[] { Localization.Integer(this.UpgradeJobs(base.CurrentLevel + 1)), this.UpgradeProfit(base.CurrentLevel + 1).LocalizedString() }) }); } return localizedString; } public override List ShownProperties { get { List shownProperties = base.ShownProperties; shownProperties.Add(BuildingProperty.Profit); shownProperties.Add(BuildingProperty.Employees); shownProperties.Add(BuildingProperty.TimeUntilProfit); return shownProperties; } } public override Currencies PurchasePrice { get { Currencies purchasePrice = base.PurchasePrice; if (purchasePrice.Contains("Cash")) { return purchasePrice * SingletonMonobehaviour.Instance.Multipliers.CommercialBuildingCostCashMultiplier; } return purchasePrice * SingletonMonobehaviour.Instance.Multipliers.CommercialBuildingCostGoldMultiplier; } } public override Currencies UpgradeCost { get { if (this.activatable && !this.Activated) { return base.UpgradeCost; } Currencies result; try { decimal num = this.baseUpgradeCost.GetValue("Cash"); int num2 = (!this.activatable) ? 0 : -1; num *= this._upgradeCostFactor[base.CurrentLevel + 1 + num2] * 0.01m; result = new Currencies("Cash", Math.Ceiling(num)); } catch (Exception ex) { throw new Exception(string.Format("[{0}|{2}]: {1}", base.name, ex.Message, this.stringReference), ex); } return result; } } protected virtual bool HasTimeLeft { get { return this._waitForProfitRoutine != null; } } public virtual ILocalizedString TimeLeftString() { if (this._waitForProfitRoutine == null) { return Localization.TimeSpan(TimeSpan.Zero, false); } return Localization.TimeSpan(TimeSpan.FromSeconds(Scheduler.TimeLeft(this._waitForProfitRoutine)), false); } private bool UpdateEmployees() { int globalEmployees = base.GameState.GlobalEmployees; int num = this.Employees; if (this.checkForRoad && !base.CheckForRoad()) { num--; } else if (base.IslandState.AvailablePopulation < globalEmployees) { num--; } else if (base.IslandState.AvailablePopulation > globalEmployees) { num++; } num = Math.Max(0, Math.Min(num, this.MaxEmployees)); if (num != this.Employees) { this.Employees = num; this.serializing.Serialize(); return true; } return false; } protected virtual void CollectProfit(Currencies profit, bool maxed) { profit = profit.Round(); base.GameState.EarnCurrencies(profit, this._currencyAnimationObject); base.GameStats.AddCashCollected(profit); if (SingletonMonobehaviour.Instance != null && SingletonMonobehaviour.Instance.AreNotificationsAllowed) { SingletonMonobehaviour.Instance.RequestPermissions(); } Bounds bounds = this._renderer.bounds; bounds.center = new Vector3(bounds.center.x, this._renderer.bounds.max.y, bounds.center.z); decimal value; PlingType plingType; if (profit.ContainsPositive("Gold")) { value = profit.GetValue("Gold"); plingType = PlingType.Gold; } else if (maxed) { value = profit.GetValue("Cash"); plingType = PlingType.Cash_Green; } else { value = profit.GetValue("Cash"); plingType = PlingType.Cash_Red; } Pling pling = this._plingManager.Show(plingType, Vector3.zero, Clip.Ping); if (plingType == PlingType.Cash_Green || plingType == PlingType.Cash_Red) { pling.ShowWithParticles(Localization.Integer(value), ParticleType.CashFountain); } else { pling.Show(Localization.Integer(value)); } decimal xpValue = profit.GetValue("XP"); if (xpValue > 0m && !SingletonMonobehaviour.Instance.ReachedMaxLevel) { XPBoostReward xpboostReward = Singleton.Instance.FindActiveReward((IOngoingReward reward) => reward is XPBoostReward) as XPBoostReward; if (xpboostReward != null) { decimal additionalValue = (decimal)xpboostReward.BoostPercentage * 0.01m * xpValue; base.GameState.EarnCurrencies(new Currencies("XP", additionalValue), this._currencyAnimationObject); this._delayedPlingEnumerator = SingletonMonobehaviour.Instance.ExecuteDelayed(delegate { Pling pling2 = this._plingManager.Show(PlingType.XP, 0.9f * Vector3.down * 50f); pling2.Show(Localization.Integer(additionalValue)); this._delayedPlingEnumerator = null; }, 0.06f); } else { this._delayedPlingEnumerator = SingletonMonobehaviour.Instance.ExecuteDelayed(delegate { Pling pling2 = this._plingManager.Show(PlingType.XP, 0.9f * Vector3.down * 50f); pling2.Show(Localization.Integer(xpValue)); this._delayedPlingEnumerator = null; }, 0.06f); } } } protected virtual IEnumerator WaitForProfit() { if (this.storedProfitTimeLeft < 0.0) { yield return Timing.time + (double)this.profitTime; } else { double t = Timing.time + this.storedProfitTimeLeft; this.storedProfitTimeLeft = -1.0; yield return t; } yield break; } private IEnumerator WaitForClick() { for (; ; ) { yield return Timing.time + 60.0; } yield break; } private IEnumerator ProfitLoopBehaviour() { if (this.profitTime <= 0) { UnityEngine.Debug.LogWarning(string.Format("{1}: profitTime({0}) should not be <= 0", this.profitTime, base.name)); yield break; } for (; ; ) { yield return this._waitForProfitRoutine = this.WaitForProfit(); this._waitForProfitRoutine = null; Currencies profit = this.Profit; bool maxed = profit.MissingCurrencies(this.currentProfit).IsEmpty(); if (!profit.IsEmpty()) { this.ShowProfitIcon(maxed); yield return this._clickRoutine = this.WaitForClick(); this._clickRoutine = null; this.HideProfitIcon(); this.CollectProfit(profit, maxed); this.serializing.Serialize(); } } yield break; } private IEnumerator ProfitBehaviour() { yield return this._profitLoopRoutine = this.ProfitLoopBehaviour(); this._profitLoopRoutine = null; this.HideProfitIcon(); yield break; } private IEnumerator EmployeesBehaviour() { bool changed = true; for (; ; ) { yield return Timing.time + ((!changed) ? this.EmployeeUnchangedUpdateWaitTime : this.EmployeeChangedUpdateWaitTime); changed = this.UpdateEmployees(); } yield break; } protected virtual void OnEmployeesChanged() { this.UpdateNoEmployeesIcon(); } protected void ClickProfitIcon(GameObject target) { if (this._clickRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._clickRoutine); this._clickRoutine = null; } } protected override void OnConstructionCompleted() { base.OnConstructionCompleted(); if (!this.activatable) { this.MaxEmployees = this.maxEmployeesBaseValue; this.currentProfit = this.baseProfitCurrencies; this.StartRoutines(); this.UpdateNoEmployeesIcon(); SingletonMonobehaviour.Instance.AddGlobalProfitPerHour(this.ProfitPerHour); } } protected override void OnSerialize(Dictionary values) { base.OnSerialize(values); values["maxEmployees"] = this.currentMaxEmployees; values["employees"] = this.currentEmployees; values["profit"] = this.currentProfit; if (this._maxEmployeesWhenDemolishStarted != 0) { values["maxEmployeesWhenDemolishStarted"] = this._maxEmployeesWhenDemolishStarted; } if (this._clickRoutine != null) { values["profitTimestamp"] = Timing.UtcNow; } else if (this._waitForProfitRoutine != null) { values["profitTimestamp"] = Timing.UtcNow + Scheduler.TimeLeft(this._waitForProfitRoutine); } else if (base.IsUpgrading) { values["profitTimestamp"] = Timing.UtcNow + base.UpgradeTimeLeft + 1.0 + (double)this.profitTime; } else if (base.state == BuildingState.Normal) { values["profitTimestamp"] = Timing.UtcNow + (double)this.profitTime; } else if (values.ContainsKey("profitTimestamp")) { values.Remove("profitTimestamp"); } } protected override void OnDeserialize(Dictionary values) { base.OnDeserialize(values); if (values.ContainsKey("maxEmployees")) { this.currentMaxEmployees = (int)values["maxEmployees"]; } if (values.ContainsKey("maxEmployeesWhenDemolishStarted")) { this._maxEmployeesWhenDemolishStarted = (int)values["maxEmployeesWhenDemolishStarted"]; } if (values.ContainsKey("employees")) { this.currentEmployees = (int)values["employees"]; } if (values.ContainsKey("profit")) { this.currentProfit = (Currencies)values["profit"]; } if (values.ContainsKey("profitTimestamp")) { this.storedProfitTimeLeft = Math.Max(0.0, (double)values["profitTimestamp"] - Timing.UtcNow); } else { this.storedProfitTimeLeft = -1.0; } } protected override void OnDeserialized() { base.OnDeserialized(); if (base.state == BuildingState.Normal) { this.UpdateNoEmployeesIcon(); if (base.IsUpgrading) { SingletonMonobehaviour.Instance.StartRoutine(this._employeesRoutine = this.EmployeesBehaviour(), base.gameObject); } else { this.StartRoutines(); } } } protected override void OnUpgradeStarted() { base.OnUpgradeStarted(); if (this._profitRoutine != null) { this.StopProfitRoutine(); this.HideProfitIcon(); } } protected override void OnUpgradeCompleted(double upgradedTime) { base.OnUpgradeCompleted(upgradedTime); if (this.activatable && base.CurrentLevel == 1) { this.MaxEmployees = this.maxEmployeesBaseValue; this.currentProfit = this.baseProfitCurrencies; this.StartRoutines(); this.UpdateNoEmployeesIcon(); SingletonMonobehaviour.Instance.AddGlobalProfitPerHour(this.ProfitPerHour); } else { this.MaxEmployees += this.UpgradeJobs(base.CurrentLevel); Currencies currencies = this.UpgradeProfit(base.CurrentLevel); this.currentProfit += currencies; SingletonMonobehaviour.Instance.AddGlobalProfitPerHour(3600m * currencies / this.profitTime); if (this._profitLoopRoutine != null) { UnityEngine.Debug.LogWarning(string.Format("{0}: profitLoopRoutine is not null OnUpgradeCompleted", base.name)); } this.storedProfitTimeLeft = Math.Max(0.0, (double)this.profitTime - (Timing.time - upgradedTime)); SingletonMonobehaviour.Instance.StartRoutine(this._profitRoutine = this.ProfitBehaviour(), base.gameObject); } } protected override void OnDemolishStarted() { base.OnDemolishStarted(); SingletonMonobehaviour.Instance.AddGlobalProfitPerHour(-this.ProfitPerHour); this.StopRoutines(); this.Employees = 0; this._maxEmployeesWhenDemolishStarted = this.MaxEmployees; this.MaxEmployees = 0; } protected override void OnDemolishCancelled() { base.OnDemolishCancelled(); SingletonMonobehaviour.Instance.AddGlobalProfitPerHour(this.ProfitPerHour); this.MaxEmployees = this._maxEmployeesWhenDemolishStarted; this._maxEmployeesWhenDemolishStarted = 0; this.StartRoutines(); } protected override void ClickHandler(GameObject target) { if (this._clickRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._clickRoutine); this._clickRoutine = null; } else { base.ClickHandler(target); } } private void StartRoutines() { SingletonMonobehaviour.Instance.StartRoutine(this._profitRoutine = this.ProfitBehaviour(), base.gameObject); SingletonMonobehaviour.Instance.StartRoutine(this._employeesRoutine = this.EmployeesBehaviour(), base.gameObject); } private void StopRoutines() { this.StopProfitRoutine(); if (this._employeesRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._employeesRoutine); this._employeesRoutine = null; } } private void StopProfitRoutine() { if (this._profitRoutine != null) { SingletonMonobehaviour.Instance.StopRoutine(this._profitRoutine); this._profitRoutine = null; this._profitLoopRoutine = null; this._waitForProfitRoutine = null; this._clickRoutine = null; } } private double EmployeeUnchangedUpdateWaitTime { get { return (double)UnityEngine.Random.Range(2f, 30f); } } private double EmployeeChangedUpdateWaitTime { get { return (double)UnityEngine.Random.Range(1f, 3f); } } protected virtual void ShowProfitIcon(bool maxed) { GridTileIconType icon = (!maxed) ? GridTileIconType.LowProfit : GridTileIconType.Profit; ButtonGridTileIcon buttonGridTileIcon = this._gridTileIconManager.SetIcon(icon); buttonGridTileIcon.Init(delegate { this.ClickProfitIcon(base.gameObject); }); } protected void HideProfitIcon() { this._gridTileIconManager.RemoveIcon(GridTileIconType.Profit); this._gridTileIconManager.RemoveIcon(GridTileIconType.LowProfit); this._gridTileIconManager.RemoveIcon(GridTileIconType.GoldProfit); } public int UpgradeJobs(int toLevel) { if (this.activatable && base.CurrentLevel == 0 && toLevel == 1) { return this.maxEmployeesBaseValue; } if (base.GetMaxLevel() != 0) { int val = Math.Max(0, toLevel - base.CurrentLevel); return Math.Max(val, this.maxEmployeesBaseValue + toLevel * this.maxEmployeesBaseValue / 10 - this.currentMaxEmployees); } return 0; } public override int UpgradeTime { get { if (this.activatable && !this.Activated) { return base.UpgradeTime; } int num = this.constructionTime; if (this.activatable) { num = this.activationTime; } return this._upgradeTimeFactor[base.CurrentLevel + 1 + ((!this.activatable) ? 0 : -1)] * num / 100; } } public Currencies UpgradeProfit(int toLevel) { if (this.activatable && base.CurrentLevel == 0 && toLevel == 1) { return this.baseProfitCurrencies; } if (this.activatable) { toLevel--; } if (base.GetMaxLevel() != 0 && toLevel >= 0 && toLevel < this._upgradeProfitFactor.Length) { return this.baseProfitCurrencies.WithoutXPCurrency() + (this._upgradeProfitFactor[toLevel] * this.baseProfitCurrencies.WithoutXPCurrency() / 100m).Round(Currencies.RoundingMethod.Floor) - this.currentProfit.WithoutXPCurrency(); } return new Currencies(); } public void FixProfit() { Currencies currencies = this.UpgradeProfit(base.CurrentLevel); if (currencies.ContainsPositive("Cash")) { this.currentProfit += currencies; if (this.serializing != null) { this.serializing.Serialize(); } } } private void UpdateNoEmployeesIcon() { if (this.Employees == 0) { ButtonGridTileIcon buttonGridTileIcon = this._gridTileIconManager.SetIcon(GridTileIconType.NoEmployees); buttonGridTileIcon.Init(delegate { this.ClickHandler(base.gameObject); }); } else { this._gridTileIconManager.RemoveIcon(GridTileIconType.NoEmployees); } } public int profitTime; public Currencies baseProfitCurrencies; public int maxEmployeesBaseValue; private int currentEmployees; private int currentMaxEmployees; private int _maxEmployeesWhenDemolishStarted; private Currencies currentProfit = new Currencies(); private double storedProfitTimeLeft = -1.0; private MagicalReference _expansions = new MagicalReference(); private bool _showingCommercialProgressTimer; private IEnumerator _delayedPlingEnumerator; private readonly int[] _upgradeCostFactor = new int[] { 100, 30, 38, 48, 60, 75, 94, 118, 148, 185, 231, 277, 346, 433, 541, 676, 845, 1056, 1320, 1650, 2063 }; private IEnumerator _waitForProfitRoutine; private IEnumerator _clickRoutine; private IEnumerator _profitLoopRoutine; private IEnumerator _profitRoutine; private IEnumerator _employeesRoutine; private readonly int[] _upgradeTimeFactor = new int[] { 100, 25, 33, 43, 56, 73, 95, 124, 161, 209, 272, 354, 460, 598, 777, 1010, 1313, 1707, 2219, 2885, 3751 }; private readonly int[] _upgradeProfitFactor = new int[] { 0, 10, 21, 33, 46, 61, 77, 95, 115, 137, 161, 187, 216, 248, 283, 321, 363, 409, 460, 516, 578 }; }