/// <summary> /// Constructor for Battlefield for battle with heroless units /// </summary> /// <param name="width">Width of battlefield</param> /// <param name="height">Height of battlefield</param> /// <param name="attacker">The attacking hero</param> /// <param name="defender">The defending units</param> /// <param name="canWalk">Canwalk</param> public BattleField(int width, int height, Hero attacker, UnitTree defender, int[,] canWalk) { Width = width; Height = height; Attacker = attacker; CanWalk = canWalk; aStar = new AStarAlgo(canWalk, width, height, true); attackingUnits = attacker.Units; defendingUnits = defender; Unit[] aUnits = attacker.Units.GetUnits(); Unit[] dUnits = defender.GetUnits(); int increment = height / UnitTree.TREESIZE; int place = 0; unitsPos = new UnitAndAmount[width, height]; for (int i = 0; i < UnitTree.TREESIZE; i++) { if (aUnits[i] != null) { UnitAndAmount atroop = new UnitAndAmount(attacker.Units, i); unitsPos[0, place] = atroop; } if (dUnits[i] != null) { UnitAndAmount dtroop = new UnitAndAmount(defender, i); unitsPos[width - 1, place] = dtroop; } place += increment; } }
/// <summary> /// Method for moving unit and attacking target /// </summary> /// <param name="start">Start position</param> /// <param name="goal">Goal position</param> /// <param name="attackedUnitPos">Position of unit to be attacked</param> /// <returns>List with movement path, empty list if no path</returns> public List <Vector2> UnitMoveAndAttack(Point start, Point goal, Point attackedUnitPos) { List <Vector2> path = aStar.calculate(start, goal); if (path.Count != 0) { unitsPos[goal.x, goal.y] = unitsPos[start.x, start.y]; unitsPos[start.x, start.y] = null; UnitAndAmount attackingUnits = unitsPos[goal.x, goal.y]; UnitAndAmount defendingUnits = unitsPos[attackedUnitPos.x, attackedUnitPos.y]; attackingUnits.dealDamage(defendingUnits, false, 0); if (defendingUnits.Unit.HaveNotRetaliated && defendingUnits.Amount > 0) { defendingUnits.dealDamage(attackingUnits, false, 0); defendingUnits.Unit.HaveNotRetaliated = false; } if (attackingUnits.Amount < 0) { attackingUnits.Amount = 0; } if (defendingUnits.Amount < 0) { defendingUnits.Amount = 0; } } return(path); }
/// <summary> /// Method for dealing damage /// </summary> /// <param name="defendingUnits">Defending side</param> public void dealDamage(UnitAndAmount defendingUnits, bool ranged, int distance) { //Calculates min and max damage int minDamage = Unit.Unitstats.MinDamage * Amount; int maxDamage = Unit.Unitstats.MaxDamage * Amount; //Gets elementalAdvantage int elementAdvantage = defendingUnits.unit.Element.getElementResistance(unit.Element.getElement()); //Determines total damage based on elementalAdvantage int totalDamage; if (elementAdvantage == Element.MIN) { totalDamage = maxDamage; } else if (elementAdvantage == Element.MAX) { totalDamage = minDamage; } else { totalDamage = Random.Range(minDamage, maxDamage + 1); } //Checks for meele penalty or outside effective range if (unit.IsRanged) { Ranged r = (Ranged)unit; if (!ranged && r.MeleePenalty) { totalDamage /= 2; } else if (ranged) { if (r.Unitstats.EffectiveRange < distance) { totalDamage /= 2; } r.Ammo--; } } //Checks if crit if (unit.Unitstats.Luck / 10.0f >= Random.value) { totalDamage *= 2; } //Adjust totaldamage based on attack vs defense totalDamage = (int)(totalDamage * ((float)unit.Unitstats.Attack / defendingUnits.Unit.Unitstats.Defence)); //Applies damage and kills units. int killedUnits = totalDamage / defendingUnits.Unit.Unitstats.Health; defendingUnits.Amount -= killedUnits; defendingUnits.UnitTree.changeAmount(-killedUnits, PosInUnitTree); defendingUnits.unit.CurrentHealth -= totalDamage % defendingUnits.Unit.Unitstats.Health; if (defendingUnits.unit.CurrentHealth <= 0) { defendingUnits.Amount--; defendingUnits.Unit.CurrentHealth = defendingUnits.Unit.Unitstats.Health + defendingUnits.Unit.CurrentHealth; } }
/// <summary> /// Method for attacking without moving /// </summary> /// <param name="attackingUnitPos">Position of attacking unit</param> /// <param name="defendingUnitPos">Position of defending unit</param> public void attackWithoutMoving(Point attackingUnitPos, Point defendingUnitPos, bool ranged) { int distance = HandyMethods.DistanceHex(attackingUnitPos, defendingUnitPos); UnitAndAmount attackingUnits = unitsPos[attackingUnitPos.x, attackingUnitPos.y]; UnitAndAmount defendingUnits = unitsPos[defendingUnitPos.x, defendingUnitPos.y]; attackingUnits.dealDamage(defendingUnits, ranged, distance); if (defendingUnits.Unit.HaveNotRetaliated && defendingUnits.Amount > 0 && !ranged) { defendingUnits.dealDamage(attackingUnits, ranged, distance); defendingUnits.Unit.HaveNotRetaliated = false; } if (attackingUnits.Amount < 0) { attackingUnits.Amount = 0; } if (defendingUnits.Amount < 0) { defendingUnits.Amount = 0; } }