PC-20230316NUNE\Administrator 31db916fec 临时提交
2024-10-18 17:48:59 +08:00

182 lines
6.7 KiB
C#
Raw 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 GAS.General;
using Sirenix.OdinInspector;
using UnityEngine;
namespace GAS.Runtime
{
public enum EffectsDurationPolicy
{
[LabelText("瞬时(Instant)", SdfIconType.LightningCharge)]
Instant = 1,
[LabelText("永久(Infinite)", SdfIconType.Infinity)]
Infinite,
[LabelText("限时(Duration)", SdfIconType.HourglassSplit)]
Duration
}
public enum GameplayEffectSnapshotPolicy
{
[LabelText("配置指定", SdfIconType.UiChecksGrid)]
Specified = 0,
[LabelText("施法者全部", SdfIconType.Magic)]
AllOfSource = 1,
[LabelText("持有者全部", SdfIconType.Person)]
AllOfTarget = 2,
[LabelText("我全都要", SdfIconType.People)]
AllOfBoth = 3,
}
public class GameplayEffect
{
public readonly string GameplayEffectName;
public readonly EffectsDurationPolicy DurationPolicy;
public readonly float Duration; // -1 represents infinite duration
public readonly float Period;
public readonly GameplayEffect PeriodExecution;
public readonly GameplayEffectTagContainer TagContainer;
// Snapshot
public readonly GameplayEffectSnapshotPolicy SnapshotPolicy;
public readonly GameplayEffectSpecifiedSnapshotConfig[] SpecifiedSnapshotConfigs;
// Cues
public readonly GameplayCueInstant[] CueOnExecute;
public readonly GameplayCueInstant[] CueOnRemove;
public readonly GameplayCueInstant[] CueOnAdd;
public readonly GameplayCueInstant[] CueOnActivate;
public readonly GameplayCueInstant[] CueOnDeactivate;
public readonly GameplayCueDurational[] CueDurational;
// Modifiers
public readonly GameplayEffectModifier[] Modifiers;
public readonly ExecutionCalculation[] Executions; // TODO: this should be a list of execution calculations
// Granted Ability
public readonly GrantedAbilityFromEffect[] GrantedAbilities;
//Stacking
public readonly GameplayEffectStacking Stacking;
// TODO: Expiration Effects
public readonly GameplayEffect[] PrematureExpirationEffect;
public readonly GameplayEffect[] RoutineExpirationEffectClasses;
public EntityRef<GameplayEffectSpec> CreateSpec(
AbilitySystemComponent creator,
AbilitySystemComponent owner,
float level = 1,
object userData = null)
{
var spec = JexGasObjectPool.Instance.Fetch<GameplayEffectSpec>();
spec.Awake(this, userData);
spec.Init(creator, owner, level);
return spec;
}
/// <summary>
/// 分离GameplayEffectSpec的实例化过程为实例 + 数据初始化
/// </summary>
/// <returns></returns>
public EntityRef<GameplayEffectSpec> CreateSpec(object userData = null)
{
var spec = JexGasObjectPool.Instance.Fetch<GameplayEffectSpec>();
spec.Awake(this, userData);
return spec;
}
public GameplayEffect(IGameplayEffectData data)
{
if (data is null)
{
throw new Exception($"GE data can't be null!");
}
GameplayEffectName = data.GetDisplayName();
DurationPolicy = data.GetDurationPolicy();
Duration = data.GetDuration();
Period = data.GetPeriod();
SnapshotPolicy = data.GetSnapshotPolicy();
SpecifiedSnapshotConfigs = data.GetSpecifiedSnapshotConfigs();
TagContainer = new GameplayEffectTagContainer(data);
var periodExecutionGe = data.GetPeriodExecution();
#if UNITY_EDITOR
if (periodExecutionGe != null && periodExecutionGe.GetDurationPolicy() != EffectsDurationPolicy.Instant)
{
Debug.LogError($"PeriodExecution of {GameplayEffectName} should be Instant type.");
}
#endif
PeriodExecution = periodExecutionGe != null ? new GameplayEffect(periodExecutionGe) : null;
CueOnExecute = data.GetCueOnExecute();
CueOnRemove = data.GetCueOnRemove();
CueOnAdd = data.GetCueOnAdd();
CueOnActivate = data.GetCueOnActivate();
CueOnDeactivate = data.GetCueOnDeactivate();
CueDurational = data.GetCueDurational();
Modifiers = data.GetModifiers();
Executions = data.GetExecutions();
GrantedAbilities = GetGrantedAbilities(data.GetGrantedAbilities());
Stacking = data.GetStacking();
}
public void Release()
{
PeriodExecution?.Release();
GrantedAbilityFromEffectArrayPool.Recycle(GrantedAbilities);
}
private static readonly ArrayPool<GrantedAbilityFromEffect> GrantedAbilityFromEffectArrayPool = new();
private static GrantedAbilityFromEffect[] GetGrantedAbilities(IReadOnlyCollection<GrantedAbilityConfig> grantedAbilities)
{
if (grantedAbilities.Count == 0)
{
return Array.Empty<GrantedAbilityFromEffect>();
}
var grantedAbilityFromEffects = JexGasObjectPool.Instance.Fetch<List<GrantedAbilityFromEffect>>();
foreach (var grantedAbilityConfig in grantedAbilities)
{
if (grantedAbilityConfig.AbilityAsset != null)
grantedAbilityFromEffects.Add(new GrantedAbilityFromEffect(grantedAbilityConfig));
}
var ret = GrantedAbilityFromEffectArrayPool.Fetch(grantedAbilityFromEffects.Count);
grantedAbilityFromEffects.CopyTo(ret);
grantedAbilityFromEffects.Clear();
JexGasObjectPool.Instance.Recycle(grantedAbilityFromEffects);
return ret;
}
public bool CanApplyTo(IAbilitySystemComponent target)
{
return target.HasAllTags(TagContainer.ApplicationRequiredTags);
}
public bool CanRunning(IAbilitySystemComponent target)
{
return target.HasAllTags(TagContainer.OngoingRequiredTags);
}
public bool IsImmune(IAbilitySystemComponent target)
{
return target.HasAnyTags(TagContainer.ApplicationImmunityTags);
}
public bool StackEqual(GameplayEffect effect)
{
if (Stacking.stackingType == StackingType.None) return false;
if (effect.Stacking.stackingType == StackingType.None) return false;
if (string.IsNullOrEmpty(Stacking.stackingCodeName)) return false;
if (string.IsNullOrEmpty(effect.Stacking.stackingCodeName)) return false;
return Stacking.stackingHashCode == effect.Stacking.stackingHashCode;
}
}
}