using CIG.Translation; using CIGEnums; using SUISS.Core; using SUISSEngine; using System; using System.Collections.Generic; using UnityEngine; public abstract class CIGBuilding : HappinessBuilding { public const string FreeBuildingTypeKey = "building_name"; private const int TutorialOverrideConstructionTime = 5; public Currencies constructionXP; public int[] unlockLevels; public int maxFacilities; public int buildMenuOrdering; public int strictMax = -1; public Island island; public GameObject upgradeSignPrefab; public Currencies baseUpgradeCost; public Vehicle.VehicleType spawnsVehicleType = Vehicle.VehicleType.None; private OverlayButtons _overlayButtons; private OverlayTitle _overlayTitle; [SelfReference(true)] public Animator animator; [ChildReference(true)] public Animator bottomAnimator; private readonly int[] _upgradeTimeFactor = new int[21] { 100, 25, 33, 43, 56, 73, 95, 124, 161, 209, 272, 326, 391, 469, 563, 676, 811, 973, 1168, 1402, 1682 }; private CIGIslandState _islandState; private static bool errorSent; private CIGGameState _gameState; private CIGGameStats _gameStats; protected CIGGameConstants constants; protected GameObject prefab; protected GameObject _upgradeSign; public override Currencies PurchasePrice { get { IOngoingReward ongoingReward = Singleton.Instance.FindActiveReward((IOngoingReward reward) => reward is FreeBuildingReward && ((FreeBuildingReward)reward).BuildingName == base.name); if ((ongoingReward != null && ongoingReward.IsActive) || SingletonMonobehaviour.Instance.IsUnconsumed(this)) { return new Currencies("Gold", 0.0m); } if (constants == null) { constants = SingletonMonobehaviour.Instance; } Currencies currencies = base.PurchasePrice; if (unlockLevels.Length == 0) { return currencies; } int num = GameStats.CashCount(base.name); int num2 = GameStats.NumberOf(base.name); int b = num2 - num; if (!currencies.ContainsPositive("Gold")) { int num3 = Array.BinarySearch(unlockLevels, GameState.Level); int num4 = num3 + 1; if (num3 < 0) { num4 = ~num3; } if (num >= num4) { currencies = new Currencies("Gold", goldCostAtMax); } } if (currencies.ContainsPositive("Gold")) { decimal value = ConstructionCostGoldPenalty * (decimal)Mathf.Max(0, b); currencies += new Currencies("Gold", value); } return currencies; } } public override bool IsUnlocked { get { if (!base.IsUnlocked) { return false; } if (unlockLevels.Length > 0) { return unlockLevels[0] <= GameState.Level; } return true; } } public int NextUnlockLevel { get { if (!IsUnlocked) { return unlockLevels[0]; } int num = Array.BinarySearch(unlockLevels, GameState.Level); num = ((num >= 0) ? (num + 1) : (~num)); if (num < unlockLevels.Length) { return unlockLevels[num]; } return int.MaxValue; } } public override Currencies UpgradeCost { get { if (activatable && !Activated) { return base.UpgradeCost; } decimal value = baseUpgradeCost.GetValue("Cash"); value *= (decimal)base.CurrentLevel + 1m; value /= (decimal)GetMaxLevel(); value = Math.Ceiling(value); return new Currencies("Cash", value); } } public override int UpgradeTime { get { if (activatable && !Activated) { return base.UpgradeTime; } int num = constructionTime; if (activatable) { num = activationTime; } int num2 = activatable ? (-1) : 0; return _upgradeTimeFactor[base.CurrentLevel + 1 + num2] * num / 100; } } public virtual decimal SpeedupCostCash { get { long seconds = Math.Max(60L, GetSecondsLeft()); return GetSpeedupCostCashForSeconds(seconds); } } public virtual decimal SpeedupCostGold { get { long secondsLeft = GetSecondsLeft(); return GetSpeedupCostGoldForSeconds(secondsLeft); } } public virtual Currencies SpeedupProfit => Currencies.Zero; public GameObject Prefab { get { if (prefab == null) { prefab = base.gameObject; } return prefab; } } protected CIGIslandState IslandState { get { if (_islandState == null) { _islandState = GetComponentInParent(); } return _islandState; } } protected virtual decimal ConstructionCostGoldPenalty => SingletonMonobehaviour.Instance.ConstructionCostGoldPenalty; public override List ShownProperties { get { List shownProperties = base.ShownProperties; if (base.state == BuildingState.Preview && constructionXP.ContainsPositive("XP")) { shownProperties.Add(BuildingProperty.ConstructionXp); } return shownProperties; } } public override bool InfoRequiresFrequentRefresh { get { if (base.IsUpgrading || base.state == BuildingState.Constructing || base.state == BuildingState.Demolishing) { return true; } if ((activatable && !Activated) || base.state == BuildingState.Preview) { return false; } return base.InfoRequiresFrequentRefresh; } } public override bool CanSpeedup { get { if (base.IsUpgrading || base.state == BuildingState.Constructing || base.state == BuildingState.Demolishing) { return true; } if ((activatable && !Activated) || base.state == BuildingState.Preview) { return false; } return base.CanSpeedup; } } public override int Happiness { get { return base.Happiness; } protected set { int num = value - base.Happiness; base.Happiness = value; if (num != 0) { IslandState.AddHappiness(num); } } } protected virtual bool UseGreyShader => activatable && base.CurrentLevel == 0; protected CIGGameStats GameStats { get { if (_gameStats == null) { _gameStats = SingletonMonobehaviour.Instance; } return _gameStats; } } protected CIGGameState GameState { get { if (_gameState == null) { _gameState = SingletonMonobehaviour.Instance; } return _gameState; } } protected void OnEnable() { GameEvents.Subscribe(OnUnemiShouldCloseEvent); } protected void OnDisable() { GameEvents.Unsubscribe(OnUnemiShouldCloseEvent); } public override int UpgradeHappiness(int toLevel) { if (GetMaxLevel() != 0) { int num = Math.Max(0, toLevel - base.CurrentLevel); int val = baseHappinessValue + toLevel * baseHappinessValue / 10 - Happiness; if (baseHappinessValue < 0) { return Math.Min(-num, val); } return Math.Max(num, val); } return 0; } public long GetSecondsLeft() { if (base.state == BuildingState.Constructing) { return 1 + (long)base.ConstructionTimeLeft; } if (base.IsUpgrading) { return 1 + (long)base.UpgradeTimeLeft; } if (base.state == BuildingState.Demolishing) { return 1 + (long)base.DemolishTimeLeft; } if (base.state == BuildingState.WaitingForDemolishing) { return demolishTime; } return 0L; } public static Currencies GetImmediateConstructionCost(GameObject prefab) { CIGBuilding component = prefab.GetComponent(); if (component == null) { throw new ArgumentException($"Prefab {prefab.name} does not contain CIGBuilding component."); } Currencies currencies = component.PurchasePrice; if (!currencies.ContainsPositive("Gold")) { currencies = new Currencies("Gold", component.goldCostAtMax); } return (currencies + new Currencies("Gold", 2m + GetSpeedupCostGoldForSeconds(component.constructionTime))).Round(); } public static decimal GetSpeedupCostGoldForSeconds(long seconds) { decimal d = Math.Ceiling((decimal)seconds / 60m); if (d <= 15m) { return 1m; } return Math.Floor((1m + d / 50m) * SingletonMonobehaviour.Instance.Multipliers.UpspeedCostGoldMultiplier); } public static decimal GetSpeedupCostCashForSeconds(long seconds) { CIGGameStats instance = SingletonMonobehaviour.Instance; CIGGameConstants instance2 = SingletonMonobehaviour.Instance; decimal d = Math.Max(10000m, instance.GlobalProfitPerHour.GetValue("Cash")); return Math.Max(instance2.minimumSpeedupCostCash, Math.Ceiling(instance2.factorForSpeedupCostCash * d * (decimal)seconds / 3600m / instance2.speedupCashCostFactor * SingletonMonobehaviour.Instance.Multipliers.UpspeedCostCashMultiplier)); } private void OnUnemiShouldCloseEvent(UnemiShouldCloseEvent e) { RemoveButtonsAndTitle(); } protected override void ClickHandler(GameObject target) { base.ClickHandler(target); if (activatable && !Activated && !base.IsUpgrading) { SingletonMonobehaviour.Instance.RequestFirstPopup(delegate (State state) { ((BuildingInfoPopupState)state).SetBuildingAndContent(this, BuildingPopupContent.Activate); }); } else if (base.state != BuildingState.Demolishing && base.state != BuildingState.WaitingForDemolishing) { ToggleButtonsAndTitle(); } } private void ToggleButtonsAndTitle() { if (CanSpeedup) { RemoveButtonsAndTitle(); SingletonMonobehaviour.Instance.RequestFirstPopup(delegate (State state) { ((BuildingSpeedupPopupState)state).SetBuilding(this); }); } else if (_overlayTitle == null && _overlayButtons == null) { GameEvents.Invoke(new UnemiShouldCloseEvent(this)); _overlayTitle = OverlayTitle.Get(this); _overlayTitle.ShowOpenAnimation(); ILocalizedString subtitleText = Localization.EmptyLocalizedString; if (CanUpgrade || DisplayLevel > 1) { subtitleText = Localization.Format("{0} {1}", Localization.Key("level"), Localization.Integer(DisplayLevel)); } SingletonMonobehaviour.Instance.PlayClip(Clip.ButtonClick); _overlayTitle.Initialize(base.LocalName, subtitleText); _overlayButtons = OverlayButtons.Get(this); _overlayButtons.ShowOpenAnimation(); _overlayButtons.DisableAllButtons(); if (base.state != BuildingState.Normal) { return; } if (ShownProperties.Count > 0) { _overlayButtons.InfoButton.EnableButton(InfoAction); } if (!base.IsUpgrading) { if (movable && Activated) { _overlayButtons.MoveButton.EnableButton(MoveBuildingAction); } if (CanUpgrade) { _overlayButtons.UpgradeButton.EnableButton(UpgradeAction); } } } else { RemoveButtonsAndTitle(); } } private void InfoAction() { SingletonMonobehaviour.Instance.RequestFirstPopup(delegate (State state) { ((BuildingInfoPopupState)state).SetBuildingAndContent(this, BuildingPopupContent.Info); }); } private void MoveBuildingAction() { CityIsland.Current.StartMoving(base.gameObject); } private void UpgradeAction() { BuildingPopupContent content = BuildingPopupContent.Upgrade; if (activatable && !Activated) { content = BuildingPopupContent.Activate; } SingletonMonobehaviour.Instance.RequestFirstPopup(delegate (State state) { ((BuildingInfoPopupState)state).SetBuildingAndContent(this, content); }); } protected void RemoveButtonsAndTitle() { if ((bool)_overlayButtons) { OverlayButtons overlayButtonsTemp = _overlayButtons; overlayButtonsTemp.ShowCloseAnimation(delegate { UnityEngine.Object.Destroy(overlayButtonsTemp.gameObject); }); _overlayButtons = null; } if ((bool)_overlayTitle) { OverlayTitle overlayTitleTemp = _overlayTitle; overlayTitleTemp.ShowCloseAnimation(delegate { UnityEngine.Object.Destroy(overlayTitleTemp.gameObject); }); _overlayTitle = null; } } protected override void OnConstructionStarted() { CIGTutorialManager instanceIfAvailable = SingletonMonobehaviour.InstanceIfAvailable; if (instanceIfAvailable != null && instanceIfAvailable.ShouldOverrideBuildingConstructionTime(this)) { constructionTime = 5; } base.OnConstructionStarted(); IOngoingReward ongoingReward = Singleton.Instance.FindActiveReward((IOngoingReward reward) => reward is FreeBuildingReward && ((FreeBuildingReward)reward).BuildingName == base.name); if (ongoingReward != null && ongoingReward.IsActive) { ((FreeBuildingReward)ongoingReward).Claim(); } if (activatable) { return; } if (constructionXP.ContainsPositive("XP")) { GameState.EarnCurrencies(constructionXP, _currencyAnimationObject); Pling pling = _plingManager.Show(PlingType.XP, Vector3.zero, Clip.Ping); pling.Show(Localization.Integer(constructionXP.GetValue("XP"))); } if (tile.gridSizeU * tile.gridSizeV > 1) { GameStats.AddGlobalBuildingsBuilt(1); if (initialPurchasePrice.ContainsPositive("Gold")) { GameStats.AddGoldBuilding(); } } } protected override void OnConstructionCompleted() { base.OnConstructionCompleted(); HideMovingArrow(); CheckUpgradePossible(); CIGVehicleManager cIGVehicleManager = UnityEngine.Object.FindObjectOfType(); if (cIGVehicleManager != null) { cIGVehicleManager.BuildingStateChanged(tile); } } protected override void OnDemolishStarted() { base.OnDemolishStarted(); CIGVehicleManager cIGVehicleManager = UnityEngine.Object.FindObjectOfType(); if (cIGVehicleManager != null) { cIGVehicleManager.BuildingStateChanged(tile); } } protected override void OnDemolishCancelled() { base.OnDemolishCancelled(); CIGVehicleManager cIGVehicleManager = UnityEngine.Object.FindObjectOfType(); if (cIGVehicleManager != null) { cIGVehicleManager.BuildingStateChanged(tile); } } public override ILocalizedString InfoText() { if (base.IsUpgrading) { double upgradeTimeLeft = base.UpgradeTimeLeft; int num = activatable ? (-1) : 0; return Localization.Concat(Localization.Format(Localization.Key("upgrading_to_level"), Localization.Integer(base.CurrentLevel + 1 + num)), Localization.LiteralNewLineString, Localization.Format(Localization.Key("upgrade_time_left"), Localization.TimeSpan(TimeSpan.FromSeconds(upgradeTimeLeft), hideSecondPartWhenZero: false)), Localization.LiteralDoubleNewLineString, Localization.Format(Localization.Key("building_speedup"), Localization.Integer(SpeedupCostGold), Localization.Integer(SpeedupCostCash))); } if (base.state == BuildingState.Constructing) { double constructionTimeLeft = base.ConstructionTimeLeft; return Localization.Concat(Localization.Format(Localization.Key("construction_time_left"), Localization.TimeSpan(TimeSpan.FromSeconds(constructionTimeLeft), hideSecondPartWhenZero: false)), Localization.LiteralDoubleNewLineString, Localization.Format(Localization.Key("building_speedup"), Localization.Integer(SpeedupCostGold), Localization.Integer(SpeedupCostCash))); } if (base.state == BuildingState.Demolishing) { double demolishTimeLeft = base.DemolishTimeLeft; return Localization.Concat(Localization.Format(Localization.Key("destroy_time_left"), Localization.TimeSpan(TimeSpan.FromSeconds(demolishTimeLeft), hideSecondPartWhenZero: false)), Localization.LiteralDoubleNewLineString, Localization.Format(Localization.Key("building_speedup"), Localization.Integer(SpeedupCostGold), Localization.Integer(SpeedupCostCash))); } if ((activatable && !Activated) || base.state == BuildingState.Preview) { ILocalizedString localizedString = Localization.EmptyLocalizedString; if (tile != null) { int requiredGridType = tile.requiredGridType; if (requiredGridType > 0 && requiredGridType < 10) { SurfaceType surfaceType = (SurfaceType)requiredGridType; string key = "surfacetype_" + surfaceType.ToString().ToLower().Replace("driedswamp", "swamp"); localizedString = Localization.Concat(Localization.Format(Localization.Key("must_be_built_on"), Localization.Key(key)), Localization.LiteralNewLineString); } } localizedString = ((!activatable) ? Localization.Concat(localizedString, Localization.Key("construction_time"), Localization.LiteralSemiColonSpaceString, Localization.TimeSpan(TimeSpan.FromSeconds(constructionTime), hideSecondPartWhenZero: false), Localization.LiteralNewLineString) : Localization.Concat(localizedString, Localization.Format(Localization.Key("activation_cost"), UpgradeCost.LocalizedString(), Localization.Integer(activationTime)), Localization.LiteralNewLineString)); if (!activatable && maxFacilities > 0) { int num2 = SingletonMonobehaviour.Instance.NumberOf(base.CachedName); if (PurchasePrice.Contains("Cash")) { localizedString = Localization.Concat(localizedString, Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_max_facilities"), Localization.Integer(maxFacilities))); } else if (num2 > 0) { localizedString = Localization.Concat(localizedString, Localization.LiteralNewLineString, Localization.Format(Localization.Key("building_costs_gold_max_facilities"), Localization.Integer(num2))); } } if (base.state == BuildingState.Preview && tile != null) { localizedString = Localization.Concat(localizedString, Localization.LiteralNewLineString, Localization.Key("size"), Localization.LiteralSemiColonSpaceString, Localization.Integer(tile.gridSizeU), Localization.Literal("x"), Localization.Integer(tile.gridSizeV)); localizedString = Localization.Concat(localizedString, Localization.LiteralNewLineString, Localization.Key("size"), Localization.LiteralSemiColonSpaceString, Localization.Integer(tile.gridSizeU), Localization.Literal("x"), Localization.Integer(tile.gridSizeV)); } if (constructionXP.ContainsPositive("XP")) { localizedString = Localization.Concat(localizedString, Localization.LiteralNewLineString, Localization.Key("experience"), Localization.Literal(": "), constructionXP.LocalizedString()); } return localizedString; } return base.InfoText(); } public override bool StartUpgrade() { Currencies cost = UpgradeCost; decimal extraCost = 0m; if (CanUpgrade) { Action action = delegate { cost += new Currencies("Gold", extraCost); GameState.SpendCurrencies(cost, true, delegate (bool succes, Currencies spent) { if (succes) { base.StartUpgrade(); } }); }; if (SingletonMonobehaviour.Instance.CurrentBuildCount < SingletonMonobehaviour.Instance.MaxBuildCount) { action(); return true; } extraCost = 1m; Currencies extraCost2 = new Currencies("Gold", extraCost); SingletonMonobehaviour.Instance.ShowTooMuchParallelBuildsPopup(action, null, extraCost2); return false; } return false; } protected override void OnUpgradeStarted() { if (activatable && !Activated) { if (constructionXP.ContainsPositive("XP")) { GameState.EarnCurrencies(constructionXP, _currencyAnimationObject); Pling pling = _plingManager.Show(PlingType.XP, Vector3.zero, Clip.Ping); pling.Show(Localization.Integer(constructionXP.GetValue("XP"))); } } else { GameStats.AddNumberOfUpgrades(1); } base.OnUpgradeStarted(); CheckUpgradePossible(); } protected override void OnUpgradeCompleted(double upgradedTime) { base.OnUpgradeCompleted(upgradedTime); if (base.CurrentLevel == 10) { GameStats.AddNumberOfLevel10Upgrades(1); } if (base.CurrentLevel == GetMaxLevel() && GetMaxLevel() > 1) { GameStats.GetCurrentIslandStats().MaxLevelBuildingCount++; } if (activatable && base.CurrentLevel == 1) { SetGreyShader(UseGreyShader); } CheckUpgradePossible(); } private void SetGreyShader(bool enabled) { Material material; if (enabled) { material = new Material(Shader.Find("Sprites/Greyscale")); if (animator != null) { animator.enabled = false; } if (bottomAnimator != null) { bottomAnimator.enabled = false; } } else { material = new Material(Shader.Find("Sprites/Default")); if (animator != null) { animator.enabled = true; } if (bottomAnimator != null) { bottomAnimator.enabled = true; } } tile.spriteRenderer.material = material; if (tile.bottomRenderer != null) { tile.bottomRenderer.material = material; } } protected void ShowUpgradeSign() { if (_upgradeSign == null) { if (upgradeSignPrefab == null) { if (!errorSent) { string arg = (!(this != null)) ? "(null)" : base.name; UnityEngine.Debug.LogError($"Building {arg} has no upgradeSignPrefab"); errorSent = true; } return; } _upgradeSign = UnityEngine.Object.Instantiate(upgradeSignPrefab); _upgradeSign.transform.parent = base.transform; tile.DidUpdateTransformEvent += DidUpdateTileTransform; } _upgradeSign.SetActive(value: true); _upgradeSign.transform.localPosition = Vector3.zero; SpriteRenderer component = _upgradeSign.GetComponent(); if (component != null) { component.sortingOrder = tile.spriteRenderer.sortingOrder + 1; } } protected void HideUpgradeSign() { if (_upgradeSign != null) { _upgradeSign.SetActive(value: false); } } protected void DidUpdateTileTransform(GridTile tile) { if (_upgradeSign != null) { SpriteRenderer component = _upgradeSign.GetComponent(); if (component != null) { component.sortingOrder = tile.spriteRenderer.sortingOrder + 1; } } } protected void OnGameStateValueChanged(string key, object oldValue, object newValue) { if (key == "EarnedBalance" || key == "GiftedBalance") { CheckUpgradePossible(); } } protected void CheckUpgradePossible() { if (!SingletonMonobehaviour.IsAvailable || GameState.Level < 10) { HideUpgradeSign(); return; } bool flag = false; if (base.state == BuildingState.Normal && (!activatable || Activated) && base.CurrentLevel < GetMaxLevel() && !base.IsUpgrading && CanUpgrade) { decimal value = GameState.Balance.GetValue("Cash"); decimal value2 = UpgradeCost.GetValue("Cash"); flag = (value2 <= value); } if (flag) { ShowUpgradeSign(); } else { HideUpgradeSign(); } } public void ShowMovingArrow() { _gridTileIconManager.SetIcon(GridTileIconType.MovingArrow); } public void HideMovingArrow() { _gridTileIconManager.RemoveIcon(GridTileIconType.MovingArrow); } protected override void Awake() { base.Awake(); constants = SingletonMonobehaviour.Instance; GameState.ValueChangedEvent += OnGameStateValueChanged; } protected override void OnDestroy() { base.OnDestroy(); if (SingletonMonobehaviour.IsAvailable) { GameState.ValueChangedEvent -= OnGameStateValueChanged; } } protected override void OnGridTileStatusChanged(GridTile.Status oldStatus) { base.OnGridTileStatusChanged(oldStatus); if (tile.status == GridTile.Status.Moving || tile.status == GridTile.Status.Preview) { ShowMovingArrow(); } else if (oldStatus == GridTile.Status.Moving || oldStatus == GridTile.Status.Preview) { HideMovingArrow(); } } protected override void OnDeserialized() { base.OnDeserialized(); if (UseGreyShader) { SetGreyShader(enabled: true); } CheckUpgradePossible(); } }