コード例 #1
0
        protected virtual void AttackTarget(ICombatList offensiveCombatList,
                                            ICombatList defensiveCombatList,
                                            ICombatGroup attackerGroup,
                                            ICombatObject attacker,
                                            BattleSide sideAttacking,
                                            CombatList.Target target,
                                            int attackIndex,
                                            uint round,
                                            out decimal carryOverDmg)
        {
            var attackerCount = attacker.Count;
            var targetCount   = target.CombatObject.Count;

            #region Damage

            decimal dmg = battleFormulas.GetAttackerDmgToDefender(attacker, target.CombatObject, round);

            if (target.DamageCarryOverPercentage.HasValue)
            {
                dmg *= target.DamageCarryOverPercentage.Value;
            }

            decimal actualDmg;
            target.CombatObject.CalcActualDmgToBeTaken(offensiveCombatList,
                                                       defensiveCombatList,
                                                       battleRandom,
                                                       dmg,
                                                       attackIndex,
                                                       out actualDmg);

            Resource defenderDroppedLoot;
            int      attackPoints;
            int      initialCount = target.CombatObject.Count;

            carryOverDmg = 0;
            if (dmg > 0 && target.CombatObject.Hp - actualDmg < 0m)
            {
                carryOverDmg = (actualDmg - target.CombatObject.Hp) / actualDmg;
            }

            actualDmg = Math.Min(target.CombatObject.Hp, actualDmg);

            target.CombatObject.TakeDamage(actualDmg, out defenderDroppedLoot, out attackPoints);
            if (initialCount > target.CombatObject.Count)
            {
                UnitCountDecreased(this,
                                   sideAttacking == BattleSide.Attack ? BattleSide.Defense : BattleSide.Attack,
                                   target.Group,
                                   target.CombatObject,
                                   initialCount - target.CombatObject.Count);
            }

            attacker.DmgDealt   += actualDmg;
            attacker.MaxDmgDealt = (ushort)Math.Max(attacker.MaxDmgDealt, actualDmg);
            attacker.MinDmgDealt = (ushort)Math.Min(attacker.MinDmgDealt, actualDmg);
            ++attacker.HitDealt;
            attacker.HitDealtByUnit += attacker.Count;

            target.CombatObject.DmgRecv   += actualDmg;
            target.CombatObject.MaxDmgRecv = (ushort)Math.Max(target.CombatObject.MaxDmgRecv, actualDmg);
            target.CombatObject.MinDmgRecv = (ushort)Math.Min(target.CombatObject.MinDmgRecv, actualDmg);
            ++target.CombatObject.HitRecv;

            #endregion

            #region Loot and Attack Points

            // NOTE: In the following rewardStrategy calls we are in passing in whatever the existing implementations
            // of reward startegy need. If some specific implementation needs more info then add more params or change it to
            // take the entire BattleManager as a param.
            if (sideAttacking == BattleSide.Attack)
            {
                // Only give loot if we are attacking the first target in the list
                Resource loot;
                rewardStrategy.RemoveLoot(this, attackIndex, attacker, target.CombatObject, out loot);

                if (attackPoints > 0 || (loot != null && !loot.Empty))
                {
                    rewardStrategy.GiveAttackerRewards(attacker, attackPoints, loot ?? new Resource());
                }
            }
            else
            {
                // Give defender rewards if there are any
                if (attackPoints > 0 || (defenderDroppedLoot != null && !defenderDroppedLoot.Empty))
                {
                    rewardStrategy.GiveDefendersRewards(attacker,
                                                        attackPoints,
                                                        defenderDroppedLoot ?? new Resource());
                }
            }

            #endregion

            #region Object removal

            bool isDefenderDead = target.CombatObject.IsDead;

            ActionAttacked(this, sideAttacking, attackerGroup, attacker, target.Group, target.CombatObject, actualDmg, attackerCount, targetCount);

            if (isDefenderDead)
            {
                bool isGroupDead = target.Group.IsDead();
                if (isGroupDead)
                {
                    // Remove the entire group
                    Remove(target.Group,
                           sideAttacking == BattleSide.Attack ? BattleSide.Defense : BattleSide.Attack,
                           ReportState.Dying);
                }
                else if (!target.CombatObject.Disposed)
                {
                    // Only remove the single object
                    BattleReport.WriteExitingObject(target.Group, sideAttacking != BattleSide.Attack, target.CombatObject);
                    target.Group.Remove(target.CombatObject);
                }

                UnitKilled(this,
                           sideAttacking == BattleSide.Attack ? BattleSide.Defense : BattleSide.Attack,
                           target.Group,
                           target.CombatObject);

                if (!target.CombatObject.Disposed)
                {
                    target.CombatObject.ExitBattle();
                }

                if (isGroupDead)
                {
                    GroupKilled(this, target.Group);
                }
            }
            else
            {
                if (!target.CombatObject.Disposed)
                {
                    dbManager.Save(target.CombatObject);
                }
            }

            #endregion
        }