Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/Entity/Attributes.cs

131 lines
5.5 KiB
C#
Raw Normal View History

2025-09-02 11:08:15 +08:00
using System;
using Data;
namespace Entity
{
public class Attributes
{
public int health = 10;
public float moveSpeed = 1;
public int attack = 1;
public int defense = 0;
public float attackSpeed = 2;
public float attackRange = 3;
public int attackTargetCount = 1;
2025-09-02 11:08:15 +08:00
public Attributes(AttributesDef def)
{
health = def.health;
moveSpeed = def.moveSpeed;
attack = def.attack;
defense = def.defense;
attackSpeed = def.attackSpeed;
attackRange = def.attackRange;
attackTargetCount = def.attackTargetCount;
}
2025-09-02 11:08:15 +08:00
public Attributes(Attributes other)
{
health = other.health;
moveSpeed = other.moveSpeed;
attack = other.attack;
defense = other.defense;
attackSpeed = other.attackSpeed;
attackRange = other.attackRange;
attackTargetCount = other.attackTargetCount;
}
public Attributes()
2025-09-02 11:08:15 +08:00
{
}
/// <summary>
/// 根据给定的属性偏移,生成一个新的 Attributes 实例。
/// 原有的 Attributes 实例保持不变。
/// </summary>
/// <param name="offset">要应用的属性偏移定义。</param>
/// <returns>一个新的 Attributes 实例,包含了应用偏移后的值。</returns>
public Attributes GetModifiedAttributes(AttributesOffsetDef offset)
{
// 1. 创建当前 Attributes 实例的一个副本
var newAttributes = new Attributes(this);
if (offset == null)
{
return newAttributes; // 如果没有偏移,直接返回副本
}
// 2. 在副本上应用绝对值偏移
newAttributes.health += (int)offset.healthOffset;
newAttributes.moveSpeed += offset.moveSpeedOffset;
newAttributes.attack += (int)offset.attackOffset;
newAttributes.defense += (int)offset.defenseOffset;
// 修正: attackSpeed 和 attackRange 是 float不应强制转换为 int
newAttributes.attackSpeed += offset.attackSpeedOffset;
newAttributes.attackRange += offset.attackRangeOffset;
2025-09-02 11:08:15 +08:00
newAttributes.attackTargetCount += (int)offset.attackTargetCountOffset;
// 3. 在副本上应用百分比偏移 (基于应用绝对值偏移后的结果)
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));
// 修正: attackSpeed 和 attackRange 是 float不应强制转换为 int
newAttributes.attackSpeed *= (1 + offset.attackSpeedPercentOffset);
newAttributes.attackRange *= (1 + offset.attackRangePercentOffset);
2025-09-02 11:08:15 +08:00
newAttributes.attackTargetCount =
(int)(newAttributes.attackTargetCount * (1 + offset.attackTargetCountPercentOffset));
// 4. 确保属性不低于最小值
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);
// 修正: Math.Max 期望相同类型0f 对于 float 类型更准确
newAttributes.attackSpeed = Math.Max(0f, newAttributes.attackSpeed);
newAttributes.attackRange = Math.Max(0f, newAttributes.attackRange);
2025-09-02 11:08:15 +08:00
newAttributes.attackTargetCount = Math.Max(1, newAttributes.attackTargetCount);
// 5. 返回修改后的新 Attributes 实例
return newAttributes;
}
/// <summary>
/// 合并两个 Attributes 实例,生成一个新的 Attributes 实例,
/// 其中每个属性值都取自传入两个实例中对应属性的最小值。
/// 这对于应用属性上限或限制非常有用。
/// </summary>
/// <param name="a">第一个 Attributes 实例。</param>
/// <param name="b">第二个 Attributes 实例。</param>
/// <returns>一个新的 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)
};
return result;
}
}
}