sea-battle/Assets/Scripts/GameManager.cs

769 lines
20 KiB
C#

using System;
using System.Collections;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public static event System.Action<int, int> OnInviteSent;
public static event System.Action <int, bool, GameMode> OnReady;
public event System.Action<InputMode> OnInputModeChanged;
private IBotAI bot;
public Transform shipPlacementCameraPosition;
public Transform mainMenuCameraPosition;
public Transform gameplayCameraPosition;
public bool isReady = false; // Ãîòîâ ëè èãðîê (ðàññòàâèë ëè êîðàáëè)
public GameManager opponentManager; // Ïðîòèâíèê (åñëè åñòü)
public CannonBattery battery;
public CannonBattery enemyBattery;
public GameState currentState;
public UIManager uiManager;
public GamePole playerField;
public GamePole enemyField;
public GameObject targetCursorPrefab;
private GameObject targetCursorInstance;
public bool isPlayerTurn = false;
public int playerShips = 0;
public int enemyShips = 0;
public int playerId = 1; // 1 - ïåðâûé èãðîê, 2 - âòîðîé èãðîê è ò.ä.
public Camera playerCamera;
public Transform cameraPivot;
public int currentBotLevel = 0;
public EnemyManager enemyManager;
public FortInitializer fortInitializer;
[Header("Âðåìÿ áåçäåéñòâèÿ")]
[SerializeField] float inactionTimer = 360f;
public float timerBackToMenu = 0;
public enum InputMode
{
UI,
Settings,
ShipPlacement,
Battle
}
private bool paidFroFriend = false;
public InputMode currentInputMode = InputMode.UI;
[Header("Íàñòðîéêè áîòà")]
public bool useManualDifficulty = false;
public BotDifficulty manualDifficulty = BotDifficulty.Level1;
public enum BotDifficulty
{
Level1,
Level2,
Level3,
Level4,
Level5,
Level6,
}
public GameMode gameMode = GameMode.PlayerVsBot;
public BotDifficulty botDifficulty = BotDifficulty.Level1;
public float cameraMoveDuration = 1.0f; // Âðåìÿ ïåðåìåùåíèÿ â ñåêóíäàõ
void Start()
{
var player = GetComponentInParent<Player>();
if (player != null)
playerId = player.PlayerId;
SetState(GameState.MainMenu);
}
private void Update()
{
timerBackToMenu += Time.deltaTime;
if (timerBackToMenu >= inactionTimer)
{
ReturnToMainMenu();
timerBackToMenu = 0;
}
}
private void OnEnable()
{
In.ButtonEvent += ResetTimer;
}
private void OnDisable()
{
In.ButtonEvent -= ResetTimer;
}
private void ResetTimer()
{
timerBackToMenu = 0;
}
void SetPlayerReady(bool ready)
{
isReady = ready;
if (gameMode == GameMode.PlayerVsBot)
{
uiManager.SetupPlayButtons(ready);
}
else
{
var rez = isReady & opponentManager.isReady;
uiManager.SetupPlayButtons(rez);
opponentManager.uiManager.SetupPlayButtons(rez);
}
OnReady?.Invoke(playerId, ready, gameMode);
}
public void AddShipPlayer()
{
playerShips++;
if (playerShips == 10)
{
SetPlayerReady(true);
}
}
public void SetInputMode(InputMode newMode)
{
currentInputMode = newMode;
OnInputModeChanged?.Invoke(newMode);
}
public void ShipDestroyed(bool isPlayer)
{
if (isPlayer)
{
enemyManager.TriggerEventReaction(DialogueEventType.PlayerShipDestroyed);
playerShips--;
}
else
{
enemyManager.TriggerEventReaction(DialogueEventType.BotShipDestroyed);
enemyShips--;
}
CheckVictoryCondition();
}
private void CheckVictoryCondition()
{
if (playerShips <= 0)
{
Debug.Log("Èãðîê ïðîèãðàë!");
enemyManager.TriggerEndGameReaction(false);
EndGame();
}
else if (enemyShips <= 0)
{
Debug.Log("Èãðîê ïîáåäèë!");
enemyManager.TriggerEndGameReaction(true);
EndGame();
}
}
public void ProcessShotResult(bool hit, bool isPlayer, bool wasShipDestroyed = false)
{
if (wasShipDestroyed)
{
ShipDestroyed(!isPlayer);
return;
}
if (!isPlayer)
{
if (hit)
{
enemyManager.TriggerEventReaction(DialogueEventType.BotHit);
}
else
{
SoundManager.Instance.PlayMiss(playerId);
enemyManager.TriggerEventReaction(DialogueEventType.BotMiss);
}
}
else
{
if (hit)
{
enemyManager.TriggerEventReaction(DialogueEventType.PlayerHit);
}
else
{
SoundManager.Instance.PlayMiss(playerId);
enemyManager.TriggerEventReaction(DialogueEventType.PlayerMiss);
}
}
}
public void SetState(GameState newState)
{
currentState = newState;
uiManager.ShowPanel(newState);
switch(newState)
{
case GameState.MainMenu:
MoveCameraTo(mainMenuCameraPosition);
break;
case GameState.BotPlacement:
MoveCameraTo(shipPlacementCameraPosition);
break;
case GameState.ShipPlacement:
MoveCameraTo(shipPlacementCameraPosition);
break;
case GameState.Playing:
MoveCameraTo(gameplayCameraPosition);
break;
case GameState.GameOver:
break;
}
}
private BotDifficulty GetDifficultyFromLevel()
{
if (useManualDifficulty)
{
return manualDifficulty;
}
int level = Mathf.Clamp(currentBotLevel, 0, 4);
Debug.Log("øàíñ íà ïîáåäó : " + DifficultyManager.GetChance());
if (level == 4) // äîøåë äî 5ãî óðîâíÿ
{
// Ñèñòåìà øàíñà íà ïîáåäó
if (DifficultyManager.GetChance() <= 0)
{
Debug.Log("Øàíñ íà ïîáåäó ñðàáîòàë!");
DifficultyManager.ResetChance();
return BotDifficulty.Level5; // äàåì øàíñ ïîáåäèòü
}
else
{
DifficultyManager.DecreaseChance();
return BotDifficulty.Level6; // ïî÷òè íåïîáåäèìûé
}
}
return (BotDifficulty)level;
}
public void PrepareForBattle()
{
if (playerShips != 10)
{
playerField.ArrangeShip();
playerShips = 10;
}
if (targetCursorInstance != null)
{
Destroy(targetCursorInstance);
targetCursorInstance = null;
}
SetInputMode(InputMode.Battle);
InitTargetCursor();
}
public void StartBattle()
{
Debug.Log("Èãðîâîé ýòàï íà÷àò");
if (gameMode == GameMode.PlayerVsPlayer)
{
if (!isReady || opponentManager == null || !opponentManager.isReady)
{
Debug.Log("Îæèäàåì ãîòîâíîñòè îïïîíåíòà...");
return;
}
PrepareForBattle();
opponentManager.PrepareForBattle();
SetState(GameState.Playing);
opponentManager.SetState(GameState.Playing);
// êîïèðóåì êîðàáëè íà ïîëÿ
if (!enemyField.IsReady)
{
enemyField.CopyShipsFrom(opponentManager.playerField, true);
enemyShips = 10;
}
if (!opponentManager.enemyField.IsReady)
{
opponentManager.enemyField.CopyShipsFrom(playerField, true);
opponentManager.enemyShips = 10;
}
paidFroFriend = false;
opponentManager.paidFroFriend = false;
opponentManager.uiManager.ShowTimer(false);
isReady = false;
opponentManager.isReady = false;
}
else // áîò
{
PrepareForBattle();
enemyShips = 10;
enemyField.ArrangeShip(true);
SetState(GameState.Playing);
}
StartPlayerTurn();
}
public void InitTargetCursor(bool isPlacingShips = false)
{
if (targetCursorInstance != null)
return;
targetCursorInstance = Instantiate(targetCursorPrefab);
TargetCursor cursorScript = targetCursorInstance.GetComponent<TargetCursor>();
cursorScript.Initialize(this, playerId, isPlacingShips);
targetCursorInstance.SetActive(isPlacingShips); // ïî äåôîëòó ñêðûò
}
public void EndGame()
{
SetState(GameState.GameOver);
SetInputMode(InputMode.UI);
bool isWin = enemyShips <= 0;
bool isBotGame = (gameMode == GameMode.PlayerVsBot);
if (gameMode == GameMode.PlayerVsBot)
{
if (isWin)
{
Prize priz = PrizeSerializer.GetPrizes()[currentBotLevel];
Debug.Log("Ïðèç :"+ priz);
if (priz.PrizeType == PrizeType.Special)
{
bool settingEnabled = SettingsManager.instance.GetSettingValue("Âûäà÷à ïðèçîâ ïðè èãðå ñ áîòîì") == "Âûäàâàòü";
if (settingEnabled)
{
SetState(GameState.Prize); // ïîêàçàòü Qr-code
return;
}
}
else
{
PrizeSystem.GivePrize(priz);
}
if (currentBotLevel <= 4)
currentBotLevel++;
else
DifficultyManager.DecreaseChance();
}
}
uiManager.ShowGameOverMenu(isWin, isBotGame);
}
// ============= buttons ==========================================================================
public void OnReplayPressed() // ïî èäååå ôóíêöèè ðàçíûå òàê êàê íóæíà ïðîâåðêà íà áàëàíñ $
{
if (gameMode == GameMode.PlayerVsBot)
{
StartBotGame();
}
else
{
if (ComWrapper.GetPlayerCredits(opponentManager.playerId) > 0)
{
ComWrapper.Pay(1, playerId);
ComWrapper.Pay(1, opponentManager.playerId);
}
else
{
paidFroFriend = true;
ComWrapper.Pay(2, playerId);
}
opponentManager.StartPlayerGame();
StartPlayerGame();
}
}
public void OnContinuePressed()
{
if (gameMode == GameMode.PlayerVsBot)
{
ComWrapper.AddCredit(1, playerId); // âîçâðàò êðåäèòà çà ïîáåäó
StartBotGame();
}
}
public void MenuGame(bool endGame = false)
{
// Âîçâðàò êðåäèòîâ ïðè âûõîäå (åñëè íå çàâåðøèëàñü èãðà)
if (!endGame)
{
if (gameMode == GameMode.PlayerVsPlayer)
{
if (paidFroFriend) ComWrapper.AddCredit(2, playerId);
else if(opponentManager.paidFroFriend) ComWrapper.AddCredit(2, opponentManager.playerId);
else
{
ComWrapper.AddCredit(1, playerId);
ComWrapper.AddCredit(1, opponentManager.playerId);
}
opponentManager.ReturnToMainMenu();
}
else
{
if(currentBotLevel == 0) ComWrapper.AddCredit(1, playerId); // Âîçâðàò îäíîìó èãðîêó åñëè òîò íå èãðàë
}
}
if (gameMode == GameMode.PlayerVsPlayer)opponentManager.ReturnToMainMenu();
ReturnToMainMenu();
}
public void ClearPole()
{
if (playerField != null)
{
playerField.ClearPole();
playerShips = 0;
SetPlayerReady(false);
Debug.Log("Ïîëå î÷èùåíî");
}
}
public void ArrangeGame()
{
if (playerField != null)
{
playerField.ArrangeShip();
playerShips = 10;
SetPlayerReady(true);
Debug.Log("Ïîëå î÷èùåíî è êîðàáëè ðàññòàâëåíû çàíîâî");
}
else
{
Debug.LogWarning("GamePole íå íàçíà÷åí â GameManager");
}
}
public void OnPlayVsPlayerClicked(int playerId) // ìèñòð êàñòûëü
{
int opponentId = playerId == 1 ? 2 : 1;
OnInviteSent?.Invoke(playerId, opponentId);
}
public void AcceptInvite()
{
if (ComWrapper.GetPlayerCredits(playerId) > 0)
{
ComWrapper.Pay(1, playerId);
ComWrapper.Pay(1, opponentManager.playerId);
}
else
{
opponentManager.paidFroFriend = true;
ComWrapper.Pay(2, opponentManager.playerId);
}
StartPlayerGame();
opponentManager.StartPlayerGame();
}
public void DeclineInvite()
{
uiManager.HideInvite();
}
public void StartPlayerGame()
{
PrepareNewGame();
Debug.Log("Íà÷èíàåì èãðó ñ èãðîêîì");
gameMode = GameMode.PlayerVsPlayer;
SetState(GameState.ShipPlacement);
SetInputMode(InputMode.ShipPlacement);
InitTargetCursor(true);
fortInitializer.FortSwitch(3);
enemyManager.SetEnemyPlayer();
}
public void StartBotGame()
{
// Åñëè åñòü îïïîíåíò, êîòîðûé æä¸ò â ãëàâíîì ìåíþ - çàêðûâàåì åãî ïðèãëàøåíèå
if (opponentManager != null &&
opponentManager.currentState == GameState.MainMenu)
{
opponentManager.DeclineInvite();
}
ComWrapper.Pay(1, playerId);
PrepareNewGame();
Debug.Log("Íà÷èíàåì èãðó ñ áîòîì");
gameMode = GameMode.PlayerVsBot;
SetState(GameState.ShipPlacement);
SetInputMode(InputMode.ShipPlacement);
InitTargetCursor(true);
InitBot();
}
//==========================================================================================
private void InitBot()
{
BotDifficulty selectedDifficulty = GetDifficultyFromLevel();
Debug.Log("Âûáðàí áîò: " + selectedDifficulty);
switch (selectedDifficulty)
{
case BotDifficulty.Level1:
bot = new EasyBotAI();
enemyManager.SetEnemy(0);
fortInitializer.FortSwitch(0);
break;
case BotDifficulty.Level2:
bot = new NormalBotAI();
enemyManager.SetEnemy(1);
fortInitializer.FortSwitch(1);
break;
case BotDifficulty.Level3:
bot = new HardBotAI();
enemyManager.SetEnemy(2);
fortInitializer.FortSwitch(2);
break;
case BotDifficulty.Level4:
bot = new VeryHardBotAI();
enemyManager.SetEnemy(3);
fortInitializer.FortSwitch(3);
break;
case BotDifficulty.Level5:
bot = new CrazyBotAI();
enemyManager.SetEnemy(4);
fortInitializer.FortSwitch(4);
break;
case BotDifficulty.Level6:
bot = new UltimateBotAI();
enemyManager.SetEnemy(4);
fortInitializer.FortSwitch(4);
break;
default:
bot = new EasyBotAI();
enemyManager.SetEnemy(0);
fortInitializer.FortSwitch(0);
break;
}
}
// õîäû
public void StartPlayerTurn()
{
isPlayerTurn = true;
uiManager.ShowTimer(true);
if (targetCursorInstance != null)
targetCursorInstance.SetActive(true);
}
public void EndPlayerTurn()
{
isPlayerTurn = false;
uiManager.ShowTimer(false);
if (targetCursorInstance != null)
targetCursorInstance.SetActive(false);
if (gameMode == GameMode.PlayerVsPlayer)
{
opponentManager.StartPlayerTurn();
}
else
{
// enemyManager.ShowNextDialogue();
StartCoroutine(BotTurn());
}
}
public IEnumerator BotTurn()
{
bool hit;
do
{
yield return new WaitForSeconds(1f);
Vector2Int target = bot.MakeMove(playerField);
if (target.x < 0 || target.y < 0)
{
Debug.LogWarning("Áîòó íå÷åãî ñòðåëÿòü, ïðîïóñêàåì õîä");
break; // èëè EndGame, åñëè íåò õîäîâ
}
bool shotComplete = false;
hit = false;
enemyBattery.FireShot(playerField, target.x, target.y, (wasHit, wasShipDestroyed) =>
{
hit = wasHit;
shotComplete = true;
ProcessShotResult(wasHit,false, wasShipDestroyed);
// if (hit) SoundManager.Instance.PlayBotHit(playerId);
// else SoundManager.Instance.PlayBotMiss(playerId);
// if(wasShipDestroyed) SoundManager.Instance.PlayPlayerShipDestroyed(playerId);
});
yield return new WaitUntil(() => shotComplete);
} while (hit);
StartPlayerTurn();
}
public void MoveCameraTo(Transform target)
{
if (playerCamera != null && target != null)
{
StopAllCoroutines();
StartCoroutine(MoveCameraSmoothly(target));
}
}
private IEnumerator MoveCameraSmoothly(Transform target)
{
Transform cam = playerCamera.transform;
Vector3 startPos = cam.position;
Quaternion startRot = cam.rotation;
Vector3 endPos = target.position;
Quaternion endRot = target.rotation;
float elapsed = 0f;
while (elapsed < cameraMoveDuration)
{
float t = elapsed / cameraMoveDuration;
cam.position = Vector3.Lerp(startPos, endPos, t);
cam.rotation = Quaternion.Slerp(startRot, endRot, t);
elapsed += Time.deltaTime;
yield return null;
}
cam.position = endPos;
cam.rotation = endRot;
}
/// <summary>
/// Ñáðàñûâàåò èãðîâîå ñîñòîÿíèå - î÷èùàåò ïîëÿ, óäàëÿåò êóðñîð, ñáðàñûâàåò ïåðåìåííûå
/// </summary>
private void ResetGameState()
{
Debug.Log("Ñáðîñ ñîñòîÿíèÿ èãðû...");
// 1. Ñáðàñûâàåì èãðîâûå ïîëÿ
if (playerField != null)
{
playerField.ClearPole(); // î÷èñòêà ñâîåãî ïîëÿ (óäàëÿåì êîðàáëè è ñáðàñûâàåì ìàññèâû)
}
if (enemyField != null)
{
enemyField.ClearPole(); // î÷èñòêà âðàæåñêîãî ïîëÿ
}
// 2. Óäàëÿåì êóðñîð
if (targetCursorInstance != null)
{
Destroy(targetCursorInstance);
targetCursorInstance = null;
}
// 3. Ñáðàñûâàåì ïåðåìåííûå
playerShips = 0;
enemyShips = 0;
SetPlayerReady(false);
isPlayerTurn = false;
SetInputMode(InputMode.UI);
Debug.Log("Ñáðîñ çàâåðø¸í");
}
/// <summary>
/// Ïîäãîòîâêà ê íîâîé èãðå - ñáðàñûâàåò ñîñòîÿíèå è ïåðåâîäèò â ñîñòîÿíèå ðàññòàíîâêè
/// </summary>
private void PrepareNewGame()
{
ResetGameState();
// Ñîñòîÿíèå áóäåò óñòàíîâëåíî â âûçûâàþùåì ìåòîäå (StartPlayerGame èëè StartBotGame)
}
/// <summary>
/// Âîçâðàò â ãëàâíîå ìåíþ - ñáðàñûâàåò ñîñòîÿíèå è ïîêàçûâàåò ãëàâíîå ìåíþ
/// </summary>
public void ReturnToMainMenu()
{
paidFroFriend = false;
currentBotLevel = 0;
ResetGameState();
SetState(GameState.MainMenu);
}
}