i'm currently working on a small game-engine and i'm kinda stuck on finding the right pattern. First here are some code snippets to understand what i'm trying to achieve :
The Unit : the ability-caster/target ( throw the ability or receive it)
public class Unit { public string Name { get; set; } // Unit name public List<BaseAbility> MyAbilities{get; set;} // abilities that an unit has. }
The Ability :
public abstract class BaseAbility { public string Name {get; set;} // ability name public Unit Caster { get; set; } // ability caster (owner) public List<BaseEffect> EffectList {get; set;} // effects that an ability possess // apply all effects that this ability has on the selected target public virtual void DoAbility(Unit target) { foreach (BaseEffect eff in this.EffectList) { eff.CalculateEffect(target); } } // here we gonna subscribe to some events public abstract void initListeners(); }
The Effect :
public abstract class BaseEffect { public BaseAbility Owner { get; set; } // each effect belong to an ability protected string Name { get; set; } // effect name public EventDispatcher Event { get; set; } // the event to dispatched when this effect is called or used //apply effect on target public virtual void CalculateEffect(Unit target) { // Do Stuffs here like damage and poison etc etc this.Event.DispatchMyEvent(); } }
the Event Dispatcher :
public class EventDispatcher { private object mySender; private EffectEventArgs myArgument; public delegate void EventHandler(object sender, EffectEventArgs argument); public event EventHandler OnMyEvent; public EventDispatcher(object sender, EffectEventArgs argument) { this.mySender = sender; this.myArgument = argument; } public void DispatchMyEvent() { if (OnMyEvent != null) { OnMyEvent(this.mySender, this.myArgument); Debug.WriteLine("event has been raised"); } } }
The Effect Event Arguments :
public class EffectEventArgs : EventArgs { private Unit target; // target affected by effect // not sure if we even need this EffectEventArgs ?! public EffectEventArgs(Unit unit) { this.target = unit; } }
Now i'm gonna create 2 effects and 2 abilities and 2 units for the simulation :
Fire Effect :
public class FireEffect : BaseEffect { public FireEffect(BaseAbility effectOwner) { this.Owner = effectOwner; this.Name = "Fire"; } public override void CalculateEffect(Unit target) { // set the event here (to get the target as argument for the event) this.Event = new EventDispatcher(this.Owner, new EffectEventArgs(target)); base.CalculateEffect(target); } }
Wind Effect : same as fire effect but with a different name and event and apply also a different Effect.
Fire Ball ability :
public class FireBall : BaseAbility { public FireBall(Unit caster) { this.Name = "FireBall"; this.Caster = caster; this.EffectList = new List<BaseEffect>(); this.EffectList.Add(new FireEffect(this)); // fire ball ability has "FireEffect" as effect } public override void DoEffect(Unit target) { base.DoEffect(target); } }
Two Units , let´s say : "Dragon" as Unit => has FireBall (ability) and gonna hit => "shaolin master of the wind " as Unit has a passiveAbility called "WindFury"
WindFury :
public class PassiveAbility : BaseAbility { public PassiveAbility(Unit caster) { this.Name = "WindFury"; this.Caster = caster; this.EffectList = new List<BaseEffect>(); this.EffectList.Add(new WindEffect(this)); this.initListeners(); // subscribe to events (aka add listeners) } public override void DoEffect(Unit target) { base.DoEffect(target); } // THE MAIN PROBLEM : public override void initListeners() { // here i need to subscribe to an event fired from any Instance/Object of type FireEffect so that the targeted Unit // can react to the Unit caster (kind of counter attack) // to resume this , it should follows this logic : // if any Ability has The effect(FireEffect => FireBall for example) was casted // on this Unit thats possess this passive, react to it and counter with (WindEffect) // otherwise put : when our dragon or Ryu or even Sasuke throw an ability with // a FireEffect on our friend "Shaolin" ,he should react to it // and send the attacker flying with a powerfull WindEffect } public void CallBack(object sender, EffectEventArgs e) { BaseAbility ab = (BaseAbility)sender; this.DoEffect(ab.UnitCaster); // hit the unit caster back (revenge) } }
Notice please that we can have so many dragons and Shaolins in this game or simulation and any passive holder (unit) should only react to the attacker (unit) etc.
Edit : (Recap of the main problem)
How to subscribe via PassiveAbility.initListeners() to an event fired from any instance of type FireEffect (an ability that use fireEffect) ???
Many thanks in advance for your support and contribution.
Youness