Files

169 lines
8.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using Data;
namespace Entity
{
public class Attributes
{
public int attack = 1;
public float attackRange = 3;
public float attackSpeed = 2;
public int attackTargetCount = 1;
public int defense;
public int health = 10;
public float moveSpeed = 1;
public float totalDamageDealtAbsoluteOffset; // 累计造成的伤害绝对值偏移 (原 effectiveDamageOffset 对应)
public float totalDamageDealtPercentOffset; // 累计造成的伤害百分比偏移 (原 effectiveDamagePercentOffset 对应)
public float totalDamageTakenAbsoluteOffset; // 累计受到的伤害绝对值偏移
public float totalDamageTakenPercentOffset; // 累计受到的伤害百分比偏移 (例如 0.1 表示 +10%)
/// <summary>
/// 根据属性定义初始化 <see cref="Attributes" /> 类的新实例。
/// </summary>
/// <param name="def">属性定义。</param>
public Attributes(AttributesDef def)
{
if (def == null)
return;
health = def.health;
moveSpeed = def.moveSpeed;
attack = def.attack;
defense = def.defense;
attackSpeed = MathF.Max(0.0001f, def.attackSpeed);
attackRange = def.attackRange;
attackTargetCount = def.attackTargetCount;
}
/// <summary>
/// 从另一个 <see cref="Attributes" /> 实例复制属性,初始化 <see cref="Attributes" /> 类的新实例。
/// </summary>
/// <param name="other">要复制的 <see cref="Attributes" /> 实例。</param>
public Attributes(Attributes other)
{
if (other == null)
return;
health = other.health;
moveSpeed = other.moveSpeed;
attack = other.attack;
defense = other.defense;
attackSpeed = other.attackSpeed;
attackRange = other.attackRange;
attackTargetCount = other.attackTargetCount;
}
/// <summary>
/// 初始化 <see cref="Attributes" /> 类的新实例。
/// </summary>
public Attributes()
{
}
/// <summary>
/// 根据给定的属性偏移,生成一个新的 <see cref="Attributes" /> 实例。
/// 原有的 <see cref="Attributes" /> 实例保持不变。
/// </summary>
/// <param name="offset">要应用的属性偏移定义。</param>
/// <returns>一个新的 <see cref="Attributes" /> 实例,包含了应用偏移后的值。</returns>
public Attributes GetModifiedAttributes(AttributesOffsetDef offset)
{
// 创建当前 Attributes 实例的一个副本
var newAttributes = new Attributes(this);
if (offset == null)
// 如果没有偏移,直接返回副本
return newAttributes;
// 在副本上应用绝对值偏移
newAttributes.health += (int)offset.healthOffset;
newAttributes.moveSpeed += offset.moveSpeedOffset;
newAttributes.attack += (int)offset.attackOffset;
newAttributes.defense += (int)offset.defenseOffset;
newAttributes.attackSpeed += offset.attackSpeedOffset;
newAttributes.attackRange += offset.attackRangeOffset;
newAttributes.attackTargetCount += (int)offset.attackTargetCountOffset;
// 在副本上应用百分比偏移 (基于应用绝对值偏移后的结果)
newAttributes.health = (int)(newAttributes.health * (1 + offset.healthPercentOffset));
newAttributes.moveSpeed *= 1 + offset.moveSpeedPercentOffset;
newAttributes.attack = (int)(newAttributes.attack * (1 + offset.attackPercentOffset));
newAttributes.defense = (int)(newAttributes.defense * (1 + offset.defensePercentOffset));
newAttributes.attackSpeed *= 1 + offset.attackSpeedPercentOffset;
newAttributes.attackRange *= 1 + offset.attackRangePercentOffset;
newAttributes.attackTargetCount =
(int)(newAttributes.attackTargetCount * (1 + offset.attackTargetCountPercentOffset));
newAttributes.totalDamageDealtAbsoluteOffset = offset.effectiveDamageOffset;
newAttributes.totalDamageDealtPercentOffset = offset.effectiveDamagePercentOffset;
newAttributes.totalDamageTakenAbsoluteOffset = offset.damageTakenOffset;
newAttributes.totalDamageTakenPercentOffset = offset.damageTakenPercentOffset;
// 确保属性不低于最小值
newAttributes.health = Math.Max(0, newAttributes.health);
newAttributes.moveSpeed = Math.Max(0f, newAttributes.moveSpeed);
newAttributes.attack = Math.Max(0, newAttributes.attack);
newAttributes.defense = Math.Max(0, newAttributes.defense);
newAttributes.attackSpeed = Math.Max(0f, newAttributes.attackSpeed);
newAttributes.attackRange = Math.Max(0f, newAttributes.attackRange);
newAttributes.attackTargetCount = Math.Max(1, newAttributes.attackTargetCount);
// 返回修改后的新 Attributes 实例
return newAttributes;
}
/// <summary>
/// 合并两个 <see cref="Attributes" /> 实例,生成一个新的 <see cref="Attributes" /> 实例,
/// 其中每个属性值都取自传入两个实例中对应属性的最小值。
/// 这对于应用属性上限或限制非常有用。
/// </summary>
/// <param name="a">第一个 <see cref="Attributes" /> 实例。</param>
/// <param name="b">第二个 <see cref="Attributes" /> 实例。</param>
/// <returns>一个新的 <see cref="Attributes" /> 实例,其属性是输入实例中对应属性的最小值。</returns>
public static Attributes Min(Attributes a, Attributes b)
{
// 处理 null 情况
if (a == null && b == null) return new Attributes(); // 两者都为null返回默认空属性
if (a == null) return new Attributes(b); // a为null返回b的副本
if (b == null) return new Attributes(a); // b为null返回a的副本
// 创建一个新的 Attributes 实例来存储结果
var result = new Attributes
{
health = Math.Min(a.health, b.health),
moveSpeed = Math.Min(a.moveSpeed, b.moveSpeed),
attack = Math.Min(a.attack, b.attack),
defense = Math.Min(a.defense, b.defense),
attackSpeed = Math.Min(a.attackSpeed, b.attackSpeed),
attackRange = Math.Min(a.attackRange, b.attackRange),
attackTargetCount = Math.Min(a.attackTargetCount, b.attackTargetCount),
totalDamageDealtAbsoluteOffset = a.totalDamageDealtAbsoluteOffset,
totalDamageDealtPercentOffset = a.totalDamageDealtPercentOffset,
totalDamageTakenAbsoluteOffset = a.totalDamageTakenAbsoluteOffset,
totalDamageTakenPercentOffset = a.totalDamageTakenPercentOffset
};
return result;
}
/// <summary>
/// 返回当前 <see cref="Attributes" /> 实例的字符串表示形式。
/// </summary>
/// <returns>包含所有属性名称和值的字符串。</returns>
public override string ToString()
{
return "Attributes {\n" +
$" Health: {health}\n" +
$" Move Speed: {moveSpeed:F2}\n" +
$" Attack: {attack}\n" +
$" Defense: {defense}\n" +
$" Attack Speed: {attackSpeed:F2}\n" +
$" Attack Range: {attackRange:F2}\n" +
$" Attack Target Count: {attackTargetCount}\n" +
$" Total Damage Dealt (Absolute Offset): {totalDamageDealtAbsoluteOffset:F2}\n" +
$" Total Damage Dealt (Percent Offset): {totalDamageDealtPercentOffset:P2}\n" +
$" Total Damage Taken (Absolute Offset): {totalDamageTakenAbsoluteOffset:F2}\n" +
$" Total Damage Taken (Percent Offset): {totalDamageTakenPercentOffset:P2}\n" +
"}";
}
}
}