using System; using System.Collections.Generic; using I2.Loc; using Pathfinding; using UnityEngine; using UnityEngine.Events; [SelectionBase] public class BuildSlot : MonoBehaviour, DayNightCycle.IDaytimeSensitive { public enum BuildingState { Blueprint, Built } [Serializable] public class Upgrade { public string upgradeTooltip; [Min(0f)] public int cost = 3; public List upgradeBranches; } [Serializable] public class UpgradeBranch { [Tooltip("Only necessary when there are multiple options:")] public Choice choiceDetails; public Mesh replacementMesh; public int goldIncomeChange; public int hpChange; public List objectsToActivate = new List(); public List objectsToDisable = new List(); } public string buildingName; [Tooltip("The root is the required parent object no arrow points to, so this is pretty much always gonna be the casle center.E.g. this is set to 0 this building can not have a higher level than the castle center level.")] [SerializeField] private int requiredRootLevelDifference = -100; private BuildSlot requiredRoot; private List isRootOf = new List(); [SerializeField] private bool startDeactivated = true; [SerializeField] private BuildSlot activatorBuilding; [Min(0f)] [SerializeField] private int activatorLevel; [SerializeField] private bool activatorUpgradesThis; public List upgrades = new List(); private int level; [SerializeField] private GameObject buildingParent; [SerializeField] private GameObject bluepringParent; [SerializeField] private BuildingInteractor interactor; [SerializeField] private MeshFilter mainMesh; [SerializeField] private BoxCollider mainCollider; [SerializeField] private BoxCollider damageCollider; [SerializeField] private BoxCollider interactorCollider; [SerializeField] private NavmeshCut navmeshCut; public bool hideGizmos; public float navmeshCutPadding = 1f; public BuildingMeshTracker buildingMeshTracker; [HideInInspector] public BuildingInteractor buildingInteractor; private int goldIncome; [HideInInspector] public UnityEvent OnUpgrade = new UnityEvent(); [HideInInspector] public UnityEvent OnParentUpgrade = new UnityEvent(); [HideInInspector] public UnityEvent OnUpgradeCancel = new UnityEvent(); private List builtSlotsThatRelyOnThisBuilding = new List(); private bool gotActivated; private Upgrade upgradeSelected; private PlayerInteraction playerInteractionSelected; public string LOCIDENTIFIER_NAME => "Building/" + buildingName; public List IsRootOf => isRootOf; public BuildSlot ActivatorBuilding => activatorBuilding; public int ActivatorLevel { get { return activatorLevel; } set { activatorLevel = value; } } public bool ActivatorUpgradesThis => activatorUpgradesThis; public List Upgrades { get { if (!activatorUpgradesThis) { return upgrades; } return activatorBuilding.Upgrades; } } public int Level { get { if (!activatorUpgradesThis) { return level; } return activatorBuilding.Level; } } public BuildingInteractor Interactor => interactor; public MeshFilter MainMesh => mainMesh; public BuildingState State { get { if (level < 1) { return BuildingState.Blueprint; } return BuildingState.Built; } } public int GoldIncome { get { return goldIncome; } set { goldIncome = value; } } public bool CanBeUpgraded { get { if (activatorUpgradesThis) { return activatorBuilding.CanBeUpgraded; } if (requiredRoot == null) { return level < upgrades.Count; } if (level < upgrades.Count) { if (requiredRoot.Level <= level + requiredRootLevelDifference && level != 0) { return requiredRoot.Level >= 3; } return true; } return false; } } public bool NextUpgradeIsChoice { get { if (CanBeUpgraded) { return upgrades[level].upgradeBranches.Count > 1; } return false; } } public int NextUpgradeOrBuildCost { get { if (activatorUpgradesThis) { return activatorBuilding.NextUpgradeOrBuildCost; } if (CanBeUpgraded) { return upgrades[level].cost; } return 100; } set { if (activatorUpgradesThis) { activatorBuilding.NextUpgradeOrBuildCost = value; } if (CanBeUpgraded) { upgrades[level].cost = value; } } } public GameObject BuildingParent => buildingParent; private bool IsBlueprint => level == 0; public List BuiltSlotsThatRelyOnThisBuilding => builtSlotsThatRelyOnThisBuilding; public string GET_LOCIDENTIFIER_UPGRADE(int upgradeNumber) { return LOCIDENTIFIER_NAME + " Upgrade " + upgradeNumber; } public string GET_LOCIDENTIFIER_CHOICENAME(Choice choice) { return LOCIDENTIFIER_NAME + " Choice " + choice.name; } public string GET_LOCIDENTIFIER_CHOICEDESCRIPTION(Choice choice) { return GET_LOCIDENTIFIER_CHOICENAME(choice) + " Description"; } public string ReturnTooltip() { if (!CanBeUpgraded) { return ""; } string text = ((level <= 0) ? LocalizationManager.GetTranslation("Tooltip/Build") : LocalizationManager.GetTranslation("Tooltip/Upgrade Building")); string text2 = "" + text + " " + LocalizationManager.GetTranslation(LOCIDENTIFIER_NAME) + ":\n"; text2 = text2 + "" + LocalizationManager.GetTranslation(GET_LOCIDENTIFIER_UPGRADE(level)) + "\n"; text2 += ""; int num = 0; Hp componentInChildren = GetComponentInChildren(includeInactive: true); if ((bool)componentInChildren) { num = (int)componentInChildren.maxHp; } List list = new List(); List list2 = new List(); foreach (UpgradeBranch upgradeBranch in upgrades[level].upgradeBranches) { int item = goldIncome + upgradeBranch.goldIncomeChange; if (!list.Contains(item)) { list.Add(item); } int item2 = num + upgradeBranch.hpChange; if (!list2.Contains(item2)) { list2.Add(item2); } } list2.Sort(); list.Sort(); string text3 = ""; string text4 = ""; for (int i = 0; i < list.Count; i++) { if (i > 0) { text3 += "/"; } text3 += list[i]; } for (int j = 0; j < list2.Count; j++) { if (j > 0) { text4 += "/"; } text4 += list2[j]; } if (level > 0) { text2 = ((list2.Count <= 1 && list2[0] == num) ? (text2 + "\n" + num + "") : (text2 + "\n" + num + " " + text4 + "")); if (list.Count > 1 || list[0] != goldIncome) { return text2 + "\n" + goldIncome + " " + text3 + ""; } return text2 + "\n" + goldIncome + ""; } text2 = ((list2.Count <= 1 && list2[0] == num) ? (text2 + "\n " + num + "") : (text2 + "\n " + text4 + "")); if (list.Count > 1 || list[0] != goldIncome) { return text2 + "\n " + text3 + ""; } return text2 + "\n " + goldIncome + ""; } private void OnEnable() { foreach (Upgrade upgrade in upgrades) { foreach (UpgradeBranch upgradeBranch in upgrade.upgradeBranches) { foreach (GameObject item in upgradeBranch.objectsToActivate) { item.SetActive(value: false); } } } } public List GetBuildSlotsThatWillUnlockWhenUpgraded() { List list = new List(); for (int i = 0; i < builtSlotsThatRelyOnThisBuilding.Count; i++) { if (builtSlotsThatRelyOnThisBuilding[i].activatorLevel == level) { list.Add(builtSlotsThatRelyOnThisBuilding[i]); } } return list; } public List GetBlueprintPreviewsThatWillUnlockWhenUpgraded() { List list = new List(); for (int i = 0; i < builtSlotsThatRelyOnThisBuilding.Count; i++) { if (builtSlotsThatRelyOnThisBuilding[i].activatorLevel == level) { if (builtSlotsThatRelyOnThisBuilding[i].State == BuildingState.Built || builtSlotsThatRelyOnThisBuilding[i].activatorUpgradesThis) { MeshFilter[] componentsInChildren = builtSlotsThatRelyOnThisBuilding[i].buildingParent.GetComponentsInChildren(); list.AddRange(componentsInChildren); } else { MeshFilter[] componentsInChildren2 = builtSlotsThatRelyOnThisBuilding[i].bluepringParent.GetComponentsInChildren(); list.AddRange(componentsInChildren2); } } } return list; } public List GetGameObjectsThatWillUnlockWhenUpgraded(int _upgradeBranch) { if (level >= upgrades.Count) { return new List(); } return upgrades[level].upgradeBranches[_upgradeBranch % upgrades[level].upgradeBranches.Count].objectsToActivate; } private void Start() { requiredRoot = this; while (requiredRoot.activatorBuilding != null) { requiredRoot = requiredRoot.activatorBuilding; } if (requiredRoot != this) { requiredRoot.isRootOf.Add(this); } if ((bool)activatorBuilding) { activatorBuilding.builtSlotsThatRelyOnThisBuilding.Add(this); } if (startDeactivated) { base.gameObject.SetActive(value: false); if ((bool)activatorBuilding) { activatorBuilding.OnUpgrade.AddListener(Activate); } } else { Activate(); } DayNightCycle.Instance.RegisterDaytimeSensitiveObject(this); } public void Activate() { if (!gotActivated && (!startDeactivated || activatorBuilding.Level > activatorLevel)) { gotActivated = true; base.gameObject.SetActive(value: true); ActivateOrDeactivateBuliding(State); } } private void ActivateOrDeactivateBuliding(BuildingState nextState) { switch (nextState) { case BuildingState.Blueprint: buildingParent.SetActive(value: false); bluepringParent.SetActive(value: true); break; case BuildingState.Built: buildingParent.SetActive(value: true); bluepringParent.SetActive(value: false); break; } } public void TryToBuildOrUpgradeAndPay(PlayerInteraction player, bool _presentChoice = true) { if (!CanBeUpgraded) { return; } if (activatorUpgradesThis) { activatorBuilding.TryToBuildOrUpgradeAndPay(player, _presentChoice); return; } for (int i = 0; i < builtSlotsThatRelyOnThisBuilding.Count; i++) { BuildSlot buildSlot = builtSlotsThatRelyOnThisBuilding[i]; if (buildSlot.ActivatorUpgradesThis && buildSlot.activatorBuilding == this) { buildSlot.gameObject.SetActive(value: true); buildSlot.ExecuteBuildOrUpgrade(player, _presentChoice: false); } } ExecuteBuildOrUpgrade(player, _presentChoice); for (int j = 0; j < builtSlotsThatRelyOnThisBuilding.Count; j++) { BuildSlot buildSlot2 = builtSlotsThatRelyOnThisBuilding[j]; if ((bool)buildSlot2.buildingInteractor) { buildSlot2.buildingInteractor.UpdateInteractionState(); } } if ((bool)buildingInteractor) { buildingInteractor.UpdateInteractionState(); } } public void ExecuteBuildOrUpgrade(PlayerInteraction _player, bool _presentChoice) { if (CanBeUpgraded) { ExecuteUpgrade(upgrades[level], _player, _presentChoice); } } private void ExecuteUpgrade(Upgrade _upg, PlayerInteraction _player, bool _presentChoice) { if (ChoiceManager.instance.ChoiceCoroutineRunning) { return; } List list = new List(); foreach (UpgradeBranch upgradeBranch in _upg.upgradeBranches) { list.Add(upgradeBranch.choiceDetails); } upgradeSelected = _upg; playerInteractionSelected = _player; if (_presentChoice) { ChoiceManager.instance.PresentChoices(list, this, OnUpgradeChoiceComplete); } else { OnUpgradeChoiceComplete(_upg.upgradeBranches[UnityEngine.Random.Range(0, _upg.upgradeBranches.Count)].choiceDetails); } } public void OnUpgradeChoiceComplete(Choice _choiceMade) { if (_choiceMade == null) { OnUpgradeCancel.Invoke(); return; } if (level == 0) { ActivateOrDeactivateBuliding(BuildingState.Built); } level++; UpgradeBranch upgradeBranch = null; foreach (UpgradeBranch upgradeBranch2 in upgradeSelected.upgradeBranches) { if (upgradeBranch2.choiceDetails == _choiceMade) { upgradeBranch = upgradeBranch2; } } buildingMeshTracker.Unfreeze(); buildingMeshTracker.FreezeMeshWithDelay(); if (upgradeBranch.replacementMesh != null) { mainMesh.mesh = upgradeBranch.replacementMesh; } goldIncome += upgradeBranch.goldIncomeChange; Hp component = buildingParent.GetComponent(); if ((bool)component) { component.maxHp += upgradeBranch.hpChange; component.Heal(upgradeBranch.hpChange); } foreach (GameObject item in upgradeBranch.objectsToActivate) { item.SetActive(value: true); } foreach (GameObject item2 in upgradeBranch.objectsToDisable) { item2.SetActive(value: false); } foreach (BuildSlot item3 in isRootOf) { BuildingInteractor[] componentsInChildren = item3.GetComponentsInChildren(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].UpdateInteractionState(); } } if (activatorUpgradesThis) { OnParentUpgrade.Invoke(); return; } OnUpgrade.Invoke(); TooltipManager.instance.SetInteractorRefreshFlag(); } public void DEBUGUpgradeToMax() { while (CanBeUpgraded) { TryToBuildOrUpgradeAndPay(null, _presentChoice: false); } if ((bool)interactor) { interactor.UpdateInteractionState(); } } public void OnDusk() { if (IsBlueprint) { bluepringParent.SetActive(value: false); } } public void OnDawn_AfterSunrise() { if (IsBlueprint) { bluepringParent.SetActive(value: true); } } public void OnDawn_BeforeSunrise() { } }