2025-09-03 19:59:22 +08:00
|
|
|
|
using System;
|
2025-08-27 19:56:49 +08:00
|
|
|
|
using Data;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Entity
|
|
|
|
|
|
{
|
|
|
|
|
|
public class Attributes
|
|
|
|
|
|
{
|
|
|
|
|
|
public int attack = 1;
|
2025-09-03 19:59:22 +08:00
|
|
|
|
public float attackRange = 3;
|
2025-10-10 14:08:23 +08:00
|
|
|
|
public float attackSpeed = 2;
|
2025-08-27 19:56:49 +08:00
|
|
|
|
public int attackTargetCount = 1;
|
2025-10-10 14:08:23 +08:00
|
|
|
|
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%)
|
2025-09-03 19:59:22 +08:00
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据属性定义初始化 <see cref="Attributes" /> 类的新实例。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="def">属性定义。</param>
|
2025-08-27 19:56:49 +08:00
|
|
|
|
public Attributes(AttributesDef def)
|
|
|
|
|
|
{
|
2025-09-19 08:26:54 +08:00
|
|
|
|
if (def == null)
|
|
|
|
|
|
return;
|
2025-08-27 19:56:49 +08:00
|
|
|
|
health = def.health;
|
|
|
|
|
|
moveSpeed = def.moveSpeed;
|
|
|
|
|
|
attack = def.attack;
|
|
|
|
|
|
defense = def.defense;
|
2025-10-10 14:08:23 +08:00
|
|
|
|
attackSpeed = MathF.Max(0.0001f, def.attackSpeed);
|
2025-08-27 19:56:49 +08:00
|
|
|
|
attackRange = def.attackRange;
|
|
|
|
|
|
attackTargetCount = def.attackTargetCount;
|
|
|
|
|
|
}
|
2025-09-03 19:59:22 +08:00
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 从另一个 <see cref="Attributes" /> 实例复制属性,初始化 <see cref="Attributes" /> 类的新实例。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="other">要复制的 <see cref="Attributes" /> 实例。</param>
|
2025-09-03 19:59:22 +08:00
|
|
|
|
public Attributes(Attributes other)
|
|
|
|
|
|
{
|
2025-10-10 14:08:23 +08:00
|
|
|
|
if (other == null)
|
|
|
|
|
|
return;
|
2025-09-03 19:59:22 +08:00
|
|
|
|
health = other.health;
|
|
|
|
|
|
moveSpeed = other.moveSpeed;
|
|
|
|
|
|
attack = other.attack;
|
|
|
|
|
|
defense = other.defense;
|
|
|
|
|
|
attackSpeed = other.attackSpeed;
|
|
|
|
|
|
attackRange = other.attackRange;
|
|
|
|
|
|
attackTargetCount = other.attackTargetCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化 <see cref="Attributes" /> 类的新实例。
|
|
|
|
|
|
/// </summary>
|
2025-08-27 19:56:49 +08:00
|
|
|
|
public Attributes()
|
2025-09-03 19:59:22 +08:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 根据给定的属性偏移,生成一个新的 <see cref="Attributes" /> 实例。
|
|
|
|
|
|
/// 原有的 <see cref="Attributes" /> 实例保持不变。
|
2025-09-03 19:59:22 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="offset">要应用的属性偏移定义。</param>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// <returns>一个新的 <see cref="Attributes" /> 实例,包含了应用偏移后的值。</returns>
|
2025-09-03 19:59:22 +08:00
|
|
|
|
public Attributes GetModifiedAttributes(AttributesOffsetDef offset)
|
|
|
|
|
|
{
|
2025-10-10 14:08:23 +08:00
|
|
|
|
// 创建当前 Attributes 实例的一个副本
|
2025-09-03 19:59:22 +08:00
|
|
|
|
var newAttributes = new Attributes(this);
|
|
|
|
|
|
|
|
|
|
|
|
if (offset == null)
|
2025-10-10 14:08:23 +08:00
|
|
|
|
// 如果没有偏移,直接返回副本
|
|
|
|
|
|
return newAttributes;
|
2025-09-03 19:59:22 +08:00
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
// 在副本上应用绝对值偏移
|
2025-09-03 19:59:22 +08:00
|
|
|
|
newAttributes.health += (int)offset.healthOffset;
|
|
|
|
|
|
newAttributes.moveSpeed += offset.moveSpeedOffset;
|
|
|
|
|
|
newAttributes.attack += (int)offset.attackOffset;
|
|
|
|
|
|
newAttributes.defense += (int)offset.defenseOffset;
|
2025-10-10 14:08:23 +08:00
|
|
|
|
newAttributes.attackSpeed += offset.attackSpeedOffset;
|
|
|
|
|
|
newAttributes.attackRange += offset.attackRangeOffset;
|
2025-09-03 19:59:22 +08:00
|
|
|
|
newAttributes.attackTargetCount += (int)offset.attackTargetCountOffset;
|
|
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
// 在副本上应用百分比偏移 (基于应用绝对值偏移后的结果)
|
2025-09-03 19:59:22 +08:00
|
|
|
|
newAttributes.health = (int)(newAttributes.health * (1 + offset.healthPercentOffset));
|
2025-10-10 14:08:23 +08:00
|
|
|
|
newAttributes.moveSpeed *= 1 + offset.moveSpeedPercentOffset;
|
2025-09-03 19:59:22 +08:00
|
|
|
|
newAttributes.attack = (int)(newAttributes.attack * (1 + offset.attackPercentOffset));
|
|
|
|
|
|
newAttributes.defense = (int)(newAttributes.defense * (1 + offset.defensePercentOffset));
|
2025-10-10 14:08:23 +08:00
|
|
|
|
newAttributes.attackSpeed *= 1 + offset.attackSpeedPercentOffset;
|
|
|
|
|
|
newAttributes.attackRange *= 1 + offset.attackRangePercentOffset;
|
2025-09-03 19:59:22 +08:00
|
|
|
|
newAttributes.attackTargetCount =
|
|
|
|
|
|
(int)(newAttributes.attackTargetCount * (1 + offset.attackTargetCountPercentOffset));
|
|
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
newAttributes.totalDamageDealtAbsoluteOffset = offset.effectiveDamageOffset;
|
|
|
|
|
|
newAttributes.totalDamageDealtPercentOffset = offset.effectiveDamagePercentOffset;
|
|
|
|
|
|
newAttributes.totalDamageTakenAbsoluteOffset = offset.damageTakenOffset;
|
|
|
|
|
|
newAttributes.totalDamageTakenPercentOffset = offset.damageTakenPercentOffset;
|
|
|
|
|
|
|
|
|
|
|
|
// 确保属性不低于最小值
|
2025-09-03 19:59:22 +08:00
|
|
|
|
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);
|
2025-10-10 14:08:23 +08:00
|
|
|
|
newAttributes.attackSpeed = Math.Max(0f, newAttributes.attackSpeed);
|
2025-09-03 19:59:22 +08:00
|
|
|
|
newAttributes.attackRange = Math.Max(0f, newAttributes.attackRange);
|
|
|
|
|
|
newAttributes.attackTargetCount = Math.Max(1, newAttributes.attackTargetCount);
|
|
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
// 返回修改后的新 Attributes 实例
|
2025-09-03 19:59:22 +08:00
|
|
|
|
return newAttributes;
|
|
|
|
|
|
}
|
2025-10-10 14:08:23 +08:00
|
|
|
|
|
2025-09-03 19:59:22 +08:00
|
|
|
|
/// <summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// 合并两个 <see cref="Attributes" /> 实例,生成一个新的 <see cref="Attributes" /> 实例,
|
|
|
|
|
|
/// 其中每个属性值都取自传入两个实例中对应属性的最小值。
|
|
|
|
|
|
/// 这对于应用属性上限或限制非常有用。
|
2025-09-03 19:59:22 +08:00
|
|
|
|
/// </summary>
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// <param name="a">第一个 <see cref="Attributes" /> 实例。</param>
|
|
|
|
|
|
/// <param name="b">第二个 <see cref="Attributes" /> 实例。</param>
|
|
|
|
|
|
/// <returns>一个新的 <see cref="Attributes" /> 实例,其属性是输入实例中对应属性的最小值。</returns>
|
2025-09-03 19:59:22 +08:00
|
|
|
|
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),
|
2025-10-10 14:08:23 +08:00
|
|
|
|
attackTargetCount = Math.Min(a.attackTargetCount, b.attackTargetCount),
|
|
|
|
|
|
totalDamageDealtAbsoluteOffset = a.totalDamageDealtAbsoluteOffset,
|
|
|
|
|
|
totalDamageDealtPercentOffset = a.totalDamageDealtPercentOffset,
|
|
|
|
|
|
totalDamageTakenAbsoluteOffset = a.totalDamageTakenAbsoluteOffset,
|
|
|
|
|
|
totalDamageTakenPercentOffset = a.totalDamageTakenPercentOffset
|
2025-09-03 19:59:22 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-10 14:08:23 +08:00
|
|
|
|
/// <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" +
|
|
|
|
|
|
"}";
|
|
|
|
|
|
}
|
2025-08-27 19:56:49 +08:00
|
|
|
|
}
|
2025-10-10 14:08:23 +08:00
|
|
|
|
}
|