USER
using UnityEngine;
using UnityEngine.UI;
using W.o.N_Stats;
using System;
using System.Collections;
using UnityEngine.EventSystems;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class Player : MonoBehaviour
{
#region Stats Name And Player Info
// Property to set or get the player name
public string PlayerName
{
get { return PlayerPrefs.GetString("PlayerName", "Default Name"); }
set { PlayerPrefs.SetString("PlayerName", value); }
}
[Header("Level and Experience")]
public int PlayerLevel;
public int CurrentEXP;
public int ExpToLevelUp;
[Header("Health")]
public int currentHealth;
public int maxHealth;
[Header("Mana")]
public int currentMana;
public int maxMana;
[Header("Defense")]
public int currentDefense;
public int maxDefense;
[Header("Attack")]
public int currentAttack;
public int maxAttack;
[Header("Attack Speed")]
public float currentAttackSpeed;
public float maxAttackSpeed;
[Header("Critical")]
public int currentCritical;
public int maxCritical;
[Header("Life Steal")]
public float currentLifeSteal;
public float maxLifeSteal;
[Header("Range")]
public float currentRange;
public float maxRange;
[Header("Elemental Mastery")]
public float currentElementalMastery;
public float maxElementalMastery;
[Header("Cooldown")]
public float currentCooldown;
public float maxCooldown;
[Header("Knockback")]
public float currentKnockback;
public float maxKnockback;
[Header("Speed")]
public float currentSpeed;
public float maxSpeed;
[Header("Recovery")]
public float currentRecovery;
public float maxRecovery;
[Header("Evade")]
public float currentEvade;
public float maxEvade;
[Header("Fortune")]
public float currentFortune;
public float maxFortune;
[Header("Character and Stat Panel")]
public Character character;
public StatPanel statPanel;
public PlayerSkill playerSkill;
public Inventory inventory;
public EquipmentPanel equipmentPanel;
[Header("Hurt Effect")]
[SerializeField] private GameObject hurtParticlePrefab;
[SerializeField]
private PlayerDamageIndicator damageIndicatorScript; // Reference to the PlayerDamageIndicator script
public PlayerLevelUpText levelUpTextScript; // Reference to the PlayerLevelUpText script
#endregion
private float lastDamageTime = 0f; // Track the time of the last damage taken or mana used
private float lastRecoveryTime = 0f;
private bool hasEquippedItemRecently = false;
private float timeSinceEquippingItem = 0f;
private float equipItemRecoveryDelay = 30f;
[Header("Player Camera")]
public Camera playerCamera; // Assign the player's camera directly in the inspector
[Header("Button Assignment")]
public float attackRange = 2f;
public LayerMask mobsLayer; // Specify the layer for "Mobs"
[SerializeField] private bool displayGizmo = true; // Toggle to display Gizmo
// Event to notify UI that stats have changed
public Action OnStatsChanged { get; set; }
private void OnDrawGizmos()
{
if (displayGizmo)
{
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(transform.position, attackRange);
}
}
// Method to update the player's name
public void UpdatePlayerName(string newName)
{
PlayerName = newName;
}
#region Take Damage & Respawn
public void TakeDamage(int damage)
{
// Spawn the hurt particle effect if the prefab is assigned
if (hurtParticlePrefab != null)
{
GameObject hurtParticle = Instantiate(hurtParticlePrefab, transform.position, Quaternion.identity);
Destroy(hurtParticle, 0.45f); // Destroy the particle effect after 0.45 seconds
}
// Call the ShowDamageText method from PlayerDamageIndicator script and pass the damage value
if (damageIndicatorScript != null)
{
damageIndicatorScript.ShowDamageText(damage);
}
// Check if the player can evade
if (UnityEngine.Random.Range(0f, 100f) <= currentEvade)
{
Debug.Log($"{PlayerName} Evaded the Attack & Avoided {damage} Damage!");
}
else
{
// Calculate actual damage after considering defense
int actualDamage = Mathf.Max(0, damage - currentDefense);
// Damage defense first if there's any
if (currentDefense > 0)
{
int defenseDamage = Mathf.Max(0, damage - actualDamage);
currentDefense = Mathf.Max(0, currentDefense - damage);
// Log damage taken to defense if defense is greater than 0
if (defenseDamage > 0)
{
Debug.Log($"{PlayerName} Defense took {defenseDamage} damage!");
}
}
// If defense is reduced to 0, or no defense, damage health
if (currentDefense == 0)
{
int healthDamage = actualDamage;
currentHealth -= healthDamage;
// Log the health damage
Debug.Log($"{PlayerName} took {healthDamage} damage to health!");
// Check if health reaches 0
if (currentHealth <= 0)
{
Debug.Log($"{PlayerName} Died!");
// Respawn the player at the saved location and restore all stats to full
LoadPlayerData(PlayerName); // Respawn the player using saved data
RespawnPlayer();
}
}
}
// Update the last damage time to trigger recovery
lastDamageTime = Time.time;
}
private void RespawnPlayer()
{
// Restore all stats to full
SetCurrentStatsToMax(); // Reset current stats to their maximum values
// Teleport the player back to the saved location using the PlayerSaveLocation script
PlayerSaveLocation saveLocationScript = GetComponent<PlayerSaveLocation>();
if (saveLocationScript != null)
{
saveLocationScript.TeleportToSavedLocation();
}
}
#endregion
#region Start And Update
void Start()
{
// Construct the base directory path
SetStartingStats(); // Call this method to set starting stats
InitializeStats();
SetCurrentStatsToMax();
// Set the initial values for level and experience
PlayerLevel = 1;
CurrentEXP = 0;
ExpToLevelUp = 250;
string baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA", PlayerName);
// Check if the player's directory exists
if (Directory.Exists(baseDirectory))
{
// Construct the full file path for the player's data file
string filePath = Path.Combine(baseDirectory, $"{PlayerName}_Data.sav");
// Check if the player's data file exists
if (File.Exists(filePath))
{
// Load player data from file
LoadPlayerData(PlayerName);
}
}
}
private void Update()
{
// This Bellow When An Item Is Equipped It Will Update The Stats on Both The UI And The Player
UpdateMaxStats();
// Check if enough time has passed since the last damage or mana/defense depletion
if (!hasEquippedItemRecently && Time.time - lastDamageTime >= 30f)
{
// Increment current health, mana, and defense towards their maximum values over time
if (Time.time - lastRecoveryTime >= 5f) // Check if 5 seconds have passed since last recovery
{
// Increment stats by maxRecovery amount
currentHealth = Mathf.Min(maxHealth, currentHealth + Mathf.RoundToInt(maxRecovery));
currentMana = Mathf.Min(maxMana, currentMana + Mathf.RoundToInt(maxRecovery));
currentDefense = Mathf.Min(maxDefense, currentDefense + Mathf.RoundToInt(maxRecovery));
// Update the last recovery time
lastRecoveryTime = Time.time;
}
}
// Update the time since equipping an item
if (hasEquippedItemRecently)
{
timeSinceEquippingItem += Time.deltaTime;
if (timeSinceEquippingItem >= equipItemRecoveryDelay)
{
// Enough time has passed after equipping an item, reset the flag and trigger recovery
hasEquippedItemRecently = false;
lastDamageTime = Time.time;
}
}
}
#endregion
#region Level Up
public void LevelUp()
{
// Call the LevelUpText method from PlayerLevelUpText script
if (levelUpTextScript != null)
{
levelUpTextScript.ShowLevelUpText();
}
PlayerLevel++;
CurrentEXP -= ExpToLevelUp;
ExpToLevelUp *= 2;
// Update character stats
character.Health.BaseValue += 5 * PlayerLevel;
character.Mana.BaseValue += 2 * PlayerLevel;
character.Defence.BaseValue += 1 * PlayerLevel;
character.Attack.BaseValue += 1 * PlayerLevel;
character.AttackSpeed.BaseValue += 0.008f * PlayerLevel;
character.Critical.BaseValue += 0.05F * PlayerLevel;
character.LifeSteal.BaseValue += 0.5f * PlayerLevel;
character.Range.BaseValue += 0.015f * PlayerLevel;
character.ElementalMastery.BaseValue += 0.13f * PlayerLevel;
character.Cooldown.BaseValue += 0.1f * PlayerLevel;
character.Knockback.BaseValue += 0.025f * PlayerLevel;
character.Speed.BaseValue += 0.005f * PlayerLevel;
character.Recovery.BaseValue += 0.5f * PlayerLevel;
character.Evade.BaseValue += 0.01f * PlayerLevel;
character.Fortune.BaseValue += 0.015f * PlayerLevel;
// Update stat values
character.UpdateStatValues();
// Update max stats
UpdateMaxStats();
// Set current stats to max
SetCurrentStatsToMax();
// Show updated stats on UI
statPanel.SetStats(character.Health, character.Mana, character.Defence, character.Attack , character.AttackSpeed, character.Critical, character.LifeSteal, character.Range, character.ElementalMastery, character.Speed, character.Cooldown, character.Knockback, character.Recovery, character.Evade, character.Fortune);
}
#endregion
private void SetStartingStats()
{
// Set starting stats for the player based on character stats
currentHealth = (int)character.Health.Value;
maxHealth = (int)character.Health.Value;
currentMana = (int)character.Mana.Value;
maxMana = (int)character.Mana.Value;
currentDefense = (int)character.Defence.Value;
maxDefense = (int)character.Defence.Value;
currentAttack = (int)character.Attack.Value;
maxAttack = (int)character.Attack.Value;
currentAttackSpeed = character.AttackSpeed.Value;
maxAttackSpeed = character.AttackSpeed.Value;
currentCritical = (int)character.Critical.Value;
maxCritical = (int)character.Critical.Value;
currentLifeSteal = character.LifeSteal.Value;
maxLifeSteal = character.LifeSteal.Value;
currentRange = character.Range.Value;
maxRange = character.Range.Value;
currentElementalMastery = character.ElementalMastery.Value;
maxElementalMastery = character.ElementalMastery.Value;
currentSpeed = character.Speed.Value;
maxSpeed = character.Speed.Value;
currentCooldown = character.Cooldown.Value;
maxCooldown = character.Cooldown.Value;
currentKnockback = character.Knockback.Value;
maxKnockback = character.Knockback.Value;
currentRecovery = character.Recovery.Value;
maxRecovery = character.Recovery.Value;
currentEvade = character.Evade.Value;
maxEvade = character.Evade.Value;
currentFortune = character.Fortune.Value;
maxFortune = character.Fortune.Value;
// Call UpdateStatValues to apply the changes
character.UpdateStatValues();
// Update max and current stats
UpdateMaxStats();
SetCurrentStatsToMax();
}
// Update the maximum stats of the character
public void UpdateMaxStats()
{
// Update max stats for the player based on character stats
maxHealth = (int)character.Health.Value;
maxMana = (int)character.Mana.Value;
maxDefense = (int)character.Defence.Value;
maxAttack = (int)character.Attack.Value;
maxAttackSpeed = character.AttackSpeed.Value;
maxCritical = (int)character.Critical.Value;
maxLifeSteal = character.LifeSteal.Value;
maxRange = character.Range.Value;
maxElementalMastery = character.ElementalMastery.Value;
maxSpeed = character.Speed.Value;
maxCooldown = character.Cooldown.Value;
maxKnockback = character.Knockback.Value;
maxRecovery = character.Recovery.Value;
maxEvade = character.Evade.Value;
maxFortune = character.Fortune.Value;
}
// Check if any current stats have changed due to equipping items
public void CurrentStatsChange()
{
// Mark that an item has been equipped recently
hasEquippedItemRecently = true;
timeSinceEquippingItem = 0f;
}
public void InitializeStats()
{
// Update max stats
UpdateMaxStats();
// Initialize current stats
maxHealth = Mathf.RoundToInt(character.Health.Value);
currentHealth = maxHealth;
maxMana = Mathf.RoundToInt(character.Mana.Value);
currentMana = maxMana;
maxDefense = Mathf.RoundToInt(character.Defence.Value);
currentDefense = maxDefense;
maxAttack = Mathf.RoundToInt(character.Attack.Value);
currentAttack = maxAttack;
maxAttackSpeed = character.AttackSpeed.Value;
currentAttackSpeed = maxAttackSpeed;
maxCritical = Mathf.RoundToInt(character.Critical.Value);
currentCritical = maxCritical;
maxLifeSteal = Mathf.RoundToInt(character.LifeSteal.Value);
currentLifeSteal = maxLifeSteal;
maxRange = Mathf.RoundToInt(character.Range.Value);
currentRange = maxRange;
maxElementalMastery = Mathf.RoundToInt(character.ElementalMastery.Value);
currentElementalMastery = maxElementalMastery;
maxSpeed = Mathf.RoundToInt(character.Speed.Value);
currentSpeed = maxSpeed;
maxCooldown = character.Cooldown.Value;
currentCooldown = maxCooldown;
maxKnockback = Mathf.RoundToInt(character.Knockback.Value);
currentKnockback = maxKnockback;
maxRecovery = character.Recovery.Value;
currentRecovery = maxRecovery;
maxEvade = character.Evade.Value;
currentEvade = maxEvade;
maxFortune = Mathf.RoundToInt(character.Fortune.Value);
currentFortune = maxFortune;
// Replace UpdateCurrentStats with the appropriate method
// (e.g., SetCurrentStatsToMax or any other method that updates your current stats)
SetCurrentStatsToMax();
}
public void SetCurrentStatsToMax()
{
currentHealth = maxHealth;
currentMana = maxMana;
currentDefense = maxDefense;
currentAttack = maxAttack;
currentAttackSpeed = maxAttackSpeed;
currentCritical = maxCritical;
currentLifeSteal = maxLifeSteal;
currentRange = maxRange;
currentElementalMastery = maxElementalMastery;
currentCooldown = maxCooldown;
currentKnockback = maxKnockback;
currentSpeed = maxSpeed;
currentRecovery = maxRecovery;
currentEvade = maxEvade;
currentFortune = maxFortune;
// Reset the last recovery time to prevent immediate recovery
lastRecoveryTime = Time.time;
}
public void AdjustStatsIfNeeded()
{
// Health
int newMaxHealth = Mathf.RoundToInt(character.Health.Value);
if (newMaxHealth < currentHealth)
{
currentHealth = newMaxHealth;
}
// Mana
int newMaxMana = Mathf.RoundToInt(character.Mana.Value);
if (newMaxMana < currentMana)
{
currentMana = newMaxMana;
}
// Defense
int newMaxDefense = Mathf.RoundToInt(character.Defence.Value);
if (newMaxDefense < currentDefense)
{
currentDefense = newMaxDefense;
}
// Attack
int newMaxAttack = Mathf.RoundToInt(character.Attack.Value);
if (newMaxAttack < currentAttack)
{
currentAttack = newMaxAttack;
}
// Attack Speed
float newMaxAttackSpeed = character.AttackSpeed.Value;
if (newMaxAttackSpeed < currentAttackSpeed)
{
currentAttackSpeed = newMaxAttackSpeed;
}
// Critical
int newMaxCritical = Mathf.RoundToInt(character.Critical.Value);
if (newMaxCritical < currentCritical)
{
currentCritical = newMaxCritical;
}
// LifeSteal
int newMaxLifeSteal = Mathf.RoundToInt(character.LifeSteal.Value);
if (newMaxLifeSteal < currentLifeSteal)
{
currentLifeSteal = newMaxLifeSteal;
}
// Range
int newMaxRange = Mathf.RoundToInt(character.Range.Value);
if (newMaxRange < currentRange)
{
currentRange = newMaxRange;
}
// ElementalMastery
int newMaxElementalMastery = Mathf.RoundToInt(character.ElementalMastery.Value);
if (newMaxElementalMastery < currentElementalMastery)
{
currentElementalMastery = newMaxElementalMastery;
}
// Speed
float newMaxSpeed = character.Speed.Value;
if (newMaxSpeed < currentSpeed)
{
currentSpeed = newMaxSpeed;
}
// Cooldown
float newMaxCooldown = character.Cooldown.Value;
if (newMaxCooldown < currentCooldown)
{
currentCooldown = newMaxCooldown;
}
// Knockback
int newMaxKnockback = Mathf.RoundToInt(character.Knockback.Value);
if (newMaxKnockback < currentKnockback)
{
currentKnockback = newMaxKnockback;
}
// Recovery
float newMaxRecovery = character.Recovery.Value;
if (newMaxRecovery < currentRecovery)
{
currentRecovery = newMaxRecovery;
}
// Evade
float newMaxEvade = character.Evade.Value;
if (newMaxEvade < currentEvade)
{
currentEvade = newMaxEvade;
}
// Fortune
int newMaxFortune = Mathf.RoundToInt(character.Fortune.Value);
if (newMaxFortune < currentFortune)
{
currentFortune = newMaxFortune;
}
CurrentStatsChange();
}
public void IncreaseExperience(int amount)
{
CurrentEXP += amount;
while (CurrentEXP >= ExpToLevelUp)
{
LevelUp();
}
}
public void AddStats(int healthToAdd, int defenseToAdd, int manaToAdd)
{
// Check if adding health would exceed the maximum
if (currentHealth < maxHealth)
{
// Calculate the new health after adding
int newHealth = currentHealth + healthToAdd;
// Ensure the new health doesn't exceed the maximum
newHealth = Mathf.Clamp(newHealth, 0, maxHealth);
// If the new health is different from the current health, apply the change
if (newHealth != currentHealth)
{
currentHealth = newHealth;
CurrentStatsChange(); // Notify stats change if needed
}
}
// Check if adding defense would exceed the maximum
if (currentDefense < maxDefense)
{
// Calculate the new defense after adding
int newDefense = currentDefense + defenseToAdd;
// Ensure the new defense doesn't exceed the maximum
newDefense = Mathf.Clamp(newDefense, 0, maxDefense);
// If the new defense is different from the current defense, apply the change
if (newDefense != currentDefense)
{
currentDefense = newDefense;
CurrentStatsChange(); // Notify stats change if needed
}
}
// Check if adding mana would exceed the maximum
if (currentMana < maxMana)
{
// Calculate the new mana after adding
int newMana = currentMana + manaToAdd;
// Ensure the new mana doesn't exceed the maximum
newMana = Mathf.Clamp(newMana, 0, maxMana);
// If the new mana is different from the current mana, apply the change
if (newMana != currentMana)
{
currentMana = newMana;
CurrentStatsChange(); // Notify stats change if needed
}
}
}
// This allows the UsableItem to start coroutines on the player
public new Coroutine StartCoroutine(IEnumerator routine)
{
return base.StartCoroutine(routine);
}
#region Save And Load System
public void SavePlayerData()
{
// Create a PlayerData object and populate it with current player state
PlayerData data = new PlayerData();
data.playerName = PlayerName;
data.playerLevel = PlayerLevel;
data.currentEXP = CurrentEXP;
data.expToLevelUp = ExpToLevelUp;
data.currentHealth = currentHealth;
data.maxHealth = maxHealth;
data.currentMana = currentMana;
data.maxMana = maxMana;
data.currentDefense = currentDefense;
data.maxDefense = maxDefense;
data.currentAttack = currentAttack;
data.maxAttack = maxAttack;
data.currentAttackSpeed = currentAttackSpeed;
data.maxAttackSpeed = maxAttackSpeed;
data.currentCritical = currentCritical;
data.maxCritical = maxCritical;
data.currentLifeSteal = currentLifeSteal;
data.maxLifeSteal = maxLifeSteal;
data.currentRange = currentRange;
data.maxRange = maxRange;
data.currentElementalMastery = currentElementalMastery;
data.maxElementalMastery = maxElementalMastery;
data.currentSpeed = currentSpeed;
data.maxSpeed = maxSpeed;
data.currentCooldown = currentCooldown;
data.maxCooldown = maxCooldown;
data.currentKnockback = currentKnockback;
data.maxKnockback = maxKnockback;
data.currentRecovery = currentRecovery;
data.maxRecovery = maxRecovery;
data.currentEvade = currentEvade;
data.maxEvade = maxEvade;
data.currentFortune = currentFortune;
data.maxFortune = maxFortune;
data.playerPosX = transform.position.x;
data.playerPosY = transform.position.y;
data.playerPosZ = transform.position.z;
// Adjusted file path
string saveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA", PlayerName);
string fileName = $"{PlayerName}_Data.sav"; // Adjusted file name here
string savePath = Path.Combine(saveDirectory, fileName);
try
{
// Create directory if it doesn't exist
Directory.CreateDirectory(saveDirectory);
using (FileStream fileStream = new FileStream(savePath, FileMode.Create))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fileStream, data);
}
Debug.Log($"<color=#ADD8E6><b>Player data saved successfully</b></color> to: {savePath}");
}
catch (Exception e)
{
Debug.LogError($"<color=red><b>Failed to save player data: {e.Message}</b></color>");
}
}
public void LoadPlayerData(string playerName)
{
// Construct the base directory path
string baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA");
// Check if the base directory exists
if (!Directory.Exists(baseDirectory))
{
Debug.LogWarning("<color=red><b>No saved player data found.</b></color>");
return;
}
// Append the player's folder based on PlayerName
string playerDirectory = Path.Combine(baseDirectory, PlayerName);
// Ensure the player's directory exists
if (!Directory.Exists(playerDirectory))
{
Debug.LogWarning($"<color=red><b>No saved data found for player: {PlayerName}</b></color>");
return;
}
// Construct the full file path
string filePath = Path.Combine(playerDirectory, $"{PlayerName}_Data.sav");
// Check if the file exists
if (File.Exists(filePath))
{
BinaryFormatter formatter = new BinaryFormatter();
try
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
{
PlayerData data = formatter.Deserialize(fileStream) as PlayerData;
// Assign loaded data back to the player (optional, depends on your game's logic)
PlayerName = data.playerName;
PlayerLevel = data.playerLevel;
CurrentEXP = data.currentEXP;
ExpToLevelUp = data.expToLevelUp;
currentHealth = data.currentHealth;
maxHealth = data.maxHealth;
currentMana = data.currentMana;
maxMana = data.maxMana;
currentDefense = data.currentDefense;
maxDefense = data.maxDefense;
currentAttack = data.currentAttack;
maxAttack = data.maxAttack;
currentAttackSpeed = data.currentAttackSpeed;
maxAttackSpeed = data.maxAttackSpeed;
currentCritical = data.currentCritical;
maxCritical = data.maxCritical;
currentLifeSteal = data.currentLifeSteal;
maxLifeSteal = data.maxLifeSteal;
currentRange = data.currentRange;
maxRange = data.maxRange;
currentElementalMastery = data.currentElementalMastery;
maxElementalMastery = data.maxElementalMastery;
currentSpeed = data.currentSpeed;
maxSpeed = data.maxSpeed;
currentCooldown = data.currentCooldown;
maxCooldown = data.maxCooldown;
currentKnockback = data.currentKnockback;
maxKnockback = data.maxKnockback;
currentRecovery = data.currentRecovery;
maxRecovery = data.maxRecovery;
currentEvade = data.currentEvade;
maxEvade = data.maxEvade;
currentFortune = data.currentFortune;
maxFortune = data.maxFortune;
// Assuming 'character' is an instance of the Character class
character.LoadStatsFromData(data);
playerSkill.LoadSkillData(PlayerName);
// Position (example)
Vector3 playerPosition = new Vector3(data.playerPosX, data.playerPosY, data.playerPosZ);
transform.position = playerPosition;
Debug.Log($"<color=#00FF00><b>Loaded PlayerData</b></color>");
}
}
catch (Exception e)
{
Debug.LogError($"<color=red><b>Failed to load player data: {e.Message}</b></color>");
}
}
else
{
Debug.LogWarning("<color=red><b>No saved player data found.</b></color>");
}
}
#endregion
}
when i save i need to save characters base values
and when i load i need to set characters base values to = players max values ASSISTANT
To ensure that the character's base values are saved and loaded correctly, follow these steps to modify your saving and loading logic accordingly:
### 1. Update the `PlayerData` Class
The `PlayerData` class needs to accommodate storing the character's base values. Add fields for these values in your `PlayerData` class. Here's an example of additional fields you might add:
```csharp
[Serializable]
public class PlayerData
{
public string playerName;
public int playerLevel;
public int currentEXP;
public int expToLevelUp;
public int currentHealth;
public int maxHealth;
public int currentMana;
public int maxMana;
public int currentDefense;
public int maxDefense;
public int currentAttack;
public int maxAttack;
public float currentAttackSpeed;
public float maxAttackSpeed;
public int currentCritical;
public int maxCritical;
public float currentLifeSteal;
public float maxLifeSteal;
public float currentRange;
public float maxRange;
public float currentElementalMastery;
public float maxElementalMastery;
public float currentSpeed;
public float maxSpeed;
public float currentCooldown;
public float maxCooldown;
public float currentKnockback;
public float maxKnockback;
public float currentRecovery;
public float maxRecovery;
public float currentEvade;
public float maxEvade;
public float currentFortune;
public float maxFortune;
// Add fields for the character's base values
public float healthBaseValue;
public float manaBaseValue;
public float defenseBaseValue;
public float attackBaseValue;
public float attackSpeedBaseValue;
public float criticalBaseValue;
public float lifeStealBaseValue;
public float rangeBaseValue;
public float elementalMasteryBaseValue;
public float speedBaseValue;
public float cooldownBaseValue;
public float knockbackBaseValue;
public float recoveryBaseValue;
public float evadeBaseValue;
public float fortuneBaseValue;
// Add fields to store position here as needed
public float playerPosX;
public float playerPosY;
public float playerPosZ;
}
```
### 2. Update Saving Logic
When saving, you'll want to ensure the `PlayerData` instance includes the character's current base values. Update the `SavePlayerData` method like this:
```csharp
public void SavePlayerData()
{
PlayerData data = new PlayerData();
data.playerName = PlayerName;
data.playerLevel = PlayerLevel;
data.currentEXP = CurrentEXP;
data.expToLevelUp = ExpToLevelUp;
data.currentHealth = currentHealth;
data.maxHealth = maxHealth;
data.currentMana = currentMana;
data.maxMana = maxMana;
data.currentDefense = currentDefense;
data.maxDefense = maxDefense;
data.currentAttack = currentAttack;
data.maxAttack = maxAttack;
data.currentAttackSpeed = currentAttackSpeed;
data.maxAttackSpeed = maxAttackSpeed;
data.currentCritical = currentCritical;
data.maxCritical = maxCritical;
data.currentLifeSteal = currentLifeSteal;
data.maxLifeSteal = maxLifeSteal;
data.currentRange = currentRange;
data.maxRange = maxRange;
data.currentElementalMastery = currentElementalMastery;
data.maxElementalMastery = maxElementalMastery;
data.currentSpeed = currentSpeed;
data.maxSpeed = maxSpeed;
data.currentCooldown = currentCooldown;
data.maxCooldown = maxCooldown;
data.currentKnockback = currentKnockback;
data.maxKnockback = maxKnockback;
data.currentRecovery = currentRecovery;
data.maxRecovery = maxRecovery;
data.currentEvade = currentEvade;
data.maxEvade = maxEvade;
data.currentFortune = currentFortune;
data.maxFortune = maxFortune;
// Save character base values here
data.healthBaseValue = character.Health.BaseValue;
data.manaBaseValue = character.Mana.BaseValue;
data.defenseBaseValue = character.Defence.BaseValue;
data.attackBaseValue = character.Attack.BaseValue;
data.attackSpeedBaseValue = character.AttackSpeed.BaseValue;
data.criticalBaseValue = character.Critical.BaseValue;
data.lifeStealBaseValue = character.LifeSteal.BaseValue;
data.rangeBaseValue = character.Range.BaseValue;
data.elementalMasteryBaseValue = character.ElementalMastery.BaseValue;
data.speedBaseValue = character.Speed.BaseValue;
data.cooldownBaseValue = character.Cooldown.BaseValue;
data.knockbackBaseValue = character.Knockback.BaseValue;
data.recoveryBaseValue = character.Recovery.BaseValue;
data.evadeBaseValue = character.Evade.BaseValue;
data.fortuneBaseValue = character.Fortune.BaseValue;
data.playerPosX = transform.position.x;
data.playerPosY = transform.position.y;
data.playerPosZ = transform.position.z;
string saveDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA", PlayerName);
try
{
Directory.CreateDirectory(saveDirectory);
string filePath = Path.Combine(saveDirectory, $"{PlayerName}_Data.sav");
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fileStream, data);
}
Debug.Log($"Player data saved successfully to: {saveDirectory}");
}
catch (Exception e)
{
Debug.LogError($"Failed to save player data: {e.Message}");
}
}
```
### 3. Update Loading Logic
When loading, you'll want to set the character's base values to the player's max values stored. Update the `LoadPlayerData` method:
```csharp
public void LoadPlayerData(string playerName)
{
string baseDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "World Of Normies", "SAVE DATA");
if (!Directory.Exists(baseDirectory)) return;
string playerDirectory = Path.Combine(baseDirectory, PlayerName);
if (!Directory.Exists(playerDirectory)) return;
string filePath = Path.Combine(playerDirectory, $"{PlayerName}_Data.sav");
if (File.Exists(filePath))
{
try
{
using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
{
BinaryFormatter formatter = new BinaryFormatter();
PlayerData data = formatter.Deserialize(fileStream) as PlayerData;
PlayerName = data.playerName;
PlayerLevel = data.playerLevel;
CurrentEXP = data.currentEXP;
ExpToLevelUp = data.expToLevelUp;
currentHealth = data.currentHealth;
maxHealth = data.maxHealth;
currentMana = data.currentMana;
maxMana = data.maxMana;
currentDefense = data.currentDefense;
maxDefense = data.maxDefense;
currentAttack = data.currentAttack;
maxAttack = data.maxAttack;
currentAttackSpeed = data.currentAttackSpeed;
maxAttackSpeed = data.maxAttackSpeed;
currentCritical = data.currentCritical;
maxCritical = data.maxCritical;
currentLifeSteal = data.currentLifeSteal;
maxLifeSteal = data.maxLifeSteal;
currentRange = data.currentRange;
maxRange = data.maxRange;
currentElementalMastery = data.currentElementalMastery;
maxElementalMastery = data.maxElementalMastery;
currentSpeed = data.currentSpeed;
maxSpeed = data.maxSpeed;
currentCooldown = data.currentCooldown;
maxCooldown = data.maxCooldown;
currentKnockback = data.currentKnockback;
maxKnockback = data.maxKnockback;
currentRecovery = data.currentRecovery;
maxRecovery = data.maxRecovery;
currentEvade = data.currentEvade;
maxEvade = data.maxEvade;
currentFortune = data.currentFortune;
maxFortune = data.maxFortune;
// Set character base values to the player's max values
character.Health.BaseValue = maxHealth;
character.Mana.BaseValue = maxMana;
character.Defence.BaseValue = maxDefense;
character.Attack.BaseValue = maxAttack;
character.AttackSpeed.BaseValue = maxAttackSpeed;
character.Critical.BaseValue = maxCritical;
character.LifeSteal.BaseValue = maxLifeSteal;
character.Range.BaseValue = maxRange;
character.ElementalMastery.BaseValue = maxElementalMastery;
character.Speed.BaseValue = maxSpeed;
character.Cooldown.BaseValue = maxCooldown;
character.Knockback.BaseValue = maxKnockback;
character.Recovery.BaseValue = maxRecovery;
character.Evade.BaseValue = maxEvade;
character.Fortune.BaseValue = maxFortune;
Vector3 position = new Vector3(data.playerPosX, data.playerPosY, data.playerPosZ);
transform.position = position;
character.UpdateStatValues();
Debug.Log($"Loaded PlayerData: {PlayerName}");
}
}
catch (Exception e)
{
Debug.LogError($"Failed to load player data: {e.Message}");
}
}
else
{
Debug.LogWarning("No saved player data found.");
}
}
```
By following these steps, your save and load logic will handle the character's base values, ensuring they're properly managed between game sessions. This setup ensures consistency between the player's state and the character's attributes each time the game is loaded.