using Photon.Pun; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; namespace Kryz.CharacterStats.Examples { public class PlayerCharacterStats : CharacterStats { [Header("Listeners:")] [SerializeField] private GameEventListener_Float experienceOnNPCDeath; [SerializeField] private GameEventListener_JobInstance onJobCompleted; [Header("Components:")] [SerializeField] Inventory inventory; [SerializeField] EquipmentPanel equipmentPanel; [SerializeField] StatPanel statPanel; [HideInInspector] public RiftPlayer player; public Level level; public ReputationLevel reputationLevel; PhotonView photonView; Health health; Mana mana; SpiritPower spiritPower; [Header("Runtime Data:")] public List AllocatedStatPoints = new List(); public int AvailablePointsToAllocate; CharacterData characterData = new CharacterData(); PlayerAccountData accountData = new PlayerAccountData(); List statsCollection = new List(); protected override void Awake() { player = GetComponentInParent(); photonView = GetComponentInParent(); health = player.GetComponent(); mana = player.GetComponent(); spiritPower = player.GetComponent(); level = new Level(); base.Awake(); statsCollection.Add(Strength); statsCollection.Add(Agility); statsCollection.Add(Intelligence); statsCollection.Add(Spirit); statsCollection.Add(Vitality); if (!photonView.IsMine) return; //Debug.Log("HEALTH GET BASE MAX VALUE: " + health.GetBaseMaxValue()); MaxHealth.BaseValue = health.GetBaseMaxValue(); //Debug.Log("MAX HEALTH GET BASE MAX VALUE: " + MaxHealth.BaseValue); accountData = PlayerDataHandler.Instance.LoadPlayerAccountData(PlayerDataHandler.Instance.currentPlayerName.Value); characterData = PlayerDataHandler.Instance.LoadCharacterData(PlayerDataHandler.Instance.currentPlayerName.Value, PlayerDataHandler.Instance.currentCharacterName.Value); if (characterData != null) { Debug.Log("Success Loading CharacterData"); level = new Level(characterData.currentLevel, characterData.currentExperience); reputationLevel = new ReputationLevel(accountData.currentReputationLevel, accountData.currentReputationExperience); int totalAllocatedPoints = 0; for (int i = 0; i < primaryStatsDictionary.Keys.Count; i++) { AllocatedStatPoints.Add(characterData.allocatedStatPoints[i]); totalAllocatedPoints += characterData.allocatedStatPoints[i]; } int totalPointsFromLevels = level.currentLevel * GameConstants.CharacterStatsBalancing.StatPointsPerLevel; int totalPointsFromRep = reputationLevel.currentLevel * GameConstants.CharacterStatsBalancing.StatPointsPerReputationLevel; if(totalAllocatedPoints + characterData.availablePointsToAllocate < totalPointsFromLevels + totalPointsFromRep) { characterData.availablePointsToAllocate = totalPointsFromLevels + totalPointsFromRep - totalAllocatedPoints; } AvailablePointsToAllocate = characterData.availablePointsToAllocate; UpdateAllocatedStats(); UpdateStatsBasedOnLevel(); } else { characterData = new CharacterData(); reputationLevel = new ReputationLevel(accountData.currentReputationLevel, accountData.currentReputationExperience); for (int i = 0; i < primaryStatsDictionary.Keys.Count; i++) { AllocatedStatPoints.Add(0); } AvailablePointsToAllocate = GameConstants.CharacterStatsBalancing.StatPointsPerLevel; AvailablePointsToAllocate += accountData.currentReputationLevel * GameConstants.CharacterStatsBalancing.StatPointsPerReputationLevel; characterData.playerOwnerID = PlayerDataHandler.Instance.currentPlayerName.Value; characterData.currentLevel = level.currentLevel; characterData.currentExperience = level.GetCurrentExperience(); characterData.availablePointsToAllocate = AvailablePointsToAllocate; for (int i = 0; i < AllocatedStatPoints.Count; i++) { characterData.allocatedStatPoints[i] = AllocatedStatPoints[i]; } PlayerDataHandler.Instance.SaveCharacterData(PlayerDataHandler.Instance.currentPlayerName.Value, PlayerDataHandler.Instance.currentCharacterName.Value, characterData); } if (statPanel == null) statPanel = FindObjectOfType(); statPanel.SetPlayerStats(this); statPanel.SetStats(Strength, Agility, Intelligence, Spirit, Vitality); statPanel.SetSecondaryStats(AttackDamage, SpellDamage, CritChance, CritDamage, MaxHealth, Armor, MagicResistance); statPanel.UpdateStatValues(); statPanel.SetCharacterInfo(PlayerDataHandler.Instance.currentCharacterName.Value, level.currentLevel.ToString(), reputationLevel.currentLevel.ToString()); statPanel.ToggleAllocateButtonsInteractable(AvailablePointsToAllocate > 0); onUpdateStatValues.AddListener(statPanel.UpdateStatValues); onUpdateStatValues.Invoke(); if (inventory == null) inventory = FindObjectOfType(); inventory.OnItemRightClickedEvent.AddListener(EquipFromInventory); if (equipmentPanel == null) equipmentPanel = FindObjectOfType(); equipmentPanel.OnItemRightClickedEvent.AddListener(UnequipFromEquipPanel); RefreshCurrentEquipmentStats(); level.OnLevelUpEvent.AddListener(OnLevelUp); level.OnExperienceChanged.AddListener(OnExperienceChanged); reputationLevel.OnLevelUpEvent.AddListener(OnReputationLevelUp); reputationLevel.OnExperienceChanged.AddListener(OnReputationExperienceChanged); experienceOnNPCDeath.Response.AddListener(level.GainExperience); onJobCompleted.Response.AddListener(job => level.GainExperience(job.experienceReward)); onJobCompleted.Response.AddListener(job => reputationLevel.GainExperience(job.reputationReward)); UpdateLevelOnOthers(); statPanel.UpdateStatValues(); } private void Start() { if (photonView.IsMine) onUpdateStatValues.Invoke(); } private void OnExperienceChanged() { characterData.currentLevel = level.currentLevel; characterData.currentExperience = level.GetCurrentExperience(); PlayerDataHandler.Instance.SaveCharacterData(PlayerDataHandler.Instance.currentPlayerName.Value, PlayerDataHandler.Instance.currentCharacterName.Value, characterData); } private void OnReputationExperienceChanged() { accountData.currentReputationLevel = reputationLevel.currentLevel; accountData.currentReputationExperience = reputationLevel.GetCurrentExperience(); PlayerDataHandler.Instance.SavePlayerAccountData(PlayerDataHandler.Instance.currentPlayerName.Value, accountData); } private void OnReputationLevelUp() { AvailablePointsToAllocate += GameConstants.CharacterStatsBalancing.StatPointsPerReputationLevel; characterData.availablePointsToAllocate = AvailablePointsToAllocate; statPanel.ToggleAllocateButtonsInteractable(AvailablePointsToAllocate > 0); } private void OnLevelUp() { UpdateLevelOnOthers(); statPanel.UpdateLevelInfo(level.currentLevel.ToString(), reputationLevel.currentLevel.ToString()); UpdateStatsBasedOnLevel(); AvailablePointsToAllocate += GameConstants.CharacterStatsBalancing.StatPointsPerLevel; characterData.availablePointsToAllocate = AvailablePointsToAllocate; statPanel.ToggleAllocateButtonsInteractable(AvailablePointsToAllocate > 0); health.ChangeValue(health.GetMaxValue() * 0.2f); mana.ChangeValue(mana.GetMaxValue() * 0.2f); } private void EquipFromInventory(ItemInstance item) { if (item is EquippableItemInstance) { Equip((EquippableItemInstance)item); } } private void UnequipFromEquipPanel(ItemInstance item) { if (item is EquippableItemInstance) { Unequip((EquippableItemInstance)item); } } public void Equip(EquippableItemInstance item) { if (inventory.RemoveItem(item)) { ItemTooltip.Instance.HideTooltip(); EquippedItemTooltip.Instance.HideTooltip(); EquippableItemInstance previousItem; if (equipmentPanel.AddItem(item, out previousItem)) { if (previousItem != null && !string.IsNullOrEmpty(previousItem.ItemName)) { inventory.AddItem(previousItem); previousItem.Unequip(this); statPanel.UpdateStatValues(); } item.Equip(this); statPanel.UpdateStatValues(); onUpdateStatValues.Invoke(); } else { inventory.AddItem(item); } } } public void Unequip(EquippableItemInstance item) { if (!inventory.IsFull() && equipmentPanel.RemoveItem(item)) { item.Unequip(this); statPanel.UpdateStatValues(); inventory.AddItem(item); onUpdateStatValues.Invoke(); } } public void UpdateLevelOnOthers() { if (photonView.IsMine) photonView.RPC(nameof(RPC_OnLevelUp), RpcTarget.OthersBuffered, this.level.currentLevel); } [PunRPC] public void RPC_OnLevelUp(int level) { this.level.currentLevel = level; this.level.OnLevelUpEvent.Invoke(); } public void UpdateAllocatedStats() { Strength.RemoveAllModifiersFromSource(GameConstants.ObjectSources.AllocatedSource); Agility.RemoveAllModifiersFromSource(GameConstants.ObjectSources.AllocatedSource); Intelligence.RemoveAllModifiersFromSource(GameConstants.ObjectSources.AllocatedSource); Spirit.RemoveAllModifiersFromSource(GameConstants.ObjectSources.AllocatedSource); Vitality.RemoveAllModifiersFromSource(GameConstants.ObjectSources.AllocatedSource); Strength.AddModifier(new StatModifier(AllocatedStatPoints[0], StatModType.Flat, GameConstants.ObjectSources.AllocatedSource)); Agility.AddModifier(new StatModifier(AllocatedStatPoints[1], StatModType.Flat, GameConstants.ObjectSources.AllocatedSource)); Intelligence.AddModifier(new StatModifier(AllocatedStatPoints[2], StatModType.Flat, GameConstants.ObjectSources.AllocatedSource)); Spirit.AddModifier(new StatModifier(AllocatedStatPoints[3], StatModType.Flat, GameConstants.ObjectSources.AllocatedSource)); Vitality.AddModifier(new StatModifier(AllocatedStatPoints[4], StatModType.Flat, GameConstants.ObjectSources.AllocatedSource)); characterData.availablePointsToAllocate = AvailablePointsToAllocate; for (int i = 0; i < AllocatedStatPoints.Count; i++) { characterData.allocatedStatPoints[i] = AllocatedStatPoints[i]; } PlayerDataHandler.Instance.SaveCharacterData(PlayerDataHandler.Instance.currentPlayerName.Value, PlayerDataHandler.Instance.currentCharacterName.Value, characterData); onUpdateStatValues.Invoke(); } public void UpdateStatsBasedOnLevel() { Strength.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource); Agility.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource); Intelligence.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource); Spirit.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource); Vitality.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource); MaxHealth.RemoveAllModifiersFromSource(GameConstants.ObjectSources.LevelSource); Strength.AddModifier(new StatModifier((level.currentLevel - 1), StatModType.Flat, GameConstants.ObjectSources.LevelSource)); Agility.AddModifier(new StatModifier((level.currentLevel - 1), StatModType.Flat, GameConstants.ObjectSources.LevelSource)); Intelligence.AddModifier(new StatModifier((level.currentLevel - 1), StatModType.Flat, GameConstants.ObjectSources.LevelSource)); Spirit.AddModifier(new StatModifier((level.currentLevel - 1), StatModType.Flat, GameConstants.ObjectSources.LevelSource)); Vitality.AddModifier(new StatModifier((level.currentLevel - 1), StatModType.Flat, GameConstants.ObjectSources.LevelSource)); //Debug.Log("MAX HEALTH BASE VALUE: " + MaxHealth.BaseValue); MaxHealth.AddModifier(new StatModifier(MaxHealth.BaseValue * (level.currentLevel - 1) * GameConstants.CharacterStatsBalancing.BaseMaxHealthGrowthPerLevel, StatModType.Flat, GameConstants.ObjectSources.LevelSource)); onUpdateStatValues.Invoke(); } EquipmentSlot[] slots; public void RefreshCurrentEquipmentStats() { slots = equipmentPanel.GetCurrentSlots(); for (int i = 0; i < slots.Length; i++) { if (slots[i].Item == null) continue; for (int j = 0; j < statsCollection.Count; j++) { if (statsCollection[j].HasModifiersFromSource(slots[i].Item)) { break; } } ((EquippableItemInstance)slots[i].Item).Equip(this); statPanel.UpdateStatValues(); onUpdateStatValues.Invoke(); } } } }