using System.Collections.Generic; using I2.Loc; using Pathfinding.RVO; using UnityEngine; public class TutorialManager : MonoBehaviour { public static TutorialManager instance; private PlayerInteraction playerInteraction; private DayNightCycle dayNightCycle; private TooltipManager tooltipManager; private TagManager tagManager; private EnemySpawner enemySpawner; private bool allowStartingTheNight = true; private static readonly string LOCIDENTIFIER = "Tutorial/"; [SerializeField] private Transform arrowMarkerTransform; [SerializeField] private ScreenMarker arrowMarker; [SerializeField] private Transform player; [Header("When you're dead")] [SerializeField] private Hp playerHp; [Header("Movement Tutorial")] [SerializeField] private RVOController playerRvo; [SerializeField] private float requiredMoveDist; private bool playerHasLearnedHowToMove; private bool destroyedPracticeTargets; private bool playerDidSprint; [Header("Build Castle Center")] [SerializeField] private BuildingInteractor caslteBuildInteractor; private bool castleCenterBuilt; private bool mayShowEnemySpawn; [Header("Start The Night")] private bool firstNightStarted; [Header("First Night")] [SerializeField] private StabMA activeStabAttack; [Header("Build Houses")] [SerializeField] private List houses; private bool housesBuilt; [Header("Start The 2nd Night")] private bool secondNightStarted; [Header("2nd Night")] [Header("Collect Taxes")] [SerializeField] private List towers; private bool towersBuilt; [Header("Start The 3d Night")] private bool thirdNightStarted; [Header("Upgrade Castle Center")] [SerializeField] private BuildSlot caslteBuilSlot; [SerializeField] private GameObject royalTraining; [SerializeField] private GameObject buildersGuild; private bool castleCenterUpgraded; private bool fourthNightStarted; [Header("It's up to you!")] [SerializeField] private BuildSlot barracks; [SerializeField] private CommandUnits command; private bool commandingUnits; private bool commandedUnits; private bool triedHoldPosition; [TextArea(1, 10)] public string whileDead; [TextArea(1, 10)] public string howToMove; [TextArea(1, 10)] public string howToSprint; [TextArea(1, 10)] public string howToBuild; [TextArea(1, 10)] public string startTheNight; [TextArea(1, 10)] public string howToStartTheNight; [TextArea(1, 10)] public string tooExpensiveToBuild; [TextArea(1, 10)] public string tooExpensiveToUpgrade; [TextArea(1, 10)] public string tooExpensiveToUpgradeCastleCenter; [TextArea(1, 10)] public string firstNight; [TextArea(1, 10)] public string firstNightDone; [TextArea(1, 10)] public string buildHouses; [TextArea(1, 10)] public string startThe2ndNight; [TextArea(1, 10)] public string secondNight; [TextArea(1, 10)] public string buildTowers; [TextArea(1, 10)] public string startThe3ndNight; [TextArea(1, 10)] public string upgradeCastleCenter; [TextArea(1, 10)] public string howToUpgrade; [TextArea(1, 10)] public string chooseAnUpgrade; [TextArea(1, 10)] public string goodChoiceGeneric; [TextArea(1, 10)] public string goodChoiceRoyalTraining; [TextArea(1, 10)] public string goodChoiceBuildersGuild; [TextArea(1, 10)] public string itsUpToYou; [TextArea(1, 10)] public string maybeBuildBarracksSomeTime; [TextArea(1, 10)] public string tryToCommandYourUnits; [TextArea(1, 10)] public string makeThemHoldPosition; [TextArea(1, 10)] public string howToHeal; [TextArea(1, 10)] public string lastDay; [TextArea(1, 10)] public string lastNight; private List findTaggedObjects = new List(); private List mustHaveTag = new List(); private List mayNotHaveTag = new List(); public static bool AllowStartingTheNight { get { if (!instance) { return true; } return instance.allowStartingTheNight; } } public bool MayShowEnemySpawn => mayShowEnemySpawn; private void SetArrowMarker(bool _enabled, Vector3 _pos, bool _offScreenOnly = false) { arrowMarkerTransform.gameObject.SetActive(_enabled); arrowMarkerTransform.position = _pos + Vector3.up * 10f; arrowMarker.showWhenOnScreen = !_offScreenOnly; } private void MarkNearestObjectWithTag(TagManager.ETag _tag, bool _offScreenOnly = false) { findTaggedObjects.Clear(); mustHaveTag.Clear(); mayNotHaveTag.Clear(); mustHaveTag.Add(_tag); TagManager.instance.FindAllTaggedObjectsWithTags(findTaggedObjects, mustHaveTag, mayNotHaveTag); if (findTaggedObjects.Count <= 0) { return; } TaggedObject taggedObject = null; float num = float.MaxValue; for (int i = 0; i < findTaggedObjects.Count; i++) { float magnitude = (player.transform.position - findTaggedObjects[i].transform.position).magnitude; if (magnitude < num) { num = magnitude; taggedObject = findTaggedObjects[i]; } } SetArrowMarker(_enabled: true, taggedObject.transform.position, _offScreenOnly); } private void MarkNearestUnbuiltBuilding(List _buildSlots) { List list = new List(_buildSlots); for (int num = list.Count - 1; num >= 0; num--) { if (list[num].State == BuildSlot.BuildingState.Built) { list.RemoveAt(num); } else if (!list[num].gameObject.activeInHierarchy) { list.RemoveAt(num); } } if (list.Count <= 0) { return; } BuildSlot buildSlot = null; float num2 = float.MaxValue; for (int i = 0; i < list.Count; i++) { float magnitude = (player.transform.position - list[i].transform.position).magnitude; if (magnitude < num2) { num2 = magnitude; buildSlot = list[i]; } } SetArrowMarker(_enabled: true, buildSlot.transform.position); } private void MarkNearestGoldCoin() { List freeCoins = TagManager.instance.freeCoins; if (freeCoins.Count <= 0) { return; } Coin coin = null; float num = float.MaxValue; for (int i = 0; i < freeCoins.Count; i++) { float magnitude = (player.transform.position - freeCoins[i].transform.position).magnitude; if (magnitude < num) { num = magnitude; coin = freeCoins[i]; } } SetArrowMarker(_enabled: true, coin.transform.position); } private void Awake() { instance = this; } private void OnEnable() { LocalizationManager.OnLocalizeEvent += FetchLocalizedTexts; } private void OnDisable() { LocalizationManager.OnLocalizeEvent -= FetchLocalizedTexts; } private void Start() { dayNightCycle = DayNightCycle.Instance; tooltipManager = TooltipManager.instance; tagManager = TagManager.instance; playerInteraction = PlayerInteraction.instance; enemySpawner = EnemySpawner.instance; FetchLocalizedTexts(); } private void Update() { if (SceneTransitionManager.instance.SceneTransitionIsRunning) { return; } SetArrowMarker(_enabled: false, Vector3.zero); tooltipManager.SetTutorialOverride(""); tooltipManager.SetTutorialOverride("", _priorityText: false); if (playerHp.KnockedOut) { tooltipManager.SetTutorialOverride(whileDead); return; } if (!playerHasLearnedHowToMove) { MarkNearestObjectWithTag(TagManager.ETag.PracticeTargets); tooltipManager.SetTutorialOverride(howToMove); requiredMoveDist -= playerRvo.velocity.magnitude * Time.deltaTime; if (requiredMoveDist < 0f) { playerHasLearnedHowToMove = true; } return; } if (!destroyedPracticeTargets) { MarkNearestObjectWithTag(TagManager.ETag.PracticeTargets); if (tagManager.CountAllTaggedObjectsWithTag(TagManager.ETag.PracticeTargets) <= 0) { destroyedPracticeTargets = true; } return; } if (tagManager.freeCoins.Count > 0 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day && enemySpawner.Wavenumber == -1 && enemySpawner.Wavenumber <= 3) { MarkNearestGoldCoin(); return; } if (!castleCenterBuilt) { if (PlayerManager.Instance.RegisteredPlayers[0].Sprinting) { playerDidSprint = true; } if (playerInteraction.FocussedInteractor == caslteBuildInteractor) { tooltipManager.SetTutorialOverride(howToBuild); } else { tooltipManager.SetTutorialOverride(howToSprint); if (playerDidSprint) { SetArrowMarker(_enabled: true, caslteBuildInteractor.transform.position); } } if (tagManager.CountAllTaggedObjectsWithTag(TagManager.ETag.Building) > 0) { castleCenterBuilt = true; mayShowEnemySpawn = true; enemySpawner.EnemySpawnersHornUnFocussed(); } return; } if (playerInteraction.FocussedInteractor != null && playerInteraction.FocussedInteractor.GetType() == typeof(BuildingInteractor)) { BuildingInteractor buildingInteractor = (BuildingInteractor)playerInteraction.FocussedInteractor; if (buildingInteractor.targetBuilding.CanBeUpgraded && playerInteraction.Balance + CostDisplay.currentlyFilledCoinsFromLastActiveDisplay < buildingInteractor.targetBuilding.NextUpgradeOrBuildCost && !buildingInteractor.UpgradeCueVisible) { if (buildingInteractor.targetBuilding.State == BuildSlot.BuildingState.Blueprint) { tooltipManager.SetTutorialOverride(tooExpensiveToBuild); } else if (buildingInteractor.targetBuilding.GetComponentInChildren().Tags.Contains(TagManager.ETag.CastleCenter)) { tooltipManager.SetTutorialOverride(tooExpensiveToUpgradeCastleCenter); } else { tooltipManager.SetTutorialOverride(tooExpensiveToUpgrade); } return; } } if (!firstNightStarted) { tooltipManager.SetTutorialOverride(startTheNight); if (dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { firstNightStarted = true; } return; } if (enemySpawner.Wavenumber == 0 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { EnemySpawner.instance.InfinitelySpawning = activeStabAttack.TargetsStabeed < 3; MarkNearestObjectWithTag(TagManager.ETag.EnemyOwned, _offScreenOnly: true); allowStartingTheNight = false; if (activeStabAttack.TargetsStabeed < 3) { tooltipManager.SetTutorialOverride(firstNight + " (" + activeStabAttack.TargetsStabeed + "/3)"); } else { tooltipManager.SetTutorialOverride(firstNightDone); } return; } if (!housesBuilt && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { MarkNearestUnbuiltBuilding(houses); int num = tagManager.CountAllTaggedObjectsWithTag(TagManager.ETag.Building); int num2 = num - 1; tooltipManager.SetTutorialOverride(buildHouses + " (" + num2 + "/3)"); if (playerInteraction.FocussedInteractor != null && playerInteraction.FocussedInteractor.GetType() == typeof(BuildingInteractor)) { SetArrowMarker(_enabled: false, Vector3.zero); if (num2 == 0) { tooltipManager.SetTutorialOverride(howToBuild); } } if (num >= 4) { housesBuilt = true; } return; } if (!secondNightStarted && housesBuilt) { allowStartingTheNight = true; tooltipManager.SetTutorialOverride(startThe2ndNight); if (dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { secondNightStarted = true; } return; } if (enemySpawner.Wavenumber == 1 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { MarkNearestObjectWithTag(TagManager.ETag.EnemyOwned, _offScreenOnly: true); allowStartingTheNight = false; tooltipManager.SetTutorialOverride(secondNight); return; } if (!towersBuilt && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { if (dayNightCycle.AfterSunrise) { MarkNearestUnbuiltBuilding(towers); if (playerInteraction.FocussedInteractor != null && playerInteraction.FocussedInteractor.GetType() == typeof(BuildingInteractor)) { SetArrowMarker(_enabled: false, Vector3.zero); } int num3 = tagManager.CountAllTaggedObjectsWithTag(TagManager.ETag.Building) - 4; tooltipManager.SetTutorialOverride(buildTowers + " (" + num3 + "/2)"); if (num3 >= 2) { towersBuilt = true; } } return; } if (!thirdNightStarted && towersBuilt) { allowStartingTheNight = true; tooltipManager.SetTutorialOverride(startThe3ndNight); if (dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { thirdNightStarted = true; } return; } if (ChoiceManager.instance.ChoiceCoroutineRunning) { tooltipManager.SetTutorialOverride(chooseAnUpgrade); return; } if (thirdNightStarted && !castleCenterUpgraded && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { allowStartingTheNight = false; if (!dayNightCycle.AfterSunrise) { return; } if (playerInteraction.FocussedInteractor == caslteBuildInteractor) { tooltipManager.SetTutorialOverride(howToUpgrade); return; } SetArrowMarker(_enabled: true, caslteBuildInteractor.transform.position); tooltipManager.SetTutorialOverride(upgradeCastleCenter); if (caslteBuilSlot.Level == 2) { castleCenterUpgraded = true; allowStartingTheNight = true; } return; } if (!fourthNightStarted && castleCenterUpgraded) { allowStartingTheNight = true; if (royalTraining.activeInHierarchy) { tooltipManager.SetTutorialOverride(goodChoiceRoyalTraining); } else if (buildersGuild.activeInHierarchy) { tooltipManager.SetTutorialOverride(goodChoiceBuildersGuild); } else { tooltipManager.SetTutorialOverride(goodChoiceGeneric); } if (dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { fourthNightStarted = true; } return; } if (enemySpawner.Wavenumber == 3 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { allowStartingTheNight = false; return; } if (barracks.State == BuildSlot.BuildingState.Built && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { if (!dayNightCycle.AfterSunrise) { return; } if (!commandedUnits) { if (command.commanding) { commandingUnits = true; } if (commandingUnits && !command.commanding) { commandedUnits = true; } tooltipManager.SetTutorialOverride(tryToCommandYourUnits); return; } if (!triedHoldPosition) { foreach (TaggedObject playerUnit in TagManager.instance.PlayerUnits) { if (playerUnit.GetComponent().HoldPosition) { triedHoldPosition = true; } } tooltipManager.SetTutorialOverride(makeThemHoldPosition); } } if (enemySpawner.Wavenumber == 3 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { if (dayNightCycle.AfterSunrise) { tooltipManager.SetTutorialOverride(itsUpToYou, _priorityText: false); allowStartingTheNight = true; } } else if (enemySpawner.Wavenumber == 4 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { tooltipManager.SetTutorialOverride(howToHeal); } else if (enemySpawner.Wavenumber >= 4 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day && barracks.State != BuildSlot.BuildingState.Built && playerInteraction.Balance + CostDisplay.currentlyFilledCoinsFromLastActiveDisplay >= 4) { if (dayNightCycle.AfterSunrise) { tooltipManager.SetTutorialOverride(maybeBuildBarracksSomeTime, _priorityText: false); if (playerInteraction.FocussedInteractor == null) { SetArrowMarker(_enabled: true, barracks.transform.position + Vector3.up * 3f); } } } else if (enemySpawner.Wavenumber == 5 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { tooltipManager.SetTutorialOverride(howToHeal); } else if (enemySpawner.Wavenumber == 5 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { _ = dayNightCycle.AfterSunrise; } else if (enemySpawner.Wavenumber == 6 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { tooltipManager.SetTutorialOverride(howToHeal); } else if (enemySpawner.Wavenumber == 6 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Day) { tooltipManager.SetTutorialOverride(lastDay, _priorityText: false); } else if (enemySpawner.Wavenumber == 7 && dayNightCycle.CurrentTimestate == DayNightCycle.Timestate.Night) { tooltipManager.SetTutorialOverride(lastNight); } } private void FetchLocalizedTexts() { whileDead = LocalizationManager.GetTranslation(LOCIDENTIFIER + "whileDead"); howToMove = LocalizationManager.GetTranslation(LOCIDENTIFIER + "howToMove"); howToSprint = LocalizationManager.GetTranslation(LOCIDENTIFIER + "howToSprint"); howToBuild = LocalizationManager.GetTranslation(LOCIDENTIFIER + "howToBuild"); startTheNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "startTheNight"); howToStartTheNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "howToStartTheNight"); tooExpensiveToBuild = LocalizationManager.GetTranslation(LOCIDENTIFIER + "tooExpensiveToBuild"); tooExpensiveToUpgrade = LocalizationManager.GetTranslation(LOCIDENTIFIER + "tooExpensiveToUpgrade"); tooExpensiveToUpgradeCastleCenter = LocalizationManager.GetTranslation(LOCIDENTIFIER + "tooExpensiveToUpgradeCastleCenter"); firstNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "firstNight"); firstNightDone = LocalizationManager.GetTranslation(LOCIDENTIFIER + "firstNightDone"); buildHouses = LocalizationManager.GetTranslation(LOCIDENTIFIER + "buildHouses"); startThe2ndNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "startThe2ndNight"); secondNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "secondNight"); buildTowers = LocalizationManager.GetTranslation(LOCIDENTIFIER + "buildTowers"); startThe3ndNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "startThe3ndNight"); upgradeCastleCenter = LocalizationManager.GetTranslation(LOCIDENTIFIER + "upgradeCastleCenter"); howToUpgrade = LocalizationManager.GetTranslation(LOCIDENTIFIER + "howToUpgrade"); chooseAnUpgrade = LocalizationManager.GetTranslation(LOCIDENTIFIER + "chooseAnUpgrade"); goodChoiceGeneric = LocalizationManager.GetTranslation(LOCIDENTIFIER + "goodChoiceGeneric"); goodChoiceRoyalTraining = LocalizationManager.GetTranslation(LOCIDENTIFIER + "goodChoiceRoyalTraining"); goodChoiceBuildersGuild = LocalizationManager.GetTranslation(LOCIDENTIFIER + "goodChoiceBuildersGuild"); itsUpToYou = LocalizationManager.GetTranslation(LOCIDENTIFIER + "itsUpToYou"); maybeBuildBarracksSomeTime = LocalizationManager.GetTranslation(LOCIDENTIFIER + "maybeBuildBarracksSomeTime"); tryToCommandYourUnits = LocalizationManager.GetTranslation(LOCIDENTIFIER + "tryToCommandYourUnits"); makeThemHoldPosition = LocalizationManager.GetTranslation(LOCIDENTIFIER + "makeThemHoldPosition"); howToHeal = LocalizationManager.GetTranslation(LOCIDENTIFIER + "howToHeal"); lastDay = LocalizationManager.GetTranslation(LOCIDENTIFIER + "lastDay"); lastNight = LocalizationManager.GetTranslation(LOCIDENTIFIER + "lastNight"); } }