/// <summary> /// Извлечение всех оборон актёра, способных противостоять указанному типу урона. /// Включая DivineDefence, противодействующий всем типам урона. /// </summary> /// <param name="targetActor"> Целевой актёр. </param> /// <param name="offenceType"> Тип урона. </param> /// <returns> Возвращает набор оборон. </returns> private static IEnumerable <PersonDefenceItem> GetCurrentDefences(IActor targetActor, OffenseType offenceType) { var defenceType = HitHelper.GetDefence(offenceType); return(targetActor.Person.CombatStats.DefenceStats.Defences .Where(x => x.Type == defenceType || x.Type == DefenceType.DivineDefence)); }
/// <summary> /// Производит попытку нанесения урона целевову актёру с учётом обороны и брони. /// </summary> /// <param name="actor"> Актёр, который совершил действие. </param> /// <param name="targetActor"> Цель использования действия. </param> /// <param name="combatActRoll"> Эффективность действия. </param> private void DamageActor(IActor actor, IActor targetActor, CombatActRoll combatActRoll, ISectorMap map) { var targetIsDeadLast = targetActor.Person.CheckIsDead(); var offence = combatActRoll.CombatAct.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(combatActRoll.CombatAct.ToHit); if (factToHitRoll >= successToHitRoll) { ProcessSuccessfullHit(actor, targetActor, combatActRoll, targetIsDeadLast, successToHitRoll, factToHitRoll, map); } else { ProcessFailedHit(actor, targetActor, combatActRoll, prefferedDefenceItem, successToHitRoll, factToHitRoll); } }
/// <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); } } }
/// <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) { ProcessSuccessfullHit(actor, targetActor, tacticalActRoll, targetIsDeadLast, successToHitRoll, factToHitRoll); } else { ProcessFailedHit(actor, targetActor, prefferedDefenceItem, successToHitRoll, factToHitRoll); } }
/// <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); } } }