You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

291 lines
8.6 KiB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using CIG;
  6. using CIG.Translation;
  7. using CIGEnums;
  8. using SUISS.Core;
  9. using SUISS.Core.Utilities;
  10. using SUISSEngine;
  11. using UnityEngine;
  12. [RequireComponent(typeof(Serializing))]
  13. public sealed class CIGBuyOneBuildingGetOneFreeManager : SingletonMonobehaviour<CIGBuyOneBuildingGetOneFreeManager>
  14. {
  15. //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  16. public event CIGBuyOneBuildingGetOneFreeManager.StateChangedEventHandler StateChangedEvent;
  17. private void FireStateChangedEvent()
  18. {
  19. if (this.StateChangedEvent != null)
  20. {
  21. this.StateChangedEvent();
  22. }
  23. }
  24. protected override void OnDestroy()
  25. {
  26. this.StopSaleIntervalRoutine();
  27. this.StopTimeOutRoutine();
  28. base.OnDestroy();
  29. }
  30. public void Buy()
  31. {
  32. if (this.State == CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState.Active)
  33. {
  34. SingletonMonobehaviour<PopupManager>.Instance.CloseRecursive(true);
  35. if (SingletonMonobehaviour<CIGGameState>.Instance.SpendCurrencies(this.PaidBuilding.PurchasePrice, false, null))
  36. {
  37. int num = (int)this.PaidBuilding.PurchasePrice.GetValue("Gold");
  38. CIGGameStats instance = SingletonMonobehaviour<CIGGameStats>.Instance;
  39. instance.AddGoldSpent_DiscountedGoldBuildings(num);
  40. instance.AddVirtualCurrencySpent();
  41. SingletonMonobehaviour<CIGPurchasedBuildingsManager>.Instance.AddBuilding(this.PaidBuilding);
  42. SingletonMonobehaviour<CIGPurchasedBuildingsManager>.Instance.AddBuilding(this.FreeBuilding);
  43. CIGBuilding cigbuilding = null;
  44. this.FreeBuilding = cigbuilding;
  45. this.PaidBuilding = cigbuilding;
  46. this.StopTimeOutRoutine();
  47. this.SetStateInactive();
  48. this.StartSaleIntervalRoutine();
  49. SingletonMonobehaviour<PopupManager>.Instance.RequestGenericPopup(UISpriteType.ShopIcon, Localization.Key("reward_congratulations"), Localization.Key("purchased_buildings_in_menu"), Localization.Key("thank_you"), null, null, null, null, true);
  50. }
  51. }
  52. }
  53. public CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState State { get; private set; }
  54. public TimeSpan SaleTimeLeft
  55. {
  56. get
  57. {
  58. DateTime utcNow = DateTime.UtcNow;
  59. if (this._saleEndsAt < utcNow)
  60. {
  61. return TimeSpan.Zero;
  62. }
  63. return this._saleEndsAt - utcNow;
  64. }
  65. }
  66. public CIGBuilding FreeBuilding { get; private set; }
  67. public CIGBuilding PaidBuilding { get; private set; }
  68. private bool FindGoldBuildings(out CIGBuilding paidBuilding, out CIGBuilding freeBuilding)
  69. {
  70. CIGBuilding cigbuilding;
  71. freeBuilding = (cigbuilding = null);
  72. paidBuilding = cigbuilding;
  73. List<CIGBuilding> list = new List<CIGBuilding>();
  74. foreach (CIGBuilding cigbuilding2 in SingletonMonobehaviour<GameObjectManager>.Instance.AllBuildings)
  75. {
  76. if (cigbuilding2.IsUnlocked && !cigbuilding2.activatable && !this.HasReachedBuiltLimit(cigbuilding2) && cigbuilding2.PurchasePrice.ContainsPositive("Gold"))
  77. {
  78. list.Add(cigbuilding2);
  79. }
  80. }
  81. int num = list.Count;
  82. if (num > 1)
  83. {
  84. paidBuilding = list.PickRandom<CIGBuilding>();
  85. list.Remove(paidBuilding);
  86. num--;
  87. list.Sort((CIGBuilding a, CIGBuilding b) => this.GetGoldPrice(a).CompareTo(this.GetGoldPrice(b)));
  88. if (this.GetGoldPrice(list[0]) > this.GetGoldPrice(paidBuilding))
  89. {
  90. freeBuilding = list[0];
  91. }
  92. else
  93. {
  94. for (int j = 0; j < num; j++)
  95. {
  96. if (!(this.GetGoldPrice(list[j]) <= this.GetGoldPrice(paidBuilding)))
  97. {
  98. decimal freeBuildingPurchasePrice = this.GetGoldPrice(freeBuilding);
  99. freeBuilding = list.FindAll((CIGBuilding b) => this.GetGoldPrice(b) == freeBuildingPurchasePrice).PickRandom<CIGBuilding>();
  100. break;
  101. }
  102. freeBuilding = list[j];
  103. }
  104. }
  105. return true;
  106. }
  107. UnityEngine.Debug.LogWarningFormat("Found only {0} available gold buildings which is not enough. Skipping Buy One Building Get One Free sale.", new object[]
  108. {
  109. num
  110. });
  111. return false;
  112. }
  113. private IEnumerator SaleIntervalRoutine()
  114. {
  115. yield return new WaitForSecondsRealtime(480f);
  116. CIGBuilding paid;
  117. CIGBuilding free;
  118. if (UnityEngine.Random.value < 0.25f && this.FindGoldBuildings(out paid, out free))
  119. {
  120. this.PaidBuilding = paid;
  121. this.FreeBuilding = free;
  122. this._saleEndsAt = DateTime.UtcNow.AddSeconds(600.0);
  123. this.SetStateActive();
  124. this._startSaleRoutine = null;
  125. }
  126. yield break;
  127. }
  128. private void StartSaleIntervalRoutine()
  129. {
  130. this.StopSaleIntervalRoutine();
  131. base.StartCoroutine(this._startSaleRoutine = this.SaleIntervalRoutine());
  132. }
  133. private void StopSaleIntervalRoutine()
  134. {
  135. if (this._startSaleRoutine != null)
  136. {
  137. base.StopCoroutine(this._startSaleRoutine);
  138. this._startSaleRoutine = null;
  139. }
  140. }
  141. private IEnumerator SaleTimeout()
  142. {
  143. yield return new WaitForSecondsRealtime((float)(this._saleEndsAt - DateTime.UtcNow).TotalSeconds);
  144. if (this.State == CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState.Active)
  145. {
  146. this.SetStateInactive();
  147. }
  148. this._saleTimeoutRoutine = null;
  149. this.StartSaleIntervalRoutine();
  150. yield break;
  151. }
  152. private void StartTimeoutRoutine()
  153. {
  154. this.StopTimeOutRoutine();
  155. base.StartCoroutine(this._saleTimeoutRoutine = this.SaleTimeout());
  156. }
  157. private void StopTimeOutRoutine()
  158. {
  159. if (this._saleTimeoutRoutine != null)
  160. {
  161. base.StopCoroutine(this._saleTimeoutRoutine);
  162. this._saleTimeoutRoutine = null;
  163. }
  164. }
  165. private void SetStateActive()
  166. {
  167. this.State = CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState.Active;
  168. this.StartTimeoutRoutine();
  169. this.FireStateChangedEvent();
  170. this._serializing.Serialize();
  171. }
  172. private void SetStateInactive()
  173. {
  174. this.State = CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState.Inactive;
  175. this._saleEndsAt = DateTime.UtcNow;
  176. this.StopTimeOutRoutine();
  177. this.FireStateChangedEvent();
  178. this._serializing.Serialize();
  179. }
  180. private decimal GetGoldPrice(CIGBuilding building)
  181. {
  182. if (building.PurchasePrice.ContainsPositive("Gold"))
  183. {
  184. return building.PurchasePrice.GetValue("Gold");
  185. }
  186. return 0m;
  187. }
  188. private bool HasReachedBuiltLimit(CIGBuilding building)
  189. {
  190. int strictMax = building.strictMax;
  191. return strictMax >= 0 && SingletonMonobehaviour<CIGGameStats>.Instance.NumberOf(building.CachedName) >= strictMax;
  192. }
  193. private void OnSerialize(Dictionary<string, object> values)
  194. {
  195. values["BOBGOFState"] = (int)this.State;
  196. values["BOBGOFEndsAt"] = this._saleEndsAt.ToBinary();
  197. this.SetOrRemove("BOBGOFPaidBuilding", this.PaidBuilding, values);
  198. this.SetOrRemove("BOBGOFFreeBuilding", this.FreeBuilding, values);
  199. }
  200. private void OnDeserialize(Dictionary<string, object> values)
  201. {
  202. this.State = (CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState)values.GetInt("BOBGOFState", 0);
  203. this._saleEndsAt = DateTime.FromBinary(values.GetLong("BOBGOFEndsAt", 0L));
  204. string @string = values.GetString("BOBGOFPaidBuilding", string.Empty);
  205. this.PaidBuilding = SingletonMonobehaviour<GameObjectManager>.Instance.GetBuilding(@string);
  206. string string2 = values.GetString("BOBGOFFreeBuilding", string.Empty);
  207. this.FreeBuilding = SingletonMonobehaviour<GameObjectManager>.Instance.GetBuilding(string2);
  208. if (this.PaidBuilding == null || this.FreeBuilding == null)
  209. {
  210. this.State = CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState.Inactive;
  211. this._saleEndsAt = DateTime.UtcNow;
  212. values.Remove("BOBGOFPaidBuilding");
  213. values.Remove("BOBGOFFreeBuilding");
  214. }
  215. if (this.State == CIGBuyOneBuildingGetOneFreeManager.BuyOneBuildingGetOneFreeState.Inactive)
  216. {
  217. this.StartSaleIntervalRoutine();
  218. }
  219. else
  220. {
  221. this.StartTimeoutRoutine();
  222. }
  223. }
  224. private void SetOrRemove(string key, CIGBuilding building, Dictionary<string, object> storage)
  225. {
  226. if (building == null)
  227. {
  228. storage.Remove(key);
  229. }
  230. else
  231. {
  232. storage[key] = building.CachedName;
  233. }
  234. }
  235. public const string TrackingName = "BOBGOF";
  236. private const int SaleDurationInSeconds = 600;
  237. private const int TryStartingSaleIntervalInSeconds = 480;
  238. private const float NormalisedChanceSaleStarts = 0.25f;
  239. private const string StateKey = "BOBGOFState";
  240. private const string SaleEndAtKey = "BOBGOFEndsAt";
  241. private const string PaidBuildingKey = "BOBGOFPaidBuilding";
  242. private const string FreeBuildingKey = "BOBGOFFreeBuilding";
  243. [SerializeField]
  244. private Serializing _serializing;
  245. private IEnumerator _startSaleRoutine;
  246. private DateTime _saleEndsAt;
  247. private IEnumerator _saleTimeoutRoutine;
  248. public enum BuyOneBuildingGetOneFreeState
  249. {
  250. Inactive,
  251. Active
  252. }
  253. public delegate void StateChangedEventHandler();
  254. }