using UnityEngine;
namespace BulletHellTemplate
{
///
/// Manages game data and settings.
///
public class GameInstance : MonoBehaviour
{
[Header("GameData (Scriptables)")]
[Tooltip("Array of character data scriptable objects.")]
public CharacterData[] characterData;
[Tooltip("Array of icon items.")]
public IconItem[] iconItems;
[Tooltip("Array of frame items.")]
public FrameItem[] frameItems;
[Tooltip("Array of inventory items.")]
public InventoryItem[] inventoryItems;
[Tooltip("List of all character types.")]
public CharacterTypeData[] characterTypes;
[Tooltip("Array of all map info data in the game.")]
public MapInfoData[] mapInfoData;
[Tooltip("Array of quest items.")]
public QuestItem[] questData;
[Tooltip("Array of coupon items.")]
public CouponItem[] couponData;
[Header("Controller Reference")]
[Tooltip("Reference to the main character entity.")]
public CharacterEntity characterEntity;
[Header("Account Levels")]
[Tooltip("Information about account levels.")]
public AccountLevel accountLevels;
[Header("Character Mastery")]
[Tooltip("Settings for character mastery.")]
public CharacterMastery characterMastery;
[Header("Mastery Levels")]
[Tooltip("Array of mastery level details.")]
public CharacterMasteryLevel[] masteryLevels;
[Header("Elements Settings")]
[Tooltip("Percentage increase in damage when advantage element.")]
public float advantageDamageIncrease = 0.2f; // 20% increase
[Tooltip("Percentage reduction in damage when weakness element.")]
public float weaknessDamageReduction = 0.2f; // 20% reduction
[Header("Platform Selection")]
[Tooltip("Specifies the platform type to determine the correct UIGameplay.")]
public PlatformType platformType;
[Header("Prefab References")]
[Tooltip("Reference to the UIGameplay for mobile platform.")]
public UIGameplay mobileGameplay;
[Tooltip("Reference to the UIGameplay for desktop platform.")]
public UIGameplay desktopGameplay;
public static GameInstance Singleton;
private bool isInitialized;
///
/// Initializes the GameInstance as a singleton.
///
private void Awake()
{
if (Singleton == null)
{
Singleton = this;
DontDestroyOnLoad(gameObject);
isInitialized = true;
}
else
{
Destroy(gameObject);
}
}
///
/// Checks if the GameInstance has been initialized.
///
/// True if initialized; otherwise, false.
public bool IsInitialized()
{
return isInitialized;
}
///
/// Gets the CharacterData for the selected character.
///
/// The matching CharacterData, or null if not found.
public CharacterData GetCharacterData()
{
foreach (var character in characterData)
{
if (character.characterId == PlayerSave.GetSelectedCharacter())
{
return character;
}
}
Debug.LogWarning($"CharacterData with ID '{PlayerSave.GetSelectedCharacter()}' not found.");
return null;
}
///
/// Gets the icon for a given character type.
///
/// The character type data.
/// The corresponding icon sprite.
public Sprite GetIconForCharacterType(CharacterTypeData characterType)
{
return characterType.icon;
}
///
/// Calculates the total damage with elemental advantages and disadvantages.
///
/// The element of the attacker.
/// The element of the target.
/// The base damage before elemental adjustments.
/// The final damage after applying elemental adjustments.
public float TotalDamageWithElements(CharacterTypeData attackerElement, CharacterTypeData targetElement, float totalDamageWithoutElements)
{
if (attackerElement == null || targetElement == null)
{
Debug.LogWarning("Attacker or target element is null.");
return totalDamageWithoutElements;
}
if (System.Array.Exists(targetElement.weaknesses, element => element == attackerElement))
{
return totalDamageWithoutElements * (1 + advantageDamageIncrease);
}
if (System.Array.Exists(attackerElement.strengths, element => element == targetElement))
{
return totalDamageWithoutElements * (1 - weaknessDamageReduction);
}
return totalDamageWithoutElements;
}
///
/// Gets the UIGameplay instance based on the current platform.
///
/// The corresponding UIGameplay instance for PC or Mobile.
public UIGameplay GetUIGameplayForPlatform()
{
switch (platformType)
{
case PlatformType.PC:
return desktopGameplay;
case PlatformType.Mobile:
return mobileGameplay;
default:
Debug.LogWarning("Unsupported platform type specified.");
return null;
}
}
///
/// Gets the current platform type.
///
/// The platform type.
public PlatformType GetCurrentPlatform()
{
return platformType;
}
public int GetAccountExpForLevel(int level)
{
if (accountLevels.accountExpPerLevel != null && level >= 1 && level < accountLevels.accountExpPerLevel.Length)
{
return accountLevels.accountExpPerLevel[level - 1];
}
Debug.LogWarning("Invalid account level requested.");
return -1;
}
///
/// Gets the required mastery experience for a specific mastery level.
///
/// The mastery level (1-based index).
/// The required experience for the given mastery level, or -1 if level is invalid.
public int GetMasteryExpForLevel(int level)
{
if (characterMastery.masteryExpPerLevel != null && level >= 0 && level < characterMastery.masteryExpPerLevel.Length)
{
return characterMastery.masteryExpPerLevel[level];
}
Debug.LogWarning("Invalid mastery level requested.");
return 0;
}
///
/// Gets the mastery level details for a specific level.
///
/// The mastery level (1-based index).
/// The mastery level details, or a default value if level is invalid.
public CharacterMasteryLevel GetMasteryLevel(int level)
{
if (masteryLevels != null && level < masteryLevels.Length)
{
return masteryLevels[level];
}
Debug.LogWarning("Invalid mastery level requested.");
return masteryLevels[masteryLevels.Length -1];
}
///
/// Automatically fills the mastery experience array based on the calculation method set in 'characterMastery.characterExpCalculationMethod'.
///
public void AutoFillMasteryExp()
{
if (characterMastery.Equals(null))
{
Debug.LogWarning("CharacterMastery is not assigned.");
return;
}
ExpCalculationMethod method = characterMastery.characterExpCalculationMethod;
int maxLevel = characterMastery.maxMasteryLevel;
characterMastery.masteryExpPerLevel = new int[maxLevel];
for (int i = 0; i < maxLevel; i++)
{
int value = 0;
float t = (maxLevel > 1) ? (float)i / (maxLevel - 1) : 0f;
switch (method)
{
case ExpCalculationMethod.Linear:
value = Mathf.RoundToInt(Mathf.Lerp(characterMastery.initialExp, characterMastery.finalExp, t));
break;
case ExpCalculationMethod.Exponential:
if (characterMastery.initialExp <= 0) characterMastery.initialExp = 1;
value = Mathf.RoundToInt(characterMastery.initialExp * Mathf.Pow((float)characterMastery.finalExp / characterMastery.initialExp, t));
break;
case ExpCalculationMethod.Custom:
default:
value = Mathf.RoundToInt(Mathf.Lerp(characterMastery.initialExp, characterMastery.finalExp, t));
break;
}
characterMastery.masteryExpPerLevel[i] = value;
}
}
///
/// Automatically fills the account experience array based on the calculation method set in 'accountLevels.accountExpCalculationMethod'.
///
public void AutoFillAccountExp()
{
if (accountLevels.Equals(null))
{
Debug.LogWarning("AccountLevel is not assigned.");
return;
}
ExpCalculationMethod method = accountLevels.accountExpCalculationMethod;
int maxLevel = accountLevels.accountMaxLevel;
accountLevels.accountExpPerLevel = new int[maxLevel];
for (int i = 0; i < maxLevel; i++)
{
int value = 0;
float t = (maxLevel > 1) ? (float)i / (maxLevel - 1) : 0f;
switch (method)
{
case ExpCalculationMethod.Linear:
value = Mathf.RoundToInt(Mathf.Lerp(accountLevels.initialExp, accountLevels.finalExp, t));
break;
case ExpCalculationMethod.Exponential:
if (accountLevels.initialExp <= 0) accountLevels.initialExp = 1;
value = Mathf.RoundToInt(accountLevels.initialExp * Mathf.Pow((float)accountLevels.finalExp / accountLevels.initialExp, t));
break;
case ExpCalculationMethod.Custom:
default:
value = Mathf.RoundToInt(Mathf.Lerp(accountLevels.initialExp, accountLevels.finalExp, t));
break;
}
accountLevels.accountExpPerLevel[i] = value;
}
}
}
///
/// Represents the available platform types.
///
public enum PlatformType
{
Mobile,
PC
}
[System.Serializable]
public struct AccountLevel
{
[Tooltip("Maximum account level.")]
public int accountMaxLevel;
[Tooltip("Initial EXP for account leveling.")]
public int initialExp;
[Tooltip("Final EXP for the highest account level.")]
public int finalExp;
[Tooltip("Selected calculation method for account EXP progression.")]
public ExpCalculationMethod accountExpCalculationMethod;
[Tooltip("EXP required per account level.")]
public int[] accountExpPerLevel;
}
///
/// Represents the character mastery settings.
///
[System.Serializable]
public struct CharacterMastery
{
[Tooltip("Maximum mastery level.")]
public int maxMasteryLevel;
[Tooltip("Initial EXP for mastery leveling.")]
public int initialExp;
[Tooltip("Final EXP for the highest mastery level.")]
public int finalExp;
[Tooltip("Selected calculation method for mastery EXP progression.")]
public ExpCalculationMethod characterExpCalculationMethod;
[Tooltip("Experience points required per mastery level.")]
public int[] masteryExpPerLevel;
}
///
/// Represents the details for a specific mastery level.
///
[System.Serializable]
public struct CharacterMasteryLevel
{
[Tooltip("Name of the mastery level.")]
public string masteryName;
[Tooltip("Translated name of the mastery level.")]
public NameTranslatedByLanguage[] masteryNameTranslated;
[Tooltip("Icon representing the mastery level.")]
public Sprite masteryIcon;
}
///
/// Contains translation data for a name by language.
///
[System.Serializable]
public struct NameTranslatedByLanguage
{
public string LanguageId;
public string Translate;
}
///
/// Contains translation data for a description by language.
///
[System.Serializable]
public struct DescriptionTranslatedByLanguage
{
public string LanguageId;
[TextArea]
public string Translate;
}
///
/// Methods for calculating experience progression.
///
public enum ExpCalculationMethod
{
Linear,
Exponential,
Custom
}
}