606 lines
18 KiB
C#
606 lines
18 KiB
C#
using CharacterSystem;
|
||
using PrizeSystem;
|
||
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
public enum GameMode { pve, pvp }
|
||
public class GameManager : MonoBehaviour
|
||
{
|
||
public static event Action<GameMode> OnGameStarted;
|
||
public static event Action<GameMode> OnGameFinished;
|
||
public event Action OnRoundStarted;
|
||
|
||
public PlayerStatsService StatsService;
|
||
|
||
public int botsAmount = 5;
|
||
|
||
[Header("General")]
|
||
public static GameManager Instance;
|
||
public GameObject AdminPanel, NumberPanel;
|
||
public TimerManager timerManager;
|
||
public RulesController rulesController;
|
||
|
||
public ChipPointer chipPointer;
|
||
|
||
[Header("Menu")]
|
||
public GameMode gameMode;
|
||
[HideInInspector] public Team currentPlayer = Team.Player2;
|
||
|
||
[Header("Scores")]
|
||
public int player1score = 0, player2score = 0, vsBotScore = 0;
|
||
|
||
private bool increaseVsBotTimer = false;
|
||
public int vsBotMoves;
|
||
public float vsBotThinkTime;
|
||
|
||
[HideInInspector]
|
||
public CheckResult lastResult;
|
||
|
||
[Header("Gameplay")]
|
||
public GameObject player1Chip;
|
||
public GameObject player2Chip;
|
||
public GameObject botChip;
|
||
public Chip chipPrefab;
|
||
[HideInInspector] public Chip currentChip;
|
||
|
||
public bool canReturnToMenu = false; //todo: разобраться нафига эта переменная
|
||
|
||
[Header("Панели ввода")]
|
||
public TextInput nameInput;
|
||
public Leaderboard leaderboard;
|
||
public GameObject CharactersConfigurator;
|
||
|
||
|
||
[Header("Переходы")]
|
||
[SerializeField] private MenuGameplayTransit menuGameplayTransit;
|
||
[SerializeField] private BackToMenuController _backToMenu;
|
||
|
||
[SerializeField] TurnManager turnManager;
|
||
[SerializeField] private FieldCleaner _fieldCleaner;
|
||
public EndGameHandler endGameHandler;
|
||
|
||
public TurnTracker turnTracker;
|
||
|
||
public GameObject setPasswordPanel;
|
||
//public EnterPasswordPanel enterPasswordPanel;
|
||
|
||
public VitrinaPanel vitrinaPanel;
|
||
public QrPanel qrPanel;
|
||
public TakeOrRiskPanel takeOrRiskPanel;
|
||
|
||
private const int PvpWinningScore = 5;
|
||
private const int VictoryNameLength = 10;
|
||
private bool _isLeavingGameplay;
|
||
private int _paidEntryAmount;
|
||
private bool _canRefundEntry;
|
||
private bool _returnToMenuAfterPrize;
|
||
|
||
public void Initialize()
|
||
{
|
||
if (Instance == null)
|
||
{
|
||
Instance = this;
|
||
}
|
||
ComWrapper.PaymentReceived += ProcessDifficultyCounter;
|
||
|
||
ProcessDifficultyCounter();
|
||
SettingsManager.OnSettingsChanged+=ProcessDifficultyCounter;
|
||
|
||
StatsService = new();
|
||
StatsService.Initialize();
|
||
|
||
timerManager.TimerEnded -= turnManager.HandleTimerEnded;
|
||
timerManager.TimerEnded += turnManager.HandleTimerEnded;
|
||
|
||
StartCoroutine(AddBotRecordEvery2Days());// добавлять каждые 2 дня запись
|
||
//stateMachine.ChangeState(new MenuState());
|
||
}
|
||
|
||
public void TryEnterGame(GameMode mode)
|
||
{
|
||
int entryPrice = PaymentSystem.GetModePrice(mode);
|
||
if (!PaymentSystem.TryPayForMode(mode))
|
||
return;
|
||
|
||
_paidEntryAmount = PaymentSystem.Freeplay ? 0 : entryPrice;
|
||
_canRefundEntry = true;
|
||
SetMode(mode);
|
||
_isLeavingGameplay = false;
|
||
|
||
if (mode == GameMode.pvp)
|
||
{
|
||
ResetPvpScores();
|
||
CharactersController.I.SuspendForPvp();
|
||
}
|
||
|
||
if (mode == GameMode.pve)
|
||
CharactersController.I.ApplyFirstCharacterColorsToBoard();
|
||
else
|
||
Board.Instance.ApplyPvpColors();
|
||
|
||
menuGameplayTransit.GameplayOpened += OnGameplayOpened;
|
||
menuGameplayTransit.GotoGameplay();
|
||
ControlsPerformer.Instance.SetControlable(null);
|
||
}
|
||
|
||
void OnGameplayOpened()
|
||
{
|
||
menuGameplayTransit.GameplayOpened -= OnGameplayOpened;
|
||
turnTracker.ResetTracking();
|
||
_backToMenu.Show();
|
||
OnGameStarted?.Invoke(gameMode);
|
||
|
||
if (gameMode == GameMode.pve)
|
||
{
|
||
_fieldCleaner.Clear();
|
||
CharactersController.I.StartSession(StartRound);
|
||
}
|
||
else
|
||
{
|
||
if (DualAvatarController.Instance != null)
|
||
DualAvatarController.Instance.ShowCharacters(StartRound);
|
||
else
|
||
StartRound();
|
||
}
|
||
}
|
||
|
||
private void OnApplicationQuit()
|
||
{
|
||
ComWrapper.Shutdown();
|
||
ComNativeWrapper.Serial_CloseAll();
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
if (increaseVsBotTimer)
|
||
vsBotThinkTime += Time.deltaTime;
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
if (timerManager != null && turnManager != null)
|
||
timerManager.TimerEnded -= turnManager.HandleTimerEnded;
|
||
|
||
if (nameInput != null)
|
||
nameInput.OnComplete -= HandleVictoryNameEntered;
|
||
|
||
UnsubscribeFromPrizePanels();
|
||
}
|
||
|
||
public void GotoMenu()
|
||
{
|
||
if (_isLeavingGameplay)
|
||
return;
|
||
|
||
RefundEntryIfAvailable();
|
||
_isLeavingGameplay = true;
|
||
CancelPrizeFlow();
|
||
VitrinaView.Instance?.Deactivate();
|
||
ControlsPerformer.Instance.SetControlable(null);
|
||
timerManager.HideBars();
|
||
VideoUtility.CrossFadeToMenu();
|
||
turnManager.CancelPlayerPreparation();
|
||
_fieldCleaner.Clear();
|
||
|
||
if (gameMode == GameMode.pve)
|
||
{
|
||
CharactersController.I.ReturnToMenu();
|
||
}
|
||
else
|
||
{
|
||
DualAvatarController.Instance?.HideCharacters();
|
||
CharactersController.I.PreloadMenuCharacter();
|
||
}
|
||
|
||
OnGameFinished?.Invoke(gameMode);
|
||
menuGameplayTransit.GotoMenu();
|
||
}
|
||
|
||
public void StartVsBotTimer() => increaseVsBotTimer = true;
|
||
public void StopVsBotTimer() => increaseVsBotTimer = false;
|
||
|
||
public void SwitchPlayer()
|
||
{
|
||
currentPlayer = currentPlayer == Team.Player1 ? Team.Player2 : Team.Player1;
|
||
}
|
||
|
||
public void SetMode(GameMode mode) => gameMode = mode;
|
||
|
||
public void EnableEarlyMenuExit() => _backToMenu.EnableExit();
|
||
|
||
public void DisableEarlyMenuExit()
|
||
{
|
||
_paidEntryAmount = 0;
|
||
_canRefundEntry = false;
|
||
_backToMenu.Hide();
|
||
}
|
||
|
||
public void PerformRevenge()
|
||
=> ContinueAfterPveLoss();
|
||
|
||
public void PerformDrawRevenge()
|
||
=> ContinueAfterPveDraw();
|
||
|
||
public void ContinueAfterPveWin()
|
||
{
|
||
if (CharactersController.HasActiveCharacter)
|
||
CharactersController.CurrentCharacter.difficultyModule.IncreaseDifficulty();
|
||
|
||
int nextCharacterIndex = CharactersController.CharacterIndex + 1;
|
||
|
||
if (nextCharacterIndex >= CharactersController.CharactersAmount)
|
||
{
|
||
GotoMenu();
|
||
return;
|
||
}
|
||
|
||
StartPveRound(nextCharacterIndex);
|
||
}
|
||
|
||
public bool TryStartPvePrizeFlow()
|
||
{
|
||
if (gameMode != GameMode.pve
|
||
|| !SettingsManager.GetBool(SettingKey.PRIZING)
|
||
|| !CharactersController.HasActiveCharacter)
|
||
return false;
|
||
|
||
if (!CharactersController.I.TryFetchCurrentPrizes(out List<Prize> configuredPrizes))
|
||
return false;
|
||
|
||
List<Prize> availablePrizes = GetAvailablePrizes(configuredPrizes);
|
||
|
||
if (availablePrizes.Count == 0)
|
||
return false;
|
||
|
||
bool isLastBot = CharactersController.CharacterIndex >= CharactersController.CharactersAmount - 1;
|
||
bool takeOrRiskEnabled = SettingsManager.GetBool(SettingKey.TAKE_OR_RISK);
|
||
bool continueAvailable = takeOrRiskEnabled && !isLastBot;
|
||
_returnToMenuAfterPrize = continueAvailable;
|
||
|
||
if (availablePrizes.Count > 1 || continueAvailable)
|
||
{
|
||
SubscribeToPrizePanels();
|
||
takeOrRiskPanel.Open(availablePrizes, continueAvailable, GetNextBotPrize());
|
||
}
|
||
else
|
||
{
|
||
StartPrizeIssue(availablePrizes[0]);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public void ShowFinalVictoryNameInput()
|
||
{
|
||
ControlsPerformer.Instance.SetControlable(null);
|
||
nameInput.OnComplete -= HandleVictoryNameEntered;
|
||
nameInput.OnComplete += HandleVictoryNameEntered;
|
||
nameInput.SetDestroyOnComplete(false);
|
||
nameInput.gameObject.SetActive(true);
|
||
nameInput.Initialize(VictoryNameLength, Alphabets.RUS_AND_DIGITS);
|
||
ControlsPerformer.Instance.SetControlable(nameInput);
|
||
}
|
||
|
||
public void ContinueAfterPveLoss()
|
||
{
|
||
if (CharactersController.HasActiveCharacter)
|
||
CharactersController.CurrentCharacter.difficultyModule.DecreaseDifficulty();
|
||
|
||
int previousCharacterIndex = Mathf.Max(CharactersController.CharacterIndex - 1, 0);
|
||
StartPveRound(previousCharacterIndex);
|
||
}
|
||
|
||
public void ContinueAfterPveDraw()
|
||
=> StartPveRound(CharactersController.CharacterIndex);
|
||
|
||
public void ContinueAfterPvpRound()
|
||
{
|
||
_fieldCleaner.Clear();
|
||
StartRound();
|
||
}
|
||
|
||
public void RestartPvpMatch()
|
||
{
|
||
ResetPvpScores();
|
||
ContinueAfterPvpRound();
|
||
}
|
||
|
||
public void IncreaseScore(Team player)
|
||
{
|
||
if (player == Team.Player1)
|
||
player1score += 1;
|
||
else
|
||
player2score += 1;
|
||
|
||
timerManager.RefreshPvpScores();
|
||
}
|
||
|
||
public bool HasPvpMatchWinner(Team player)
|
||
=> player == Team.Player1 ? player1score >= PvpWinningScore : player2score >= PvpWinningScore;
|
||
|
||
public void ProcessDifficultyCounter()//вызывается каждый раз, когда приходит COIN с платы или обновились настройки
|
||
{
|
||
string previous = PlayerPrefs.GetString("PreviousBaseBotDifficulty", "Прохождение");
|
||
string difficultyType = SettingsManager.GetString(SettingKey.DIFFICULTY_MODE);
|
||
|
||
//Инициализация
|
||
if (!PlayerPrefs.HasKey("PulsesToResetDifficulty"))
|
||
PlayerPrefs.SetInt("PulsesToResetDifficulty", 100);
|
||
|
||
//если переход с повышенной на обычную - сброс счетчика
|
||
if (previous == "Заработок" && difficultyType != previous)
|
||
{
|
||
PaymentSystem.ResetPulsesCounter();
|
||
}
|
||
PlayerPrefs.SetString("PreviousBaseBotDifficulty", difficultyType);
|
||
|
||
|
||
if (difficultyType == "Заработок")
|
||
{
|
||
int pulses = PaymentSystem.PulsesCounter;
|
||
int pulsesToResetDifficulty = PlayerPrefs.GetInt("PulsesToResetDifficulty", 10);
|
||
|
||
//todo: разобраться
|
||
//if (pulses >= pulsesToResetDifficulty)
|
||
//{
|
||
// PaymentSystem.ResetPulsesCounter();
|
||
//Setting difficultySetting = SettingsManager.Container.TryGetSetting(SettingKeys.DIFFICULTY_MODE);
|
||
// difficultySetting.StringValue = "Прохождение";
|
||
// SettingsManager.OnSettingsChanged?.Invoke();
|
||
// SettingsManager.SaveContainerToFile();
|
||
// AdminPanel.GetComponent<SettingsScreen>().RefreshViews();
|
||
// print("Сложность сброшена");
|
||
//}
|
||
}
|
||
}
|
||
|
||
public void PrepareRound(Team firstPlayer)
|
||
{
|
||
currentPlayer = firstPlayer;
|
||
|
||
timerManager.SetupTimers(gameMode);
|
||
if (gameMode == GameMode.pve)
|
||
{
|
||
timerManager.SetActiveTimer(Team.Player1);
|
||
}
|
||
|
||
VitrinaView.Instance.ActivateIfNeed();
|
||
DetermineNextTurn(switchPlayer: false);
|
||
}
|
||
|
||
public void DetermineNextTurn(bool switchPlayer = true)
|
||
{
|
||
if (switchPlayer) SwitchPlayer();
|
||
//spawnChip();
|
||
|
||
if (gameMode == GameMode.pvp)//переключаем таймеры только в pvp
|
||
{
|
||
timerManager.SetActiveTimer(currentPlayer);
|
||
LightSystem.Player(currentPlayer);
|
||
}
|
||
}
|
||
|
||
public void ResetGameSession()
|
||
{
|
||
vsBotThinkTime = 0;
|
||
StopVsBotTimer();
|
||
vsBotMoves = 0;
|
||
//movesAndTimeCounter.SetVisibility(false);
|
||
|
||
CharactersController.I.ReturnToMenu();
|
||
CharactersController.I.SetAllCharactersPrizeAvailable();
|
||
DualAvatarController.Instance?.HideCharacters();
|
||
|
||
player1score = 0;
|
||
player2score = 0;
|
||
vsBotScore = 0;
|
||
|
||
VitrinaView.Instance.Deactivate();
|
||
|
||
canReturnToMenu = true;
|
||
}
|
||
|
||
private void StartPveRound(int characterIndex)
|
||
{
|
||
_fieldCleaner.Clear();
|
||
CharactersController.I.ShowCharacter(characterIndex, StartRound);
|
||
}
|
||
|
||
private void StartRound()
|
||
{
|
||
turnManager.StartGame(gameMode);
|
||
PrepareRound(Team.Player1);
|
||
OnRoundStarted?.Invoke();
|
||
}
|
||
|
||
private static List<Prize> GetAvailablePrizes(IEnumerable<Prize> prizes)
|
||
{
|
||
List<Prize> result = new();
|
||
|
||
if (prizes == null)
|
||
return result;
|
||
|
||
foreach (Prize prize in prizes)
|
||
{
|
||
if (prize != null && prize is not EmptyPrize)
|
||
result.Add(prize);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private Prize GetNextBotPrize()
|
||
{
|
||
int nextIndex = CharactersController.CharacterIndex + 1;
|
||
|
||
if (nextIndex >= CharactersController.CharactersAmount)
|
||
return null;
|
||
|
||
List<Prize> nextPrizes = GetAvailablePrizes(CharactersController.I.GetPrizes(nextIndex));
|
||
return nextPrizes.Count > 0 ? nextPrizes[0] : null;
|
||
}
|
||
|
||
private void SubscribeToPrizePanels()
|
||
{
|
||
UnsubscribeFromPrizePanels();
|
||
takeOrRiskPanel.PrizeSelected += StartPrizeIssue;
|
||
takeOrRiskPanel.ContinueSelected += HandlePrizeSkipped;
|
||
qrPanel.OnComplete += HandlePrizeIssueFinished;
|
||
vitrinaPanel.OnComplete += HandleVitrinaIssueFinished;
|
||
}
|
||
|
||
private void UnsubscribeFromPrizePanels()
|
||
{
|
||
if (takeOrRiskPanel != null)
|
||
{
|
||
takeOrRiskPanel.PrizeSelected -= StartPrizeIssue;
|
||
takeOrRiskPanel.ContinueSelected -= HandlePrizeSkipped;
|
||
}
|
||
|
||
if (qrPanel != null)
|
||
qrPanel.OnComplete -= HandlePrizeIssueFinished;
|
||
|
||
if (vitrinaPanel != null)
|
||
vitrinaPanel.OnComplete -= HandleVitrinaIssueFinished;
|
||
|
||
PrizeSystemManager.PrizeIssueFinished -= HandleCountablePrizeIssueFinished;
|
||
}
|
||
|
||
private void StartPrizeIssue(Prize prize)
|
||
{
|
||
SubscribeToPrizePanels();
|
||
|
||
if (prize is CountablePrize)
|
||
{
|
||
PrizeSystemManager.PrizeIssueFinished -= HandleCountablePrizeIssueFinished;
|
||
PrizeSystemManager.PrizeIssueFinished += HandleCountablePrizeIssueFinished;
|
||
PrizeSystemManager.GivePrize(prize);
|
||
}
|
||
else if (prize is QrPrize)
|
||
{
|
||
qrPanel.gameObject.SetActive(true);
|
||
qrPanel.Initialize(prize);
|
||
}
|
||
else if (prize is VitrinaPrize vitrinaPrize)
|
||
{
|
||
vitrinaPanel.gameObject.SetActive(true);
|
||
vitrinaPanel.Initialize(vitrinaPrize.Boxes);
|
||
}
|
||
else
|
||
{
|
||
HandlePrizeIssueFinished();
|
||
}
|
||
}
|
||
|
||
private void HandlePrizeSkipped()
|
||
{
|
||
_returnToMenuAfterPrize = false;
|
||
UnsubscribeFromPrizePanels();
|
||
ContinueAfterPveWin();
|
||
}
|
||
|
||
private void HandleCountablePrizeIssueFinished(bool success)
|
||
{
|
||
PrizeSystemManager.PrizeIssueFinished -= HandleCountablePrizeIssueFinished;
|
||
HandlePrizeIssueFinished();
|
||
}
|
||
|
||
private void HandleVitrinaIssueFinished(bool success)
|
||
=> HandlePrizeIssueFinished();
|
||
|
||
private void HandlePrizeIssueFinished()
|
||
{
|
||
UnsubscribeFromPrizePanels();
|
||
|
||
if (_returnToMenuAfterPrize)
|
||
{
|
||
GotoMenu();
|
||
return;
|
||
}
|
||
|
||
bool isLastBot = CharactersController.CharacterIndex >= CharactersController.CharactersAmount - 1;
|
||
|
||
if (isLastBot)
|
||
ShowFinalVictoryNameInput();
|
||
else
|
||
ContinueAfterPveWin();
|
||
}
|
||
|
||
private void CancelPrizeFlow()
|
||
{
|
||
UnsubscribeFromPrizePanels();
|
||
|
||
if (takeOrRiskPanel != null)
|
||
takeOrRiskPanel.gameObject.SetActive(false);
|
||
|
||
if (qrPanel != null)
|
||
qrPanel.gameObject.SetActive(false);
|
||
|
||
if (vitrinaPanel != null)
|
||
vitrinaPanel.gameObject.SetActive(false);
|
||
}
|
||
|
||
private void RefundEntryIfAvailable()
|
||
{
|
||
if (!_canRefundEntry)
|
||
return;
|
||
|
||
PaymentSystem.ReturnCredits(_paidEntryAmount);
|
||
_paidEntryAmount = 0;
|
||
_canRefundEntry = false;
|
||
}
|
||
|
||
private void ResetPvpScores()
|
||
{
|
||
player1score = 0;
|
||
player2score = 0;
|
||
timerManager.RefreshPvpScores();
|
||
}
|
||
|
||
private void HandleVictoryNameEntered(string playerName)
|
||
{
|
||
nameInput.OnComplete -= HandleVictoryNameEntered;
|
||
ControlsPerformer.Instance.SetControlable(null);
|
||
StatsService.AddRecord(playerName, TurnTracker.Timer, TurnTracker.Moves);
|
||
nameInput.gameObject.SetActive(false);
|
||
GotoMenu();
|
||
}
|
||
|
||
|
||
public void upgradeFeeshkaDifficulty()
|
||
{
|
||
string difficultyMode = SettingsManager.GetString(SettingKey.DIFFICULTY_MODE);
|
||
//todo: разобраться
|
||
//if (difficultyMode == "Прохождение")
|
||
//{
|
||
// PaymentSystem.ResetPulsesCounter();
|
||
// Setting difficultySetting = SettingsManager.Container.TryGetSetting(SettingKeys.DIFFICULTY_MODE);
|
||
// difficultySetting.StringValue = "Заработок";
|
||
// SettingsManager.OnSettingsChanged?.Invoke();
|
||
// SettingsManager.SaveContainerToFile();
|
||
// GameManager.instance.AdminPanel.GetComponent<SettingsScreen>().RefreshViews();
|
||
// print("Сложность повышена");
|
||
//}
|
||
}
|
||
|
||
|
||
IEnumerator AddBotRecordEvery2Days()
|
||
{
|
||
while (true)
|
||
{
|
||
yield return new WaitForSeconds(3600f); // ✅ Проверка каждый час
|
||
|
||
double lastRecordTime = PlayerPrefs.GetFloat("LastBotRecord", 0);
|
||
double currentTime = (DateTime.UtcNow - new System.DateTime(1970, 1, 1)).TotalSeconds;
|
||
|
||
if (currentTime - lastRecordTime >= 172800f)
|
||
{
|
||
StatsService.AddDailyRecord();
|
||
PlayerPrefs.SetFloat("LastBotRecord", (float)currentTime);
|
||
PlayerPrefs.Save();
|
||
}
|
||
}
|
||
}
|
||
}
|