using System; using UnityEngine; public class TargetCursor : MonoBehaviour { public GameManager gameManager; public GameObject cursorVisual; public CursorAnimator cursorAnimator; private CameraController cameraController; private bool isShootingInProgress = false; public bool isPlacingShips = false; public GamePole ownField; private int x; private int y; private int width; private int height; private Direction currentDirection = Direction.Right; // биндинг кнопок private PlayerKeySet player1Keys = new PlayerKeySet { Up = ButtonPinMapping.up1, Down = ButtonPinMapping.down1, Left = ButtonPinMapping.left1, Right = ButtonPinMapping.right1, Fire = ButtonPinMapping.action1, TurnLeft = ButtonPinMapping.turnLeft1, TurnRight = ButtonPinMapping.turnRight1 }; private PlayerKeySet player2Keys = new PlayerKeySet { Up = ButtonPinMapping.up2, Down = ButtonPinMapping.down2, Left = ButtonPinMapping.left2, Right = ButtonPinMapping.right2, Fire = ButtonPinMapping.action2, TurnLeft = ButtonPinMapping.turnLeft2, TurnRight = ButtonPinMapping.turnRight2 }; private PlayerKeySet activeKeys; // Текущий квадрант камеры: 0=вперёд, 1=вправо, 2=назад, 3=влево private int cameraQuadrant = 0; // Возвращает физическую кнопку которую нужно нажать чтобы сдвинуть курсор в нужном направлении // dx,dy — логическое направление движения курсора на поле private ButtonPinMapping GetKeyForDirection(int dx, int dy) { // Поворот камеры на 90° вправо: физическая ось поворачивается // q=0: вперёд=вверх, вправо=вправо, назад=вниз, влево=влево // q=1: вперёд=вправо, вправо=вниз, назад=влево, влево=вверх // q=2: вперёд=вниз, вправо=влево, назад=вверх, влево=вправо // q=3: вперёд=влево, вправо=вверх, назад=вправо, влево=вниз int rotDx = dx; int rotDy = dy; for (int i = 0; i < cameraQuadrant; i++) { // Поворот вектора на -90° (камера повернулась вправо — вектор поворачиваем влево) int tmp = rotDx; rotDx = rotDy; rotDy = -tmp; } // Теперь rotDx/rotDy — это какую физическую кнопку нажать if (rotDx == 0 && rotDy == -1) return activeKeys.Up; if (rotDx == 0 && rotDy == 1) return activeKeys.Down; if (rotDx == 1 && rotDy == 0) return activeKeys.Right; if (rotDx == -1 && rotDy == 0) return activeKeys.Left; return activeKeys.Up; // fallback } // кнопочки (только fire и поворот корабля — они не зависят от камеры) private ButtonPinMapping fireKey; private ButtonPinMapping turnLeftKey; private ButtonPinMapping turnRightKey; public Transform cameraPivot; private int playerId; public void Initialize(GameManager gm, Transform pivotTransform, int playerId = 1, bool isPlacingShips = false) { this.isPlacingShips = isPlacingShips; gameManager = gm; if (isPlacingShips) ownField = gm.playerField; else ownField = gm.enemyField; // Размеры и начальная позиция — из текущей конфигурации поля width = ownField.LengPole; height = ownField.LengPole; x = width / 2; y = height / 2; BindKeys(playerId); cameraPivot = pivotTransform; UpdateCursorPosition(); // Мгновенно выставить состояние курсора под стартовой позицией if (cursorAnimator != null) { bool blocked = isPlacingShips ? (ownField.FreePole[x, y] != 0) : (ownField.PoleShot[x, y] != 0); cursorAnimator.RefreshState(blocked); } } private void BindKeys(int playerId) { activeKeys = (playerId == 1) ? player1Keys : player2Keys; // Направления (up/down/left/right) не копируем — они вычисляются через MapKey + cameraQuadrant fireKey = activeKeys.Fire; turnLeftKey = activeKeys.TurnLeft; turnRightKey = activeKeys.TurnRight; } public void SwitchButton(Vector3 rotate) { if (activeKeys == null) return; // защита от вызова до Initialize float y = rotate.y; if (y > 180) y -= 360; if (y >= -45 && y < 45) cameraQuadrant = 0; // вперёд else if (y >= 45 && y < 135) cameraQuadrant = 1; // вправо else if (y >= 135 || y < -135) cameraQuadrant = 2; // назад else cameraQuadrant = 3; // влево } void Update() { if (isShootingInProgress) return; if (gameManager.currentInputMode == GameManager.InputMode.UI) return; // --- Поворот корабля / камеры в режиме расстановки --- if (isPlacingShips) { if (In.GetButtonDown(turnLeftKey)) currentDirection = (Direction)(((int)currentDirection + 3) % 4); else if (In.GetButtonDown(turnRightKey)) currentDirection = (Direction)(((int)currentDirection + 1) % 4); UpdateCursorPosition(); } // if (In.GetButtonUp(turnRightKey) || In.GetButtonUp(turnLeftKey)) SwitchButton(cameraPivot.rotation.eulerAngles); // // --- Только в свой ход --- if (!isPlacingShips && (gameManager.currentState != GameState.Playing || !gameManager.isPlayerTurn)) return; // --- Движение курсора --- bool anyMove = In.GetButtonDown(activeKeys.Up) || In.GetButtonDown(activeKeys.Down) || In.GetButtonDown(activeKeys.Left) || In.GetButtonDown(activeKeys.Right); if (anyMove) SwitchButton(cameraPivot.rotation.eulerAngles); // ? bool moved = false; if (In.GetButtonDown(GetKeyForDirection( 0, -1))) { MoveCursor( 0, -1); moved = true; } if (In.GetButtonDown(GetKeyForDirection( 0, 1))) { MoveCursor( 0, 1); moved = true; } if (In.GetButtonDown(GetKeyForDirection( 1, 0))) { MoveCursor( 1, 0); moved = true; } if (In.GetButtonDown(GetKeyForDirection(-1, 0))) { MoveCursor(-1, 0); moved = true; } if (moved) { UpdateCursorPosition(); if (!isPlacingShips) gameManager.ResetBattleIdleTimer(); } // --- Выстрел / установка --- if (In.GetButtonDown(fireKey)) { if (!isPlacingShips) { gameManager.ResetBattleIdleTimer(); TryShoot(); } else TryPlaceCurrentShip(); } } void UpdateCursorPosition() { Cell targetCell = ownField.GetCell(x, y); if (targetCell != null) { cursorVisual.transform.position = targetCell.transform.position + Vector3.back * 0.1f; // Масштаб курсора = размер клетки (в быстрых режимах клетки крупнее) cursorVisual.transform.localScale = Vector3.one * ownField.CellScale; } // Обновляем состояние аниматора if (cursorAnimator != null) { bool blocked; if (isPlacingShips) // При расстановке — красный если клетка занята или риф blocked = (ownField.FreePole[x, y] != 0); else // При стрельбе — красный если уже стреляли blocked = (ownField.PoleShot[x, y] != 0); if (blocked) cursorAnimator.SetStateBlocked(); else cursorAnimator.SetStateFree(); } if (isPlacingShips) { ownField.ClearGhost(); ownField.ShowShipGhost(x, y, currentDirection); } } void TryShoot() { if (isShootingInProgress) return; if (ownField.PoleShot[x, y] != 0) return; isShootingInProgress = true; // Анимация выстрела — клетка будет занята после выстрела cursorAnimator?.PlayShot(true); if (gameManager.gameMode == GameMode.PlayerVsPlayer) { gameManager.opponentManager.enemyBattery.FireShot( gameManager.opponentManager.playerField, x, y, (wasHit, wasShipDestroyed) => { // мистр кастыль gameManager.opponentManager.ProcessShotResult(wasHit, false, wasShipDestroyed); }); } gameManager.battery.FireShot(gameManager.enemyField, x, y, (wasHit, wasShipDestroyed) => { gameManager.ProcessShotResult(wasHit, true, wasShipDestroyed); if (!wasHit)gameManager.EndPlayerTurn(); isShootingInProgress = false; }); } void TryPlaceCurrentShip() { bool placed = ownField.PlaceShipManual(x, y, currentDirection); if (placed) gameManager.AddShipPlayer(); } void MoveCursor(int dx, int dy) { if (isPlacingShips) { x += dx; y += dy; if (x < 0) x = width - 1; if (x >= width) { x = width - 1; gameManager.SetInputMode(GameManager.InputMode.UI); return; } if (y < 0) y = height - 1; if (y >= height) y = 0; return; } else { x += dx; y += dy; if (x < 0) x = width - 1; if (x >= width) x = 0; if (y < 0) y = height - 1; if (y >= height) y = 0; } } } [System.Serializable] public class PlayerKeySet { public ButtonPinMapping Up; public ButtonPinMapping Down; public ButtonPinMapping Left; public ButtonPinMapping Right; public ButtonPinMapping Fire; public ButtonPinMapping TurnLeft; public ButtonPinMapping TurnRight; }