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)); } }
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(); }
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); }
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); }
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); }
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)); } }
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"); } }
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"); } }
/// <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); } }
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); } }
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); }
private static SurvivalStat CreateUselessStat(SurvivalStatType statType) { var stat = new SurvivalStat(100, 0, 100) { Type = statType, Rate = 1, DownPassRoll = 0 }; return(stat); }
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); }
protected void ChangeStatInner(SurvivalStat stat, int value) { if (stat is null) { throw new ArgumentNullException(nameof(stat)); } stat.Value += value; ProcessIfHealth(stat, value); ProcessIfWound(stat); }
/// <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); } } }
/// <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); } }
private void ProcessIfWound(SurvivalStat stat) { if (stat.Type != SurvivalStatType.Wound) { return; } var woundCounter = stat.Value; if (woundCounter <= 0) { // Если счётчик раны дошёл до 0, // то восстанавливаем единицу здоровья. RestoreStat(SurvivalStatType.Health, 1); } }
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); }
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); }
/// <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(); } } }
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>())); }
public SurvivalStatChangedEventArgs(SurvivalStat stat) { Stat = stat ?? throw new ArgumentNullException(nameof(stat)); }
private static int GetStatDownRoll(SurvivalStat stat) { return(stat.DownPassRoll); }
private void DoStatChanged(SurvivalStat stat) { var args = new SurvivalStatChangedEventArgs(stat); InvokeStatChangedEvent(this, args); }