531 lines
19 KiB
C#
531 lines
19 KiB
C#
using BulletHellTemplate.PVP;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace BulletHellTemplate
|
|
{
|
|
/// <summary>
|
|
/// Manages game data and settings.
|
|
/// </summary>
|
|
public class GameInstance : MonoBehaviour
|
|
{
|
|
[Tooltip("Array of currency GameData.")]
|
|
public List<Currency> currencyData = new List<Currency>();
|
|
|
|
[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;
|
|
|
|
[Tooltip("Array of shop items.")]
|
|
public ShopItem[] shopData;
|
|
|
|
[Tooltip("Array of battle pass items.")]
|
|
public BattlePassItem[] battlePassData;
|
|
|
|
[Tooltip("Rewards for new players, typically one per day.")]
|
|
public RewardItem[] newPlayerRewardItems;
|
|
|
|
[Tooltip("All daily reward items for each day.")]
|
|
public RewardItem[] dailyRewardItems;
|
|
|
|
[Header("PVP")]
|
|
public PvpModeData[] pvpModes;
|
|
|
|
[Header("Password Length Rules")]
|
|
[Tooltip("Minimum number of characters required in the password.")]
|
|
public int minPasswordLength = 8;
|
|
|
|
[Tooltip("Maximum number of characters allowed in the password.")]
|
|
public int maxPasswordLength = 20;
|
|
|
|
[Header("Password Complexity Requirements")]
|
|
[Tooltip("Whether at least one uppercase letter is required.")]
|
|
public bool requireUppercase = false;
|
|
|
|
[Tooltip("Whether at least one lowercase letter is required.")]
|
|
public bool requireLowercase = false;
|
|
|
|
[Tooltip("Whether at least one numeric digit is required.")]
|
|
public bool requireNumbers = false;
|
|
|
|
[Tooltip("Whether at least one special character (!@#...) is required.")]
|
|
public bool requireSpecial = false;
|
|
|
|
[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;
|
|
|
|
[Tooltip("Percentage reduction in damage when weakness element.")]
|
|
public float weaknessDamageReduction = 0.2f;
|
|
|
|
[Header("BattlePass earn EXP for winning?")]
|
|
[Tooltip("Battle Pass EXP awarded for winning a match")]
|
|
public int BattlePassEXP = 210;
|
|
|
|
public int battlePassDurationDays = 60;
|
|
|
|
[Header("Map Name MainMenu")]
|
|
[Tooltip("Name of the main menu scene")]
|
|
public string mainMenuScene = "Home";
|
|
|
|
[Header("Currency earned in matches")]
|
|
[Tooltip("Currency used in the game")]
|
|
public string goldCurrency = "GO";
|
|
|
|
[Header("Battle Pass Settings")]
|
|
public int maxLevelPass = 100; // Maximum level for the Battle Pass
|
|
public float baseExpPass = 1000;
|
|
public int SeasonLengthInDays = 30;
|
|
[Header("0.1 = 10% more at each level // 1 = 100% more")]
|
|
public float incPerLevelPass = 0.1f;
|
|
public string battlePassCurrencyID = "DM"; // Currency ID for purchasing the Battle Pass
|
|
public int battlePassPrice = 1000; // Price of the Battle Pass
|
|
|
|
[Tooltip("Currency ID used for name change.")]
|
|
public string changeNameTick = "TKN";
|
|
|
|
[Tooltip("Minimum length for the player's name.")]
|
|
public int minNameLength = 3;
|
|
|
|
[Tooltip("Maximum length for the player's name.")]
|
|
public int maxNameLength = 20;
|
|
|
|
[Tooltip("Number of tickets required to change the player's name.")]
|
|
public int ticketsToChange = 1;
|
|
|
|
[Tooltip("Indicates if a ticket is required for name change.")]
|
|
public bool needTicket;
|
|
|
|
[Header("Platform Selection")]
|
|
[Tooltip("Specifies the platform type to determine the correct UIGameplay.")]
|
|
public PlatformType platformType;
|
|
|
|
public WorldType worldType = WorldType.World3D;
|
|
|
|
[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;
|
|
|
|
/// <summary>
|
|
/// Initializes the GameInstance as a singleton.
|
|
/// </summary>
|
|
private void Awake()
|
|
{
|
|
if (Singleton == null)
|
|
{
|
|
Singleton = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
isInitialized = true;
|
|
}
|
|
else
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the GameInstance has been initialized.
|
|
/// </summary>
|
|
/// <returns>True if initialized; otherwise, false.</returns>
|
|
public bool IsInitialized()
|
|
{
|
|
return isInitialized;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the CharacterData for the currently selected character.
|
|
/// </summary>
|
|
/// <returns>The matching CharacterData, or null if not found.</returns>
|
|
public CharacterData GetCharacterData()
|
|
{
|
|
int selectedId = PlayerSave.GetSelectedCharacter();
|
|
var character = characterData.FirstOrDefault(c => c.characterId == selectedId);
|
|
if (character == null)
|
|
Debug.LogWarning($"CharacterData with ID '{selectedId}' not found.");
|
|
return character;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the character data that matches the given ID.
|
|
/// </summary>
|
|
public CharacterData GetCharacterDataById(int charId) =>
|
|
characterData.FirstOrDefault(c => c.characterId == charId);
|
|
|
|
/// <summary>
|
|
/// Returns the inventory item that matches the given ID.
|
|
/// </summary>
|
|
public InventoryItem GetInventoryItemById(string id) =>
|
|
inventoryItems.FirstOrDefault(i => i.itemId == id);
|
|
|
|
/// <summary>
|
|
/// Returns the quest item that matches the given ID.
|
|
/// </summary>
|
|
public QuestItem GetQuestItemById(int id) =>
|
|
questData.FirstOrDefault(q => q.questId == id);
|
|
|
|
/// <summary>
|
|
/// Returns the IconItem that matches the given ID.
|
|
/// </summary>
|
|
public IconItem GetIconItemById(string id) =>
|
|
iconItems.FirstOrDefault(i => i.iconId == id);
|
|
|
|
/// <summary>
|
|
/// Returns the FrameItem that matches the given ID.
|
|
/// </summary>
|
|
public FrameItem GetFrameItemById(string id) =>
|
|
frameItems.FirstOrDefault(f => f.frameId == id);
|
|
|
|
/// <summary>
|
|
/// Returns the CouponItem that matches the given ID.
|
|
/// </summary>
|
|
public CouponItem GetCouponItemById(string id) =>
|
|
couponData.FirstOrDefault(c => c.idCoupon == id);
|
|
|
|
/// <summary>
|
|
/// Returns the MapInfoData that matches the given ID.
|
|
/// </summary>
|
|
public MapInfoData GetMapInfoDataById(int mapId) =>
|
|
mapInfoData.FirstOrDefault(m => m.mapId == mapId);
|
|
|
|
public PvpModeData GetPvpModeByKey(string key)
|
|
{
|
|
foreach (var m in pvpModes)
|
|
if (m && m.GetModeKey() == key) return m;
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the icon for a given character type.
|
|
/// </summary>
|
|
/// <param name="characterType">The character type data.</param>
|
|
/// <returns>The corresponding icon sprite.</returns>
|
|
public Sprite GetIconForCharacterType(CharacterTypeData characterType) =>
|
|
characterType.icon;
|
|
|
|
/// <summary>
|
|
/// Gets the required account experience for a specific level.
|
|
/// </summary>
|
|
/// <param name="level">The account level (1-based index).</param>
|
|
/// <returns>The required experience, or -1 if level is invalid.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the required mastery experience for a specific mastery level.
|
|
/// </summary>
|
|
/// <param name="level">The mastery level (0-based index).</param>
|
|
/// <returns>The required experience, or -1 if level is invalid.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the mastery level details for a specific level.
|
|
/// </summary>
|
|
/// <param name="level">The mastery level (1-based index).</param>
|
|
/// <returns>The mastery level details, or a default value if level is invalid.</returns>
|
|
public CharacterMasteryLevel GetMasteryLevel(int level)
|
|
{
|
|
if (masteryLevels != null && level >= 0 && level < masteryLevels.Length)
|
|
{
|
|
return masteryLevels[level];
|
|
}
|
|
Debug.LogWarning("Invalid mastery level requested.");
|
|
return masteryLevels[masteryLevels.Length - 1];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the UIGameplay instance based on the current platform.
|
|
/// </summary>
|
|
/// <returns>The corresponding UIGameplay instance for PC or Mobile.</returns>
|
|
public UIGameplay GetUIGameplayForPlatform()
|
|
{
|
|
switch (platformType)
|
|
{
|
|
case PlatformType.PC:
|
|
return desktopGameplay;
|
|
case PlatformType.Mobile:
|
|
return mobileGameplay;
|
|
default:
|
|
Debug.LogWarning("Unsupported platform type specified.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the current platform type.
|
|
/// </summary>
|
|
/// <returns>The platform type.</returns>
|
|
public PlatformType GetCurrentPlatform() => platformType;
|
|
|
|
public WorldType GetCurrentWorldType() => worldType;
|
|
|
|
/// <summary>
|
|
/// Automatically fills the mastery experience array based on the calculation method set in 'characterMastery.characterExpCalculationMethod'.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Calculates the total damage with elemental advantages and disadvantages.
|
|
/// </summary>
|
|
/// <param name="attackerElement">The element of the attacker.</param>
|
|
/// <param name="targetElement">The element of the target.</param>
|
|
/// <param name="totalDamageWithoutElements">The base damage before elemental adjustments.</param>
|
|
/// <returns>The final damage after applying elemental adjustments.</returns>
|
|
public float TotalDamageWithElements(CharacterTypeData attackerElement, CharacterTypeData targetElement, float baseDamage)
|
|
{
|
|
if (attackerElement == null || targetElement == null)
|
|
return baseDamage;
|
|
|
|
bool advantage =
|
|
Array.Exists(attackerElement.strengths, e => e == targetElement) ||
|
|
Array.Exists(targetElement.weaknesses, e => e == attackerElement);
|
|
|
|
bool disadvantage =
|
|
Array.Exists(attackerElement.weaknesses, e => e == targetElement) ||
|
|
Array.Exists(targetElement.strengths, e => e == attackerElement);
|
|
|
|
if (advantage && !disadvantage)
|
|
return baseDamage * (1f + advantageDamageIncrease);
|
|
|
|
if (disadvantage && !advantage)
|
|
return baseDamage * (1f - weaknessDamageReduction);
|
|
|
|
return baseDamage;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Automatically fills the account experience array based on the calculation method set in 'accountLevels.accountExpCalculationMethod'.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents the available platform types.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents the character mastery settings.
|
|
/// </summary>
|
|
[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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents the details for a specific mastery level.
|
|
/// </summary>
|
|
[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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Contains translation data for a name by language.
|
|
/// </summary>
|
|
[System.Serializable]
|
|
public struct NameTranslatedByLanguage
|
|
{
|
|
public string LanguageId;
|
|
public string Translate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Contains translation data for a description by language.
|
|
/// </summary>
|
|
[System.Serializable]
|
|
public struct DescriptionTranslatedByLanguage
|
|
{
|
|
public string LanguageId;
|
|
|
|
[TextArea]
|
|
public string Translate;
|
|
}
|
|
/// <summary>
|
|
/// Methods for calculating experience progression.
|
|
/// </summary>
|
|
[System.Serializable]
|
|
public enum ExpCalculationMethod
|
|
{
|
|
Linear,
|
|
Exponential,
|
|
Custom
|
|
}
|
|
[System.Serializable]
|
|
public enum WorldType
|
|
{
|
|
World3D,
|
|
World2D
|
|
}
|
|
}
|