Ejemplo n.º 1
0
        /// <summary>
        /// Производит попытку нанесения урона целевову актёру с учётом обороны и брони.
        /// </summary>
        /// <param name="actor"> Актёр, который совершил действие. </param>
        /// <param name="targetActor"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private void DamageActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            var targetIsDeadLast = targetActor.Person.CheckIsDead();

            var offence = tacticalActRoll.TacticalAct.Stats.Offence;

            if (offence is null)
            {
                throw new InvalidOperationException();
            }

            var offenceType  = offence.Type;
            var usedDefences = GetCurrentDefences(targetActor, offenceType);

            var prefferedDefenceItem = HitHelper.CalcPreferredDefense(usedDefences);
            var successToHitRoll     = HitHelper.CalcSuccessToHit(prefferedDefenceItem);
            var factToHitRoll        = _actUsageRandomSource.RollToHit(tacticalActRoll.TacticalAct.ToHit);

            if (factToHitRoll >= successToHitRoll)
            {
                ProcessSuccessfullHit(actor, targetActor, tacticalActRoll, targetIsDeadLast, successToHitRoll,
                                      factToHitRoll);
            }
            else
            {
                ProcessFailedHit(actor, targetActor, prefferedDefenceItem, successToHitRoll, factToHitRoll);
            }
        }
Ejemplo n.º 2
0
        private void ProcessSuccessfullHit(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll,
                                           bool targetIsDeadLast, int successToHitRoll, int factToHitRoll)
        {
            var damageEfficientCalcResult = CalcEfficient(targetActor, tacticalActRoll);
            var actEfficient = damageEfficientCalcResult.ResultEfficient;

            ProcessSuccessfulAttackEvent(
                actor,
                targetActor,
                damageEfficientCalcResult,
                successToHitRoll,
                factToHitRoll);

            if (actEfficient > 0)
            {
                targetActor.TakeDamage(actEfficient);

                CountTargetActorAttack(actor, targetActor, tacticalActRoll.TacticalAct);

                ProcessDiseaseInfection(actor, targetActor);

                LogDamagePlayerEvent(actor, targetActor, tacticalActRoll.TacticalAct);

                ReduceTargetEquipmentDurability(targetActor);

                if (!targetIsDeadLast && targetActor.Person.CheckIsDead())
                {
                    CountTargetActorDefeat(actor, targetActor);
                }
            }
        }
        /// <summary>
        /// Расчитывает эффективность умения с учётом поглощения броней.
        /// </summary>
        /// <param name="targetActor"> Целевой актёр. </param>
        /// <param name="tacticalActRoll"> Результат броска исходной эфективности действия. </param>
        /// <returns> Возвращает числовое значение эффективности действия. </returns>
        private DamageEfficientCalc CalcEfficient(IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            var damageEfficientCalcResult = new DamageEfficientCalc();

            var actApRank = GetActApRank(tacticalActRoll.TacticalAct);;

            damageEfficientCalcResult.ActApRank = actApRank;
            var armorRank = GetArmorRank(targetActor, tacticalActRoll.TacticalAct);

            damageEfficientCalcResult.ArmorRank = armorRank;

            var actEfficientArmorBlocked = tacticalActRoll.Efficient;
            var rankDiff = actApRank - armorRank;

            if (armorRank != null && rankDiff < 10)
            {
                var factArmorSaveRoll = RollArmorSave();
                damageEfficientCalcResult.FactArmorSaveRoll = factArmorSaveRoll;
                var successArmorSaveRoll = GetSuccessArmorSave(targetActor, tacticalActRoll.TacticalAct);
                damageEfficientCalcResult.SuccessArmorSaveRoll = successArmorSaveRoll;
                if (factArmorSaveRoll >= successArmorSaveRoll)
                {
                    damageEfficientCalcResult.TargetSuccessfullUsedArmor = true;
                    var armorAbsorbtion = GetArmorAbsorbtion(targetActor, tacticalActRoll.TacticalAct);
                    damageEfficientCalcResult.ArmorAbsorbtion = armorAbsorbtion;
                    actEfficientArmorBlocked = AbsorbActEfficient(actEfficientArmorBlocked, armorAbsorbtion);
                }
            }

            damageEfficientCalcResult.ActEfficientArmorBlocked = actEfficientArmorBlocked;

            return(damageEfficientCalcResult);
        }
        /// <summary>
        /// Возвращает случайное значение эффективность действия.
        /// </summary>
        /// <param name="act"> Соверщённое действие. </param>
        /// <returns> Возвращает выпавшее значение эффективности. </returns>
        private TacticalActRoll GetActEfficient(ITacticalAct act)
        {
            var rolledEfficient = _actUsageRandomSource.RollEfficient(act.Efficient);

            var roll = new TacticalActRoll(act, rolledEfficient);

            return(roll);
        }
Ejemplo n.º 5
0
        /// <inheritdoc />
        public void ProcessActUsage(IActor actor, IAttackTarget target, TacticalActRoll tacticalActRoll)
        {
            if (tacticalActRoll is null)
            {
                throw new ArgumentNullException(nameof(tacticalActRoll));
            }

            UseOnStaticObject(target as IStaticObject, tacticalActRoll);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Применяет действие на предмет, на который можно подействовать (сундук/дверь/камень).
        /// </summary>
        /// <param name="target"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private static void UseOnStaticObject(IAttackTarget target, TacticalActRoll tacticalActRoll)
        {
            if (target is null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            target.TakeDamage(tacticalActRoll.Efficient);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Возвращает случайное значение эффективность действия.
        /// </summary>
        /// <param name="act"> Соверщённое действие. </param>
        /// <returns> Возвращает выпавшее значение эффективности. </returns>
        private TacticalActRoll GetActEfficient(ITacticalAct act)
        {
            var minEfficient    = act.MinEfficient;
            var maxEfficient    = act.MaxEfficient;
            var rolledEfficient = _actUsageRandomSource.SelectEfficient(minEfficient, maxEfficient);

            var roll = new TacticalActRoll(act, rolledEfficient);

            return(roll);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Применяет действие на актёра.
        /// </summary>
        /// <param name="actor"> Актёр, который совершил действие. </param>
        /// <param name="targetActor"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private void UseOnActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            var targetIsDeadLast = targetActor.State.IsDead;

            targetActor.TakeDamage(tacticalActRoll.Efficient);

            if (!targetIsDeadLast && targetActor.State.IsDead)
            {
                CountTargetActorDefeat(actor, targetActor);
            }
        }
        /// <summary>
        /// Наносит урон актёру.
        /// </summary>
        /// <param name="actor"> Актёр, который совершил действие. </param>
        /// <param name="targetActor"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private void DamageActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            var targetIsDeadLast = targetActor.Person.Survival.IsDead;

            var offenceType  = tacticalActRoll.TacticalAct.Stats.Offence.Type;
            var usedDefences = GetCurrentDefences(targetActor, offenceType);

            var prefferedDefenceItem = HitHelper.CalcPreferredDefense(usedDefences);
            var successToHitRoll     = HitHelper.CalcSuccessToHit(prefferedDefenceItem);
            var factToHitRoll        = _actUsageRandomSource.RollToHit();

            if (factToHitRoll >= successToHitRoll)
            {
                int actEfficient = CalcEfficient(targetActor, tacticalActRoll);

                if (actEfficient <= 0)
                {
                    return;
                }

                targetActor.TakeDamage(actEfficient);

                if (EquipmentDurableService != null && targetActor.Person.EquipmentCarrier != null)
                {
                    var damagedEquipment = GetDamagedEquipment(targetActor);

                    // может быть null, если нет брони вообще
                    if (damagedEquipment != null)
                    {
                        EquipmentDurableService.UpdateByUse(damagedEquipment, targetActor.Person);
                    }
                }

                if (!targetIsDeadLast && targetActor.Person.Survival.IsDead)
                {
                    CountTargetActorDefeat(actor, targetActor);
                }
            }
            else
            {
                if (prefferedDefenceItem != null)
                {
                    targetActor.ProcessDefence(prefferedDefenceItem,
                                               successToHitRoll,
                                               factToHitRoll);
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Применяет действие на актёра.
        /// </summary>
        /// <param name="actor"> Актёр, который совершил действие. </param>
        /// <param name="targetActor"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private void UseOnActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            switch (tacticalActRoll.TacticalAct.Stats.Effect)
            {
            case TacticalActEffectType.Damage:
                DamageActor(actor, targetActor, tacticalActRoll);
                break;

            case TacticalActEffectType.Heal:
                HealActor(targetActor, tacticalActRoll);
                break;

            default:
                var effect      = tacticalActRoll.TacticalAct.Stats.Effect;
                var tacticalAct = tacticalActRoll.TacticalAct;
                throw new ArgumentException($"Не определённый эффект {effect} действия {tacticalAct}.");
            }
        }
        /// <summary>
        /// Применяет действие на актёра.
        /// </summary>
        /// <param name="actor"> Актёр, который совершил действие. </param>
        /// <param name="targetActor"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private void UseOnActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            switch (tacticalActRoll.TacticalAct.Stats.Effect)
            {
            case TacticalActEffectType.Damage:
                DamageActor(actor, targetActor, tacticalActRoll);
                break;

            case TacticalActEffectType.Heal:
                HealActor(actor, targetActor, tacticalActRoll);
                break;

            default:
                throw new ArgumentException(string.Format("Не определённый эффект {0} действия {1}.",
                                                          tacticalActRoll.TacticalAct.Stats.Effect,
                                                          tacticalActRoll.TacticalAct));
            }
        }
Ejemplo n.º 12
0
        /// <inheritdoc />
        public void ProcessActUsage(IActor actor, IAttackTarget target, TacticalActRoll tacticalActRoll)
        {
            if (actor is null)
            {
                throw new ArgumentNullException(nameof(actor));
            }

            if (target is null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (tacticalActRoll is null)
            {
                throw new ArgumentNullException(nameof(tacticalActRoll));
            }

            UseOnActor(actor, target as IActor, tacticalActRoll);
        }
        /// <summary>
        /// Расчитывает эффективность умения с учётом поглощения броней.
        /// </summary>
        /// <param name="targetActor"> Целевой актёр. </param>
        /// <param name="tacticalActRoll"> Результат броска исходной эфективности действия. </param>
        /// <returns> Возвращает числовое значение эффективности действия. </returns>
        private int CalcEfficient(IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            var actApRank = GetActApRank(tacticalActRoll.TacticalAct);
            var armorRank = GetArmorRank(targetActor, tacticalActRoll.TacticalAct);

            var actEfficientArmorBlocked = tacticalActRoll.Efficient;
            var rankDiff = actApRank - armorRank;

            if (armorRank != null && rankDiff < 10)
            {
                var factArmorSaveRoll    = RollArmorSave();
                var successArmorSaveRoll = GetSuccessArmorSave(targetActor, tacticalActRoll.TacticalAct);
                if (factArmorSaveRoll >= successArmorSaveRoll)
                {
                    var armorAbsorbtion = GetArmorAbsorbtion(targetActor, tacticalActRoll.TacticalAct);
                    actEfficientArmorBlocked = AbsorbActEfficient(actEfficientArmorBlocked, armorAbsorbtion);
                }

                targetActor.ProcessArmor(armorRank.Value, successArmorSaveRoll, factArmorSaveRoll);
            }

            return(actEfficientArmorBlocked);
        }
 /// <summary>
 /// Лечит актёра.
 /// </summary>
 /// <param name="actor"> Актёр, который совершил действие. </param>
 /// <param name="targetActor"> Цель использования действия. </param>
 /// <param name="tacticalActRoll"> Эффективность действия. </param>
 private void HealActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
 {
     targetActor.Person.Survival?.RestoreStat(SurvivalStatType.Health, tacticalActRoll.Efficient);
 }
        /// <summary>
        /// Производит попытку нанесения урона целевову актёру с учётом обороны и брони.
        /// </summary>
        /// <param name="actor"> Актёр, который совершил действие. </param>
        /// <param name="targetActor"> Цель использования действия. </param>
        /// <param name="tacticalActRoll"> Эффективность действия. </param>
        private void DamageActor(IActor actor, IActor targetActor, TacticalActRoll tacticalActRoll)
        {
            var targetIsDeadLast = targetActor.Person.CheckIsDead();

            var offenceType  = tacticalActRoll.TacticalAct.Stats.Offence.Type;
            var usedDefences = GetCurrentDefences(targetActor, offenceType);

            var prefferedDefenceItem = HitHelper.CalcPreferredDefense(usedDefences);
            var successToHitRoll     = HitHelper.CalcSuccessToHit(prefferedDefenceItem);
            var factToHitRoll        = _actUsageRandomSource.RollToHit(tacticalActRoll.TacticalAct.ToHit);

            if (factToHitRoll >= successToHitRoll)
            {
                var damageEfficientCalcResult = CalcEfficient(targetActor, tacticalActRoll);
                var actEfficient = damageEfficientCalcResult.ResultEfficient;

                ProcessSuccessfulAttackEvent(
                    actor,
                    targetActor,
                    damageEfficientCalcResult,
                    successToHitRoll,
                    factToHitRoll);

                if (actEfficient <= 0)
                {
                    return;
                }

                targetActor.TakeDamage(actEfficient);

                CountTargetActorAttack(actor, targetActor, tacticalActRoll.TacticalAct);

                if (EquipmentDurableService != null && targetActor.Person.EquipmentCarrier != null)
                {
                    var damagedEquipment = GetDamagedEquipment(targetActor);

                    // может быть null, если нет брони вообще
                    if (damagedEquipment != null)
                    {
                        EquipmentDurableService.UpdateByUse(damagedEquipment, targetActor.Person);
                    }
                }

                if (!targetIsDeadLast && targetActor.Person.CheckIsDead())
                {
                    CountTargetActorDefeat(actor, targetActor);
                }
            }
            else
            {
                if (prefferedDefenceItem != null)
                {
                    // Это промах, потому что целевой актёр увернулся.
                    ProcessAttackDodgeEvent(actor,
                                            targetActor,
                                            prefferedDefenceItem,
                                            successToHitRoll,
                                            factToHitRoll);
                }
                else
                {
                    // Это промах чистой воды.
                    ProcessPureMissEvent(actor,
                                         targetActor,
                                         successToHitRoll,
                                         factToHitRoll);
                }
            }
        }
 /// <summary>
 /// Применяет действие на предмет, на который можно подействовать (сундук/дверь).
 /// </summary>
 /// <param name="target"> Цель использования действия. </param>
 /// <param name="tacticalActRoll"> Эффективность действия. </param>
 private static void UseOnChest(IAttackTarget target, TacticalActRoll tacticalActRoll)
 {
     target.TakeDamage(tacticalActRoll.Efficient);
 }
Ejemplo n.º 17
0
 /// <summary>
 /// Лечит актёра.
 /// </summary>
 /// <param name="targetActor"> Цель использования действия. </param>
 /// <param name="tacticalActRoll"> Эффективность действия. </param>
 private static void HealActor(IActor targetActor, TacticalActRoll tacticalActRoll)
 {
     targetActor.Person.GetModuleSafe <ISurvivalModule>()
     ?.RestoreStat(SurvivalStatType.Health, tacticalActRoll.Efficient);
 }