Skip to content

Instantly share code, notes, and snippets.

@CoffeeVampir3
Last active June 2, 2021 02:52
Show Gist options
  • Save CoffeeVampir3/59319b7e09f9047645e2f18507dd5ca0 to your computer and use it in GitHub Desktop.
Save CoffeeVampir3/59319b7e09f9047645e2f18507dd5ca0 to your computer and use it in GitHub Desktop.
Overcomplicated Command Thingy
public static class EffectsSystem
{
private static readonly Dictionary<Type, List<IEffectRule>> allRules = new();
public static void RegisterRule<T>(this IEffectRule<T> rule, Type ruleType)
where T : IEffect
{
if(!allRules.TryGetValue(ruleType, out var specificRules))
{
specificRules = new List<IEffectRule>();
allRules.Add(ruleType, specificRules);
}
specificRules.Add(rule);
Debug.Log("Command: " + ruleType + " was registered by " + rule);
}
public static void UnregisterRule<T>(this IEffectRule<T> rule, Type ruleType)
where T : IEffect
{
if(!allRules.TryGetValue(ruleType, out var rules))
return;
if(rules.Contains(rule))
rules.Remove(rule);
Debug.Log("Command: " + ruleType + " was unregistered by " + rule);
}
public static bool SystemCheck(this IEffect effect)
=> ValidateWithMutation(effect.Clone());
private static bool ValidateWithMutation(IEffect clonedEffect)
{
if (!allRules.TryGetValue(clonedEffect.GetType(), out var rules))
return clonedEffect.Validate();
for (var i = rules.Count - 1; i >= 0; i--)
{
var rule = rules[i];
clonedEffect.TryMutate(rule);
}
return clonedEffect.Validate();
}
public static void SystemKickoff(this IEffect effect)
=> KickoffWithMutations(effect.Clone());
private static void KickoffWithMutations(IEffect clonedEffect)
{
if (!allRules.TryGetValue(clonedEffect.GetType(), out var rules))
{
clonedEffect.Run();
return;
}
for (var i = rules.Count - 1; i >= 0; i--)
{
var rule = rules[i];
if (clonedEffect.TryMutate(rule) && rule is IOnRuleUsedReceiver limitedRule)
limitedRule.OnRuleUsed();
}
clonedEffect.Run();
}
}
[Serializable]
public class ChangeStatEffect : IEffect
{
public int Id => 0;
public ScriptableStat targetStat;
public int changeAmount = 0;
[OdinSerialize]
public IEffectTarget EffectTarget;
private StatBlock targetStatBlock;
private int actualChange = 0;
IEffect IEffect.Clone()
{
return new ChangeStatEffect
{
targetStat = targetStat,
changeAmount = changeAmount,
EffectTarget = EffectTarget
};
}
void IEffect.Run()
{
targetStatBlock ??= EffectTarget.CurrentTarget.GetComponent<StatBlock>();
var stat = targetStatBlock[targetStat];
if (stat == null)
return;
stat.Current += changeAmount;
actualChange = stat.GetLastActualChange();
}
void IEffect.Undo()
{
var stat = targetStatBlock[targetStat];
if (stat == null)
return;
stat.Current -= actualChange;
actualChange = -actualChange;
}
bool IEffect.TryMutate(IEffectRule mutator) => mutator.TryRule(this);
bool IEffect.Validate()
{
targetStatBlock ??= EffectTarget.CurrentTarget.GetComponent<StatBlock>();
var stat = targetStatBlock[targetStat];
if (stat == null)
return false;
return (stat.Current + changeAmount) >= stat.min;
}
}
public class ChangeStatRule : MonoBehaviour,
IEffectRule<ChangeStatEffect>, IOnRuleUsedReceiver
{
public int changeMutation = 0;
public int limitedUses = 3;
bool IEffectRule<ChangeStatEffect>.RunIfValid(ChangeStatEffect cmd)
{
if (!(cmd.EffectTarget.CurrentTarget == gameObject))
return false;
Debug.Log("Mutation: " + this.name + " applied to command " + cmd);
cmd.changeAmount += changeMutation;
return true;
}
void IOnRuleUsedReceiver.OnRuleUsed()
{
limitedUses--;
if (limitedUses > 0) return;
Destroy(this);
}
public void OnEnable() => this.RegisterRule(typeof(ChangeStatEffect));
public void OnDisable() => this.UnregisterRule(typeof(ChangeStatEffect));
}
public interface IEffectRule<in Command> : IEffectRule
where Command : IEffect
{
/// <summary>
/// Tries to run this specific rule.
/// </summary>
/// <returns>Returns true if the rule ran on this command.</returns>
bool RunIfValid(Command cmd);
}
public interface IEffectRule
{
}
public static class IEffectRuleHelper
{
public static bool TryRule<T>(this IEffectRule mutator, T cmd)
where T : IEffect
=> mutator is IEffectRule<T> cscMutator && cscMutator.RunIfValid(cmd);
}
public interface IEffect
{
int Id { get; }
bool Validate();
void Run();
void Undo();
bool TryMutate(IEffectRule mutator);
IEffect Clone();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment