using UnityEngine;
using UnityEngine.Events;
///
/// Хранит и управляет балансом кредитов обоих игроков.
/// Инициализируется всегда — независимо от режима ввода (клавиатура или COM).
/// COM-плата пишет монеты через CreditSystem.AddImpulse(), а не напрямую в UI.
///
public class CreditSystem : MonoBehaviour
{
[SerializeField] private bool saveMoneyBetweenSessions;
// ── Events ───────────────────────────────────────────────────────────────
public static UnityEvent onCoinAdded;
public static UnityEvent onCoinRemoved;
public static System.Action OnInitialize;
public static event System.Action OnInsufficientFunds;
// ── Private data ──────────────────────────────────────────────────────────
private static int _creditsPlayer1;
private static int _creditsPlayer2;
// ── Prices (read from PlayerPrefs, same keys as AdminContactsController) ──
/// Сколько кредитов даёт один физический импульс (монета). Минимум 1.
public static int ImpulsePrice => ParsePositive(PlayerPrefs.GetString("ImpulsePrice", "1"), 1);
/// Стоимость игры с ботом в кредитах. Минимум 1.
public static int BotGamePrice => ParsePositive(PlayerPrefs.GetString("PriceBotGame", "1"), 1);
/// Стоимость игры с другом в кредитах. Минимум 1.
public static int PlayerGamePrice => ParsePositive(PlayerPrefs.GetString("PricePlayerGame", "1"), 1);
/// Цена реванша с ботом — рассчитывается через скидку из настроек.
[System.Obsolete("Используй PayBotGame(isReplay, playerId) — он сам считает скидку из настроек.")]
public static int BotReplayPrice => Mathf.Max(1, BotGamePrice / 2);
private static int ParsePositive(string s, int fallback)
=> (int.TryParse(s, out int r) && r > 0) ? r : fallback;
// ── Shared balance ────────────────────────────────────────────────────────
///
/// true — включён режим общего баланса: оба игрока видят единый пул кредитов.
///
public static bool IsSharedBalance()
=> SettingsManager.instance != null &&
SettingsManager.instance.GetSettingValue("Общий баланс") == "Вкл";
// ── Init ──────────────────────────────────────────────────────────────────
public void Initialize()
{
onCoinAdded = new UnityEvent();
onCoinRemoved = new UnityEvent();
if (!saveMoneyBetweenSessions)
{
PlayerPrefs.SetInt("Player1_Coins", 0);
PlayerPrefs.SetInt("Player2_Coins", 0);
}
_creditsPlayer1 = PlayerPrefs.GetInt("Player1_Coins", 0);
_creditsPlayer2 = PlayerPrefs.GetInt("Player2_Coins", 0);
// При общем балансе синхронизируем — источник истины Player1_Coins
if (IsSharedBalance())
{
_creditsPlayer2 = _creditsPlayer1;
PlayerPrefs.SetInt("Player2_Coins", _creditsPlayer2);
}
OnInitialize?.Invoke();
}
// ── Public API ────────────────────────────────────────────────────────────
///
/// Пополняет баланс на один физический импульс (монету):
/// добавляет ImpulsePrice кредитов и считает монету в счётчике призовой системы.
/// Вызывается из ComWrapper и Player.cs при приёме монеты.
///
public static void AddImpulse(int playerId = 1)
{
AddCredit(ImpulsePrice, playerId);
// Счётчик физических монет для призовой системы
PlayerPrefs.SetInt(PrizeSystem.key_starts, PlayerPrefs.GetInt(PrizeSystem.key_starts) + 1);
PlayerPrefs.SetInt(PrizeSystem.key_startsNul, PlayerPrefs.GetInt(PrizeSystem.key_startsNul) + 1);
}
///
/// Добавляет точное количество кредитов (используется для возвратов/рефандов).
/// НЕ трогает счётчики призовой системы.
///
public static void AddCredit(int coins = 1, int playerId = 1)
{
if (IsSharedBalance())
{
// Единый пул — пишем в Player1, синхронизируем Player2, уведомляем оба UI
_creditsPlayer1 += coins;
_creditsPlayer2 = _creditsPlayer1;
PlayerPrefs.SetInt("Player1_Coins", _creditsPlayer1);
PlayerPrefs.SetInt("Player2_Coins", _creditsPlayer2);
onCoinAdded?.Invoke(1, _creditsPlayer1);
onCoinAdded?.Invoke(2, _creditsPlayer2);
return;
}
if (playerId == 1)
{
_creditsPlayer1 += coins;
PlayerPrefs.SetInt("Player1_Coins", _creditsPlayer1);
onCoinAdded?.Invoke(playerId, _creditsPlayer1);
}
else if (playerId == 2)
{
_creditsPlayer2 += coins;
PlayerPrefs.SetInt("Player2_Coins", _creditsPlayer2);
onCoinAdded?.Invoke(playerId, _creditsPlayer2);
}
}
/// Списывает кредиты за старт игры. Возвращает false если денег нет.
public static bool Pay(int coins = 1, int playerId = 1)
{
if (SettingsManager.instance.GetSettingValue("Бесплатная игра") == "Вкл") return true;
if (IsSharedBalance())
{
// Единый пул — списываем из Player1, синхронизируем Player2, уведомляем оба UI
if (_creditsPlayer1 >= coins)
{
_creditsPlayer1 -= coins;
_creditsPlayer2 = _creditsPlayer1;
PlayerPrefs.SetInt("Player1_Coins", _creditsPlayer1);
PlayerPrefs.SetInt("Player2_Coins", _creditsPlayer2);
onCoinRemoved?.Invoke(1, _creditsPlayer1);
onCoinRemoved?.Invoke(2, _creditsPlayer2);
return true;
}
OnInsufficientFunds?.Invoke(playerId);
return false;
}
ref int credits = ref (playerId == 1 ? ref _creditsPlayer1 : ref _creditsPlayer2);
string key = playerId == 1 ? "Player1_Coins" : "Player2_Coins";
if (credits >= coins)
{
credits -= coins;
PlayerPrefs.SetInt(key, credits);
onCoinRemoved?.Invoke(playerId, credits);
return true;
}
OnInsufficientFunds?.Invoke(playerId);
return false;
}
///
/// Возвращает эффективную стоимость игры с ботом с учётом скидки за реванш.
/// Используется и для списания (PayBotGame) и для проверки баланса в UI.
///
public static int GetEffectiveBotPrice(bool isReplay)
{
int price = BotGamePrice;
if (isReplay && SettingsManager.instance != null)
{
bool discountOn = SettingsManager.instance.GetSettingValue("Скидка за реванш при игре с ботом") == "Вкл";
if (discountOn)
{
string pctStr = SettingsManager.instance.GetSettingValue("Размер скидки за реванш");
if (int.TryParse(pctStr, out int pct) && pct > 0 && pct < 100)
price = Mathf.Max(1, price - price * pct / 100);
}
}
return price;
}
///
/// Списывает кредиты за игру с ботом.
/// Если isReplay=true и в настройках включена скидка — применяет % скидку.
///
public static bool PayBotGame(bool isReplay, int playerId)
{
return Pay(GetEffectiveBotPrice(isReplay), playerId);
}
/// Возвращает текущий баланс игрока.
public static int GetPlayerCredits(int playerId = 1)
{
if (IsSharedBalance()) return _creditsPlayer1;
return playerId == 1 ? _creditsPlayer1 : _creditsPlayer2;
}
}