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; } } }
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); }
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()); }
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); } } }
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(); }
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); } } }
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(); }