public StandardCharacter _targetCharacter; // attack target #endregion Fields #region Constructors public Action(ActionTypeEnum actionType) { _actionType = actionType; _animationSeqs = new ArrayList(); _currentAnimationSeq = null; _path = null; _isEnd = false; _targetCharacter = null; _subActions = new ArrayList(); }
public static Action CreateAttackAction(StandardCharacter character, CellPartEnum attackDirection, ArrayList path, ArrayList targets) { Action action = new Action(ActionTypeEnum.Attack); SubAction subAction = new SubAction(); action._subActions.Add(subAction); subAction._character = character; subAction._path = path; if (path != null && path.Count > 0) { subAction.AddStartMoving(); subAction.AddMoving(); subAction.AddStopMoving(); } // target getting hit or death ArrayList defendTriggers = new ArrayList(); ArrayList hitTriggers = new ArrayList(); foreach (Heroes.Core.Battle.Characters.Armies.Army target in targets) { SubAction subAction2 = new SubAction(); action._subActions.Add(subAction2); subAction2._character = target; AnimationSequence animationSeq = null; if (target._isDead) animationSeq = subAction2.AddDeath(attackDirection); else if (target._isDefend) animationSeq = subAction2.AddDefend(attackDirection); else animationSeq = subAction2.AddGettingHit(attackDirection); subAction2._currentAnimationSeq = animationSeq; if (target._isDefend) defendTriggers.Add(animationSeq); else hitTriggers.Add(animationSeq); } subAction.AddStartAttack(attackDirection, defendTriggers); subAction.AddStopAttack(attackDirection, hitTriggers); subAction._currentAnimationSeq = (AnimationSequence)subAction._animationSeqs[0]; return action; }
public Turn(ArrayList characters, Heroes.Core.Battle.Characters.Hero attackHero, Heroes.Core.Battle.Characters.Hero defendHero) { _characters = characters; if (_characters.Count > 0) { _currentCharacter = (StandardCharacter)_characters[0]; _currentCharacter._isBeginTurn = true; //_currentCharacter._action = _currentCharacter.CreateStandingAction(_currentCharacter, _currentCharacter.CurrentFacingDirection, _currentCharacter._isBeginTurn); //_currentCharacter.SetAnimation(_currentCharacter._action._currentAnimationSeq); } else _currentCharacter = null; _attackHero = attackHero; _defendHero = defendHero; }
private void SetSpellEffect(Heroes.Core.Spell spell, StandardCharacter target) { }
public Action CreateFirstStandingAction(StandardCharacter character, HorizontalDirectionEnum facing) { Action action = new Action(ActionTypeEnum.Standing); Animation animation = null; if (facing == HorizontalDirectionEnum.Right) { animation = _animations._firstStandingRight; } else { animation = _animations._firstStandingLeft; } AnimationSequence seq = new AnimationSequence(animation, AnimationPurposeEnum.StandingStill, facing); action._animationSeqs.Add(seq); action._currentAnimationSeq = seq; return action; }
public static Action CreateMoveAction(StandardCharacter character, ArrayList path) { Action action = new Action(ActionTypeEnum.Moving); SubAction subAction = new SubAction(); subAction._character = character; subAction._path = path; subAction.AddStartMoving(); subAction.AddMoving(); subAction.AddStopMoving(); subAction._currentAnimationSeq = (AnimationSequence)subAction._animationSeqs[0]; action._subActions.Add(subAction); return action; }
private void CreateAttackActions(CellPartEnum attackDirection, StandardCharacter attacker, StandardCharacter defender, ArrayList path, bool hasRetaliate) { // attack { ArrayList targets = new ArrayList(); targets.Add(defender); Action action = Action.CreateAttackAction(attacker, attackDirection, path, targets); _actions.Add(action); } // retaliate if (hasRetaliate) { CellPartEnum oppAttackDirection = BattleTerrain.GetOppositeDirection(attackDirection); ArrayList targets = new ArrayList(); targets.Add(attacker); Action action = Action.CreateAttackAction(defender, oppAttackDirection, null, targets); _actions.Add(action); } // attack more than once { ArrayList targets = new ArrayList(); targets.Add(defender); for (int i = 1; i < attacker._noOfAttack; i++) { Action action = Action.CreateAttackAction(attacker, attackDirection, null, targets); _actions.Add(action); } } }
private int CalculateKill(StandardCharacter c, StandardCharacter target) { int kill = 0; if (c._qtyLeft >= target._qtyLeft) kill = target._qtyLeft; else kill = c._qtyLeft; return kill; }
private void SetAttackDamage(StandardCharacter c, StandardCharacter target, bool isRangeAttack) { bool hasRangePenalty = false; bool hasObstaclePenalty = false; HasRangeAttackPenalty(c, target, out hasRangePenalty, out hasObstaclePenalty); bool hasHandToHandPenalty = HasHandToHandPenalty(c); int minDamage = 0; int maxDamage = 0; int minKill = 0; int maxKill = 0; int avgKill = 0; CalculateDamage(c, target, isRangeAttack, hasRangePenalty, hasObstaclePenalty, hasHandToHandPenalty, out minDamage, out maxDamage, out minKill, out maxKill, out avgKill); // random from minDamage to maxDamage //Random rnd = new Random(); //int rndDamage = rnd.Next(minDamage, maxDamage); int rndDamage = (minDamage + maxDamage) / 2; // use average damage because rnd Damage need to inform other player SetDamage(rndDamage, target); }
private void ProcessCharacter(StandardCharacter c) { // set currentAnimationSeq._isEnd = true; CommandResult result = c.Command.Execute(c); // just runs the animation c.CurrentAnimationRunner.Run(TurnTimeSpan); }
private void HasRangeAttackPenalty(StandardCharacter c, StandardCharacter target, out bool hasRangePenalty, out bool hasObstaclePenalty) { hasRangePenalty = false; hasObstaclePenalty = false; // Range Penalty // Whenever any shooter, except Sharpshooters or those under the command of a hero with the Golden Bow or Bow of the Sharpshooter equipped, attacks a unit standing more than 10(?) hexes away, they will only do half damage. This is cumulative with the Obstacle Penalty. // obstacle Penalty // Whenever most units tries shooting over Walls into a castle, they will only do half Damage. Certain units don't have this penalty, and neither do units under the command of a hero with the Golden Bow or Bow of the Sharpshooter. This penalty is cumulative with the Range Penalty // find attack range ArrayList path = new ArrayList(); _battleTerrain.FindPath(c._cell, target._cell, path, true, true); //_battleTerrain.FindPath(c._cell, target._cell, path, true, true, false); if (path.Count > 10) hasRangePenalty = true; }
private bool HasHandToHandPenalty(StandardCharacter c) { if (c._handToHandPenalty) { if (HasAdjacentEnermy(c)) return true; } return false; }
private bool HasAdjacentEnermy(StandardCharacter c) { foreach (Cell cell in c._cell._adjacentCells.Values) { if (cell == null) continue; if (cell._character == null) continue; if (cell._character._playerId != c._playerId) { return true; } } return false; }
public Action CreateStandingAction(StandardCharacter character, HorizontalDirectionEnum facing, bool isActive) { // no standing for dead character if (character._isDead) return null; Action action = new Action(ActionTypeEnum.Standing); Animation animation = null; if (facing == HorizontalDirectionEnum.Right) { if (isActive) animation = _animations._standingRightActive; else animation = _animations._standingRight; } else { if (isActive) animation = _animations._standingLeftActive; else animation = _animations._standingLeft; } if (animation == null) { Debug.WriteLine(""); } AnimationSequence seq = new AnimationSequence(animation, AnimationPurposeEnum.StandingStill, facing); action._animationSeqs.Add(seq); action._currentAnimationSeq = seq; return action; }
public void CalculateDamage(StandardCharacter attacker, StandardCharacter defender, bool isRangeAttack, bool hasRangePenalty, bool hasObstaclePenalty, bool hasHandToHandPenalty, out int minDamage, out int maxDamage, out int minKill, out int maxKill, out int avgKill) { minDamage = 0; maxDamage = 0; minKill = 0; maxKill = 0; avgKill = 0; // totalDamage = baseDamage * (1+a+b+c+...) * (1-q) * (1-r) * (1-s) * ... // a, b, c,... are damage bonus // q, r, s,... are damage reductions (both as decimal numbers) // Damage bonuese // Attacker's Attack Skill > Defender's Defense Skill // 0.05 * (A-D), capped at 3 // Attacker is a shooter // Archery Skill bonus, // additive with artifact bonuses if Archery skill present // Damage Reductions // Defender's Defense > Attacker's Attack // 0,025 * (D – A), up to a maximum of 0,7 // if got hero // attack + 1 + hero's attack decimal attackBonus = 0m; if (attacker._attack > defender._defense) { attackBonus = 0.05m * (decimal)(attacker._attack - defender._defense); if (attackBonus > 3m) attackBonus = 3m; } decimal offenceBonus = 0m; decimal archeryBonus = 0m; { Hero hero = FindHero(attacker._heroId); if (hero != null) { if (isRangeAttack) { if (hero._skills.ContainsKey((int)SkillIdEnum.Archery)) { Skill skill = (Skill)hero._skills[(int)SkillIdEnum.Archery]; archeryBonus = (decimal)skill._effects[skill._level] / 100m; } } else { if (hero._skills.ContainsKey((int)SkillIdEnum.Offence)) { Skill skill = (Skill)hero._skills[(int)SkillIdEnum.Offence]; offenceBonus = (decimal)skill._effects[skill._level] / 100m; } } } } decimal defenseBonus = 0m; if (defender._defense > attacker._attack) { defenseBonus = 0.025m * (decimal)(defender._defense - attacker._attack); if (defenseBonus > 0.7m) defenseBonus = 0.7m; } decimal armourerBonus = 0m; { Hero hero = FindHero(defender._heroId); if (hero != null) { if (hero._skills.ContainsKey((int)SkillIdEnum.Armourer)) { Skill skill = (Skill)hero._skills[(int)SkillIdEnum.Armourer]; armourerBonus = (decimal)skill._effects[skill._level] / 100m; } } } decimal rangePenalty = 0m; if (hasRangePenalty) rangePenalty = 0.5m; decimal obstaclePenalty = 0m; if (hasObstaclePenalty) obstaclePenalty = 0.5m; decimal handToHandPenalty = 0m; if (hasHandToHandPenalty) handToHandPenalty = 0.5m; decimal defending = 0m; Heroes.Core.Battle.Characters.Armies.Army defendArmy = (Heroes.Core.Battle.Characters.Armies.Army)defender; if (defendArmy._isDefend) defending = 0.25m; minDamage = (int)decimal.Truncate((decimal)attacker._qtyLeft * (decimal)attacker._minDamage * (1m + attackBonus) * (1m + offenceBonus) * (1m + archeryBonus) * (1m - defenseBonus) * (1m - armourerBonus) * (1m - rangePenalty) * (1m - obstaclePenalty) * (1m - handToHandPenalty) * (1m - defending)); maxDamage = (int)decimal.Truncate((decimal)attacker._qtyLeft * (decimal)attacker._maxDamage * (1m + attackBonus) * (1m + offenceBonus) * (1m + archeryBonus) * (1m - defenseBonus) * (1m - armourerBonus) * (1m - rangePenalty) * (1m - obstaclePenalty) * (1m - handToHandPenalty) * (1m - defending)); // calculate kill if (defender._healthRemain > minDamage) minKill = 0; else if (defender._healthRemain == minDamage) minKill = 1; else minKill = 1 + (int)decimal.Truncate((decimal)(minDamage - defender._healthRemain) / (decimal)defender._health); if (defender._healthRemain > maxDamage) maxKill = 0; else if (defender._healthRemain == maxDamage) maxKill = 1; else maxKill = 1 + (int)decimal.Truncate((decimal)(maxDamage - defender._healthRemain) / (decimal)defender._health); avgKill = (minKill + maxKill) / 2; }
public void CalculateDamage(StandardCharacter attacker, StandardCharacter defender, bool isRangeAttack, bool hasRangePenalty, bool hasObstaclePenalty, bool hasHandToHandPenalty) { int minDmg = 0; int maxDmg = 0; int minKill = 0; int maxKill = 0; int avgKill = 0; CalculateDamage(attacker, defender, isRangeAttack, hasRangePenalty, hasObstaclePenalty, hasHandToHandPenalty, out minDmg, out maxDmg, out minKill, out maxKill, out avgKill); DamageCalculatedEventArg e2 = new DamageCalculatedEventArg(minDmg, maxDmg, minKill, maxKill, avgKill); OnDamageCalculated(e2); _statusMsg = string.Format("Damage {0}-{1}, Kill {2}-{3}, Avg Kill {4}", e2._minDamage, e2._maxDamage, e2._minKill, e2._maxKill, e2._avgKill); }
private void SetAttackNAnimate(StandardCharacter attacker, StandardCharacter defender, CellPartEnum attackDirection, ArrayList path) { // reset defend and wait Heroes.Core.Battle.Characters.Armies.Army army = (Heroes.Core.Battle.Characters.Armies.Army)attacker; army._isWait = false; army._isDefend = false; // attack SetAttackDamage(attacker, defender, false); // attack Action { ArrayList targets = new ArrayList(); targets.Add(defender); Action action = Action.CreateAttackAction(attacker, attackDirection, path, targets); _actions.Add(action); } if (!defender._isDead) { // retaliate if (defender._retaliateRemain > 0) { SetAttackDamage(defender, attacker, false); defender._retaliateRemain -= 1; // retaliate action { CellPartEnum oppAttackDirection = BattleTerrain.GetOppositeDirection(attackDirection); ArrayList targets = new ArrayList(); targets.Add(attacker); Action action = Action.CreateAttackAction(defender, oppAttackDirection, null, targets); _actions.Add(action); } } // attack more { ArrayList targets = new ArrayList(); targets.Add(defender); for (int i = 1; i < attacker._noOfAttack; i++) { SetAttackDamage(attacker, defender, false); // attack more action { Action action = Action.CreateAttackAction(attacker, attackDirection, null, targets); _actions.Add(action); } } } } }
private bool CanRangeAttack(StandardCharacter c) { if (c._hasRangeAttack && c._shotRemain > 0) { // check surrounding cell has enermy or not foreach (Cell cell2 in c._cell._adjacentCells.Values) { if (cell2 != null && cell2._character != null && !cell2._character._isDead && cell2._character._playerId != _turn._currentCharacter._playerId) { // has enermy, no range attack return false; } } } else { return false; } return true; }
private void SetDamage(int damage, StandardCharacter target) { // defender's health int totalHealthRemain = target._healthRemain + (target._qtyLeft - 1) * target._health; totalHealthRemain -= damage; if (totalHealthRemain <= 0) { target._qtyLeft = 0; target._healthRemain = 0; target._isDead = true; } else { decimal a = (decimal)totalHealthRemain / (decimal)target._health; decimal qtyRemain = decimal.Truncate(a); decimal healthRemain2 = decimal.Truncate((a - qtyRemain) * (decimal)target._health); target._qtyLeft = (int)(qtyRemain + 1); // extra 1 is not full health target._healthRemain = (int)healthRemain2; // remaining health if (target._healthRemain == 0) { target._qtyLeft -= 1; // reduce 1 if no health target._healthRemain = target._health; // full health } } }
private void ResetTurn() { foreach (StandardCharacter character in _characters) { character._retaliateRemain = character._noOfRetaliate; // reset noOfRetaliate character._isBeginTurn = false; character._isEndTurn = false; Heroes.Core.Battle.Characters.Armies.Army army = (Heroes.Core.Battle.Characters.Armies.Army)character; army._isWait = false; } _currentCharacter = null; // hero can cast spell per whole turn _attackHero._canCastSpell = true; if (_defendHero != null) _defendHero._canCastSpell = true; }
private void SetDestCell(StandardCharacter c, Cell cell) { c._cell._character = null; c._cell = cell; c._cell._character = c; }
public void NextTurn() { // end current character { Heroes.Core.Battle.Characters.Armies.Army army = (Heroes.Core.Battle.Characters.Armies.Army)_currentCharacter; if (!army._isWait) { _currentCharacter._isBeginTurn = false; _currentCharacter._isEndTurn = true; } if (!_currentCharacter._isDead) { Action action = _currentCharacter.CreateStandingAction(_currentCharacter, _currentCharacter.CurrentFacingDirection, false); _currentCharacter._action = action; _currentCharacter.SetAnimation(action._currentAnimationSeq); } } // next character { Heroes.Core.Battle.Characters.Armies.Army army = (Heroes.Core.Battle.Characters.Armies.Army)_currentCharacter; // get next character _currentCharacter = GetNextCharacter(); // get character start from 0, because of waiting if (_currentCharacter == null) _currentCharacter = GetNextCharacter(0); // reset turn if (_currentCharacter == null) { ResetTurn(); _currentCharacter = GetNextCharacter(0); } _currentCharacter._isBeginTurn = true; // reset defend army._isDefend = false; if (!_currentCharacter._isDead) { Action action = _currentCharacter.CreateStandingAction(_currentCharacter, _currentCharacter.CurrentFacingDirection, true); _currentCharacter._action = action; _currentCharacter.SetAnimation(action._currentAnimationSeq); } } OnNextTurned(); }
private void SetKill(StandardCharacter c, StandardCharacter target) { target._qtyLeft -= c._qtyLeft; if (target._qtyLeft <= 0) { target._qtyLeft = 0; target._isDead = true; } }
public static Action CreateShootAction(StandardCharacter character, CellPartEnum attackDirection, ArrayList targets, Cell targetCell) { Action action = new Action(ActionTypeEnum.RangeAttack); SubAction subAction = new SubAction(); action._subActions.Add(subAction); subAction._character = character; // add getting hit or death ArrayList defendTriggers = new ArrayList(); ArrayList hitTriggers = new ArrayList(); foreach (Heroes.Core.Battle.Characters.Armies.Army target in targets) { SubAction subAction2 = new SubAction(); action._subActions.Add(subAction2); subAction2._character = target; AnimationSequence animationSeq = null; if (target._isDead) animationSeq = subAction2.AddDeath(attackDirection); else if (target._isDefend) animationSeq = subAction2.AddDefend(attackDirection); else animationSeq = subAction2.AddGettingHit(attackDirection); subAction2._currentAnimationSeq = animationSeq; if (target._isDefend) defendTriggers.Add(animationSeq); else hitTriggers.Add(animationSeq); } subAction.AddStartShoot(attackDirection, defendTriggers); subAction.AddStopShoot(attackDirection, hitTriggers); subAction._currentAnimationSeq = (AnimationSequence)subAction._animationSeqs[0]; return action; }
private void SetRangeAttackNAnimate(StandardCharacter attacker, StandardCharacter defender, CellPartEnum attackDirection, Cell targetCell) { // reset defend and wait Heroes.Core.Battle.Characters.Armies.Army army = (Heroes.Core.Battle.Characters.Armies.Army)attacker; army._isWait = false; army._isDefend = false; // attack SetAttackDamage(attacker, defender, true); attacker._shotRemain -= 1; // attack Action { ArrayList targets = new ArrayList(); targets.Add(defender); Action action = Action.CreateShootAction(attacker, attackDirection, targets, targetCell); _actions.Add(action); } if (!defender._isDead) { // retaliate //if (defender._canRangeRetaliate && defender._retaliateRemain > 0 && defender._shotRemain > 0) //{ // SetAttackDamage(defender, attacker, true); // defender._retaliateRemain -= 1; // // retaliate action // { // CellPartEnum oppAttackDirection = BattleTerrain.GetOppositeDirection(attackDirection); // ArrayList targets = new ArrayList(); // targets.Add(attacker); // Action action = Action.CreateShootAction(defender, oppAttackDirection, targets, attacker._cell); // _actions.Add(action); // } //} // attack more { ArrayList targets = new ArrayList(); targets.Add(defender); for (int i = 1; i < attacker._noOfAttack; i++) { SetAttackDamage(attacker, defender, true); attacker._shotRemain -= 1; // attack more action { Action action = Action.CreateShootAction(attacker, attackDirection, targets, targetCell); _actions.Add(action); } } } } }
private void SetSpellDamage(Heroes.Core.Spell spell, StandardCharacter target) { SetDamage(spell._damage, target); }
public Action CreateAttackAction(ArrayList path, CellPartEnum attackDirection, StandardCharacter target) { Action action = new Action(ActionTypeEnum.Attack); action._targetCharacter = target; SetMovingAction(action, path); // attack switch (attackDirection) { case CellPartEnum.CenterRight: { // attack begin AnimationSequence seq = new AnimationSequence(_animations._attackStraightRightBegin, AnimationPurposeEnum.AttackBegin, HorizontalDirectionEnum.Right); action._animationSeqs.Add(seq); // attack end seq = new AnimationSequence(_animations._attackStraightRightEnd, AnimationPurposeEnum.AttackEnd, HorizontalDirectionEnum.Right); action._animationSeqs.Add(seq); } break; case CellPartEnum.CenterLeft: { // attack begin AnimationSequence seq = new AnimationSequence(_animations._attackStraightLeftBegin, AnimationPurposeEnum.AttackBegin, HorizontalDirectionEnum.Left); action._animationSeqs.Add(seq); // attack end seq = new AnimationSequence(_animations._attackStraightLeftEnd, AnimationPurposeEnum.AttackEnd, HorizontalDirectionEnum.Left); action._animationSeqs.Add(seq); } break; case CellPartEnum.LowerRight: { // attack begin AnimationSequence seq = new AnimationSequence(_animations._attackStraightRightBegin, AnimationPurposeEnum.AttackBegin, HorizontalDirectionEnum.Right); action._animationSeqs.Add(seq); // attack end seq = new AnimationSequence(_animations._attackStraightRightEnd, AnimationPurposeEnum.AttackEnd, HorizontalDirectionEnum.Right); action._animationSeqs.Add(seq); } break; case CellPartEnum.LowerLeft: { // attack begin AnimationSequence seq = new AnimationSequence(_animations._attackStraightLeftBegin, AnimationPurposeEnum.AttackBegin, HorizontalDirectionEnum.Left); action._animationSeqs.Add(seq); // attack end seq = new AnimationSequence(_animations._attackStraightLeftEnd, AnimationPurposeEnum.AttackEnd, HorizontalDirectionEnum.Left); action._animationSeqs.Add(seq); } break; case CellPartEnum.UpperRight: { // attack begin AnimationSequence seq = new AnimationSequence(_animations._attackStraightRightBegin, AnimationPurposeEnum.AttackBegin, HorizontalDirectionEnum.Right); action._animationSeqs.Add(seq); // attack end seq = new AnimationSequence(_animations._attackStraightRightEnd, AnimationPurposeEnum.AttackEnd, HorizontalDirectionEnum.Right); action._animationSeqs.Add(seq); } break; case CellPartEnum.UpperLeft: { // attack begin AnimationSequence seq = new AnimationSequence(_animations._attackStraightLeftBegin, AnimationPurposeEnum.AttackBegin, HorizontalDirectionEnum.Left); action._animationSeqs.Add(seq); // attack end seq = new AnimationSequence(_animations._attackStraightLeftEnd, AnimationPurposeEnum.AttackEnd, HorizontalDirectionEnum.Left); action._animationSeqs.Add(seq); } break; } action._currentAnimationSeq = (AnimationSequence)action._animationSeqs[0]; return action; }