/// <summary> /// ダメージ値を計算します /// </summary> /// <param name="attacker">Attacker.</param> public int CalcurateDamageValue(Main_Unit attacker) { // 三つ巴的な相性ダメージ Kuro < Shiro < Tora < Kuro ... var unitTypeBonus = new float[] { 1f, 2f, 0.5f }[(((int)attacker.unitType - (int)unitType) + 3) % 3]; var damage = Mathf.RoundToInt(attacker.AttackPower * unitTypeBonus * (1f - attacker.Cell.ReduceRate)); return(damage); }
/// <summary> /// 対象ユニットに攻撃します /// </summary> /// <param name="fromUnit">From unit.</param> /// <param name="toUnit">To unit.</param> public void AttackTo(Main_Unit fromUnit, Main_Unit toUnit) { Battle_SceneController.attacker = fromUnit; Battle_SceneController.defender = toUnit; SceneManager.LoadScene("Battle", LoadSceneMode.Additive); ClearHighlight(); FocusingUnit.IsMoved = true; }
/// <summary> /// 敵ユニットに攻撃可能となるマスを取得します /// </summary> /// <returns>The attack base cells.</returns> /// <param name="unit">Unit.</param> Main_Cell[] GetAttackBaseCells(Main_Unit unit) { var cells = new List <Main_Cell>(); foreach (var enemyUnit in map.GetEnemyUnits()) { cells.AddRange(map.GetCellsByDistance(enemyUnit.Cell, unit.attackRangeMin, unit.attackRangeMax).Where(c => c.Cost < 999)); } return(cells.Distinct().ToArray()); }
/// <summary> /// 移動の終了を待つコルーチン /// </summary> /// <returns>The move coroutine.</returns> /// <param name="unit">Unit.</param> /// <param name="cell">Cell.</param> IEnumerator WaitMoveCoroutine(Main_Unit unit, Main_Cell cell) { while (true) { if (cell.Unit == unit) { break; } yield return(new WaitForSeconds(0.1f)); } yield return(new WaitForSeconds(0.5f)); }
void RefreshImages(List <Image> images, Main_Unit unit, bool needToAnimate = false) { for (var i = images.Count; i > Mathf.CeilToInt((float)unit.Life / (float)unit.LifeMax * 10f); i--) { var index = Random.Range(0, images.Count); if (needToAnimate) { var image = images[index]; image.transform.DOLocalMoveY(image.transform.localPosition.y - 100f, 0.3f) .OnComplete(() => { Destroy(image.gameObject); }); } else { Destroy(images[index].gameObject); } images.RemoveAt(index); } }
/// <summary> /// 指定座標にユニットを配置します /// </summary> /// <param name="x">The x coordinate.</param> /// <param name="y">The y coordinate.</param> /// <param name="unitPrefab">Unit prefab.</param> public void PutUnit(int x, int y, Main_Unit unitPrefab, Main_Unit.Teams team) { var unit = Instantiate(unitPrefab); unit.team = team; switch (unit.team) { case Main_Unit.Teams.Player2: // 敵ユニットはちょっと色を変えて反転 var image = unit.GetComponent <Image>(); image.color = new Color(1f, 0.7f, 0.7f); var scale = image.transform.localScale; scale.x *= -1f; image.transform.localScale = scale; break; } unit.gameObject.SetActive(true); unit.transform.SetParent(unitContainer); unit.transform.position = cells.First(c => c.X == x && c.Y == y).transform.position; unit.x = x; unit.y = y; }
/// <summary> /// ユニットを対象のマスに移動させます /// </summary> /// <param name="cell">Cell.</param> public void MoveTo(Main_Unit unit, Main_Cell cell) { ClearHighlight(); var routeCells = CalculateRouteCells(unit.x, unit.y, unit.moveAmount, cell); var sequence = DOTween.Sequence(); for (var i = 1; i < routeCells.Length; i++) { var routeCell = routeCells[i]; sequence.Append(unit.transform.DOMove(routeCell.transform.position, 0.1f).SetEase(Ease.Linear)); } sequence.OnComplete(() => { unit.x = routeCells[routeCells.Length - 1].X; unit.y = routeCells[routeCells.Length - 1].Y; // 攻撃可能範囲のチェック var isAttackable = HighlightAttackableCells(unit.x, unit.y, unit.attackRangeMin, unit.attackRangeMax); if (!isAttackable) { unit.IsMoved = true; } }); }
IEnumerator AttackIfPossibleCoroutine(Main_Unit unit) { var attackableCells = map.GetAttackableCells(); if (0 < attackableCells.Length) { if (Random.Range(0, 100) < randomizeAttackTarget) { // ランダムで対象を選ぶ attackableCells[Random.Range(0, attackableCells.Length)].Unit.OnClick(); } else { // 攻撃可能なマスのうち、できるだけ倒せる/大ダメージを与えられる/反撃が痛くないマスに攻撃 attackableCells.OrderByDescending(x => { var damageValue = x.Unit.CalcurateDamageValue(unit); return(damageValue * (x.Unit.Life <= damageValue ? 10 : 1) - unit.CalcurateDamageValue(x.Unit)); }).First().Unit.OnClick(); } yield return(WaitBattleCoroutine()); } }
/// <summary> /// ダメージを与えます /// </summary> /// <param name="attacker">Attacker.</param> public void Damage(Main_Unit attacker) { life = Mathf.Max(0, life - CalcurateDamageValue(attacker)); }
IEnumerator MoveAndAttackCoroutine(Main_Unit unit) { // 移動可能な全てのマスまでの移動コストを取得 var moveCosts = map.GetMoveCostToAllCells(unit.Cell); var attackBaseCells = GetAttackBaseCells(unit).ToList(); if (attackBaseCells.Count() == 0) { // 攻撃拠点となるマスが無いなら行動終了 yield return(new WaitForSeconds(0.5f)); unit.IsMoved = true; yield return(new WaitForSeconds(0.5f)); yield break; } // 攻撃拠点となるマスのうち、一番近い場所を目標地点とする var targetCell = attackBaseCells.OrderBy(cell => moveCosts.First(cost => { return(cost.coordinate.x == unit.Cell.X && cost.coordinate.y == unit.Cell.Y); }).value).First(); // ユニットを選択 unit.OnClick(); var route = map.CalcurateRouteCoordinatesAndMoveAmount(unit.Cell, targetCell); var movableCells = map.GetMovableCells().ToList(); if (movableCells.Count == 0) { yield return(AttackIfPossibleCoroutine(unit)); if (!unit.IsMoved) { // 行動不能な場合は行動終了 unit.OnClick(); yield return(new WaitForSeconds(0.5f)); unit.IsMoved = true; yield return(new WaitForSeconds(0.5f)); } } else { // 自分の居るマスも移動先の選択肢に含める movableCells.Add(unit.Cell); var moveTargetCell = movableCells.OrderByDescending(c => { var matchedRoute = route.FirstOrDefault(r => r.coordinate.x == c.X && r.coordinate.y == c.Y); return((null != matchedRoute ? matchedRoute.value : 0) + c.ReduceRate * cellReduceRateImportance); }).First(); if (moveTargetCell != unit.Cell) { yield return(new WaitForSeconds(0.5f)); moveTargetCell.OnClick(); // 移動完了を待つ yield return(WaitMoveCoroutine(unit, moveTargetCell)); } yield return(AttackIfPossibleCoroutine(unit)); } }