using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using System.Collections; using PrizeSystem; using System.Text; public enum GameMode { pve, pvp } public class GameManager : MonoBehaviour { private const int DEFAULT_FRAME_RATE = 60; public int Rows = 7, Cols = 7; public PlayerStatsService StatsService; public int botsAmount = 5; public int boardVersion = 1; [Header("General")] public GameStateMachine stateMachine; public Transform slotLeftTop; public static FieldModel fieldModel; public static GameManager instance; public GameObject AdminPanel, NumberPanel, SettingsPointer; public TimerManager timerManager; public VFX_manager effect; public RulesController rulesController; [Header("Menu")] public bool menuOpened = true; public GameMode gameMode; public Transform coinPanel, board, noPrizeLabel; public GameObject mainMenu; public TMP_FontAsset russo_font; [Header("Scores")] public int player1score = 0, player2score = 0, vsBotScore = 0; public int vsBotMoves; public float vsBotThinkTime; public VictoryScale botScale, Player1Scale, Player2Scale; [HideInInspector] public UnityEvent OnNoMoney = new UnityEvent(); public CheckResult lastResult; [Header("Gameplay")] public GameObject player1Chip; public GameObject player2Chip; public GameObject botChip; [HideInInspector] public GameObject currentChip; public Sprite chipPointer, selectedPanel, deselectedPanel; public RectTransform EngamePanel, TimerImage; public RectTransform smallPrizesOut; public Image ReplayButton, MenuButton; public DrawVisual DrawVisual; public TextMeshProUGUI RestartButton; public TextMeshProUGUI TimerLabel; //до выхода в меню.. public TextMeshProUGUI ToMenuLabel; //это же public WinPanel winPanel; [HideInInspector] public CellState currentPlayer = CellState.Player2; public int currentColumnIndex = 0; public float stepX = 1.215f; public float stepY = 1.24f; public float startY; public bool moveMade = false; public float chipXSpeed = 10, chipYSpeed = 0, chipAcceleration = 20; public Transform[,] chipTransforms; // Кешированные компоненты для избежания GetComponent в DrawAnimation [Header("Панели ввода")] public TextInput nameInput; public TextInput ValutaNameInput; public TextInput specialPrizeInput; public TextInput NumberTech; public NumberInput pricePveInput; public NumberInput pricePvpInput; public NumberInput pricePveRevengeInput; public NumberInput prizesAvailableInput; public NumberInput pulsesToResetDifficultyInput; public NumberInput valutaPerPulseInput; public Leaderboard leaderboard; public GameObject CharactersConfigurator; public GameObject fastCheckCounters; public GameObject checkQrPanel; public DualAvatarController avatarController; public PvpPointer pvpPointer; public MovesAndTimeCounter movesAndTimeCounter; public GameObject setPasswordPanel; public EnterPasswordPanel enterPasswordPanel; public SoundManager soundManager; public VitrinaPanel vitrinaPanel; public QrPanel qrPanel; private Logger logger; public VitrinaCatcher vitrinaCatcher; public TakeOrRiskPanel takeOrRiskPanel; void Awake() { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; Instantiate(new GameObject()).AddComponent(typeof(VfxPrefab)); if (instance == null) { Application.targetFrameRate = DEFAULT_FRAME_RATE; instance = this; fieldModel = new FieldModel(Cols, Rows); chipTransforms = new Transform[Rows, Cols]; } ConfigManager.Initialize(); UnityMainThreadDispatcher.Initialize(); InitializePrefs(); SettingsManager.Initialize(); GetComponent().Initialize(); //Тестируем пока что. Не прод(ну ладно прод.) logger = GetComponent(); InitializeDevices(); SingleWallet.Initialize(); ComWrapper.PaymentReceived += ProcessDifficultyCounter; SettingsManager.OnSettingsChanged.AddListener(ProcessDifficultyCounter); soundManager.Initialize(); GetComponent().Initialize(); vitrinaCatcher.Initialize(); ProcessDifficultyCounter(); GetComponent().Initialize(); GetComponent().Initialize(); GetComponent().Initialize(); StatsService = new(); StatsService.Initialize(); #if !UNITY_EDITOR Defender.Instance.StartCoroutine(Defender.Instance.CheckLicenseCoroutine()); #endif DifficultyManager.Instance.dummyBots = false; StartCoroutine(AddBotRecordEvery2Days());// добавлять каждые 2 дня запись avatarController.GetComponent().Initialize(); avatarController.Initialize(); } private void InitializeDevices() { var sb = new StringBuilder(); //ИНИЦИАЛИЗАЦИЯ УСТРОЙСТВ var devices = ComPortScanner.ScanPorts(); sb.AppendLine($"Найдено устройств: {devices.Count}"); foreach ( var device in devices ) { sb.Append($"{device.Key} : {device.Value}"); } logger.Log(sb.ToString()); bool controllerFound = false; string vitrinaPort = null; PrizeStandController.InitializationComplete += PrizeStandController_InitializationComplete; foreach (var device in devices) { //Витрина if (device.Value == ComPortScanner.DeviceType.PrizeShowcase) { vitrinaPort = device.Key; logger.Log($"нашел витрину на порту, {vitrinaPort}"); } else if (device.Value == ComPortScanner.DeviceType.ControllerV1) { if (!controllerFound) { logger.Log("Нашел периферийник1 открываю."); ComWrapper.Initialize(device.Key, boardVersion: 1); controllerFound = true; } } else if (device.Value == ComPortScanner.DeviceType.ControllerV2) { if (!controllerFound) { logger.Log("Нашел периферийник2 открываю."); ComWrapper.Initialize(device.Key, boardVersion: 2); controllerFound = true; } } else { logger.Log($"неизвестный тип {device.Key}:{device.Value}"); } } if (vitrinaPort != null) { logger.Log($"Витрину открываем (порт {vitrinaPort}"); int h = ComNativeWrapper.Serial_Open(vitrinaPort, 115200, 8, 0, 1, 4, 10); if (h > 0) logger.Log("Открыл"); else logger.Log("Не Открыл"); PrizeStandController.Initialize(h, 5, logger); } } private void OnApplicationQuit() { ComNativeWrapper.Serial_CloseAll(); } private void PrizeStandController_InitializationComplete(bool arg1, string arg2) { logger.Log($"Инициализация витрины: {arg1} : {arg2}"); } private static void InitializePrefs() { PlayerPrefs.SetString("Serial", ConfigManager.Config.Serial); if (!PlayerPrefs.HasKey("Number")) PlayerPrefs.SetString("Number", "70000000000"); if (!PlayerPrefs.HasKey("NumberTech")) PlayerPrefs.SetString("NumberTech", "<Не указано>"); if (!PlayerPrefs.HasKey("ValutaPerImpulse")) PlayerPrefs.SetInt("ValutaPerImpulse", 10); if (!PlayerPrefs.HasKey("ValutaName")) PlayerPrefs.SetString("ValutaName", "руб."); if (!PlayerPrefs.HasKey("PricePVP")) PlayerPrefs.SetInt("PricePVP", 10); if (!PlayerPrefs.HasKey("PricePVE")) PlayerPrefs.SetInt("PricePVE", 10); if (!PlayerPrefs.HasKey("PriceRevenge")) PlayerPrefs.SetInt("PriceRevenge", 10); } private void Start() { stateMachine.ChangeState(new MenuState()); SettingsManager.OnSettingsChanged.AddListener(pullSettings); pullSettings(); Instantiate(new GameObject()).AddComponent(typeof(VfxPrefab)); } void pullSettings() { SetupCoinPanel(); } #if UNITY_EDITOR private void Update() { if (Input.GetKeyDown(KeyCode.G)) { PrizeSystemManager.GivePrize(PrizeUtils.CreatePrize(CountablePrizeType.Hopper, 1)); } if (Input.GetKeyDown(KeyCode.O)) { PlayerPrefs.SetInt("PrizeGivenBuffer", 1); } } #endif public void SetupCoinPanel() { bool shouldShowCoinCounter = !SettingsManager.GetBool("Freeplay", false); coinPanel.gameObject.SetActive(shouldShowCoinCounter); } public void spawnChip() { GameObject chipToSpawn; if (gameMode == GameMode.pvp) chipToSpawn = currentPlayer == CellState.Player1 ? player1Chip : player2Chip; else chipToSpawn = currentPlayer == CellState.Player1 ? player1Chip : botChip; currentChip = Instantiate(chipToSpawn, new Vector2(0, 20), Quaternion.identity); if (currentPlayer == CellState.Player2) currentChip.GetComponentInChildren().sprite = CharacterController.CurrentChipImage; } public void setChipTransformToArray(int row, int col, Transform entryTransform) { chipTransforms[row, col] = entryTransform; } public void SwitchPlayer() { currentPlayer = currentPlayer == CellState.Player1 ? CellState.Player2 : CellState.Player1; } public void SetMode(GameMode mode) => gameMode = mode; public void InitVictoryScales() { //Включить и обнулить нужные шкалы player1score = 0; player2score = 0; vsBotScore = 0; switch (gameMode) { case GameMode.pvp: botScale.gameObject.SetActive(false); Player1Scale.gameObject.SetActive(true); Player2Scale.gameObject.SetActive(true); Player1Scale.SetSlotsCount(5); Player2Scale.SetSlotsCount(5); Player1Scale.ResetScale(); Player2Scale.ResetScale(); break; case GameMode.pve: botScale.gameObject.SetActive(true); botScale.SetSlotsCount(botsAmount); Player1Scale.gameObject.SetActive(false); Player2Scale.gameObject.SetActive(false); botScale.ResetScale(); break; } } public void IncreaseScoreAndScaleOfPlayer(CellState player) { if (player == CellState.Player1) { player1score += 1; Player1Scale.SetMedalsCount(player1score); } else { player2score += 1; Player2Scale.SetMedalsCount(player2score); } } public int GetMovesCount() { if (chipTransforms == null) return 0; int count = 0; int rows = chipTransforms.GetLength(0); int cols = chipTransforms.GetLength(1); for (int r = 0; r < rows; r++) for (int c = 0; c < cols; c++) if (chipTransforms[r, c] != null) count++; return count; } public void ProcessDifficultyCounter()//вызывается каждый раз, когда приходит COIN с платы или обновились настройки { string previous = PlayerPrefs.GetString("PreviousBaseBotDifficulty", "Обычная"); string difficultyType = SettingsManager.GetString("BaseBotDifficulty", "?"); //Инициализация if (!PlayerPrefs.HasKey("PulsesToResetDifficulty")) PlayerPrefs.SetInt("PulsesToResetDifficulty", 100); //если переход с повышенной на обычную - сброс счетчика if (previous == "Повышенная" && difficultyType != previous) { PlayerPrefs.SetInt("PulsesCounter", 0); } PlayerPrefs.SetString("PreviousBaseBotDifficulty", difficultyType); if (difficultyType == "Повышенная") { int pulses = PlayerPrefs.GetInt("PulsesCounter", 0); int pulsesToResetDifficulty = PlayerPrefs.GetInt("PulsesToResetDifficulty", 10); if (pulses >= pulsesToResetDifficulty) { PlayerPrefs.SetInt("PulsesCounter", 0); Setting difficultySetting = SettingsManager.Container.TryGetSetting("BaseBotDifficulty"); difficultySetting.StringValue = "Обычная"; SettingsManager.OnSettingsChanged?.Invoke(); SettingsManager.SaveContainerToFile(); AdminPanel.GetComponent().RefreshViews(); print("Сложность сброшена"); } } } IEnumerator AddBotRecordEvery2Days() { while (true) { yield return new WaitForSeconds(3600f); // ✅ Проверка каждый час double lastRecordTime = PlayerPrefs.GetFloat("LastBotRecord", 0); double currentTime = Utils.GetUnixTimestamp(); if (currentTime - lastRecordTime >= 172800f) { StatsService.AddDailyRecord(); PlayerPrefs.SetFloat("LastBotRecord", (float)currentTime); PlayerPrefs.Save(); } } } }