Browse Source

百分比属性的计算--攻击、防御、血量

master
hanqin 1 week ago
parent
commit
824600d0d2
  1. 53
      Build_God_Api/Build_God_Api/Services/Game/CharacterAttributeCalculateService.cs
  2. 81
      Build_God_Api/Build_God_Api/Services/Game/EquipmentAttributeBonus.cs
  3. 24
      Build_God_Api/Build_God_Api/Services/Game/MonsterAttributeCalculateService.cs

53
Build_God_Api/Build_God_Api/Services/Game/CharacterAttributeCalculateService.cs

@ -60,32 +60,22 @@ namespace Build_God_Api.Services.Game
return (attackBonus, defendBonus, hpBonus);
}
private async Task<(decimal AttackBonus, decimal DefendBonus, decimal HPBonus, decimal CriticalBonus, decimal CriticalDamageBonus)> CalculateEquipmentBonusAsync(int characterBagId)
private async Task<EquipmentAttributeTotals> CalculateEquipmentBonusAsync(int characterBagId)
{
var equipmentInstances = await _context.Queryable<EquipmentInstance>()
.Where(x => x.CharacterBagId == characterBagId)
.ToListAsync();
decimal attackBonus = 0;
decimal defendBonus = 0;
decimal hpBonus = 0;
decimal criticalBonus = 0;
decimal criticalDamage = 0;
var totals = new EquipmentAttributeTotals();
foreach (var instance in equipmentInstances)
{
var template = await _context.Queryable<EquipmentTemplate>().FirstAsync(x => x.Id == instance.EquipmentTemplateId);
if (template == null || string.IsNullOrEmpty(instance.Attributes)) continue;
var t = EquipmentAttributeBonus.SumFromJson(instance.Attributes);
attackBonus += t.AttackBonus;
defendBonus += t.DefendBonus;
hpBonus += t.HPBonus;
criticalBonus += t.CriticalBonus;
criticalDamage += t.CriticalDamageBonus;
totals += EquipmentAttributeBonus.SumFromJson(instance.Attributes);
}
return (attackBonus, defendBonus, hpBonus, criticalBonus, criticalDamage);
return totals;
}
public async Task<CharacterAttributes> CalculateAttributesAsync(Character character)
@ -102,37 +92,42 @@ namespace Build_God_Api.Services.Game
decimal baseCritical = 0;
decimal baseCriticalDamage = 0;
decimal bonusAttack = 0;
decimal bonusDefend = 0;
decimal bonusHP = 0;
decimal bonusAttackFlat = 0;
decimal bonusDefendFlat = 0;
decimal bonusHPFlat = 0;
decimal bonusCritical = 0;
decimal bonusCriticalDamage = 0;
var equipTotals = new EquipmentAttributeTotals();
var characterBag = await _context.Queryable<CharacterBag>().FirstAsync(x => x.CharacterId == character.Id);
if (characterBag != null)
{
var (scrapAttack, scrapDefend, scrapHP) = await CalculateScrapBonusAsync(characterBag.Id);
var (equipAttack, equipDefend, equipHP, equipCritical, equipmentCriticalDamage) = await CalculateEquipmentBonusAsync(characterBag.Id);
equipTotals = await CalculateEquipmentBonusAsync(characterBag.Id);
bonusAttack = scrapAttack + equipAttack;
bonusDefend = scrapDefend + equipDefend;
bonusHP = scrapHP + equipHP;
bonusCritical = equipCritical;
bonusCriticalDamage = equipmentCriticalDamage;
bonusAttackFlat = scrapAttack + equipTotals.AttackFixed;
bonusDefendFlat = scrapDefend + equipTotals.DefendFixed;
bonusHPFlat = scrapHP + equipTotals.HealthFixed;
bonusCritical = equipTotals.CriticalRate;
bonusCriticalDamage = equipTotals.CriticalDamage;
}
decimal maxHp = EquipmentAttributeBonus.ApplyPercentToBaseAndFlat(baseMaxHP, bonusHPFlat, equipTotals.HealthPercent);
decimal attack = EquipmentAttributeBonus.ApplyPercentToBaseAndFlat(baseAttack, bonusAttackFlat, equipTotals.AttackPercent);
decimal defend = EquipmentAttributeBonus.ApplyPercentToBaseAndFlat(baseDefend, bonusDefendFlat, equipTotals.DefendPercent);
return new CharacterAttributes
{
MaxHP = baseMaxHP + bonusHP,
MaxHP = maxHp,
BaseMaxHP = baseMaxHP,
BonusMaxHP = bonusHP,
BonusMaxHP = maxHp - baseMaxHP,
CurrentHP = character.CurrentHP,
Attack = baseAttack + bonusAttack,
Attack = attack,
BaseAttack = baseAttack,
BonusAttack = bonusAttack,
Defend = baseDefend + bonusDefend,
BonusAttack = attack - baseAttack,
Defend = defend,
BaseDefend = baseDefend,
BonusDefend = bonusDefend,
BonusDefend = defend - baseDefend,
CriticalRate = baseCritical + bonusCritical,
BaseCriticalRate = baseCritical,
BonusCriticalRate = bonusCritical,

81
Build_God_Api/Build_God_Api/Services/Game/EquipmentAttributeBonus.cs

@ -10,7 +10,37 @@ namespace Build_God_Api.Services.Game
}
/// <summary>
/// 从装备属性 JSON(与 EquipmentInstance.Attributes 同格式)累加固定类加成
/// 单件装备 JSON 或背包多件的属性总和(固定值 + 百分比累加)。百分比为「百分点」累加,如两件 +10% 攻 = 20,参与公式 (基础+固定)×(1+总和/100)。
/// </summary>
public sealed class EquipmentAttributeTotals
{
public decimal AttackFixed { get; set; }
public decimal AttackPercent { get; set; }
public decimal DefendFixed { get; set; }
public decimal DefendPercent { get; set; }
public decimal HealthFixed { get; set; }
public decimal HealthPercent { get; set; }
public decimal CriticalRate { get; set; }
public decimal CriticalDamage { get; set; }
public static EquipmentAttributeTotals operator +(EquipmentAttributeTotals a, EquipmentAttributeTotals b)
{
return new EquipmentAttributeTotals
{
AttackFixed = a.AttackFixed + b.AttackFixed,
AttackPercent = a.AttackPercent + b.AttackPercent,
DefendFixed = a.DefendFixed + b.DefendFixed,
DefendPercent = a.DefendPercent + b.DefendPercent,
HealthFixed = a.HealthFixed + b.HealthFixed,
HealthPercent = a.HealthPercent + b.HealthPercent,
CriticalRate = a.CriticalRate + b.CriticalRate,
CriticalDamage = a.CriticalDamage + b.CriticalDamage
};
}
}
/// <summary>
/// 从装备属性 JSON(与 EquipmentInstance.Attributes 同格式)累加属性
/// </summary>
public static class EquipmentAttributeBonus
{
@ -19,45 +49,43 @@ namespace Build_God_Api.Services.Game
PropertyNameCaseInsensitive = true
};
public static (decimal AttackBonus, decimal DefendBonus, decimal HPBonus, decimal CriticalBonus, decimal CriticalDamageBonus) SumFromJson(string? attributesJson)
public static EquipmentAttributeTotals SumFromJson(string? attributesJson)
{
decimal attackBonus = 0;
decimal defendBonus = 0;
decimal hpBonus = 0;
decimal criticalBonus = 0;
decimal criticalDamage = 0;
if (string.IsNullOrWhiteSpace(attributesJson)) return (attackBonus, defendBonus, hpBonus, criticalBonus, criticalDamage);
var totals = new EquipmentAttributeTotals();
if (string.IsNullOrWhiteSpace(attributesJson)) return totals;
try
{
var attributes = JsonSerializer.Deserialize<List<EquipmentAttributeDto>>(attributesJson, JsonOptions);
if (attributes == null) return (attackBonus, defendBonus, hpBonus, criticalBonus, criticalDamage);
if (attributes == null) return totals;
foreach (var attr in attributes)
{
switch (attr.Type)
{
case EquipmentAttributeType.AttackFixed:
attackBonus += attr.Value;
totals.AttackFixed += attr.Value;
break;
case EquipmentAttributeType.AttackPercent:
totals.AttackPercent += attr.Value;
break;
case EquipmentAttributeType.DefendFixed:
defendBonus += attr.Value;
totals.DefendFixed += attr.Value;
break;
case EquipmentAttributeType.DefendPercent:
totals.DefendPercent += attr.Value;
break;
case EquipmentAttributeType.HealthBonusFixed:
hpBonus += attr.Value;
totals.HealthFixed += attr.Value;
break;
case EquipmentAttributeType.HealthBonusPercent:
totals.HealthPercent += attr.Value;
break;
case EquipmentAttributeType.CriticalRate:
criticalBonus += attr.Value;
totals.CriticalRate += attr.Value;
break;
case EquipmentAttributeType.CriticalDamage:
criticalDamage += attr.Value;
totals.CriticalDamage += attr.Value;
break;
}
}
@ -67,22 +95,25 @@ namespace Build_God_Api.Services.Game
// ignore parse errors — same as character path
}
return (attackBonus, defendBonus, hpBonus, criticalBonus, criticalDamage);
return totals;
}
public static (decimal AttackBonus, decimal DefendBonus, decimal HPBonus, decimal CriticalBonus, decimal CriticalDamageBonus) SumFromManyJson(IEnumerable<string?> jsonList)
public static EquipmentAttributeTotals SumFromManyJson(IEnumerable<string?> jsonList)
{
decimal a = 0, d = 0, h = 0, c = 0, cd = 0;
var acc = new EquipmentAttributeTotals();
foreach (var j in jsonList)
{
var t = SumFromJson(j);
a += t.AttackBonus;
d += t.DefendBonus;
h += t.HPBonus;
c += t.CriticalBonus;
cd += t.CriticalDamageBonus;
acc += SumFromJson(j);
}
return (a, d, h, c, cd);
return acc;
}
/// <summary>
/// (基础 + 固定加成)× (1 + 百分比/100)。百分比为装备上累加的百分点之和。
/// </summary>
public static decimal ApplyPercentToBaseAndFlat(decimal baseValue, decimal flatBonus, decimal totalPercentPoints)
{
return (baseValue + flatBonus) * (1 + totalPercentPoints / 100m);
}
}
}

24
Build_God_Api/Build_God_Api/Services/Game/MonsterAttributeCalculateService.cs

@ -49,23 +49,27 @@ namespace Build_God_Api.Services.Game
equipment ??= await _db.Queryable<MonsterEquipment>().Where(x => x.MonsterId == monster.Id).ToListAsync();
var bonus = EquipmentAttributeBonus.SumFromManyJson(equipment.Select(e => e.Attributes));
var equip = EquipmentAttributeBonus.SumFromManyJson(equipment.Select(e => e.Attributes));
decimal maxHp = EquipmentAttributeBonus.ApplyPercentToBaseAndFlat(baseMaxHp, equip.HealthFixed, equip.HealthPercent);
decimal attack = EquipmentAttributeBonus.ApplyPercentToBaseAndFlat(baseAttack, equip.AttackFixed, equip.AttackPercent);
decimal defend = EquipmentAttributeBonus.ApplyPercentToBaseAndFlat(baseDefend, equip.DefendFixed, equip.DefendPercent);
return new MonsterCombatAttributes
{
BaseMaxHP = baseMaxHp,
BonusMaxHP = bonus.HPBonus,
BonusAttack = bonus.AttackBonus,
BonusDefend = bonus.DefendBonus,
BonusCriticalRate = bonus.CriticalBonus,
BonusMaxHP = maxHp - baseMaxHp,
BonusAttack = attack - baseAttack,
BonusDefend = defend - baseDefend,
BonusCriticalRate = equip.CriticalRate,
BaseCriticalDamage = 0,
BonusCriticalDamage = bonus.CriticalDamageBonus,
MaxHP = baseMaxHp + bonus.HPBonus,
Attack = baseAttack + bonus.AttackBonus,
Defend = baseDefend + bonus.DefendBonus,
BonusCriticalDamage = equip.CriticalDamage,
MaxHP = maxHp,
Attack = attack,
Defend = defend,
BaseAttack = baseAttack,
BaseDefend = baseDefend,
CriticalRate = baseCrit + bonus.CriticalBonus,
CriticalRate = baseCrit + equip.CriticalRate,
BaseCriticalRate = baseCrit,
};
}

Loading…
Cancel
Save