public Spell(CastRoutine cast,
              AlterCastActionOnSetParams alterCastOnSetParams,
              SpellName name,
              School school,
              TargetingType targetingType,
              IconName icon,
              ClassType classType,
              string description,
              bool isCantrip,
              int rangeInSquares,
              int level,
              SpellScaler scaler)
 {
     this.cast = cast;
     this.alterCastOnSetParams = alterCastOnSetParams;
     this.name           = name;
     this.school         = school;
     this.targetingType  = targetingType;
     this.icon           = icon;
     this.classType      = classType;
     this.description    = description;
     this.isCantrip      = isCantrip;
     this.rangeInSquares = rangeInSquares;
     this.level          = level;
     this.scaler         = scaler;
 }
    void Start()
    {
        Spell s = new Spell();

        s.cast = SpellRangedAttack((Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.NECROTIC);

            int numDice = NumDiceFromScaleThresholds(new List <int> {
                5, 11, 17
            }, (cast as Cast).Spell.scaler);
            GaugeDamageRollAndTally(dmg.gauge, numDice.ToString() + "d8");

            AT.Character.Condition.ICondition condition  = new AT.Character.Condition.Necrosis(1, AT.Character.Condition.TickType.TURN_BEGIN, cast.actor.CharSheet);
            AT.Character.Effect.ConditionEffect necrosis = new AT.Character.Effect.ConditionEffect(condition);

            return(new List <AT.Character.Effect.GenericEffect> {
                dmg, necrosis
            });
        }, MissileScript.MissileAnimationName.PLACEHOLDER,
                                   (Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.NECROTIC);

            int numDice = NumDiceFromScaleThresholds(new List <int> {
                5, 11, 17
            }, (cast as Cast).Spell.scaler);
            GaugeDamageRollAndTally(dmg.gauge, numDice.ToString() + "d8", true);
            AT.Character.Condition.ICondition condition  = new AT.Character.Condition.Necrosis(1, AT.Character.Condition.TickType.TURN_BEGIN, cast.actor.CharSheet);
            AT.Character.Effect.ConditionEffect necrosis = new AT.Character.Effect.ConditionEffect(condition);

            return(new List <AT.Character.Effect.GenericEffect> {
                dmg, necrosis
            });
        });

        s.school         = School.NECROMANCY;
        s.name           = SpellName.CHILL_TOUCH;
        s.classType      = ClassType.WIZARD;
        s.targetingType  = TargetingType.SINGLE_ENEMY;
        s.rangeInSquares = 20;
        s.isCantrip      = true;

        s.description = "<i>Chill Touch\nMake a ranged spell attack against an enemy within 120ft.  The enemy suffers 1d8 necrotic damage, and cannot be healed until the start of the caster's next turn.</i>";
        RegisterSpell(s);


        CastRoutine sgCast = SpellTouchAttack((Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.LIGHTNING);

            int numDice = NumDiceFromScaleThresholds(new List <int> {
                5, 11, 17
            }, (cast as Cast).Spell.scaler);
            GaugeDamageRollAndTally(dmg.gauge, numDice.ToString() + "d8");

            AT.Character.Effect.DelegateEffect shocked = new AT.Character.Effect.DelegateEffect((character, spellCast) => {
                target.FirstOccupant.ActorComponent.PreventReactions(spellCast);
            });

            return(new List <AT.Character.Effect.GenericEffect> {
                dmg, shocked
            });
        }, (Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.LIGHTNING);

            int numDice = NumDiceFromScaleThresholds(new List <int> {
                5, 11, 17
            }, (cast as Cast).Spell.scaler);
            GaugeDamageRollAndTally(dmg.gauge, numDice.ToString() + "d8", true);

            AT.Character.Effect.DelegateEffect shocked = new AT.Character.Effect.DelegateEffect((character, spellCast) => {
                target.FirstOccupant.ActorComponent.PreventReactions(spellCast);
            });
            return(new List <AT.Character.Effect.GenericEffect> {
                dmg, shocked
            });
        });
        Spell shockingGrasp = new Spell();

        shockingGrasp.cast           = sgCast;
        shockingGrasp.school         = School.EVOCATION;
        shockingGrasp.name           = SpellName.SHOCKING_GRASP;
        shockingGrasp.classType      = ClassType.WIZARD;
        shockingGrasp.targetingType  = TargetingType.SINGLE_ENEMY;
        shockingGrasp.rangeInSquares = 1;
        shockingGrasp.isCantrip      = true;
        RegisterSpell(shockingGrasp);

        CastRoutine fbCast = SpellRangedAttack((Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.FIRE);


            int numDice = NumDiceFromScaleThresholds(new List <int> {
                5, 11, 17
            }, (cast as Cast).Spell.scaler);
            GaugeDamageRollAndTally(dmg.gauge, numDice.ToString() + "d10");

            return(new List <AT.Character.Effect.GenericEffect> {
                dmg
            });
        }, MissileScript.MissileAnimationName.PLACEHOLDER,
                                               (Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.FIRE);

            int numDice = NumDiceFromScaleThresholds(new List <int> {
                5, 11, 17
            }, (cast as Cast).Spell.scaler);
            GaugeDamageRollAndTally(dmg.gauge, numDice.ToString() + "d10", true);

            return(new List <AT.Character.Effect.GenericEffect> {
                dmg
            });
        });
        Spell firebolt = new Spell();

        firebolt.cast           = fbCast;
        firebolt.school         = School.EVOCATION;
        firebolt.name           = SpellName.FIREBOLT;
        firebolt.classType      = ClassType.WIZARD;
        firebolt.targetingType  = TargetingType.SINGLE_ENEMY;
        firebolt.rangeInSquares = 12;
        firebolt.isCantrip      = true;
        RegisterSpell(firebolt);

        CastRoutine poisonSprayCast = SpellSavingThrow((Action cast, AT.ATTile target) => {
            AT.Character.Effect.Damage dmg = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.POISON);
            dmg.Gauge.ChangeCurrentAndMax(Sheet.DiceRoll(12));

            return(new List <AT.Character.Effect.GenericEffect> {
                dmg
            });
        },
                                                       (Action cast, AT.ATTile target) => {
            //miss effect does nothing
            return(new List <AT.Character.Effect.GenericEffect>());
        }, AbilityType.CONSTITUTION);

        Spell poisonSpray = new Spell();

        poisonSpray.cast           = poisonSprayCast;
        poisonSpray.school         = School.CONJURATION;
        poisonSpray.name           = SpellName.POISON_SPRAY;
        poisonSpray.classType      = ClassType.WIZARD;
        poisonSpray.targetingType  = TargetingType.SINGLE_ENEMY;
        poisonSpray.rangeInSquares = 2;
        poisonSpray.isCantrip      = true;
        RegisterSpell(poisonSpray);

        CastRoutine magicMissileCast = ((caster, cast, targets) => {
            float delay = 0f;             //this doesn't work...  All missils have the same delay
            foreach (AT.ATTile target in targets)
            {
                CharacterCastingAnimation castingAnims = caster.GetComponent <CharacterCastingAnimation>();
                GameObject prefab = MissileAnimationPrefabDispenser.instance.GetAnimationPrefabByName(MissileScript.MissileAnimationName.PLACEHOLDER);
                if (castingAnims != null)
                {
                    castingAnims.SetupAndDoCastAnimation(cast);
                    castingAnims.OneShotSpellRelease((animationInst) => {
                        GameObject copy = Instantiate(prefab);
                        copy.transform.position = caster.transform.position;
                        MissileScript missile = copy.GetComponent <MissileScript>();

                        missile.DelayLaunchAt(target, delay, true);
                        //Safe to not worry about unsubbing, thanks to garbage cleanup
                        missile.OnConnectedWithTarget += (MissileScript self) => {
                            AT.Character.Effect.Damage d = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.FORCE);
                            d.Gauge.ChangeCurrentAndMax(Sheet.DiceRoll(4) + 1);
                            if (target.FirstOccupant != null)
                            {
                                d.ApplyTo(target.FirstOccupant.ActorComponent.CharSheet);
                            }
                            //This assumes only one missile.   Needs a "Checkin of sorts, to conditionally check on finished"
                            cast.CallOnFinished();
                        };
                    });                     //ToBe ATOCIJL
                }
                else
                {
                    GameObject copy = Instantiate(prefab);
                    copy.transform.position = caster.transform.position;
                    MissileScript missile = copy.GetComponent <MissileScript>();
                    missile.DelayLaunchAt(target, delay, true);
                    //Safe to not worry about unsubbing, thanks to garbage cleanup
                    missile.OnConnectedWithTarget += (MissileScript self) => {
                        AT.Character.Effect.Damage d = new AT.Character.Effect.Damage(AT.Character.Effect.DamageType.FORCE);
                        d.Gauge.ChangeCurrentAndMax(Sheet.DiceRoll(4) + 1);
                        if (target.FirstOccupant != null)
                        {
                            d.ApplyTo(target.FirstOccupant.ActorComponent.CharSheet);
                        }
                        //This assumes only one missile.   Needs a "Checkin of sorts, to conditionally check on finished"
                        cast.CallOnFinished();
                    };
                }
                delay += .2f;
            }
        });

        Spell magicMissile = new Spell();

        magicMissile.cast                 = magicMissileCast;
        magicMissile.level                = 1;
        magicMissile.school               = School.EVOCATION;
        magicMissile.name                 = SpellName.MAGIC_MISSILE;
        magicMissile.classType            = ClassType.WIZARD;
        magicMissile.targetingType        = TargetingType.MULTIPLE_ENEMY;
        magicMissile.alterCastOnSetParams = (cast) => {
            cast.NumTargets  = 3;
            cast.NumTargets += magicMissile.scaler.ScaleValue();
        };
        magicMissile.rangeInSquares = 60;

        RegisterSpell(magicMissile);
    }