Files
Cielonos/Assets/Scripts/MainGame/AttackArea/AttackInfo/AttackInfo.cs

209 lines
7.0 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
using System;
2025-12-08 05:27:53 -05:00
using System.Collections.Generic;
using System.Linq;
2026-05-23 08:27:50 -04:00
using System.Text;
2026-01-03 18:19:39 -05:00
using Cielonos.MainGame.Characters;
2026-02-13 09:22:11 -05:00
using SLSUtilities.General;
2025-11-25 08:19:33 -05:00
using SLSUtilities.FunctionalAnimation;
using UnityEngine;
namespace Cielonos.MainGame
{
2026-05-23 08:27:50 -04:00
public static class Attack
2025-11-25 08:19:33 -05:00
{
2026-05-23 08:27:50 -04:00
public enum Type
2026-03-20 12:07:44 -04:00
{
Energy = 1,
Kinetics = 2,
Explosion = 3,
Magic = 4,
2026-04-18 13:57:19 -04:00
Pure = 5,
Blank = 6, // 代表不具有特定攻击类型的伤害,例如持续伤害、反伤等
2026-03-20 12:07:44 -04:00
}
2026-05-23 08:27:50 -04:00
public static string AttackTypeToString(this Type type)
2026-03-20 12:07:44 -04:00
{
2026-05-23 08:27:50 -04:00
return type switch
2026-03-20 12:07:44 -04:00
{
2026-05-23 08:27:50 -04:00
Type.Energy => "Energy",
Type.Kinetics => "Kinetics",
Type.Explosion => "Explosion",
Type.Magic => "Magic",
Type.Pure => "Pure",
Type.Blank => "Blank",
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
2026-03-20 12:07:44 -04:00
};
}
2026-05-23 08:27:50 -04:00
public class Value : ICloneable<Value>
{
public bool isCritical;
public float damage;
public Type type;
public Breakthrough.Type breakthroughType;
public DisruptionType disruptionType;
public List<string> tags;
public float damageMultiplier = 1f;
public float additionalFlatDamage = 0f;
public Value(bool isCritical, float damage, Type type,
DisruptionType disruptionType = DisruptionType.None, Breakthrough.Type breakthroughType = Breakthrough.Type.None,
List<string> tags = null)
{
this.isCritical = isCritical;
this.damage = damage;
this.type = type;
this.disruptionType = disruptionType;
this.breakthroughType = breakthroughType;
this.tags = tags != null ? new List<string>(tags) : new List<string>();
}
public Value Clone()
{
Value cloned = new Value(isCritical, damage, type, disruptionType, breakthroughType, tags);
cloned.damageMultiplier = this.damageMultiplier;
cloned.additionalFlatDamage = this.additionalFlatDamage;
return cloned;
}
}
/// <summary>
/// 攻击上下文:在伤害结算前传递,允许订阅者修改攻击参数和前置决策标记。
/// <para> 用于 onStartAttack / onBeforeGetAttacked 阶段。 </para>
/// </summary>
public class Context
{
public CharacterBase attacker;
public CharacterBase target;
public Vector3 hitPosition;
public string spamGroupID;
/// <summary>
/// 可修改的攻击值,订阅者可在结算前调整 damageMultiplier、additionalFlatDamage 等。
/// </summary>
public Value value;
/// <summary>
/// 前置否决标记:设为 true 则跳过伤害结算,攻击完全无效化。
/// </summary>
public bool isImmune;
/// <summary>
/// 前置否决标记:设为 true 则强制中断攻击流程。
/// </summary>
public bool isForcedInterrupt;
public Context(CharacterBase attacker, CharacterBase target,
string spamGroupMainPart, Vector3 hitPosition = default)
{
this.attacker = attacker;
this.target = target;
StringBuilder fullIDBuilder = new StringBuilder();
fullIDBuilder.Append(attacker is null ? "Null" : attacker.GetInstanceID().ToString());
fullIDBuilder.Append("_");
fullIDBuilder.Append(spamGroupMainPart);
fullIDBuilder.Append("_");
fullIDBuilder.Append(target is null ? "Null" : target.GetInstanceID().ToString());
this.spamGroupID = fullIDBuilder.ToString();
this.hitPosition = hitPosition;
}
}
/// <summary>
/// 攻击结果:伤害结算完成后的数据载体,包含结算结果和对原始上下文的引用。
/// <para> 用于 onFinishAttack / onAfterGetAttacked 阶段。 </para>
/// </summary>
public class Result
{
/// <summary>
/// 引用原始攻击上下文,包含攻击参数和前置决策。
/// </summary>
public Context context;
public bool isBlocked;
public bool isDodged;
public bool isReflected;
public bool isMissed;
public bool isEvaded;
public bool causedDeath;
public float shieldBlockedDamage;
public float finalDamage;
// 便捷访问属性,代理到 Context
public CharacterBase attacker => context.attacker;
public CharacterBase target => context.target;
public Vector3 hitPosition => context.hitPosition;
public string spamGroupID => context.spamGroupID;
public Value value
{
get => context.value;
set => context.value = value;
}
/// <summary>
/// 从已有上下文构建结果。用于标准攻击流程Context 阶段完成后包装为 Result。
/// </summary>
public Result(Context context)
{
this.context = context;
}
/// <summary>
/// 直接从参数构建结果用于Buff直接附伤等流程。会自动构建 Context 并关联 Value。
/// </summary>
public Result(Context context, Value value)
{
this.context = context;
this.value = value;
}
}
2025-12-08 05:27:53 -05:00
}
public static class Breakthrough
{
2026-05-23 08:27:50 -04:00
public enum Type
{
None = 0,
Weak = 10,
Medium = 20,
Heavy = 30,
Disruption = 40,
Forced = 50,
Unstoppable = 100 // 不可用于攻击,只能用于防御状态,表示无法被打断
}
public static readonly List<Type> Types = new List<Type>()
2025-12-08 05:27:53 -05:00
{
2026-05-23 08:27:50 -04:00
Type.None,
Type.Weak,
Type.Medium,
Type.Heavy,
Type.Disruption,
Type.Forced,
Type.Unstoppable
2025-12-08 05:27:53 -05:00
};
2026-05-23 08:27:50 -04:00
public static List<Type> GetLowerTypes(Type type)
2025-12-08 05:27:53 -05:00
{
return Types.Where(t => t < type).ToList();
}
2026-05-23 08:27:50 -04:00
public static List<Type> GetEqualOrLowerTypes(Type type)
2026-03-20 12:07:44 -04:00
{
return Types.Where(t => t <= type).ToList();
}
2026-05-23 08:27:50 -04:00
public static List<Type> GetHigherTypes(Type type)
2025-12-08 05:27:53 -05:00
{
return Types.Where(t => t > type).ToList();
}
2026-03-20 12:07:44 -04:00
2026-05-23 08:27:50 -04:00
public static List<Type> GetEqualOrHigherTypes(Type type)
2026-03-20 12:07:44 -04:00
{
return Types.Where(t => t >= type).ToList();
}
2025-11-25 08:19:33 -05:00
}
}