Files
SoulliesOfficial 649b7a5ddc 更新
2026-05-23 08:27:50 -04:00

209 lines
7.0 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 System.Collections.Generic;
using System.Linq;
using System.Text;
using Cielonos.MainGame.Characters;
using SLSUtilities.General;
using SLSUtilities.FunctionalAnimation;
using UnityEngine;
namespace Cielonos.MainGame
{
public static class Attack
{
public enum Type
{
Energy = 1,
Kinetics = 2,
Explosion = 3,
Magic = 4,
Pure = 5,
Blank = 6, // 代表不具有特定攻击类型的伤害,例如持续伤害、反伤等
}
public static string AttackTypeToString(this Type type)
{
return type switch
{
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)
};
}
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;
}
}
}
public static class Breakthrough
{
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>()
{
Type.None,
Type.Weak,
Type.Medium,
Type.Heavy,
Type.Disruption,
Type.Forced,
Type.Unstoppable
};
public static List<Type> GetLowerTypes(Type type)
{
return Types.Where(t => t < type).ToList();
}
public static List<Type> GetEqualOrLowerTypes(Type type)
{
return Types.Where(t => t <= type).ToList();
}
public static List<Type> GetHigherTypes(Type type)
{
return Types.Where(t => t > type).ToList();
}
public static List<Type> GetEqualOrHigherTypes(Type type)
{
return Types.Where(t => t >= type).ToList();
}
}
}