Esempio n. 1
0
        public IEnumerable <IHexCoord> PathToOrigin(IHexCoord coord)
        {
            if (OutOfDate)
            {
                throw new HexNavOutOfDateException(this, _mapVersion);
            }

            var dist = GetDistance(coord);

            if (dist == null)
            {
                yield break;
            }

            yield return(coord);

            while (dist > 0)
            {
                foreach (var neighbor in HexFun.Ring(coord))
                {
                    var neighborDist = GetDistance(neighbor);
                    if (neighborDist == null || neighborDist != dist - 1)
                    {
                        continue;
                    }
                    coord = neighbor;
                    dist  = neighborDist;
                    yield return(coord);

                    break;
                }
            }
        }
Esempio n. 2
0
        private void DoSpawnUnit(Card card, SpawnUnitCardData data)
        {
            var originCoord = _gm.ActiveSquad.Config.Origin;

            _bus.Publish(new FocusCameraMessage(this, _map.GetTile(originCoord).GetTop()));

            var pickableTiles = _map.Tiles(HexFun.Ring(originCoord));

            var state = new HexPickState(Context, pickableTiles, (tile) =>
            {
                if (tile.HasEntityOnTop)
                {
                    return;
                }
                // spawn unit at that tile
                var job = new SpawnUnitJob
                {
                    Position = tile.Position.OffsetCoord,
                    EntityId = data.EntityId,
                    CardId   = card.Id
                };

                ExecuteAndSendJob(job);

                // callback
                Context.SetState(this);
            }, () =>
            {
                Context.SetState(this);
            });

            Context.SetState(state);
        }
Esempio n. 3
0
        public static List <Entity> AttackableEntitiesInRange(this Entity entity)
        {
            var squad  = entity.GetModule <SquadMember>().Squad;
            var pos    = entity.GetComponent <HexPosComp>().Position;
            var weapon = entity.GetComponent <WeaponComp>();

            // TODO: consider height diff!

            var gem = ServiceLocator.Instance.GetService <IEntityManager>();

            return(gem.GetEntities(e =>
                                   e.IsAttackable() &&
                                   e.GetModule <SquadMember>().Squad != squad &&
                                   HexFun.Distance(e.GetComponent <HexPosComp>().Position, pos) <= weapon.range
                                   ).ToList());
        }
Esempio n. 4
0
        private void FloodFill()
        {
            if (_field != null)
            {
                return;
            }
            _field = new int?[Map.Columns, Map.Rows];

            var frontLine = new Queue <HexCubeCoord>();
            var visited   = new HashSet <HexCubeCoord>();

            var origin = Settings.Origin.CubeCoord;

            frontLine.Enqueue(origin);
            visited.Add(origin);
            SetDistance(origin, 0);

            while (frontLine.Count > 0)
            {
                var pos     = frontLine.Dequeue();
                var posDist = GetDistance(pos);

                foreach (var tile in Map.Tiles(HexFun.Ring(pos)))
                {
                    if (tile.HasEntityOnTop)
                    {
                        continue;
                    }
                    var p = tile.Position;
                    if (visited.Contains(p))
                    {
                        continue;
                    }
                    int heightDiff = Math.Abs(Map.GetTile(pos).Height - tile.Height);
                    if (heightDiff > Settings.MaxHeightDiff)
                    {
                        continue;
                    }

                    frontLine.Enqueue(p);
                    visited.Add(p);
                    SetDistance(p, posDist + 1);
                }
            }
        }
Esempio n. 5
0
        public TerraformInputState(InputStateMachine context, Card card)
            : base(context)
        {
            _card           = card;
            _terrainChanges = (card.Data as TerraformCardData).GetTerrainChanges();

            _gm  = _locator.GetService <IGameManager>();
            _map = _locator.GetService <IHexMap>();

            var tiles = new HashSet <HexCubeCoord>();

            var gm = _locator.GetService <IGameManager>();

            foreach (var mem in gm.HomeSquad.AliveMembers)
            {
                var pos = mem.GetComponent <HexPosComp>().Position;

                tiles.UnionWith(HexFun.Spiral(pos, 2));
            }

            _pickableTiles = _map.Tiles(tiles).ToList();
        }
Esempio n. 6
0
        public IEnumerable <IHexCoord> Reachable(int maxDistance)
        {
            if (OutOfDate)
            {
                throw new HexNavOutOfDateException(this, _mapVersion);
            }

            var frontLine = new Queue <HexCubeCoord>();
            var visited   = new HashSet <HexCubeCoord>();

            frontLine.Enqueue(Settings.Origin.CubeCoord);
            visited.Add(Settings.Origin.CubeCoord);

            while (frontLine.Count > 0)
            {
                var pos = frontLine.Dequeue();

                yield return(pos);

                foreach (var neighbor in HexFun.Ring(pos))
                {
                    var coord = neighbor.CubeCoord;
                    if (visited.Contains(coord))
                    {
                        continue;
                    }
                    var dist = GetDistance(neighbor);
                    if (dist == null || dist > maxDistance)
                    {
                        continue;
                    }

                    frontLine.Enqueue(coord);
                    visited.Add(coord);
                }
            }
        }
Esempio n. 7
0
        public static bool Generate(IGameConfiguration game, IHexMap _map, IEntityManager _gem, out List <Squad> _squads)
        {
            _map.Columns = game.Map.Columns;
            _map.Rows    = game.Map.Rows;

            _map.GenParams.noiseOffset = game.Map.NoiseOffset;
            _map.GenParams.noiseScale  = game.Map.NoiseScale;
            _map.GenParams.heightScale = game.Map.HeightScale;

            // Initialize Random with seed!
            NetRand.Seed(game.RandomSeed);

            _map.BuildMap();

            var deckConfig = Resources.Load <CardDeckConfig>("Basic_Deck");

            _squads = new List <Squad>();
            foreach (var config in game.Squads)
            {
                var squad = new Squad(config, deckConfig);
                squad.CreateMembers(_gem);

                _squads.Add(squad);
            }

            var blacklist = new HashSet <HexOffsetCoord>();

            foreach (var s in _squads)
            {
                foreach (var e in s.Members)
                {
                    blacklist.UnionWith(HexFun.Ring(e.GetComponent <HexPosComp>().Position).Select(c => c.OffsetCoord));
                }
            }

            // hole in the middle
            var center = _map.Center.CubeCoord + HexFun.Offset(HexDirection.West);

            /*
             * //for (int i = 0; i < 2; i++)
             * {
             *  var pos = center;// + HexCubeCoord.Offset(NetRand.Enum<HexDirection>(), 1);
             *  foreach (var c in HexCubeCoord.Spiral(pos))
             *      if (NetRand.Chance(7, 10))
             *          _map.RemoveTile(c);
             * }
             * {
             *  var pos = center + HexCubeCoord.Offset(HexDirection.SouthEast) + HexCubeCoord.Offset(HexDirection.East);
             *  foreach (var c in HexCubeCoord.Spiral(pos))
             *      if (NetRand.Chance(7, 10))
             *          _map.RemoveTile(c);
             * }
             */
            foreach (var c in HexFun.Polymino(center, 9))
            {
                //_map.GetTile(c)?.SetColor(Color.blue);
                _map.RemoveTile(c);
            }

            // cut of corners with no altar
            // hard code this for now
            for (int c = 0; c < _map.Columns; c++)
            {
                for (int r = 0; r < _map.Rows; r++)
                {
                    var coord = new HexOffsetCoord(c, r).CubeCoord;
                    if (Mathf.Abs(coord.x - 2) > NetRand.Range(6, 8))
                    {
                        //_map.GetTile(coord)?.SetColor(Color.green);
                        _map.RemoveTile(coord);
                    }
                }
            }

            //foreach (var c in blacklist)
            //    _map.GetTile(c)?.SetColor(Color.red);

            // spawn debris on map
            int debrisCount = NetRand.Range(7, 10);

            for (int i = 0; i < debrisCount; i++)
            {
                // find empty position
                var pos  = NetRand.HexOffset(_map.Columns, _map.Rows);
                var tile = _map.GetTile(pos);
                while (tile == null || blacklist.Contains(pos) || tile.HasEntityOnTop)
                {
                    pos  = NetRand.HexOffset(_map.Columns, _map.Rows);
                    tile = _map.GetTile(pos);
                }

                var deb = _gem.CreateEntity("mountain");
                deb.GetComponent <HexPosComp>().SetPosition(pos);

                foreach (var npos in HexFun.Ring(pos, 2))
                {
                    var neighbor = _map.GetTile(npos);
                    if (neighbor == null || blacklist.Contains(npos.OffsetCoord) || neighbor.HasEntityOnTop)
                    {
                        continue;
                    }
                    if (NetRand.Chance(3, 10))
                    {
                        var ndeb = _gem.CreateEntity("mountain");
                        ndeb.GetComponent <HexPosComp>().SetPosition(npos);
                    }
                }
            }

            // generate forest patches
            int treeCount = NetRand.Range(7, 16);

            for (int i = 0; i < debrisCount; i++)
            {
                var pos  = NetRand.HexOffset(_map.Columns, _map.Rows);
                var tile = _map.GetTile(pos);
                while (tile == null || tile.Terrain != HexTerrain.Plain || tile.HasEntityOnTop)
                {
                    pos  = NetRand.HexOffset(_map.Columns, _map.Rows);
                    tile = _map.GetTile(pos);
                }

                tile.Terrain = HexTerrain.Forest;

                foreach (var npos in HexFun.Ring(pos))
                {
                    var neighbor = _map.GetTile(npos);
                    if (neighbor == null || neighbor.Terrain != HexTerrain.Plain || neighbor.HasEntityOnTop)
                    {
                        continue;
                    }
                    if (NetRand.Chance(3, 10))
                    {
                        neighbor.Terrain = HexTerrain.Forest;
                    }
                }
            }

            // check that there is a path from base to base
            var altarPos = _squads[0].Members[0].GetComponent <HexPosComp>().Position;
            var nav      = _map.GetNav(new HexNavSettings(altarPos));

            var otherAltar = _squads[1].Members[0].GetComponent <HexPosComp>().Position;

            var target  = otherAltar;
            int minDist = int.MaxValue;

            foreach (var n in HexFun.Ring(otherAltar))
            {
                var dist = nav.GetDistance(n);
                if (dist == null)
                {
                    Debug.Log("NO PATH BETWEEN ALTARS!");
                    return(false);
                }
                if (dist.Value < minDist)
                {
                    minDist = dist.Value;
                    target  = n.CubeCoord;
                }
            }

            //var path = nav.PathToOrigin(target).ToList();
            //foreach (var c in path)
            //{
            //    _map.GetTile(c).SetColor(new Color32(163, 198, 255, 255));
            //}

            return(true);
        }
    public override void OnInspectorGUI()
    {
        if (_hexTexture == null)
        {
            _hexTexture = (Texture)EditorGUIUtility.Load("hex_ring_big.png");
        }
        if (_raiseTexture == null)
        {
            _raiseTexture = (Texture)EditorGUIUtility.Load("hex_raise.png");
        }
        if (_lowerTexture == null)
        {
            _lowerTexture = (Texture)EditorGUIUtility.Load("hex_lower.png");
        }
        serializedObject.Update();

        EditorGUILayout.PropertyField(serializedObject.FindProperty("Name"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Description"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Art"));

        // https://catlikecoding.com/unity/tutorials/editor/custom-list/
        var list = serializedObject.FindProperty("Tiles");

        EditorGUILayout.PropertyField(list);

        EditorGUI.indentLevel++;

        if (list.isExpanded)
        {
            var tiles = (target as TerraformCardData).Tiles;

            #region Hex grid
            EditorGUILayout.BeginVertical(GUILayout.Height(_hexTexture.height + 20f));

            var cr   = EditorGUILayout.GetControlRect();
            var rect = new Rect(cr.width / 2f - _hexTexture.width / 2f, cr.yMax, _hexTexture.width, _hexTexture.height);
            EditorGUI.DrawTextureTransparent(rect, _hexTexture);

            var area = new Rect(0, 0, _raiseTexture.width, _raiseTexture.height);

            foreach (var c in HexFun.Spiral(new HexOffsetCoord(0, 0), 4))
            {
                var p = Hex2Pixel(rect.center, cellSize, c);

                area.x = p.x - area.width / 2f;
                area.y = p.y - area.height / 2f;

                var oc  = c.OffsetCoord;
                var vec = new Vector2Int(oc.col, oc.row);

                if (tiles.Where(t => t.coord == vec).Count() == 0 && GUI.Button(area, "+"))
                {
                    list.arraySize += 1;
                    var prop = list.GetArrayElementAtIndex(list.arraySize - 1);

                    var coordProp = prop.FindPropertyRelative("coord");
                    coordProp.vector2IntValue = vec;

                    var amntProp = prop.FindPropertyRelative("amount");
                    amntProp.intValue = 1;
                }
            }

            for (int i = 0; i < tiles.Length; i++)
            {
                if (tiles[i].amount == 0)
                {
                    continue;
                }
                var coord = new HexOffsetCoord(tiles[i].coord.x, tiles[i].coord.y);
                var p     = Hex2Pixel(rect.center, cellSize, coord);

                p.y -= 5f;

                area.width = _raiseTexture.width;
                area.x     = p.x - area.width / 2f;
                area.y     = p.y - area.height * 0.25f;

                EditorGUI.DrawTextureTransparent(area, tiles[i].amount > 0 ? _raiseTexture : _lowerTexture);
                area.y     -= area.height * 0.8f;
                area.width += 5f;
                GUI.Label(area, tiles[i].amount.ToString());

                var btn = new Rect(p.x - 8f, p.y + cellSize * 0.3f, 17f, 17f);

                if (GUI.Button(btn, deleteBtnContent))
                {
                    int oldSize = list.arraySize;
                    list.DeleteArrayElementAtIndex(i);
                    if (oldSize == list.arraySize)
                    {
                        list.DeleteArrayElementAtIndex(i);
                    }
                }
                btn.x = p.x + cellSize * 0.2f;
                btn.y = p.y - 5f;
                if (GUI.Button(btn, upArrowContent))
                {
                    var prop = list.GetArrayElementAtIndex(i);

                    var amntProp = prop.FindPropertyRelative("amount");
                    amntProp.intValue++;
                    if (amntProp.intValue == 0)
                    {
                        amntProp.intValue = 1;
                    }
                }
                btn.x = p.x - cellSize * 0.47f;
                if (GUI.Button(btn, downArrowContent))
                {
                    var prop = list.GetArrayElementAtIndex(i);

                    var amntProp = prop.FindPropertyRelative("amount");
                    amntProp.intValue--;
                    if (amntProp.intValue == 0)
                    {
                        amntProp.intValue = -1;
                    }
                }
            }

            EditorGUILayout.EndVertical();
            #endregion

            #region Info / Errors
            var duplicates  = new HashSet <Vector2Int>();
            var zeroEntries = new HashSet <Vector2Int>();
            for (int i = 0; i < tiles.Length; i++)
            {
                if (tiles[i].amount == 0)
                {
                    zeroEntries.Add(tiles[i].coord);
                }
                for (int j = i + 1; j < tiles.Length; j++)
                {
                    if (tiles[i].coord == tiles[j].coord)
                    {
                        duplicates.Add(tiles[i].coord);
                    }
                }
            }

            if (zeroEntries.Count > 0)
            {
                var sb = new StringBuilder();
                sb.AppendLine("These coordinates have 0 as change amount:");

                foreach (var d in zeroEntries)
                {
                    sb.AppendLine(d.ToString());
                }

                EditorGUILayout.HelpBox(sb.ToString(), MessageType.Info);
            }

            if (duplicates.Count > 0)
            {
                var sb = new StringBuilder();
                sb.AppendLine("There are duplicate entries for coordinates:");

                foreach (var d in duplicates)
                {
                    sb.AppendLine(d.ToString());
                }

                EditorGUILayout.HelpBox(sb.ToString(), MessageType.Error);
            }
            #endregion

            #region Listview

            EditorGUILayout.LabelField("Size", list.FindPropertyRelative("Array.size").intValue.ToString());

            _showList = EditorGUILayout.Foldout(_showList, "List", true);
            if (_showList)
            {
                EditorGUI.indentLevel++;
                for (int i = 0; i < list.arraySize; i++)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i), GUIContent.none);

                    if (GUILayout.Button(moveButtonContent, EditorStyles.miniButtonLeft, miniButtonWidth))
                    {
                        list.MoveArrayElement(i, i + 1);
                    }
                    if (GUILayout.Button(duplicateButtonContent, EditorStyles.miniButtonMid, miniButtonWidth))
                    {
                        list.InsertArrayElementAtIndex(i);
                    }
                    if (GUILayout.Button(deleteButtonContent, EditorStyles.miniButtonRight, miniButtonWidth))
                    {
                        int oldSize = list.arraySize;
                        list.DeleteArrayElementAtIndex(i);
                        if (oldSize == list.arraySize)
                        {
                            list.DeleteArrayElementAtIndex(i);
                        }
                    }
                    EditorGUILayout.EndHorizontal();
                }
                if (GUILayout.Button(addButtonContent, EditorStyles.miniButton))
                {
                    list.arraySize += 1;
                }
                EditorGUI.indentLevel--;
            }
        }

        EditorGUI.indentLevel--;
        #endregion

        serializedObject.ApplyModifiedProperties();
    }