public static Tuple <int, int> GetTileIndex(int posx, int posy, HexagonDirection dir, int range) { var offsetX = 0; var offsetY = 0; switch (dir) { case HexagonDirection.UpRight: offsetY = range; offsetX = range / 2; if (range % 2 == 1 && posy % 2 == 1) { offsetX++; } break; case HexagonDirection.UpLeft: offsetY = range; offsetX = -range / 2; if (range % 2 == 1 && posy % 2 == 0) { offsetX--; } break; case HexagonDirection.DownRight: offsetY = -range; offsetX = range / 2; if (range % 2 == 1 && posy % 2 == 1) { offsetX++; } break; case HexagonDirection.DownLeft: offsetY = -range; offsetX = -range / 2; if (range % 2 == 1 && posy % 2 == 0) { offsetX--; } break; case HexagonDirection.Right: offsetX = range; break; case HexagonDirection.Left: offsetX = -range; break; } return(Tuple.Create(posx + offsetX, posy + offsetY)); }
public HexagonTile GetNeighbor(HexagonTile p, HexagonDirection direction) { int dX = 0; int dZ = 0; switch (direction) { case HexagonDirection.TOP: dZ = 1; break; case HexagonDirection.BOTTOM: dZ = -1; break; case HexagonDirection.LEFT_TOP: dX = -1; dZ = p.TileX % 2 == 0 ? 0 : 1; break; case HexagonDirection.LEFT_BOTTOM: dX = -1; dZ = p.TileX % 2 == 0 ? -1 : 0; break; case HexagonDirection.RIGHT_TOP: dX = 1; dZ = p.TileX % 2 == 0 ? 0 : 1; break; case HexagonDirection.RIGHT_BOTTOM: dX = 1; dZ = p.TileX % 2 == 0 ? -1 : 0; break; } GameObject temp = this[new Point(p.TileX + dX, p.TileZ + dZ)]; if (temp == null) { return(null); } return(temp.GetComponent <HexagonTile>()); }
public override void BuffTeam(string team, HexagonCell myCell) // every unit that is in the team, if they are next to the hero, buff them { if (team == "P1") { for (int i = 1; i < editor.P1Team.Count; i++) // for every unit { for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) // for every neighboring cell { HexagonCell neighbor = myCell.GetNeighbor(d); if (neighbor != null && neighbor.unitOnTile == editor.P1Team[i]) // if the unit is next to the hero { Buff(editor.P1Team[i]); wasBuffed.Add(editor.P1Team[i]); defense += 5; } } } } else { for (int i = 1; i < editor.P2Team.Count; i++) // for every unit { for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) // for every neighboring cell { HexagonCell neighbor = myCell.GetNeighbor(d); //There is some kind of BUG happening here when a unit dies next to a fortess hero if (neighbor != null && neighbor.unitOnTile == editor.P2Team[i]) // if the unit is next to the hero { Buff(editor.P2Team[i]); wasBuffed.Add(editor.P2Team[i]); defense += 5; } } } } }
public static Tuple <int, int> GetTileIndex(int posx, int posy, HexagonDirection dir, int range) { return(TileIndexComputer.GetTileIndex(posx, posy, dir, range)); }
public static HexagonDirection Opposite(this HexagonDirection direction) { return((int)direction < 3 ? direction + 3 : direction - 3); }
public void SetNeighbor(HexagonDirection direction, HexagonCell cell) { neighbors[(int)direction] = cell; cell.neighbors[(int)direction.Opposite()] = this; }
public HexagonCell GetNeighbor(HexagonDirection direction) { return(neighbors[(int)direction]); }
public IEnumerator Kidnap(Grid hexGrid, HexagonCell unitCell) // kidnap a random dumbass { Debug.Log("kidnap the unit"); end_attack_without_retaliate = true; attacked_unit_has_died = false; string name = unitCell.unitOnTile.unit_name; attackRange = specialRange; //add a call to a retaliate function on the other unit List <HexagonCell> targetable = new List <HexagonCell>(); //Debug.Log(unitCell.unitOnTile.unit_name + " atttacking: "); foreach (HexagonCell cell in hexGrid.cells) { if (unitCell.coords.FindDistanceTo(cell.coords) <= attackRange && unitCell.coords.FindDistanceTo(cell.coords) > 0 && cell.occupied && !cell.unitOnTile.dead && tag != cell.unitOnTile.tag) { targetable.Add(cell); } } if (targetable.Count >= 1) { editor.cursor.Assign_Position(this.transform.position, hexGrid.GetCell(this.transform.position).coords); Vector3 _new_Camera_Pos = new Vector3(this.transform.position.x, this.transform.position.y, editor.Main_Cam.transform.position.z); editor.Main_Cam.transform.position = Vector3.Lerp(editor.Main_Cam.transform.position, _new_Camera_Pos, 1f); yield return(new WaitForSeconds(0.3f)); int selectedTarget = ChosenEnemy(targetable); float crit_chance = Random.value; float miss_chance = Random.value; float damage; if (targetable[selectedTarget].GetComponent <HeroUnit>() != null) { damage = (current_attack * 1.5f) - targetable[selectedTarget].unitOnTile.defense; } else { damage = current_attack - targetable[selectedTarget].unitOnTile.defense; } Debug.Log("Damage: " + damage); int dmg_txt = (int)damage; bool crit_happened = false; editor.printState(); if (targetable[selectedTarget].unitOnTile.FloatingTextPrefab) { //Debug.Log("fadef"); if (miss_chance <= miss) { damage = 0; } else { if (crit_chance <= crit && miss_chance > miss) { int rand = Random.Range(0, 2); if (rand == 0) { GameObject.FindGameObjectWithTag("SoundManager").GetComponent <SoundManager>().PlayOneFromList(GameObject.FindGameObjectWithTag("SoundManager").GetComponent <SoundManager>().critSounds); } damage = current_attack * crit_multiplier; crit_happened = true; } } dmg_txt = (int)damage; } //for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) //{ // HexagonCell neighbor = unitCell.GetNeighbor(d); // if (!neighbor.occupied && neighbor.tag != "Wall" && targetable[selectedTarget].unitOnTile.GetComponent<HeroUnit>() == null) // if a neighbor to the hero is not occupied or wall unit not hero // { // targetable[selectedTarget].unitOnTile.transform.position = neighbor.transform.position; // move the bitch // neighbor.occupied = true; // neighbor.unitOnTile = targetable[selectedTarget].unitOnTile; // temp_attacked_unit = neighbor.unitOnTile; // temp_attacked_cell = neighbor; // targetable[selectedTarget].occupied = false; // targetable[selectedTarget].unitOnTile = null; // //correctly sort kidnapped unit's meshes // editor.re_sort_unit_position(temp_attacked_unit, temp_attacked_cell); // break; // } //} StartUnit attacked_unit; HexagonCell attacked_cell; if (temp_attacked_unit != null) { attacked_unit = temp_attacked_unit; attacked_cell = temp_attacked_cell; } else { attacked_unit = targetable[selectedTarget].unitOnTile; attacked_cell = targetable[selectedTarget]; } HexagonCoord current = unitCell.coords; if (attacked_cell.gameObject.transform.position.x > transform.position.x) //unit is to the right { if (!direction) //facing left, so needs to face right { transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z); direction = true; } } else //unit is to the left { if (direction) { transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z); direction = false; } } //-------------------------- Testing Kidnapp Stuff ---------------------- StartCoroutine(move_to_kidnap(attacked_unit.gameObject, attacked_unit, attacked_cell, targetable[selectedTarget])); if (targetable[selectedTarget].unitOnTile.GetComponent <HeroUnit>() == null) { yield return(new WaitForSeconds(1.40f)); //---- for sync with kidnap to } else { yield return(new WaitForSeconds(2.10f)); //---- for sync with kidnap to } for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) { HexagonCell neighbor = unitCell.GetNeighbor(d); if (!neighbor.occupied && neighbor.tag != "Wall" && targetable[selectedTarget].unitOnTile.GetComponent <HeroUnit>() == null) // if a neighbor to the hero is not occupied or wall unit not hero { targetable[selectedTarget].unitOnTile.transform.position = neighbor.transform.position; // move the bitch neighbor.occupied = true; neighbor.unitOnTile = targetable[selectedTarget].unitOnTile; temp_attacked_unit = neighbor.unitOnTile; temp_attacked_cell = neighbor; targetable[selectedTarget].occupied = false; targetable[selectedTarget].unitOnTile = null; //correctly sort kidnapped unit's meshes editor.re_sort_unit_position(temp_attacked_unit, temp_attacked_cell); break; } } yield return(new WaitForSeconds(0.26f)); //---- for sync with kidnap to if (temp_attacked_unit != null) { attacked_unit = temp_attacked_unit; attacked_cell = temp_attacked_cell; } else { attacked_unit = targetable[selectedTarget].unitOnTile; attacked_cell = targetable[selectedTarget]; } if (attacked_cell.gameObject.transform.position.x > transform.position.x) //unit is to the right { if (!direction) //facing left, so needs to face right { transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z); direction = true; } } else //unit is to the left { if (direction) { transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z); direction = false; } } //-------------------------- Testing Kidnapp Stuff ---------------------- ^^^^ if (attacked_unit.FloatingTextPrefab) { GameObject damagetext = Instantiate(attacked_unit.FloatingTextPrefab, attacked_unit.transform.position, Quaternion.identity, attacked_unit.transform); if (damage == 0) { damagetext.GetComponent <TextMesh>().text = "MISS"; int rand = Random.Range(0, 2); if (rand == 0) { GameObject.FindGameObjectWithTag("SoundManager").GetComponent <SoundManager>().PlayOneFromList(GameObject.FindGameObjectWithTag("SoundManager").GetComponent <SoundManager>().missSounds); } damagetext.GetComponent <TextMesh>().color = Color.white; damagetext.GetComponent <TextMesh>().characterSize = 0.06f; } if (damage != 0) { damagetext.GetComponent <TextMesh>().text = dmg_txt.ToString(); if (crit_happened) { damagetext.GetComponent <TextMesh>().color = Color.red; damagetext.GetComponent <TextMesh>().characterSize = 0.03f + (0.06f * ((float)dmg_txt / 75f)); } else { damagetext.GetComponent <TextMesh>().color = Color.yellow; damagetext.GetComponent <TextMesh>().characterSize = 0.03f + (0.06f * ((float)dmg_txt / 75f)); } } if (Mathf.Sign(damagetext.transform.parent.localScale.x) == -1 && Mathf.Sign(damagetext.transform.localScale.x) == 1) { damagetext.gameObject.transform.localScale = new Vector3(damagetext.transform.localScale.x * -1, damagetext.transform.localScale.y, damagetext.transform.localScale.z); //damagetext.GetComponent<TextMesh>().color = Color.green; //Debug.Log("BackWards Text"); } else { if (Mathf.Sign(damagetext.transform.parent.localScale.x) == 1 && Mathf.Sign(damagetext.transform.localScale.x) == -1) { damagetext.gameObject.transform.localScale = new Vector3(damagetext.transform.localScale.x * -1, damagetext.transform.localScale.y, damagetext.transform.localScale.z); } } } Debug.Log(name + " attacked " + attacked_unit.unit_name + " for " + damage); TakeDamage(attacked_unit, damage); //Debug.Log("he dead"); if (attacked_unit.current_health <= 0) { GameObject.FindGameObjectWithTag("SoundManager").GetComponent <SoundManager>().PlayOneFromList(GameObject.FindGameObjectWithTag("SoundManager").GetComponent <SoundManager>().killSounds); if (attacked_unit.tag == "TeamBuff") // was a buffmonster { GameObject buffItem = Instantiate(FloatingBuffPrefab, transform.position, Quaternion.identity, transform); int randBuff = Random.Range(0, 4); //give correct buff accordingly Debug.Log("acquiring buff"); if (randBuff == 0) // movement buff { buffItem.GetComponent <SpriteRenderer>().sprite = mobilityBuff; Debug.Log(name + " got a movement buff"); current_mobility += 1; move_buff = true; if (current_health != health) { current_health += 10; } } else if (randBuff == 1) // crit buff { buffItem.GetComponent <SpriteRenderer>().sprite = critBuff; Debug.Log(name + " got a crit buff"); crit += 0.20f; crit_buff = true; if (current_health != health) { current_health += 10; } } else if (randBuff == 2) // attack buff { Debug.Log(name + " got an attack buff"); buffItem.GetComponent <SpriteRenderer>().sprite = attackBuff; attack += 25; current_attack += 25; attack_buff = true; if (current_health != health) { current_health += 10; } } else // health buff { Debug.Log(name + " got a health buff"); buffItem.GetComponent <SpriteRenderer>().sprite = healthBuff; health += 100; current_health += 100; health_buff = true; } if (current_health > (health * 0.4f)) { this.anim.SetBool("Injured", false); this.Injured = false; } gameObject.GetComponentInChildren <Buff_UI_Manager>().update_current_buffs(this); float healthpercent = current_health / health; // 120/180 = .667 float attack_deduction = 1 - healthpercent; // 1 - .667 = .333 float reduction = attack_deduction / 2; float new_attack = attacked_unit.attack * reduction; // 72 * .333 = 23.76 current_attack = attack + new_attack; // 72 - 23.76 = 48 } end_attack_without_retaliate = true; attacked_unit_has_died = true; StartCoroutine(Attack(hexGrid, unitCell, attacked_cell)); //int index = targetable[rand_index].coords.X_coord + targetable[rand_index].coords.Z_coord * hexGrid.width + targetable[rand_index].coords.Z_coord / 2; //editor.RemoveUnitInfo(targetable[rand_index], index); editor.Units_To_Delete.Add(attacked_cell); attacked_unit.dead = true; yield return(new WaitForSeconds(0.3f)); StartCoroutine(attacked_unit.Hit()); StartCoroutine(attacked_unit.Blink(editor.Unit_Hurt_Color, attacked_unit, Time.time + 1f)); //attacked_unit.Fade_Out_Body(); //Should start some sort of DEATH ANIMATION COROUTINE HERE specialAttackCounter = 3; attackRange = 1; temp_attacked_cell = null; temp_attacked_unit = null; } else { if (unitCell.coords.FindDistanceTo(attacked_cell.coords) <= attacked_cell.unitOnTile.attackRange) { end_attack_without_retaliate = false; } else { end_attack_without_retaliate = true; } if (current_health - 20 <= 0 && attacked_unit.gameObject.GetComponent <FortressHero>() != null) { end_attack_without_retaliate = true; } StartCoroutine(Attack(hexGrid, unitCell, attacked_cell)); yield return(new WaitForSeconds(0.3f)); //if (attacked_unit.gameObject.GetComponent<FortressHero>() != null && damage != 0) // handling of if attacking fortress hero //{ // Debug.Log("Hurt by fortress hero's armor"); // if (FloatingTextPrefab) // { // GameObject damagetext = Instantiate(FloatingTextPrefab, transform.position, Quaternion.identity, transform); // damagetext.GetComponent<TextMesh>().text = 20.ToString(); // damagetext.GetComponent<TextMesh>().color = Color.yellow; // damagetext.GetComponent<TextMesh>().characterSize = 0.03f + (0.06f * (20f / 75f)); // if (Mathf.Sign(damagetext.transform.parent.localScale.x) == -1 && Mathf.Sign(damagetext.transform.localScale.x) == 1) // { // damagetext.gameObject.transform.localScale = new Vector3(damagetext.transform.localScale.x * -1, damagetext.transform.localScale.y, // damagetext.transform.localScale.z); // //damagetext.GetComponent<TextMesh>().color = Color.green; // //Debug.Log("BackWards Text"); // } // else // { // if (Mathf.Sign(damagetext.transform.parent.localScale.x) == 1 && Mathf.Sign(damagetext.transform.localScale.x) == -1) // { // damagetext.gameObject.transform.localScale = new Vector3(damagetext.transform.localScale.x * -1, damagetext.transform.localScale.y, // damagetext.transform.localScale.z); // } // } // } // TakeDamage(this, 20f); // StartCoroutine(AttackToHit()); // StartCoroutine(Blink(editor.Unit_Hurt_Color, this, Time.time + 1f)); // if (current_health <= 0) // pretty sure there's more code needed here but i'll ask christophe later // { // editor.Units_To_Delete.Add(unitCell); // dead = true; // } //} StartCoroutine(attacked_unit.Hit()); StartCoroutine(attacked_unit.Blink(editor.Unit_Hurt_Color, attacked_unit, Time.time + 1f)); } specialAttackCounter = 3; attackRange = 1; temp_attacked_cell = null; temp_attacked_unit = null; } else { specialAttackCounter = 0; attackRange = 1; currently_attacking = false; } }
public void ShowPath(HexagonCell current, int mobility, int range, Color color_m, Color color_a) // displays the movement capabilities of a unit using A* { List <HexagonCell> frontier = new List <HexagonCell>(); for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; } HexagonCell fromCell = current; //fromCell.spriteRenderer.color = color_m; fromCell.Show_Move_Icon(); fromCell.Distance = 0; frontier.Add(fromCell); while (frontier.Count > 0) { HexagonCell curr = frontier[0]; frontier.RemoveAt(0); if (curr.distance == mobility) { //curr.spriteRenderer.color = color_m; curr.Show_Move_Icon(); continue; } for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) { HexagonCell neighbor = curr.GetNeighbor(d); if (neighbor == null || neighbor.Distance != int.MaxValue) // no tile there, or explored already { continue; } if (!neighbor.traversable)// if a wall { continue; } if (neighbor.occupied && neighbor.unitOnTile.tag != current.unitOnTile.tag) // if there is an enemy unit on that tile { continue; } int distance = curr.Distance; /*if(water) * distance += 3 * else if(grass) * distance += 2 */ if (neighbor.tag == "Water") { distance += 2; } else { distance += 1; } if (distance > mobility) { continue; } if (distance < neighbor.Distance) { neighbor.Show_Move_Icon(); neighbor.Distance = distance; frontier.Add(neighbor); } frontier.Sort((x, y) => x.Distance.CompareTo(y.Distance)); } } }
Stack <HexagonCell> Search(HexagonCell fromCell, HexagonCell toCell) // searrch creates a stack of the shortest path given a to and from tile. this is used for movement animations { Stack <HexagonCell> result = new Stack <HexagonCell>(); for (int i = 0; i < cells.Length; i++) { cells[i].Distance = int.MaxValue; } List <HexagonCell> frontier = new List <HexagonCell>(); fromCell.Distance = 0; frontier.Add(fromCell); while (frontier.Count > 0) { HexagonCell current = frontier[0]; frontier.RemoveAt(0); if (current == toCell) { result.Push(toCell); current = current.PathFrom; while (current != fromCell) { result.Push(current); current = current.PathFrom; } return(result); } for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) { HexagonCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.Distance != int.MaxValue) { continue; } if (!neighbor.traversable) // if its not traversable end here { continue; } if (neighbor.unitOnTile != null && neighbor.occupied && neighbor.unitOnTile.tag != fromCell.unitOnTile.tag) // if there is an enemy unit on that tile { continue; } int distance = current.Distance; /*if(water) * distance += 3 * else if(grass) * distance += 2 */ if (current.tag == "Water") // for water tiles increase by 2 { distance += 2; } else // for any other tile increase by 1 (default) { distance += 1; } if (neighbor.Distance == int.MaxValue) // if not traversed yet { neighbor.Distance = distance; neighbor.PathFrom = current; frontier.Add(neighbor); } else if (distance < neighbor.Distance) { neighbor.Distance = distance; neighbor.PathFrom = current; } frontier.Sort((x, y) => x.Distance.CompareTo(y.Distance)); } } return(result = new Stack <HexagonCell>()); }
/// <summary> /// /// </summary> /// <param name="cell"></param> /// <returns></returns> private bool Search(HexagonCell fromCell, HexagonCell toCell, int speed) { this.searchFrontierPhase += 2; if (this.searchFrontier == null) { this.searchFrontier = new HexagonCellPriorityQueue(); } else { this.searchFrontier.Clear(); } // toCell.EnableHighlight(Color.red); fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; this.searchFrontier.Enqueue(fromCell); while (this.searchFrontier.Count > 0) { // yield return delay; HexagonCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; // 找到目标单元格时结束循环 if (current == toCell) { return(true); } // 计算移动到目的需要的回合数 int currentTurn = (current.Distance - 1) / speed; for (HexagonDirection d = HexagonDirection.NE; d <= HexagonDirection.NW; d++) { HexagonCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (neighbor.Unit) { // 单元格中有单位的时候跳过这个单元格 continue; } // 避开有水的地方 //if (neighbor.IsUnderwater) //{ // continue; //} // 避开悬崖 //if (current.GetEdgeType(neighbor) == HexEdgeType.Cliff) //{ // continue; //} // 沿着道路移动更快 // int distance = current.Distance; // 根据移动成本计算 int moveCost = 1; //if (current.HasRoadThroughEdge(d)) //{ // moveCost = 1; //} //else if (current.Walled != neighbor.Walled) //{ // continue; //} //else //{ // moveCost = edgeType == HexEdgeType.Flat ? 5 : 10; // moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + // neighbor.PlantLevel; //} int distance = current.Distance + moveCost; // distance += 1; // 计算移动到目的需要的回合数 int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } //if (neighbor.Distance == int.MaxValue) if (neighbor.SearchPhase < this.searchFrontierPhase) { neighbor.SearchPhase = this.searchFrontierPhase; neighbor.Distance = distance; // neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.Coordinates.DistanceTo(toCell.Coordinates); this.searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { neighbor.Distance = distance; // neighbor.SetLabel(turn.ToString()); neighbor.PathFrom = current; } } } return(false); }
public static HexagonDirection Next2(this HexagonDirection direction) { direction += 2; return(direction <= HexagonDirection.NW ? direction : (direction - 6)); }
public static HexagonDirection Previous2(this HexagonDirection direction) { direction -= 2; return(direction >= HexagonDirection.NE ? direction : (direction + 6)); }
public static HexagonDirection Next(this HexagonDirection direction) { return(direction == HexagonDirection.NW ? HexagonDirection.NE : (direction + 1)); }
public static HexagonDirection Previous(this HexagonDirection direction) { return(direction == HexagonDirection.NE ? HexagonDirection.NW : (direction - 1)); }