diff --git a/Assets/GWConquest/Scenes/GalaxyMap.unity b/Assets/GWConquest/Scenes/GalaxyMap.unity index 758a5b0..a9d4882 100644 --- a/Assets/GWConquest/Scenes/GalaxyMap.unity +++ b/Assets/GWConquest/Scenes/GalaxyMap.unity @@ -28409,7 +28409,7 @@ MonoBehaviour: BetweenTransitionLengthFactor: 60 battleTurnLength: 30 battleTurnDeviation: 10 - battleBeginPhaseLength: 0 + battleBeginPhaseLength: 30 battleCommandPhaseLength: 20 battleCombatPhaseLength: 20 moveToFlankCooldown: 15 @@ -33393,7 +33393,7 @@ PrefabInstance: - target: {fileID: 4096209424460686482, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_SizeDelta.x - value: 13 + value: 12.88861 objectReference: {fileID: 0} - target: {fileID: 4096209424460686482, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -33514,7 +33514,7 @@ PrefabInstance: - target: {fileID: 4411086135142167815, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_AnchoredPosition.x - value: -65.8 + value: -65.688614 objectReference: {fileID: 0} - target: {fileID: 5945601791339210574, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -46408,7 +46408,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &765894939 RectTransform: m_ObjectHideFlags: 0 @@ -61805,12 +61805,12 @@ PrefabInstance: - target: {fileID: 77748483005084366, guid: f69b4b94559d7a14d99e0d870647c1f9, type: 3} propertyPath: m_AnchorMax.x - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 77748483005084366, guid: f69b4b94559d7a14d99e0d870647c1f9, type: 3} propertyPath: m_AnchorMax.y - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 77748483005084366, guid: f69b4b94559d7a14d99e0d870647c1f9, type: 3} @@ -74360,7 +74360,7 @@ PrefabInstance: - target: {fileID: 4096209424460686482, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_SizeDelta.x - value: 13 + value: 12.88861 objectReference: {fileID: 0} - target: {fileID: 4096209424460686483, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -74411,7 +74411,7 @@ PrefabInstance: - target: {fileID: 4411086135142167815, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_AnchoredPosition.x - value: 65.87012 + value: 65.75873 objectReference: {fileID: 0} - target: {fileID: 5945601791339210574, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -119791,7 +119791,7 @@ PrefabInstance: - target: {fileID: 4096209424460686482, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_SizeDelta.x - value: 13 + value: 12.88861 objectReference: {fileID: 0} - target: {fileID: 4096209424460686482, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -119917,7 +119917,7 @@ PrefabInstance: - target: {fileID: 4411086135142167815, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_AnchoredPosition.x - value: -65.8 + value: -65.688614 objectReference: {fileID: 0} - target: {fileID: 5945601791339210574, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -124486,7 +124486,7 @@ RectTransform: m_AnchorMin: {x: 0.5, y: 1} m_AnchorMax: {x: 0.5, y: 1} m_AnchoredPosition: {x: 0, y: -107.51172} - m_SizeDelta: {x: 0, y: 40.225113} + m_SizeDelta: {x: 112.77534, y: 40.225113} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1981011823 MonoBehaviour: @@ -125588,7 +125588,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!224 &1996625630 RectTransform: m_ObjectHideFlags: 0 @@ -133026,12 +133026,12 @@ PrefabInstance: - target: {fileID: 77748483005084366, guid: f69b4b94559d7a14d99e0d870647c1f9, type: 3} propertyPath: m_AnchorMax.x - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 77748483005084366, guid: f69b4b94559d7a14d99e0d870647c1f9, type: 3} propertyPath: m_AnchorMax.y - value: 0 + value: 1 objectReference: {fileID: 0} - target: {fileID: 77748483005084366, guid: f69b4b94559d7a14d99e0d870647c1f9, type: 3} @@ -134072,7 +134072,7 @@ PrefabInstance: - target: {fileID: 4096209424460686482, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_SizeDelta.x - value: 13 + value: 12.88861 objectReference: {fileID: 0} - target: {fileID: 4096209424460686483, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} @@ -134097,7 +134097,7 @@ PrefabInstance: - target: {fileID: 4411086135142167815, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} propertyPath: m_AnchoredPosition.x - value: 65.87012 + value: 65.75873 objectReference: {fileID: 0} - target: {fileID: 5945601791339210574, guid: ada9ee8cb263a4e4ba2f5874cfe9098d, type: 3} diff --git a/Assets/GWConquest/Scripts/Battle.cs b/Assets/GWConquest/Scripts/Battle.cs index 41cf060..880560e 100644 --- a/Assets/GWConquest/Scripts/Battle.cs +++ b/Assets/GWConquest/Scripts/Battle.cs @@ -16,6 +16,7 @@ namespace GWConquest private NetworkVariable victorID = new NetworkVariable(); private NetworkVariable phaseCooldown = new NetworkVariable(); private NetworkVariable battlePhase = new NetworkVariable(); + private NetworkVariable defenderPlayerID = new(); public GameObject BattleFlankPrefab; @@ -111,7 +112,7 @@ namespace GWConquest public Zone Zone { get => Zone.GetFromId(zoneID.Value); - set + private set { zoneID.Value = Zone.GetZoneId(value); transform.position = value.transform.position; @@ -150,6 +151,11 @@ namespace GWConquest get => Player.GetPlayerById(victorID.Value); } + public Player Defender + { + get => Player.GetPlayerById(defenderPlayerID.Value); + } + private void OnZoneChanged(int oldID, int newID) { if (newID != -1) @@ -171,14 +177,20 @@ namespace GWConquest go.GetComponent().Spawn(); var flank = go.GetComponent(); - flank.Battle = this; - flank.MaxUnitCount = maxUnitCount; - flank.RowCount = rowCount; + flank.Init(this, maxUnitCount, rowCount, 2.5f, 2.5f); return flank; } - public void Init() + public void Init(Zone zone, Player defenderPlayer) { + Zone = zone; + foreach(Formation f in zone.Formations) + { + AddFormation(f); + } + + defenderPlayerID.Value = defenderPlayer.PlayerId; + Phase = BattlePhase.Begin; PhaseCooldown = GameManager.Instance.GetBattlePhaseLength(BattlePhase.Begin); @@ -691,6 +703,10 @@ namespace GWConquest { Debug.LogErrorFormat("Tried to move unit {0} to flank index {1} on flank {2}, but it was already occupied by {3}", unit, flankIndex, flank, flank.GetUnit(flankIndex)); } + else if (!flank.CanPlayerMoveToField(flankIndex, unit.Player, Phase)) + { + Debug.LogErrorFormat("Tried to move unit {0} to flank index {1} on flank {2}, but it is out of movement range", unit, flankIndex, flank); + } else { Debug.LogFormat("Moving unit {0} to flank index {1} on flank {2}", unit, flankIndex, flank); diff --git a/Assets/GWConquest/Scripts/BattleFlank.cs b/Assets/GWConquest/Scripts/BattleFlank.cs index 292a5d1..d9b06b1 100644 --- a/Assets/GWConquest/Scripts/BattleFlank.cs +++ b/Assets/GWConquest/Scripts/BattleFlank.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Unity.Netcode; @@ -14,7 +15,8 @@ namespace GWConquest private NetworkVariable rowCount = new NetworkVariable(); private GWNetworkList units = new GWNetworkList(); private GWNetworkList deathCooldowns = new GWNetworkList(); - + private NetworkVariable defenderStartingCols = new(); + private NetworkVariable attackerStartingCols = new(); public HexGrid hexGrid; @@ -27,7 +29,6 @@ namespace GWConquest public Battle Battle { get => battle.Value.GetBehaviour(); - set => battle.Value = value; } public ushort FlankId @@ -41,13 +42,30 @@ namespace GWConquest public int MaxUnitCount { get => maxUnitCount.Value; - set => maxUnitCount.Value = value; } public int RowCount { get => rowCount.Value; - set => rowCount.Value = value; + } + + public float AttackerStartingCols + { + get => attackerStartingCols.Value; + } + + public float DefenderStartingCols + { + get => defenderStartingCols.Value; + } + + public void Init(Battle _battle, int _maxUnitCount, int _rowCount, float _attackerStartingCols, float _defenderStartingCols) + { + battle.Value = _battle; + maxUnitCount.Value = _maxUnitCount; + rowCount.Value = _rowCount; + attackerStartingCols.Value = _attackerStartingCols; + defenderStartingCols.Value = _defenderStartingCols; } public Unit GetUnit(int index) @@ -159,6 +177,8 @@ namespace GWConquest private void ResetGrid(int _maxUnitCount, int _rowCount) { + if(_maxUnitCount == 0 || _rowCount == 0) return; + units.Clear(); deathCooldowns.Clear(); @@ -170,59 +190,124 @@ namespace GWConquest deathCooldowns.Add(0f); } } + + public bool CanPlayerMoveToField(int index, Player player, BattlePhase phase) + { + float x = hexGrid.GetPosition(index).x; + float difference; + float allowed; + if(player == Battle.Defender) + { + difference = x + 1f; + allowed = phase == BattlePhase.Begin ? AttackerStartingCols : 1.5f; + } + else { + difference = hexGrid.ColumnCount - x; + allowed = phase == BattlePhase.Begin ? DefenderStartingCols : 1.5f; + } + + return difference <= allowed; + + } + } + + public enum HexDirection + { + Left, Right, UpLeft, UpRight, DownLeft, DownRight } public class HexGrid { + + public static Vector2 uBase { get => Vector2.right; } + private static Vector2 _vBase = new(-0.5f, Mathf.Sqrt(3f) / 2f); + public static Vector2 vBase { get => _vBase; } + + public static Vector2Int GetDirectionVector(HexDirection direction) + { + return direction switch + { + HexDirection.Left => new Vector2Int(-1, 0), + HexDirection.Right => new Vector2Int(1, 0), + HexDirection.UpLeft => new Vector2Int(-1, -1), + HexDirection.UpRight => new Vector2Int(0, -1), + HexDirection.DownLeft => new Vector2Int(0, 1), + HexDirection.DownRight => new Vector2Int(1, 1), + _ => new Vector2Int(0, 0), + }; + } + private int fieldCount; private int rowCount; private float columnCount; - private Vector2[] positions; + private Vector2Int[] coordinates; + private Dictionary indexMap; public HexGrid(int _fieldCount, int _rowCount) { + if(_fieldCount == 0 || _rowCount == 0 || _rowCount > _fieldCount) + { + throw new ArgumentException($"Invalid field / row count: {_fieldCount} / {_rowCount}"); + } fieldCount = _fieldCount; rowCount = _rowCount; - int currentColumn = 0; - int currentField = 0; + coordinates = new Vector2Int[_fieldCount]; + indexMap = new Dictionary(); - float triHeight = Mathf.Sqrt(3f) / 2f; + Vector2Int vec = new(0,0); + int index = 0; + coordinates[index] = vec; + indexMap[vec] = index; + index++; - positions = new Vector2[_fieldCount]; - - if(_fieldCount != 0 && _rowCount != 0) + int u = 1; + while(index < fieldCount) { - while(currentField < _fieldCount) + for(int v = rowCount-1; v >= 0; v--) { - for(int i = 0; i < _rowCount; i++) - { - if(i % 2 == currentColumn % 2) - { - positions[currentField] = new Vector2(currentColumn*0.5f, i*triHeight); - Debug.Log($"Placing field {currentField} at position {positions[currentField]}"); - currentField++; - } - if(currentField >= _fieldCount) - { - break; - } - } - if(currentField < _fieldCount) - { - currentColumn++; - } + // endless loop reeeeeeeeeeeeeee + if(index >= fieldCount) break; + + vec = new Vector2Int(u,v); + coordinates[index] = vec; + indexMap[vec] = index; + index++; } + u++; + } - columnCount = currentColumn / 2f + 1f; + columnCount = u-1; + } + + public Vector2Int GetCoordinates(int index) + { + return coordinates[index]; + } + + public int GetIndex(Vector2Int coords) + { + return indexMap[coords]; } public Vector2 GetPosition(int index) { - return positions[index]; + Vector2Int coords = GetCoordinates(index); + return uBase * coords.x + vBase * coords.y; + } + + public bool HasCoordinates(Vector2Int coords) + { + return indexMap.ContainsKey(coords); + } + + public int GetIndexInDirection(int index, HexDirection direction) + { + Vector2Int vec = GetCoordinates(index) + GetDirectionVector(direction); + return HasCoordinates(vec) ? GetIndex(vec) : -1; } public int RowCount => rowCount; diff --git a/Assets/GWConquest/Scripts/GWNetworkManager.cs b/Assets/GWConquest/Scripts/GWNetworkManager.cs index a7b4f4c..b631cfd 100644 --- a/Assets/GWConquest/Scripts/GWNetworkManager.cs +++ b/Assets/GWConquest/Scripts/GWNetworkManager.cs @@ -94,7 +94,10 @@ namespace GWConquest foreach (Zone z in Zone.AllZones) { - z.CheckBattleStart(); + if(z.ShouldStartBattle()) + { + SpawnBattle(z); + } } Planet.SetupPlanetPathfinding(); @@ -175,18 +178,19 @@ namespace GWConquest return playerFormation; } - public Battle SpawnBattle(Zone zone) + public Battle SpawnBattle(Zone zone, Player defender = null) { var go = Instantiate(BattlePrefab); go.GetComponent().Spawn(); Battle battle = go.GetComponent(); - battle.Zone = zone; - foreach (Formation f in zone.Formations) + + if(defender == null) { - battle.AddFormation(f); + defender = zone.Formations.FirstOrDefault().Player; } - battle.Init(); + + battle.Init(zone, defender); Debug.LogFormat("Starting battle at zone {0}", this); diff --git a/Assets/GWConquest/Scripts/UI/BattleArmyPanel.cs b/Assets/GWConquest/Scripts/UI/BattleArmyPanel.cs index 3a512b6..d871bdb 100644 --- a/Assets/GWConquest/Scripts/UI/BattleArmyPanel.cs +++ b/Assets/GWConquest/Scripts/UI/BattleArmyPanel.cs @@ -241,25 +241,29 @@ namespace GWConquest public void OnIconDragged(BattleUnitIcon icon, BattleUnitIcon target) { - if (icon.Unit.BattleState == BattleUnitState.InReserve && icon.Unit.Class.IsHero) + var unit = icon.Unit; + if (unit.BattleState == BattleUnitState.InReserve && unit.Class.IsHero) { var fui = icon.GetComponentInParent(); if (fui != null && target == fui.LeaderIcon) { - icon.Unit.Formation.AssignLeaderServerRpc(icon.Unit); + unit.Formation.AssignLeaderServerRpc(unit); } } - else if (icon.Unit.BattleState == BattleUnitState.InReserve && icon.Unit.CanGoToFlank) + else if (unit.BattleState == BattleUnitState.InReserve && unit.CanGoToFlank) { - var unitTypeFits = Battle.IsSpaceBattle == (icon.Unit.Class.ZoneType == ZoneType.Space); + var unitTypeFits = Battle.IsSpaceBattle == (unit.Class.ZoneType == ZoneType.Space); var flankUI = target.GetComponentInParent(); if (flankUI != null && unitTypeFits) { var flankIndex = System.Array.IndexOf(flankUI.Icons, target); + var flank = flankUI.BattleFlank; - if (flankUI.BattleFlank.GetUnit(flankIndex) == null) + var canMove = flank.CanPlayerMoveToField(flankIndex, unit.Player, BattleUI.Battle.Phase); + + if (canMove && flank.GetUnit(flankIndex) == null) { - Battle.MoveUnitToFlankServerRpc(icon.Unit, flankUI.BattleFlank, flankIndex); + Battle.MoveUnitToFlankServerRpc(unit, flank, flankIndex); } diff --git a/Assets/GWConquest/Scripts/UI/BattleFlankUI.cs b/Assets/GWConquest/Scripts/UI/BattleFlankUI.cs index 404fd5f..16c6900 100644 --- a/Assets/GWConquest/Scripts/UI/BattleFlankUI.cs +++ b/Assets/GWConquest/Scripts/UI/BattleFlankUI.cs @@ -24,6 +24,8 @@ namespace GWConquest private BattleUI battleUI; + private bool isFlipped; + public RectTransform RectTransform { get => GetComponent(); @@ -36,6 +38,8 @@ namespace GWConquest BattleFlank = flank; flank.CurrentUI = this; + isFlipped = flank.Battle.Defender != Player.CurrentPlayer; + var rt = RectTransform; Icons = new BattleUnitIcon[flank.MaxUnitCount]; @@ -44,11 +48,21 @@ namespace GWConquest float iconHexSize = IconSize * triHeight; float xOffset = (IconSize - iconHexSize) / 2f; + float xSize = flank.hexGrid.ColumnCount * iconHexSize; + for (int i = 0; i < flank.MaxUnitCount; i++) { Vector2 gridPos = flank.hexGrid.GetPosition(i); - float posx = iconHexSize * gridPos.x - xOffset; + float posx; + if(isFlipped) + { + posx = xSize - iconHexSize * (gridPos.x + 1) - xOffset; + } + else + { + posx = iconHexSize * gridPos.x - xOffset; + } float posy = iconHexSize * gridPos.y; var pos = new Vector2(posx, -posy); @@ -72,7 +86,7 @@ namespace GWConquest Icons[i] = icon; } - rt.sizeDelta = new Vector2(flank.hexGrid.ColumnCount * iconHexSize, flank.hexGrid.RowCount * IconSize); + rt.sizeDelta = new Vector2(xSize, flank.hexGrid.RowCount * IconSize); } public void UpdateIcons() diff --git a/Assets/GWConquest/Scripts/Zone.cs b/Assets/GWConquest/Scripts/Zone.cs index fd88028..c341ece 100644 --- a/Assets/GWConquest/Scripts/Zone.cs +++ b/Assets/GWConquest/Scripts/Zone.cs @@ -126,21 +126,31 @@ namespace GWConquest { if (GameManager.Instance.IsLoaded) { - CheckBattleStart(); + if (ShouldStartBattle()) + { + var defenders = formations.Where(f => f != formation).Select(f => f.Player).Distinct(); + var defenderCount = defenders.Count(); + if(defenderCount == 0) + { + Debug.LogWarning($"[Battle] No defender found when starting battle"); + GWNetworkManager.Instance.SpawnBattle(this); + } + else + { + if(defenderCount > 1) + { + Debug.LogWarning($"[Battle] More than one defender found when starting battle"); + } + GWNetworkManager.Instance.SpawnBattle(this, defenders.First()); + } + + } } } } } - public void CheckBattleStart() - { - if (ShouldStartBattle()) - { - GWNetworkManager.Instance.SpawnBattle(this); - } - } - public bool ShouldStartBattle() { return Formations.Select((f, i) => f.Player).Distinct().Count() > 1;