Skip to content

Commit

Permalink
Merge pull request #3022 from planetarium/improve/issue-3020
Browse files Browse the repository at this point in the history
Set Damage Reduction limit
  • Loading branch information
ipdae authored Nov 20, 2024
2 parents 879c1f8 + 25bdd3b commit 89c61f0
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 14 deletions.
16 changes: 16 additions & 0 deletions .Lib9c.Tests/Action/DamageHelperTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Lib9c.Tests.Action
{
using Xunit;

public class DamageHelperTest
{
[Theory]
[InlineData(long.MaxValue, 0.19)]
[InlineData(4000L, 0.6)]
[InlineData(long.MinValue, 0)]
public void GetDamageReductionRate(long drr, decimal expected)
{
Assert.Equal(expected, Nekoyume.Battle.DamageHelper.GetDamageReductionRate(drr));
}
}
}
39 changes: 35 additions & 4 deletions .Lib9c.Tests/Model/CharacterStatsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public CharacterStatsTest()
}

[Fact]
public void DeBuffLimit()
public void DeBuffLimitPercentage()
{
var stats =
new CharacterStats(
Expand All @@ -26,7 +26,7 @@ public void DeBuffLimit()
// -100% def but limit -50% stats
var deBuff = new StatBuff(_tableSheets.StatBuffSheet[503012]);
var groupId = deBuff.RowData.GroupId;
buffLimitSheet.Set($"group_id,percentage\n{groupId},-50");
buffLimitSheet.Set($"group_id,percentage\n{groupId},Percentage,-50");
var def = stats.DEF;
stats.AddBuff(deBuff, buffLimitSheet);
var modifier = buffLimitSheet[groupId].GetModifier(deBuff.RowData.StatType);
Expand All @@ -40,7 +40,7 @@ public void DeBuffLimit()
}

[Fact]
public void BuffLimit()
public void BuffLimitPercentage()
{
var stats =
new CharacterStats(
Expand All @@ -58,11 +58,42 @@ public void BuffLimit()
stats.RemoveBuff(buff);
Assert.Equal(atk, stats.ATK);
// +60% atk but limit 50% stats
buffLimitSheet.Set($"group_id,percentage\n{groupId},50");
buffLimitSheet.Set($"group_id,modify_type,percentage\n{groupId},Percentage,50");
var modifier = buffLimitSheet[groupId].GetModifier(buff.RowData.StatType);
stats.AddBuff(buff, buffLimitSheet);
Assert.Equal(atk * 1.5m, modifier.GetModifiedAll(atk));
Assert.Equal(atk * 1.5m, stats.ATK);
}

[Fact]
public void BuffLimitAdd()
{
const long buffDrrValue = 80;
const long buffLimitValue = 50;

var stats =
new CharacterStats(
_tableSheets.CharacterSheet[GameConfig.DefaultAvatarCharacterId],
1);
var statBuffSheet = new StatBuffSheet();
statBuffSheet.Set($"id,group,_name,chance,duration,target_type,stat_type,modify_type,modify_value,is_enhanceable,max_stack\n702001,702001,DRR (커스텀 장비),100,12,Self,DRR,Add,{buffDrrValue},true,");
var buffLimitSheet = new BuffLimitSheet();
// +80 drr with no limit
var buff = new StatBuff(statBuffSheet[702001]);
var groupId = buff.RowData.GroupId;
var drr = stats.DRR;
stats.AddBuff(buff, buffLimitSheet);
Assert.Equal(drr + buffDrrValue, stats.DRR);

// reset stats
stats.RemoveBuff(buff);
Assert.Equal(drr, stats.DRR);
// +80 drr but limit 50 stats
buffLimitSheet.Set($"group_id,modify_type,percentage\n{groupId},Add,{buffLimitValue}");
var modifier = buffLimitSheet[groupId].GetModifier(buff.RowData.StatType);
stats.AddBuff(buff, buffLimitSheet);
Assert.Equal(drr + buffLimitValue, modifier.GetModifiedAll(drr));
Assert.Equal(drr + buffLimitValue, stats.DRR);
}
}
}
3 changes: 2 additions & 1 deletion .Lib9c.Tests/Model/Skill/Adventure/CombatTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public CombatTest()
[InlineData(10, 10, 5000, 120, 50)]
[InlineData(0, 1000, 0, 999, 1)]
[InlineData(1000, 0, 0, 999, 1)]
[InlineData(0, 0, 10000, int.MaxValue, 1)]
[InlineData(0, 0, 10000, 300, 57)]
[InlineData(0, 0, 10000, int.MaxValue, 300)]
public void CalculateDEFAndDamageReduction(int def, int drv, int drr, int enemyATK, int expectedDamage)
{
_player.Stats.SetStatForTest(StatType.DEF, def);
Expand Down
47 changes: 47 additions & 0 deletions .Lib9c.Tests/Model/Skill/Arena/ArenaCombatTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -269,5 +269,52 @@ public void DispelOnDuration_Nothing()
Assert.True(battleStatus.SkillInfos.First().Affected);
Assert.Contains(600001, challenger.Buffs.Values.Select(bf => bf.BuffInfo.Id));
}

[Fact]
public void Drr()
{
var arenaSheets = _tableSheets.GetArenaSimulatorSheets();
var myDigest = new ArenaPlayerDigest(_avatar1, _arenaAvatar1);
var enemyDigest = new ArenaPlayerDigest(_avatar2, _arenaAvatar2);
var simulator = new ArenaSimulator(new TestRandom());
var challenger = new ArenaCharacter(
simulator,
myDigest,
arenaSheets,
simulator.HpModifier,
new List<StatModifier>()
);
var enemy = new ArenaCharacter(
simulator,
enemyDigest,
arenaSheets,
simulator.HpModifier,
new List<StatModifier>()
);
var statBuffRow = new Nekoyume.TableData.StatBuffSheet.Row();
var csv = $"101000,101000,20,10,Self,DRR,Add,{int.MaxValue},true";
statBuffRow.Set(csv.Split(","));
var buff = new StatBuff(statBuffRow);
enemy.AddBuff(buff);
Assert.True(enemy.DRR > 1000000);
var attackRow =
_tableSheets.SkillSheet.Values.First(bf => bf.Id == 100000);
var attack = new ArenaNormalAttack(attackRow, 100, 100, 0, StatType.NONE);
var arenaSkill = attack.Use(
challenger,
enemy,
simulator.Turn,
BuffFactory.GetBuffs(
challenger.Stats,
attack,
_tableSheets.SkillBuffSheet,
_tableSheets.StatBuffSheet,
_tableSheets.SkillActionBuffSheet,
_tableSheets.ActionBuffSheet
)
);
var info = arenaSkill.SkillInfos.Single();
Assert.True(info.Effect > 1);
}
}
}
24 changes: 24 additions & 0 deletions Lib9c/Battle/DamageHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Nekoyume.Battle
{
public static class DamageHelper
{
/// <summary>
/// calculate damage reduction rate.
/// </summary>
/// <param name="drr">enemy <see cref="Model.Stat.StatType.DRR"/> stats</param>
/// <returns>damage reduction rate.</returns>
public static decimal GetDamageReductionRate(long drr)
{
switch (drr)
{
case > 8100L:
drr = 8100L;
break;
case < 0L:
return 0m;
}

return 1 - drr / 10000m;
}
}
}
2 changes: 1 addition & 1 deletion Lib9c/Model/Skill/Arena/ArenaAttackSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ protected ArenaAttackSkill(
var finalDEF = Math.Clamp(target.DEF - caster.ArmorPenetration, 0, long.MaxValue);
damage = Math.Max(damage - finalDEF, 1);
// Apply damage reduce
damage = (int)((damage - target.DRV) * (1 - target.DRR / 10000m));
damage = (int)((damage - target.DRV) * DamageHelper.GetDamageReductionRate(target.DRR));

// ShatterStrike has max damage limitation
if (SkillRow.SkillCategory is SkillCategory.ShatterStrike)
Expand Down
2 changes: 1 addition & 1 deletion Lib9c/Model/Skill/AttackSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected AttackSkill(
// Apply multiple hits
damage = (long) (damage * multiplier);
// Apply damage reduction
damage = (long) ((damage - target.DRV) * (1 - target.DRR / 10000m));
damage = (long) ((damage - target.DRV) * DamageHelper.GetDamageReductionRate(target.DRR));

if (damage < 1)
{
Expand Down
10 changes: 5 additions & 5 deletions Lib9c/TableCSV/Skill/BuffLimitSheet.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group_id,percentage
206000,-20
709000,-50
206003,-20
206009,-50
group_id,modify_type1,percentage
206000,Percentage,-20
709000,Percentage,-50
206003,Percentage,-20
206009,Percentage,-50
10 changes: 8 additions & 2 deletions Lib9c/TableData/Skill/BuffLimitSheet.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using Nekoyume.Model.Stat;
using static Nekoyume.TableData.TableExtensions;

namespace Nekoyume.TableData
{
using OperationType = StatModifier.OperationType;

public class BuffLimitSheet : Sheet<int, BuffLimitSheet.Row>
{
public class Row : SheetRow<int>
Expand All @@ -12,17 +15,20 @@ public class Row : SheetRow<int>

public int GroupId { get; set; }

public StatModifier.OperationType StatModifier { get; private set; }

public int Value { get; set; }

public override void Set(IReadOnlyList<string> fields)
{
GroupId = ParseInt(fields[0]);
Value = ParseInt(fields[1]);
StatModifier = (OperationType)Enum.Parse(typeof(OperationType), fields[1]);
Value = ParseInt(fields[2]);
}

public StatModifier GetModifier(StatType statType)
{
return new StatModifier(statType, StatModifier.OperationType.Percentage, Value);
return new StatModifier(statType, StatModifier, Value);
}
}

Expand Down

0 comments on commit 89c61f0

Please sign in to comment.