コード例 #1
0
        private static void ThrowExceptionIfArgumentsInvalid(IConditionsModule currentСondition,
                                                             SurvivalStat stat,
                                                             IEnumerable <SurvivalStatKeySegment> keyPoints,
                                                             ISurvivalRandomSource survivalRandomSource)
        {
            if (currentСondition == null)
            {
                throw new ArgumentNullException(nameof(currentСondition));
            }

            if (stat == null)
            {
                throw new ArgumentNullException(nameof(stat));
            }

            if (keyPoints == null)
            {
                throw new ArgumentNullException(nameof(keyPoints));
            }

            if (survivalRandomSource == null)
            {
                throw new ArgumentNullException(nameof(survivalRandomSource));
            }
        }
コード例 #2
0
        public void UpdateSurvivalEffect_HasLesserEffectAndValueMoreThatKetValue_HasNoEffect()
        {
            //ARRANGE

            var currentEffects = new EffectCollection();

            var testedEffect = new SurvivalStatHazardEffect(SurvivalStatType.Satiety, SurvivalStatHazardLevel.Lesser);

            currentEffects.Add(testedEffect);

            var stat = new SurvivalStat(1)
            {
                Type      = SurvivalStatType.Satiety,
                KeyPoints = new[] {
                    new SurvivalStatKeyPoint {
                        Level = SurvivalStatHazardLevel.Lesser,
                        Value = 0
                    }
                }
            };



            // ACT
            PersonEffectHelper.UpdateSurvivalEffect(currentEffects, stat, stat.KeyPoints[0]);



            // ASSERT
            var factEffect = currentEffects.Items.OfType <SurvivalStatHazardEffect>()
                             .SingleOrDefault(x => x.Type == SurvivalStatType.Satiety);

            factEffect.Should().BeNull();
        }
コード例 #3
0
        private IActor CreateActorMock()
        {
            var actorMock = new Mock <IActor>();

            var personMock = new Mock <IPerson>();
            var person     = personMock.Object;

            actorMock.SetupGet(x => x.Person).Returns(person);

            _survivalDataMock = new Mock <ISurvivalData>();
            var survivalStats = new SurvivalStat[] {
                new SurvivalStat(0)
                {
                    Type      = SurvivalStatType.Satiety,
                    Range     = new Range <int>(-10, 10),
                    Rate      = 1,
                    KeyPoints = new SurvivalStatKeyPoint[0]
                }
            };

            _survivalDataMock.Setup(x => x.Stats).Returns(survivalStats);
            var survivalData = _survivalDataMock.Object;

            personMock.SetupGet(x => x.Survival).Returns(survivalData);

            var effectCollection = new EffectCollection();

            personMock.SetupGet(x => x.Effects).Returns(effectCollection);



            return(actorMock.Object);
        }
コード例 #4
0
        private static SurvivalStat CreateStat(
            SurvivalStatType type,
            PersonSurvivalStatType schemeStatType,
            IPersonSurvivalStatSubScheme[] survivalStats)
        {
            var statScheme = survivalStats.SingleOrDefault(x => x.Type == schemeStatType);

            if (statScheme is null)
            {
                return(null);
            }

            var keySegmentList = new List <SurvivalStatKeySegment>();

            if (statScheme.KeyPoints != null)
            {
                AddKeyPointFromScheme(SurvivalStatHazardLevel.Max, PersonSurvivalStatKeypointLevel.Max, statScheme.KeyPoints, keySegmentList);
                AddKeyPointFromScheme(SurvivalStatHazardLevel.Strong, PersonSurvivalStatKeypointLevel.Strong, statScheme.KeyPoints, keySegmentList);
                AddKeyPointFromScheme(SurvivalStatHazardLevel.Lesser, PersonSurvivalStatKeypointLevel.Lesser, statScheme.KeyPoints, keySegmentList);
            }

            var stat = new SurvivalStat(statScheme.StartValue, statScheme.MinValue, statScheme.MaxValue)
            {
                Type         = type,
                Rate         = 1,
                KeySegments  = keySegmentList.ToArray(),
                DownPassRoll = statScheme.DownPassRoll.GetValueOrDefault(SurvivalStat.DEFAULT_DOWN_PASS_VALUE)
            };

            return(stat);
        }
コード例 #5
0
        public int Update_ModifiedDownPass_StatDownCorrectly(int statDownPass, int downPassRoll)
        {
            // ARRANGE

            const int STAT_RATE              = 1;
            const int MIN_STAT_VALUE         = 0;
            const int MAX_STAT_VALUE         = 1;
            const int START_STAT_VALUE       = MAX_STAT_VALUE;
            const SurvivalStatType STAT_TYPE = SurvivalStatType.Satiety;

            var survivalRandomSourceMock = new Mock <ISurvivalRandomSource>();

            survivalRandomSourceMock.Setup(x => x.RollSurvival(It.IsAny <SurvivalStat>()))
            .Returns(downPassRoll);
            var survivalRandomSource = survivalRandomSourceMock.Object;

            var survivalStats = new SurvivalStat[] {
                new SurvivalStat(START_STAT_VALUE, MIN_STAT_VALUE, MAX_STAT_VALUE)
                {
                    Type         = STAT_TYPE,
                    Rate         = STAT_RATE,
                    DownPassRoll = statDownPass
                }
            };

            var survivalData = new HumanSurvivalData(_personScheme,
                                                     survivalStats,
                                                     survivalRandomSource);

            // ACT
            survivalData.Update();

            // ASSERT
            return(survivalStats[0].Value);
        }
コード例 #6
0
        private static void CheckArguments(EffectCollection currentEffects,
                                           SurvivalStat stat,
                                           IEnumerable <SurvivalStatKeyPoint> keyPoints,
                                           ISurvivalRandomSource survivalRandomSource)
        {
            if (currentEffects == null)
            {
                throw new ArgumentNullException(nameof(currentEffects));
            }

            if (stat == null)
            {
                throw new ArgumentNullException(nameof(stat));
            }

            if (keyPoints == null)
            {
                throw new ArgumentNullException(nameof(keyPoints));
            }

            if (survivalRandomSource == null)
            {
                throw new ArgumentNullException(nameof(survivalRandomSource));
            }
        }
コード例 #7
0
        public static string GetHealthStateKey(SurvivalStat hpStat)
        {
            var hpPercentage = hpStat.ValueShare;

            if (hpPercentage >= HEALTHLY_STATE)
            {
                return("healthy");
            }
            if (SLIGHTLY_INJURED_STATE <= hpPercentage && hpPercentage < HEALTHLY_STATE)
            {
                return("slightly-injured");
            }
            else if (WOUNDED_STATE <= hpPercentage && hpPercentage < SLIGHTLY_INJURED_STATE)
            {
                return("wounded");
            }
            else if (AT_DEATH_STATE <= hpPercentage && hpPercentage < WOUNDED_STATE)
            {
                return("badly-wounded");
            }
            else
            {
                return("at-death");
            }
        }
コード例 #8
0
    private string GetHealthString(SurvivalStat hpStat)
    {
        var hpPercentage = hpStat.ValueShare;

        if (hpPercentage >= 0.95f)
        {
            return("Healthy");
        }
        if (0.75f <= hpPercentage && hpPercentage < 0.95f)
        {
            return("Slightly Injured");
        }
        else if (0.5f <= hpPercentage && hpPercentage < 0.75f)
        {
            return("Wounded");
        }
        else if (0.25f <= hpPercentage && hpPercentage < 0.5f)
        {
            return("Badly Wounded");
        }
        else
        {
            return("At Death");
        }
    }
コード例 #9
0
        /// <summary>
        /// Обновление эффекта модуля выживания.
        /// </summary>
        /// <param name="currentEffects"> Текущий список эффектов. </param>
        /// <param name="stat"> Характеристика, на которую влияет эффект. </param>
        /// <param name="keyPoints"> Ключевые точки, которые учавствуют в изменении характеристик. </param>
        /// <param name="survivalRandomSource"> Источник рандома выживания. </param>
        public static void UpdateSurvivalEffect(
            [NotNull] EffectCollection currentEffects,
            [NotNull] SurvivalStat stat,
            [NotNull][ItemNotNull] IEnumerable <SurvivalStatKeyPoint> keyPoints,
            [NotNull] ISurvivalRandomSource survivalRandomSource)
        {
            CheckArguments(currentEffects, stat, keyPoints, survivalRandomSource);

            var statType          = stat.Type;
            var currentTypeEffect = GetCurrentEffect(currentEffects, statType);

            var keyPoint = keyPoints.Last();

            if (currentTypeEffect != null)
            {
                // Эффект уже существует. Изменим его уровень.
                if (stat.Value <= keyPoint.Value)
                {
                    currentTypeEffect.Level = keyPoint.Level;
                }
                else
                {
                    if (keyPoint.Level == SurvivalStatHazardLevel.Lesser)
                    {
                        currentEffects.Remove(currentTypeEffect);
                    }
                    else
                    {
                        switch (keyPoint.Level)
                        {
                        case SurvivalStatHazardLevel.Strong:
                            currentTypeEffect.Level = SurvivalStatHazardLevel.Lesser;
                            break;

                        case SurvivalStatHazardLevel.Max:
                            currentTypeEffect.Level = SurvivalStatHazardLevel.Strong;
                            break;

                        case SurvivalStatHazardLevel.Undefined:
                            throw new NotSupportedException();

                        case SurvivalStatHazardLevel.Lesser:
                            throw new NotSupportedException();

                        default:
                            throw new InvalidOperationException("Уровень эффекта, который не обрабатывается.");
                        }
                    }
                }
            }
            else
            {
                // Создаём эффект
                var newCurrentTypeEffect = new SurvivalStatHazardEffect(statType,
                                                                        keyPoint.Level,
                                                                        survivalRandomSource);

                currentEffects.Add(newCurrentTypeEffect);
            }
        }
コード例 #10
0
        public void Update_StatNearKeyPoint_RaiseEventWithCorrectValues()
        {
            // ARRANGE
            const SurvivalStatType STAT_TYPE = SurvivalStatType.Satiety;

            const int MIN_STAT_VALUE   = 0;
            const int MAX_STAT_VALUE   = 1;
            const int START_STAT_VALUE = MAX_STAT_VALUE;

            const int LESSER_SURVIVAL_STAT_KEYPOINT = 0;
            const SurvivalStatHazardLevel LESSER_SURVIVAL_STAT_KEYPOINT_TYPE = SurvivalStatHazardLevel.Lesser;

            const int STAT_RATE = 1;

            const int EXPECTED_SURVIVAL_STAT_KEYPOINT = LESSER_SURVIVAL_STAT_KEYPOINT;

            const int FAKE_ROLL_SURVIVAL_RESULT = 6;

            var survivalRandomSourceMock = new Mock <ISurvivalRandomSource>();

            survivalRandomSourceMock.Setup(x => x.RollSurvival(It.IsAny <SurvivalStat>()))
            .Returns(FAKE_ROLL_SURVIVAL_RESULT);
            var survivalRandomSource = survivalRandomSourceMock.Object;

            var survivalStats = new SurvivalStat[] {
                new SurvivalStat(START_STAT_VALUE, MIN_STAT_VALUE, MAX_STAT_VALUE)
                {
                    Type      = STAT_TYPE,
                    Rate      = STAT_RATE,
                    KeyPoints = new[] {
                        new SurvivalStatKeyPoint(
                            LESSER_SURVIVAL_STAT_KEYPOINT_TYPE,
                            LESSER_SURVIVAL_STAT_KEYPOINT)
                    }
                }
            };

            var survivalData = new HumanSurvivalData(_personScheme,
                                                     survivalStats,
                                                     survivalRandomSource);



            // ACT
            using (var monitor = survivalData.Monitor())
            {
                survivalData.Update();



                // ASSERT
                monitor.Should().Raise(nameof(ISurvivalData.StatCrossKeyValue))
                .WithArgs <SurvivalStatChangedEventArgs>(args =>
                                                         args.Stat.Type == STAT_TYPE &&
                                                         args.KeyPoints.FirstOrDefault().Level == LESSER_SURVIVAL_STAT_KEYPOINT_TYPE &&
                                                         args.KeyPoints.FirstOrDefault().Value == EXPECTED_SURVIVAL_STAT_KEYPOINT);
            }
        }
コード例 #11
0
        public int Value_IncrementDecrementValue_ExpectedResults(int startValue, int min, int max, int diffValue)
        {
            // ARRANGE
            var survivalStat = new SurvivalStat(startValue, min, max);

            // ACT
            survivalStat.Value += diffValue;

            // ASSERT
            return(survivalStat.Value);
        }
コード例 #12
0
        private static SurvivalStat CreateUselessStat(SurvivalStatType statType)
        {
            var stat = new SurvivalStat(100, 0, 100)
            {
                Type         = statType,
                Rate         = 1,
                DownPassRoll = 0
            };

            return(stat);
        }
コード例 #13
0
        public int Value_IncrementDecrementRange_ExpectedResults(int startValue, int min, int max,
                                                                 int newMin, int newMax)
        {
            // ARRANGE
            var survivalStat = new SurvivalStat(startValue, min, max);

            // ACT
            survivalStat.ChangeStatRange(newMin, newMax);

            // ASSERT
            return(survivalStat.Value);
        }
コード例 #14
0
        protected void ChangeStatInner(SurvivalStat stat, int value)
        {
            if (stat is null)
            {
                throw new ArgumentNullException(nameof(stat));
            }

            stat.Value += value;

            ProcessIfHealth(stat, value);
            ProcessIfWound(stat);
        }
コード例 #15
0
        /// <summary>
        /// Обновление эффекта модуля выживания.
        /// </summary>
        /// <param name="currentCondition"> Текущий список условий. </param>
        /// <param name="stat"> Характеристика, на которую влияет эффект. </param>
        /// <param name="keySegments">
        /// Ключевые сегменты, которые были пересечены при изменении характеристики.
        /// <param name="survivalRandomSource"> Источник рандома выживания. </param>
        public static void UpdateSurvivalСondition(
            [NotNull] IConditionsModule currentCondition,
            [NotNull] SurvivalStat stat,
            [NotNull] SurvivalStatKeySegment[] keySegments,
            [NotNull] ISurvivalRandomSource survivalRandomSource,
            [MaybeNull] IPlayerEventLogService?playerEventLogService)
        {
            ThrowExceptionIfArgumentsInvalid(currentCondition, stat, keySegments, survivalRandomSource);

            // Эффект выставляем на основе текущего ключевого сегмента, в которое попадает значение характеристики выживания.
            // Если текущее значение не попадает ни в один сегмент, то эффект сбрасывается.

            var currentSegments = keySegments.CalcIntersectedSegments(stat.ValueShare);

            // Если попадаем на стык с двумя сегментами, просто берём первый.
            // Иногда это будет давать более сильный штрафной эффект,
            // но пока не понятно, как по другому сделать отрезки.
            var currentSegment = currentSegments.FirstOrDefault();

            var statType             = stat.Type;
            var currentTypeСondition = GetCurrentСondition(currentCondition, statType);

            if (currentTypeСondition != null)
            {
                // Эффект уже существует. Изменим его уровень.
                // Или удалим, если текущее значение не попадает ни в один из сегментов.
                if (currentSegment == null)
                {
                    currentCondition.Remove(currentTypeСondition);
                }
                else
                {
                    currentTypeСondition.Level = currentSegment.Level;
                }
            }
            else
            {
                if (currentSegment != null)
                {
                    // Создаём эффект
                    var newEffect = new SurvivalStatHazardCondition(
                        statType,
                        currentSegment.Level,
                        survivalRandomSource)
                    {
                        PlayerEventLogService = playerEventLogService
                    };

                    currentCondition.Add(newEffect);
                }
            }
        }
コード例 #16
0
ファイル: PersonEffectHelper.cs プロジェクト: tgspn/Zilon
        /// <summary>
        /// Обновление эффекта модуля выживания.
        /// </summary>
        /// <param name="currentEffects"> Текущий список эффектов. </param>
        /// <param name="stat"> Характеристика, на которую влияет эффект. </param>
        /// <param name="keyPoint"> Ключевая точка, которую учавствует в изменении характеристики. </param>
        public static void UpdateSurvivalEffect(EffectCollection currentEffects,
                                                SurvivalStat stat,
                                                SurvivalStatKeyPoint keyPoint)
        {
            var statType = stat.Type;

            var currentTypeEffect = currentEffects.Items.OfType <SurvivalStatHazardEffect>()
                                    .SingleOrDefault(x => x.Type == statType);

            // Эффект уже существует.
            // Изменим его тип.
            if (currentTypeEffect != null)
            {
                if (stat.Value <= keyPoint.Value)
                {
                    currentTypeEffect.Level = keyPoint.Level;
                }
                else
                {
                    if (keyPoint.Level == SurvivalStatHazardLevel.Lesser)
                    {
                        currentEffects.Remove(currentTypeEffect);
                    }
                    else
                    {
                        switch (keyPoint.Level)
                        {
                        case SurvivalStatHazardLevel.Strong:
                            currentTypeEffect.Level = SurvivalStatHazardLevel.Lesser;
                            break;

                        case SurvivalStatHazardLevel.Max:
                            currentTypeEffect.Level = SurvivalStatHazardLevel.Strong;
                            break;

                        default:
                            throw new InvalidOperationException("Уровень эффекта, который не обрабатывается.");
                        }
                    }
                }
            }
            else
            {
                currentTypeEffect = new SurvivalStatHazardEffect(statType, keyPoint.Level);
                currentEffects.Add(currentTypeEffect);
            }
        }
コード例 #17
0
        private void ProcessIfWound(SurvivalStat stat)
        {
            if (stat.Type != SurvivalStatType.Wound)
            {
                return;
            }

            var woundCounter = stat.Value;

            if (woundCounter <= 0)
            {
                // Если счётчик раны дошёл до 0,
                // то восстанавливаем единицу здоровья.

                RestoreStat(SurvivalStatType.Health, 1);
            }
        }
コード例 #18
0
        public void UpdateSurvivalEffect_HasMaxEffectAndValueMoreThatKeyValue_HasStrongEffect()
        {
            //ARRANGE

            const SurvivalStatType expectedSurvivalHazardType = SurvivalStatType.Satiety;

            var survivalRandomSource = CreateMaxRollsRandomSource();

            var currentEffects = new EffectCollection();

            var testedEffect = new SurvivalStatHazardEffect(expectedSurvivalHazardType,
                                                            SurvivalStatHazardLevel.Strong,
                                                            survivalRandomSource);

            currentEffects.Add(testedEffect);

            var stat = new SurvivalStat(-5, -10, 10)
            {
                Type      = expectedSurvivalHazardType,
                KeyPoints = new[] {
                    new SurvivalStatKeyPoint(SurvivalStatHazardLevel.Lesser, 5),
                    new SurvivalStatKeyPoint(SurvivalStatHazardLevel.Strong, 0),
                    new SurvivalStatKeyPoint(SurvivalStatHazardLevel.Max, -10)
                }
            };



            // ACT
            PersonEffectHelper.UpdateSurvivalEffect(currentEffects,
                                                    stat,
                                                    new[] { stat.KeyPoints[2] },
                                                    survivalRandomSource);



            // ASSERT
            var factEffect = currentEffects.Items
                             .OfType <SurvivalStatHazardEffect>()
                             .Single(x => x.Type == expectedSurvivalHazardType);

            factEffect.Level.Should().Be(SurvivalStatHazardLevel.Strong);
        }
コード例 #19
0
        public void UpdateSurvivalEffect_HasStrongEffectAndValueMoreThatKetValue_HasLesserEffect()
        {
            //ARRANGE

            const SurvivalStatType expectedSurvivalHazardType = SurvivalStatType.Satiety;

            var currentEffects = new EffectCollection();

            var testedEffect = new SurvivalStatHazardEffect(expectedSurvivalHazardType, SurvivalStatHazardLevel.Lesser);

            currentEffects.Add(testedEffect);

            var stat = new SurvivalStat(-5)
            {
                Type      = expectedSurvivalHazardType,
                KeyPoints = new[] {
                    new SurvivalStatKeyPoint {
                        Level = SurvivalStatHazardLevel.Lesser,
                        Value = 0
                    },
                    new SurvivalStatKeyPoint {
                        Level = SurvivalStatHazardLevel.Strong,
                        Value = -10
                    }
                }
            };



            // ACT
            PersonEffectHelper.UpdateSurvivalEffect(currentEffects, stat, stat.KeyPoints[1]);



            // ASSERT
            var factEffect = currentEffects.Items
                             .OfType <SurvivalStatHazardEffect>()
                             .Single(x => x.Type == expectedSurvivalHazardType);

            factEffect.Level.Should().Be(SurvivalStatHazardLevel.Lesser);
        }
コード例 #20
0
        /// <summary>
        /// Индивидуально обрабатывает характеристику, если это здоровье.
        /// </summary>
        /// <param name="stat"> Обрабатываемая характеристика. </param>
        private void ProcessIfHealth(SurvivalStat stat, int valueDiff)
        {
            if (stat.Type != SurvivalStatType.Health)
            {
                return;
            }

            var hp = stat.Value;

            if (hp <= 0)
            {
                IsDead = true;
                DoDead();
            }
            else
            {
                if (valueDiff < 0)
                {
                    SetWoundCounter();
                }
            }
        }
コード例 #21
0
        public void UpdateSurvivalEffect_EmptyEffectsAndCrossKeyPoint_NewEffectWasAdded()
        {
            // ARRANGE

            var сonditionModuleMock = new Mock <IConditionsModule>();

            сonditionModuleMock.SetupGet(x => x.Items).Returns(Array.Empty <IPersonCondition>());
            var сonditionModule = сonditionModuleMock.Object;

            var stat            = new SurvivalStat(0, 0, 1);
            var segments        = new[] { new SurvivalStatKeySegment(0, 1, SurvivalStatHazardLevel.Lesser) };
            var randomSource    = Mock.Of <ISurvivalRandomSource>();
            var eventLogService = Mock.Of <IPlayerEventLogService>();

            // ACT
            using var monitor = сonditionModule.Monitor();

            PersonConditionHelper.UpdateSurvivalСondition(сonditionModule, stat, segments, randomSource,
                                                          eventLogService);

            // ARRANGE
            сonditionModuleMock.Verify(x => x.Add(It.IsAny <IPersonCondition>()));
        }
コード例 #22
0
 public SurvivalStatChangedEventArgs(SurvivalStat stat)
 {
     Stat = stat ?? throw new ArgumentNullException(nameof(stat));
 }
コード例 #23
0
 private static int GetStatDownRoll(SurvivalStat stat)
 {
     return(stat.DownPassRoll);
 }
コード例 #24
0
        private void DoStatChanged(SurvivalStat stat)
        {
            var args = new SurvivalStatChangedEventArgs(stat);

            InvokeStatChangedEvent(this, args);
        }