using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System; using System.Linq; using System.Collections; using TMPro; using DG.Tweening; [System.Serializable] public class AchievementManager : MonoBehaviour { [Tooltip("The number of seconds an achievement will stay on the screen after being unlocked or progress is made.")] public float DisplayTime = 3; [Tooltip("The total number of achievements which can be on the screen at any one time.")] public int NumberOnScreen = 3; [Tooltip("If true, progress notifications will display their exact progress. If false it will show the closest bracket.")] public bool ShowExactProgress = false; [Tooltip("If true, achievement unlocks/progress update notifications will be displayed on the player's screen.")] public bool DisplayAchievements; [Tooltip("The location on the screen where achievement notifications should be displayed.")] public AchievementStackLocation StackLocation; [Tooltip("If true, the state of all achievements will be saved without any call to the manual save function (Recommended = true)")] public bool AutoSave; [Tooltip("The message which will be displayed on the UI if an achievement is marked as a spoiler.")] public string SpoilerAchievementMessage = "Hidden"; [Tooltip("The sound which plays when an achievement is unlocked is displayed to a user. Sounds are only played when Display Achievements is true.")] public AudioClip AchievedSound; [Tooltip("The sound which plays when a progress update is displayed to a user. Sounds are only played when Display Achievements is true.")] public AudioClip ProgressMadeSound; private AudioSource AudioSource; [SerializeField] public List States = new List(); //List of achievement states (achieved, progress and last notification) [SerializeField] public List AchievementList = new List(); //List of all available achievements [Tooltip("If true, one achievement will be automatically unlocked once all others have been completed")] public bool UseFinalAchievement = false; [Tooltip("The key of the final achievement")] public string FinalAchievementKey; public static AchievementManager instance = null; //Singleton Instance public AchievenmentStack Stack; public Button ClaimRewardButton; public AchievenmentListIngame achievementListIngame; void Awake() { if (instance == null) { instance = this; } else if (instance != this) { Destroy(gameObject); } DontDestroyOnLoad(gameObject); AudioSource = gameObject.GetComponent(); Stack = GetComponentInChildren(); LoadAchievementState(); } private void PlaySound(AudioClip Sound) { if (AudioSource != null) { AudioSource.clip = Sound; AudioSource.Play(); } } # region Miscellaneous public bool AchievementExists(string Key) { return AchievementExists(AchievementList.FindIndex(x => x.Key.Equals(Key))); } public bool AchievementExists(int Index) { return Index <= AchievementList.Count && Index >= 0; } public int GetAchievedCount() { int Count = (from AchievementState i in States where i.Achieved == true select i).Count(); return Count; } public float GetAchievedPercentage() { if (States.Count == 0) { return 0; } return (float)GetAchievedCount() / States.Count * 100; } #endregion #region Unlock and Progress public void Unlock(string Key) { Unlock(FindAchievementIndex(Key)); } public void AddCoins(int toAdd) { //int toAdd = coinsRewards[index]; int coins = PlayerPrefs.GetInt("Coin"); Debug.Log(toAdd + " Coins Rewarded"); coins += toAdd; SafePlayerPrefs.SetInt("Coin", coins); StartCoroutine(startCoinShakeEffect(coins - toAdd, coins, .5f)); } float val; IEnumerator startCoinShakeEffect(int oldValue, int newValue, float animTime) { float ct = 0; float nt; float tot = animTime; Text coinTxt = null; HomeScene homeScene = FindAnyObjectByType(); coinTxt = homeScene.coinLbl; coinTxt.transform.DOShakePosition(1f); while (ct < tot) { ct += Time.deltaTime; nt = ct / tot; val = Mathf.Lerp(oldValue, newValue, nt); coinTxt.text = ((int)(val)).ToString(); yield return null; } } public void Unlock(int Index) { if (!States[Index].Achieved) { States[Index].Progress = AchievementList[Index].ProgressGoal; var achievementInfromation = AchievementList[Index]; States[Index].LastProgressGoal = achievementInfromation.ProgressGoal; #region Ali's Code for Reward SafePlayerPrefs.SetInt("UIAchievement" + Index + "Claimable", 1); int numOfPrevCoins = PlayerPrefs.GetInt("TotalCoinsForReward" + Index, 0); int subAchievementIndex = PlayerPrefs.GetInt("subAchievementIndex" + Index, 0); SafePlayerPrefs.SetInt("TotalCoinsForReward" + Index, numOfPrevCoins + achievementInfromation.CoinRewards[Mathf.Clamp(subAchievementIndex,0, achievementInfromation.CoinRewards.Count-1)]); subAchievementIndex++; SafePlayerPrefs.SetInt("subAchievementIndex" + Index, subAchievementIndex); #endregion achievementInfromation.ProgressGoal += 5; if (AchievementList[Index].ProgressGoal >= 50) { States[Index].Achieved = true; // Mark as achieved States[Index].Progress = AchievementList[Index].ProgressGoal; // Set progress to goal } AutoSaveStates(); if (UseFinalAchievement) { int Find = States.FindIndex(x => !x.Achieved); bool CompletedAll = (Find == -1 || AchievementList[Find].Key.Equals(FinalAchievementKey)); if (CompletedAll) { Unlock(FinalAchievementKey); // Unlock the final achievement if all others are completed } } } } /// The Key of the achievement /// Set progress to this value public void SetAchievementProgress(string Key, float Progress) { SetAchievementProgress(FindAchievementIndex(Key), Progress); } /// The index of the achievement /// Set progress to this value public void SetAchievementProgress(int Index, float Progress) { if (AchievementList[Index].Progression) { if (States[Index].Progress >= AchievementList[Index].ProgressGoal) { Unlock(Index); } else { States[Index].Progress = Progress; DisplayUnlock(Index); AutoSaveStates(); } } } /// The Key of the achievement /// Add this number to progress public void AddAchievementProgress(string Key, float Progress) { AddAchievementProgress(FindAchievementIndex(Key), Progress); } /// The index of the achievement /// Add this number to progress public void AddAchievementProgress(int Index, float Progress) { if (AchievementList[Index].Progression) { if (States[Index].Progress + Progress >= AchievementList[Index].ProgressGoal) { Unlock(Index); } else { States[Index].Progress += Progress; DisplayUnlock(Index); AutoSaveStates(); } } } #endregion #region Saving and Loading /// /// Saves progress and achieved states to player prefs. Used to allow reload of data between game loads. This function is automatically called if the Auto Save setting is set to true. /// public void SaveAchievementState() { for (int i = 0; i < States.Count; i++) { SafePlayerPrefs.SetString("AchievementState_" + i, JsonUtility.ToJson(States[i])); } PlayerPrefs.Save(); } /// /// Loads all progress and achievement states from player prefs. This function is automatically called if the Auto Load setting is set to true. /// public void LoadAchievementState() { AchievementState NewState; States.Clear(); for (int i = 0; i < AchievementList.Count; i++) { //Ensure that new project get default values if (PlayerPrefs.HasKey("AchievementState_" + i)) { NewState = JsonUtility.FromJson(PlayerPrefs.GetString("AchievementState_" + i)); States.Add(NewState); AchievementList[i].ProgressGoal = NewState.LastProgressGoal == 0 ? 5 : NewState.LastProgressGoal; } else { States.Add(new AchievementState()); AchievementList[i].ProgressGoal = 5; } } } /// /// Clears all saved progress and achieved states. /// public void ResetAchievementState() { States.Clear(); for (int i = 0; i < AchievementList.Count; i++) { PlayerPrefs.DeleteKey("AchievementState_" + i); States.Add(new AchievementState()); } SaveAchievementState(); } #endregion /// Key of achievevment private int FindAchievementIndex(string Key) { return AchievementList.FindIndex(x => x.Key.Equals(Key)); } private void AutoSaveStates() { if (AutoSave) { SaveAchievementState(); } } /// Index of achievement to display private void DisplayUnlock(int Index) { if (DisplayAchievements && !AchievementList[Index].Spoiler || States[Index].Achieved) { //If not achieved if (AchievementList[Index].Progression && States[Index].Progress < AchievementList[Index].ProgressGoal) { int Steps = (int)AchievementList[Index].ProgressGoal / (int)AchievementList[Index].NotificationFrequency; //Loop through all notification point backwards from last possible option for (int i = Steps; i > States[Index].LastProgressUpdate; i--) { //When it finds the largest valid notification point if (States[Index].Progress >= AchievementList[Index].NotificationFrequency * i) { PlaySound(ProgressMadeSound); States[Index].LastProgressUpdate = i; Stack.ScheduleAchievementDisplay(Index); return; } } } else { PlaySound(AchievedSound); Stack.ScheduleAchievementDisplay(Index); } } } }