diff --git a/Assets/Prefabs/UI/OptionPrefab.prefab b/Assets/Prefabs/UI/OptionPrefab.prefab
index a424ab77..af5a6884 100644
--- a/Assets/Prefabs/UI/OptionPrefab.prefab
+++ b/Assets/Prefabs/UI/OptionPrefab.prefab
@@ -75,7 +75,7 @@ MonoBehaviour:
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
- m_fontColor: {r: 1, g: 1, b: 1, a: 1}
+ m_fontColor: {r: 0.9725491, g: 0.854902, b: 0.5686275, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs
index ab024903..f7a1f399 100644
--- a/Assets/Scripts/GameManager.cs
+++ b/Assets/Scripts/GameManager.cs
@@ -731,7 +731,9 @@ public void DeclineInvite()
public void StartPlayerGame()
{
// PvP всегда использует классический режим 10x10
+ // Конфигурируем оба поля — это сбрасывает сохранённые рифы (если были в режиме "Рифы")
playerField.Configure(10, 10);
+ enemyField.Configure(10, 10);
PrepareNewGame();
Debug.Log("Начинаем игру с игроком");
gameMode = GameMode.PlayerVsPlayer;
@@ -752,6 +754,62 @@ public void StartPlayerGame()
enemyManager.SetEnemyPlayer();
}
+ private string _modeOverride = null;
+ /// Режим, применённый в текущей игре (определяется в ConfigureFields).
+ private string _effectiveMode = "Классика";
+
+ /// Вызывается кнопкой «Играть с ботом».
+ /// Если в настройках включён «Выбор режима игроком» — показывает панель выбора,
+ /// иначе сразу запускает игру с режимом из настроек.
+ public void TryStartBotGame()
+ {
+ bool playerChooses = SettingsManager.instance?.GetSettingValue("Выбор режима игроком") == "Вкл";
+ if (playerChooses)
+ {
+ // Проверяем баланс ДО показа панели, чтобы не открывать её зря
+ bool isFreeMode = SettingsManager.instance?.GetSettingValue("Бесплатная игра") == "Вкл";
+ if (!isFreeMode)
+ {
+ int price = CreditSystem.GetEffectiveBotPrice(isReplay: false);
+ int credits = CreditSystem.GetPlayerCredits(playerId);
+ if (credits < price)
+ {
+ uiManager?.ShowOverlay("InsufficientFunds", true, hideOtherOverlays: false);
+ return;
+ }
+ }
+
+ uiManager.ShowOverlay("GameModeSelect", true, hideOtherOverlays: true);
+ SetInputMode(InputMode.UI);
+ }
+ else
+ {
+ // Баланс проверит сам StartBotGame через PayBotGame
+ StartBotGame();
+ }
+ }
+
+ /// Кнопка «Классика» на панели выбора режима.
+ public void StartBotClassic()
+ {
+ _modeOverride = "Классика";
+ StartBotGame();
+ }
+
+ /// Кнопка «Растущие поля» на панели выбора режима.
+ public void StartBotGrowing()
+ {
+ _modeOverride = "Растущие поля";
+ StartBotGame();
+ }
+
+ /// Кнопка «Рифы» на панели выбора режима.
+ public void StartBotReefs()
+ {
+ _modeOverride = "Рифы";
+ StartBotGame();
+ }
+
public void StartBotGame(bool isReplay = false)
{
// Сбрасываем скидку Виндисты — начинается новая игра
@@ -798,7 +856,9 @@ public void StartBotGame(bool isReplay = false)
///
private void ConfigureFields()
{
- string mode = SettingsManager.instance?.GetSettingValue("Режим игры") ?? "Классика";
+ string mode = _modeOverride ?? SettingsManager.instance?.GetSettingValue("Режим игры") ?? "Классика";
+ _modeOverride = null; // сбрасываем override
+ _effectiveMode = mode; // сохраняем для ApplyModeReefs
int fieldSize = 10;
int shipCount = 10;
@@ -814,8 +874,8 @@ private void ConfigureFields()
}
else if (mode == "Рифы")
{
- fieldSize = 10; // поле всегда 10x10
- shipCount = data.shipCountGame2; // отдельное кол-во кораблей
+ fieldSize = 10;
+ shipCount = data.shipCountGame2;
}
}
@@ -825,16 +885,11 @@ private void ConfigureFields()
Debug.Log($"[GameManager] Режим игры: '{mode}', поле: {fieldSize}x{fieldSize}, кораблей: {shipCount}");
}
- ///
- /// Применяет случайные рифы для режима "Рифы".
- /// Вызывается ПОСЛЕ PrepareNewGame() (после ClearPole), ДО расстановки кораблей.
- ///
private void ApplyModeReefs()
{
if (bossLevelConfig == null) return;
- string mode = SettingsManager.instance?.GetSettingValue("Режим игры") ?? "Классика";
- if (mode != "Рифы") return;
+ if (_effectiveMode != "Рифы") return;
var data = bossLevelConfig.GetLevel(currentBotLevel);
playerField.ApplyRandomReefs(data.reefs);
diff --git a/Assets/Scripts/Settings/SettingsData.cs b/Assets/Scripts/Settings/SettingsData.cs
index 5c605b05..4fc7ea3a 100644
--- a/Assets/Scripts/Settings/SettingsData.cs
+++ b/Assets/Scripts/Settings/SettingsData.cs
@@ -86,6 +86,10 @@ public static List CreateBuiltinDefaults()
settings.Add(new SettingOption(settingName: "Ðåæèì èãðû",
options: new List() { "Êëàññèêà", "Ðàñòóùèå ïîëÿ", "Ðèôû" },
defaultIndex: 0));
+ settings.Add(new SettingOption(settingName: "Âûáîð ðåæèìà èãðîêîì",
+ options: new List() { "Âêë", "Âûêë" },
+ defaultIndex: 1,
+ type: SettingType.Svitcher));
settings.Add(new SettingOption(settingName: "Âûäà÷à ïðèçîâ ïðè èãðå ñ áîòîì",
options: new List() { "Âûäàâàòü", "Íå âûäàâàòü" },
defaultIndex: 0,
diff --git a/Assets/Scripts/UI/Panels/GameModeSelectPanel.cs b/Assets/Scripts/UI/Panels/GameModeSelectPanel.cs
new file mode 100644
index 00000000..893515f8
--- /dev/null
+++ b/Assets/Scripts/UI/Panels/GameModeSelectPanel.cs
@@ -0,0 +1,98 @@
+using UnityEngine;
+using UnityEngine.UI;
+using TMPro;
+
+///
+/// Панель выбора режима игры.
+/// Три кнопки — «Классика», «Растущие поля», «Рифы».
+/// Навигация клавишами — через PlayerCursorUI (InputMode.UI).
+///
+public class GameModeSelectPanel : MonoBehaviour
+{
+ [Header("Кнопки режимов (порядок: Классика, Растущие поля, Рифы)")]
+ [SerializeField] private Button buttonClassic;
+ [SerializeField] private Button buttonGrowing;
+ [SerializeField] private Button buttonReefs;
+
+ [Header("Отображение")]
+ [SerializeField] private Image previewImage;
+ [SerializeField] private TMP_Text descriptionText;
+
+ [Header("Картинки режимов (порядок: Классика, Растущие поля, Рифы)")]
+ [SerializeField] private Sprite spriteClassic;
+ [SerializeField] private Sprite spriteGrowing;
+ [SerializeField] private Sprite spriteReefs;
+
+ [Header("Описания режимов")]
+ [SerializeField, TextArea(3, 6)] private string descClassic = "Классический режим 10×10. Стандартные правила морского боя.";
+ [SerializeField, TextArea(3, 6)] private string descGrowing = "Растущие поля — размер поля и количество кораблей увеличиваются с каждым уровнем.";
+ [SerializeField, TextArea(3, 6)] private string descReefs = "Рифы — на поле расставляются случайные рифы, меняя тактику боя.";
+
+ private static readonly string[] ModeNames = { "Классика", "Растущие поля", "Рифы" };
+
+ private Button[] _buttons;
+ private Sprite[] _sprites;
+ private string[] _descriptions;
+ private int _selectedIndex;
+
+ private void Awake()
+ {
+ _buttons = new[] { buttonClassic, buttonGrowing, buttonReefs };
+ _sprites = new[] { spriteClassic, spriteGrowing, spriteReefs };
+ _descriptions = new[] { descClassic, descGrowing, descReefs };
+
+ for (int i = 0; i < _buttons.Length; i++)
+ {
+ int idx = i;
+ if (_buttons[i] == null) continue;
+
+ _buttons[i].onClick.AddListener(() => SelectMode(idx));
+
+ // При смене фокуса — обновляем превью и описание
+ var hl = _buttons[i].GetComponent();
+ if (hl != null)
+ hl.onFocused = () => UpdatePreview(idx);
+ }
+ }
+
+ private void OnEnable()
+ {
+ SyncFromSettings();
+ }
+
+ /// Обновляет только картинку и описание — без сохранения настройки и без подсветки.
+ private void UpdatePreview(int index)
+ {
+ if (previewImage != null) previewImage.sprite = _sprites [index];
+ if (descriptionText != null) descriptionText.text = _descriptions[index];
+ }
+
+ public void SelectMode(int index)
+ {
+ if (index < 0 || index >= ModeNames.Length) return;
+ _selectedIndex = index;
+ SettingsManager.instance?.ChangeSetting("Режим игры", index);
+ RefreshUI();
+ }
+
+ private void SyncFromSettings()
+ {
+ string current = SettingsManager.instance?.GetSettingValue("Режим игры") ?? "Классика";
+ int idx = System.Array.IndexOf(ModeNames, current);
+ _selectedIndex = idx >= 0 ? idx : 0;
+ RefreshUI();
+ }
+
+ private void RefreshUI()
+ {
+ UpdatePreview(_selectedIndex);
+
+ for (int i = 0; i < _buttons.Length; i++)
+ {
+ if (_buttons[i] == null) continue;
+ var hl = _buttons[i].GetComponent();
+ if (hl != null)
+ hl.SetHighlighted(i == _selectedIndex);
+ }
+ }
+}
diff --git a/Assets/Scripts/UI/Panels/GameModeSelectPanel.cs.meta b/Assets/Scripts/UI/Panels/GameModeSelectPanel.cs.meta
new file mode 100644
index 00000000..77bc4fac
--- /dev/null
+++ b/Assets/Scripts/UI/Panels/GameModeSelectPanel.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 234edf74d86242d08ba722398c50f340
+timeCreated: 1777026250
\ No newline at end of file