G4XIS2NEM4WHRP2775YBCLFDT7JZZS52CMEHY3PA43QSXL45XNDAC QOAVQCDV2MRAPUX62ZLDTUB6AXYSAGEEWIEZIG4TGIQKCLP5T5GAC HUULCHM5GFGZ7GKLCULFHC333LQ3LBI62VKII3YL5O4C5CDGCT4AC 2SLVO3SYIJQOEV2YNSD73BSUSWQNZVROQCGHJCPCDSMCCNKZTQFQC FNS4LRFQNFM4BCB23CYHOWA2N4MG2DEUMNK6D55BQ26TX6OJLIBQC XF52N4U7HWXOF4PDSCR7LCUENLTSXLWEZGS2IJ6562KYI567Z2GAC WKHLLZ3K732M7VJ5KWDSLRWZUARDNDP6ODAXD6SW43CHCT5DX5SAC LAFCS4AAOMBOBURWXRZEDUI4J5QGBP7CJQXIPLKXEDXNBCVE7SLQC RZAMG2H2NY73KZJIV4VXLJHJVSRGJDRWWZJERAI6O7AVDW64JEQQC IDXWT3DH3C3X7PP4VVKUZTCGDALW6NH7KREI4E2VFQVMCBJKDMTAC MHN2B5YZ2Y4G3O7UOZJKFQ3SSP5HTNJCXFKCO3KYY46I2GHM3TIQC I33Z5QD6JHPO7W7G3EHGBIXQABW6ZOC2W4NJP6L5ENDPFRORUFNAC 6UYO5OFJ5JDP3ANPDJ3NG66EQHMTBAAP6K4LPRG3DH34R2S4VZUAC VPXUP5WZTVC3OVD73TNKPK43IAGFXGUGCEJT56JM4IT4APYQXUHAC DTKCWM4J7PFNWAAES3RZHQGDA6PTDNX4TZVOXAKF5V7LCZBI3XUAC OXMN3LHBNH7CWHEZRPSZTN244O3ACTOEKZEAKQNKFXQ7VQSM26YQC L2SE4UCTEU4R7JSHG2J5H6RZPRN4SGBMXK3WCRED2HARX5JEN2AQC R475KN7MR3OG7EBLVNOO7QRIKXDGY2PIDXXV3HW4KBD5QM7B5OJQC IFN4UDLTN7TD26CPONDCRHW4G3DJEXEYV62ZHZC4QD7DKJ76JAEQC CD5FF75KTOBTMVMTMCKMR6F5DFKOF26I5K43ITNHGBI3ZAZHA4RAC HXTSBPAP75A7EC4RKWYQMVPPHPNZFPHUORBZWDHGEB6MPAGI7G7AC 6ET6RCSSOEHFM5GPIG7LDITMTLL2VHNENY2IEHKXQNQJI7VG6EEAC public void AddCurrentModifier<TResource, TUnitType>(TResource resource, Unit<TUnitType> value) where TResource : Resource<TUnitType> where TUnitType : IUnitType {var modifier = new PermanentStatModifier<TUnitType> {Amount = value};
CancellationToken _cancellationToken = CancellationToken.None;
public void AddCapacityModifier<TResource, TUnitType>(TResource resource, Unit<TUnitType> value) where TResource : Resource<TUnitType> where TUnitType : IUnitType {var modifier = new PermanentStatModifier<TUnitType> {Amount = value};resource.AddPermanentCapacityModifier(modifier);
public StatModifierAccessor(CancellationToken cancellationToken) {_cancellationToken = cancellationToken;
public void AddPermanentCapacityModifier(PermanentStatModifier<TUnitType> modifier) {_capacity.AddPermanentModifier(modifier);OnChanged?.Invoke(this, (OnChangeArgs)this);
public void AddCapacityModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {AddModifier(modifier, _capacity, cancelToken);
public void AddPermanentCurrentModifier(PermanentStatModifier<TUnitType> modifier) {_current.AddPermanentModifier(modifier);OnChanged?.Invoke(this, (OnChangeArgs)this);
public void AddCurrentModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {AddModifier(modifier, _current, cancelToken);
if (stat.AddTransientModifier(modifier)) {StartCoroutine(ExpireModifiers(modifier.ExpiryTime, stat));}
cancelToken.Register(() => {OnResourceChanged((ResourceChangeArgs)this);});
Debug.Log($"AddTransientModifier {transform.name}.{GetType().Name}.{typeof(TStatType).Name}");OnChanged?.Invoke(this, (OnChangeArgs)this);}
stat.AddModifier(modifier, cancelToken);
protected IEnumerator ExpireModifiers<TStatType>(double expiryTime, Stat<TStatType> stat)where TStatType : IStatType {var timeToWait = (float)(expiryTime - Time.timeAsDouble);yield return new WaitForSeconds(timeToWait);
Debug.Log($"AddModifier {transform.name}.{GetType().Name}.{typeof(TStatType).Name}");OnResourceChanged((ResourceChangeArgs)this);}
Debug.Log($"Retiring modifiers of {transform.name}.{GetType().Name}.{typeof(TStatType).Name} with expiry < {expiryTime}");stat.Retire(expiryTime);OnChanged?.Invoke(this, (OnChangeArgs)this);
public event EventHandler<ResourceChangeArgs> ResourceChanged;public static explicit operator ResourceChangeArgs(Resource<TUnitType> resource) {return new((int)resource.GetCurrent(), (int)resource.GetCapacity(), resource.transform);
public event EventHandler<OnChangeArgs> OnChanged;public static explicit operator OnChangeArgs(Resource<TUnitType> resource) {return new((int)resource.GetCurrent(), (int)resource.GetCapacity(), resource.transform);
void OnResourceChanged(ResourceChangeArgs e) {ResourceChanged?.Invoke(this, e);
/// <Summary>/// Adds a new permanent modifier to the stat. Taken into account in <paramref name="Base"/> property./// </Summary>public void AddPermanentModifier(PermanentStatModifier<TUnitType> modifier) {Base += modifier.Amount;
public Unit<TUnitType> Modified {get;private set;
/// <Summary>/// Adds a new transient modifier to the stat. Taken into account in <paramref name="Modified"/> and <paramref name="Value"/> properties./// </Summary>/// <returns>/// True when a transient modifier with a new expiry time is inserted./// False when a transient modifier with the same expiry time is already present./// </returns>public bool AddTransientModifier(TransientStatModifier<TUnitType> modifier) {_modifiers.Add(modifier);return _expiry.Add(modifier.ExpiryTime);
public Unit<TUnitType> Total => Base + Modified;public void AddModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {if (cancelToken == CancellationToken.None) {Base += modifier.Amount;}else {AddTransientModifier(modifier, cancelToken);}
public void Retire(double expiryTime) {_modifiers = _modifiers.Where(modifier => modifier.ExpiryTime > expiryTime).ToList();_expiry.Remove(expiryTime);
void AddTransientModifier(StatModifier<TUnitType> modifier, CancellationToken cancelToken) {LinkedListNode<StatModifier<TUnitType>> node = new(modifier);_modifiers.AddFirst(node);Modified += modifier.Amount;cancelToken.Register(() => {_modifiers.Remove(node);Modified -= modifier.Amount;});
fileFormatVersion: 2guid: 75d3569cf2cac3942ace199d3f57185aMonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
using System.Collections;using TagFighter.Effects.Triggers;using TagFighter.Resources;using UnityEngine;namespace TagFighter.Effects{public class PawnCondition : MonoBehaviour{public void Apply() {Debug.Log("Apply a new condition");Debug.Log($"Origin: {Origin} Caster: {Context.Caster} Target: {Context.EffectLocation}");Trigger.Register(this);StartCoroutine(SelfDestruct());}public void OnTrigger() {EffectInput data = new(Context, Context.GetAffectedUnits(), new PermanentStatModifierAccessor());foreach (var effect in Context.EffectsToTrigger) {effect.DelayedAction(data);}Destroy(this);}}}}protected void OnDestroy() {Trigger.UnRegister();}yield return new WaitForSeconds((float)Duration);IEnumerator SelfDestruct() {double _duration;Transform _origin;EffectContext _context;ITrigger _trigger;public double Duration { get => _duration; set => _duration = value; }public Transform Origin { get => _origin; set => _origin = value; }public EffectContext Context { get => _context; set => _context = value; }public ITrigger Trigger { get => _trigger; set => _trigger = value; }
fileFormatVersion: 2guid: 0ed9a99045057be48bae44742b4d2a00folderAsset: yesDefaultImporter:externalObjects: {}userData:assetBundleName:assetBundleVariant:
fileFormatVersion: 2guid: 83af9b93e6ef2a24a964511656caa8e5MonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
using System.Threading;namespace TagFighter.Effects{public class TransientPawnCondition : PawnCondition{CancellationTokenSource _cancellationSource;protected override void SetStatModifier() {_cancellationSource = new();StatModifier = new(_cancellationSource.Token);}protected override void OnDestroySpecific() {_cancellationSource.Cancel();_cancellationSource.Dispose();}}}
fileFormatVersion: 2guid: 75d3569cf2cac3942ace199d3f57185aMonoImporter:externalObjects: {}serializedVersion: 2defaultReferences: []executionOrder: 0icon: {instanceID: 0}userData:assetBundleName:assetBundleVariant:
using TagFighter.Effects.Triggers;using TagFighter.Resources;using UnityEngine;namespace TagFighter.Effects{public class PawnCondition : MonoBehaviour{public Transform Origin { get; set; }public EffectContext Context { get; set; }public ITrigger ApplyTrigger { get; set; }public ITrigger EndTrigger { get; set; }protected StatModifierAccessor StatModifier;public void Apply() {Debug.Log("Apply a new condition");Debug.Log($"Origin: {Origin} Caster: {Context.Caster} Target: {Context.EffectLocation}");SetStatModifier();ApplyTrigger.Register(this);ApplyTrigger.TriggerConditionMet += ApplyTrigger_OnTriggerConditionMet;EndTrigger.Register(this);EndTrigger.TriggerConditionMet += EndTrigger_OnTriggerConditionMet;}protected virtual void SetStatModifier() {StatModifier = StatModifierAccessor.Permanent;}void EndTrigger_OnTriggerConditionMet(object sender, ConditionTriggerArgs e) {Debug.Log($"{nameof(EndTrigger_OnTriggerConditionMet)}");Destroy(this);}void ApplyTrigger_OnTriggerConditionMet(object sender, ConditionTriggerArgs e) {Debug.Log($"{nameof(ApplyTrigger_OnTriggerConditionMet)}");EffectInput data = new(Context, Context.GetAffectedUnits(), StatModifier);foreach (var effect in Context.EffectsToTrigger) {effect.DelayedAction(data);}}protected void OnDestroy() {ApplyTrigger.TriggerConditionMet -= ApplyTrigger_OnTriggerConditionMet;ApplyTrigger.UnRegister();EndTrigger.TriggerConditionMet -= EndTrigger_OnTriggerConditionMet;EndTrigger.UnRegister();OnDestroySpecific();}protected virtual void OnDestroySpecific() {}}}
protected override void Trigger(int current, int before, int threshold) {if (current > before + threshold) {Condition.OnTrigger();}
protected override bool ShouldTrigger(int current, int before, int threshold) {return current > before + threshold;
protected override void Trigger(int current, int before, int threshold) {if (current < before - threshold) {Condition.OnTrigger();}
protected override bool ShouldTrigger(int current, int before, int threshold) {return current < before - threshold;
public class TransientWeave : IImmediateEffect{public ResourceInfoGet<IResourceTypeAccessor, ResourceLocationAccessors.Get.Context> Duration;public void ImmediateAction(EffectContext context, IEffect effect) {EffectInput data = new(context, context.GetAffectedUnits(), new PermanentStatModifierAccessor());if (effect != null) {effect.Apply(data);data.Affected = context.GetAffectedUnits();}/// Currently Duration is Context getter so there's only a single value in the iterator./// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>/// to be included in thisvar duration = Duration.Get(data).First();data.StatAccessor = new TransientStatModifierAccessor(duration);Materialize(data);}void Materialize(EffectInput data) {foreach (var effect in data.Context.EffectsToTrigger) {effect.DelayedAction(data);}data.Context.EffectsToTrigger.Clear();}}[Serializable]
/// Currently Duration is Context getter so there's only a single value in the iterator./// To support get from pawns, requires somekind of aggregation operator from <see cref="IResourceOperator"/>/// to be included in thisvar duration = Duration.Get(data).First();duration = Math.Clamp(duration, MinFrequency, MaxDuration);
var condition = affectedPawn.gameObject.AddComponent<PawnCondition>();condition.Duration = duration;condition.Trigger = Trigger.ShallowCopy();
var condition = IsPermanent ? affectedPawn.gameObject.AddComponent<PawnCondition>() : affectedPawn.gameObject.AddComponent<TransientPawnCondition>();condition.EndTrigger = EndTrigger.ShallowCopy();condition.ApplyTrigger = ApplyTrigger.ShallowCopy();
- rid: 4320157394915295262type: {class: Capacity, ns: TagFighter.Effects.ResourceLocationAccessors.PawnProperties,asm: Assembly-CSharp}
- rid: 4320157623323459588type: {class: OnTimePass, ns: TagFighter.Effects.Triggers, asm: Assembly-CSharp}data:_frequency: 5
- rid: 4320157394915295239type: {class: OnResourceIncrease, ns: TagFighter.Effects.Triggers, asm: Assembly-CSharp}data:Resource:rid: 4320157394915295240Stat:rid: 4320157394915295263Threshold: 0- rid: 4320157394915295240type: {class: Pain, ns: TagFighter.Effects.ResourceTypeAccessors, asm: Assembly-CSharp}