mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 03:14:47 +00:00
182 lines
6.7 KiB
C#
182 lines
6.7 KiB
C#
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;
|
||
}
|
||
}
|
||
} |