• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

GUI Spell System addon: FormOfSpells

Status
Not open for further replies.
GUI Spell System done by @Bribe is a good system which automates many things spells normaly would do.
But there could be automated more i think:
I wanted to use GUI Spell System recently to crate an spellpack. they worked fine, as expected, but after the 3. one I started to realize that i do alot of copy and paste of logic, which somehow feels unpleasent. I mean each spell had an oncast action an on Loop Action ..., but the code somehow was pretty alike, if you ignore the different names and all that i talk about the actions overall.
The different names created additional work, cause simple copy paste of same logic did not work you had to change the names.
Then i wanted to do a altered clone, which took a lot of time.
(open variable Editor: search the variable, copy paste each one, rename it and make sure you don't forget one.)
Copy all Triggers the orginal Spell had, change the names inside :( so much work.

After that i started to think more globally (yeah like blizzard).
Then i started to create this.

From my story there result 2 problems: Cloneability of abilities and repeated Spell logic, both can be solved in my opioion.

The First Problem Cloneability is actually the more easy one to solve but also the more annoyung one. Solving takes an little bit different kind of defining and Coding.

Simple Average Spell Config Trigger:
  • ConfigSpell
    • Ereignisse
      • Map initialization
    • Bedingungen
    • Aktionen
      • Set SpellAbility = Some Spell
      • Set SpellAoE[1] = 200.00
      • Set SpellAoE[2] = 200.00
      • Set SpellAoE[3] = 200.00
      • Set SpellDamage[1] = 100.00
      • Set SpellDamage[2] = 200.00
      • Set SpellDamage[3] = 300.00
The average Spell would clean leaks which i do for simplity not.
  • Spell effect
    • Events
      • Unit - A unit Startet the effect ...
    • Conditions
      • (Ability being cast) Equal SpellAbility
    • Actions
      • Set SpellLevel = (Level of (Ability being cast) for (Triggering unit))
      • Einheitengruppe - Pick every unit in (Units within SpellAoE[SpellLevel] of (Target point of ability being cast) and do (Actions)
        • Schleifen - Aktionen
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal True
              • ((Picked unit) is a Struct) Equal False
              • ((Picked unit) belongs to an enemy of (Triggering player)) Equal True
            • Then - Actions
              • Unit - Cause (Triggering unit) to damage (Picked unit), dealing SpellDamage[SpellLevel] damage of attack type Spell and damage type Magic
            • Else - Actions
As you might see the significant index of this Spell's logic is SpellLevel. Currently cloning this spell would force you to coping all triggers of this spell, duplicate the variables SpellDamage/AoE and replace inside the code of the new triggers the references to the Spells data.

Much work for the user.

But it can be done better, without much extra work.

A Solution is to save all clones in the same arrays, to simple down the creation we save the current EnterIndex and save all data relative to this Enter Index.

Additional to avoid insering all clones into the effect Trigger we create a Trigger which handles calling the right one.

at the end of the Config trigger we calc the enter index for the next clone.
  • Spell Config
    • Ereignisse
      • Map initialization
    • Bedingungen
    • Aktionen
      • Set Spell_Ability = Aas-Schwarm
      • Set Spell_Levels = 3
      • -------- Save Damage of Level 1 --------
      • Set Spell_AoE[(Spell_IndexEnter + 1)] = 200.00
      • -------- Save Damage of Level 2 --------
      • Set Spell_AoE[(Spell_IndexEnter + 2)] = 200.00
      • -------- Save Damage of Level 3 --------
      • Set Spell_AoE[(Spell_IndexEnter + 3)] = 200.00
      • Set Spell_Damage[(Spell_IndexEnter + 1)] = 100.00
      • Set Spell_Damage[(Spell_IndexEnter + 2)] = 200.00
      • Set Spell_Damage[(Spell_IndexEnter + 3)] = 300.00
      • -------- Convert Ability to integer --------
      • Custom script: set udg_Spell_AbilityId = udg_Spell_Ability
      • -------- Which Trigger is executed for this Spell --------
      • -------- saving the trigger could be skipped, if you let the user inser all clones Abilities into the effect Trigger by himself --------
      • Hashtabelle - Save Handle OfSpell effect <gen> as 0 of Spell_AbilityId in SpellHash
      • -------- Remember this Abilities Index --------
      • -------- This allows easy acces to the data without looping all create clones --------
      • Hashtabelle - Save Spell_IndexEnter as 1 of Spell_AbilityId in SpellHash
      • -------- Prepare Index for next Clone --------
      • Set Spell_IndexEnter = (Spell_IndexEnter + Spell_Levels)
      • Set Spell_IndexEnter = (Spell_IndexEnter + 1)
      • -------- Spell hash should be created first. --------
By adding an new Trigger handling the executions of the code we even get rid of for the user to inser the Clones into the effect Trigger.
By using for example GUI Spell System you already have the feature: executing the correct trigger built in in which you only would have to load the correct data index.
  • Starts any Spelleffect
    • Events
      • Unit - A unit Startet the effect ...
    • Conditions
    • Actions
      • Set Spell_Ability = (Ability being cast)
      • -------- Convert Ability to integer --------
      • Custom script: set udg_Spell_AbilityId = udg_Spell_Ability
      • -------- Load Ability BaseIndex and Increase it by Level of spoken spell --------
      • -------- This gives us the correct index of the used data. --------
      • Set Spell_Level = ((Load 1 of Spell_AbilityId from SpellHash) + (Level of (Ability being cast) for (Triggering unit)))
      • -------- Start the spells logic --------
      • Trigger - Run (Load 0 of Spell_AbilityId in SpellHash) (ignoring conditions)
The Effect remains untoched but now has nether Events nor Conditions, cause it is called by the new Trigger handling that "Starts any Spelleffect":
  • Spell effect
    • Ereignisse
    • Bedingungen
    • Aktionen
      • -------- This gives us the correct index of the used data, if you use GUI Spell System you need to call it here. --------
      • Set Spell_Level = ((Load 1 of Spell_AbilityId from SpellHash) + (Level of (Ability being cast) for (Triggering unit)))
      • Einheitengruppe - Pick every unit in (Units within Spell_AoE[Spell_Level] of (Target point of ability being cast) matching (((Matching unit) is alive) Gleich True)) and do (Actions)
        • Schleifen - Aktionen
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Condition
              • ((Picked unit) is alive)
              • not ((Picked unit) is a Struct)
              • ((Picked unit) belongs to an enemy of (Triggering player))
            • Then - Action
              • Unit - Cause (Triggering unit) to damage (Picked unit), dealing Spell_Damage[Spell_Level] damage of attack type Spell and damage type Magic
            • Else - Action


Problem 2 is less annoying to be honest and its solution takes a lot of abstraction..., so one might think its not worth it.

and that takes us to FormOfSpells, which tries to solve both Problems in one: This is still a prototype it works but might have many flaws.
So any kind of feedback or suggestion would be welcome.

What is Form of Spells:

Form of Spells is an addon for GUI Spell System, which automates Spell code flow and reduces the Spells specific data and Logic into the Spells Config.

But how a Spell then uses different Actions?

Inside the Config you choose the logic your Spell will run, by selecting Triggers doing what you want. The addon contains some basic Actions (this post does not contain all, it only shows how they work in the concept); it is recommented to create this Triggers as common as possible to allows reusage.
For Filters and conditions its the same, but here you don't fill the action block, you fill the condition block.
To use this Addon at all you have to think in small Jobs working together to achive the wanted result.

Triggers/Filters you can currently choose

FormOfSpells_BreakCondition - Runs in BuiltUp and Default loop
FormOfSpells_OnBreak - Runs when Break Conditions are true
FormOfSpells_BuiltFinishAction - Runs as soon built is finished
FormOfSpells_CastAction - this will be called at "starts the effect of.."
FormOfSpells_CostTrigger - Payments

FormOfSpells_MainAction - Runs in normal Loop when DelaycountDown is counted
FormOfSpells_Update - runs in every BuiltUp and Normal Loop

Supported by the default Damage Actions
FormOfSpells_Damage1Mod - Runs before Damage1 is done,
FormOfSpells_Damage2Mod
FormOfSpells_DamageFilter - Defines if Damage1 or Damage2 is used
FormOfSpells_DamageOverallMod - Runs only considering the caster

But what about data?


By using kind of 2d Arrays and using same variables for all Spells.
most spells take similar data anyway.
Does that not take alot of indexes?
Yes, it does but you won't reach the 8192 limit normally
even on 300 custom abilities with 4 Levels you still would only use 1500 indexes (by counting Ability / Lvl1 / Lvl2 / LVL3 / Lvl4 )

Example of such a Config: They can turn out pretty big depending on the spell.
Short explanition we save Data on current SpellGeneration-Index + Level and remember the AbilityId in the Spellhash to later easly load it.
FormOfSpells_Levels is used to calc the generation index for the next spell, which is done at the end of an Config.
Each Variable should be like this:
FormOfSpells_ManaCosts[(FormOfSpells_Index + 1)]
Name [Ability Generation Index + Level]

Spells become easy clone- and copyable configered this way, simply cause you won't have to change names etc., only logic and data in the config.

Currently Some Names are bad/uncommon.


Data which is 0/null does not have to be included actually.
  • Fire Circle Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Spell__Ability = Fire Circle
      • Custom script: set udg_AbilityId = udg_Spell__Ability
      • Hashtabelle - Save FormOfSpells_Index as 0 of AbilityId in Spell__Hash
      • -------- Spells Level Amount --------
      • Set FormOfSpells_Levels = 4
      • -------- Variables with the name FormOfSpells_x are System variables and should not be written inside the configs --------
      • -------- Data which is 0/null does not have to be included. --------
      • -------- Fire Circle Data --------
      • For each (Integer A) from 1 to FormOfSpells_Levels, do (Actions)
        • Schleifen - Actions
          • Set FormOfSpells_SFX[(FormOfSpells_Index + (Integer A))] = war3mapImported\s_RunningFlame Aura.mdx
          • Set FormOfSpells_SFXScaling[(FormOfSpells_Index + (Integer A))] = 1.00
          • Set FormOfSpells_SFXHit[(FormOfSpells_Index + (Integer A))] = Abilities\Spells\Other\ImmolationRed\ImmolationRedDamage.mdl
          • Set FormOfSpells_SFXHitOffset[(FormOfSpells_Index + (Integer A))] = chest
          • Set FormOfSpells_SFXHitDur[(FormOfSpells_Index + (Integer A))] = 1.25
          • -------- Clone Hit1 --------
          • Set FormOfSpells_SFXHit2[(FormOfSpells_Index + (Integer A))] = FormOfSpells_SFXHit[(FormOfSpells_Index + (Integer A))]
          • Set FormOfSpells_SFXHit2Offset[(FormOfSpells_Index + (Integer A))] = FormOfSpells_SFXHitOffset[(FormOfSpells_Index + (Integer A))]
          • Set FormOfSpells_SFXHit2Dur[(FormOfSpells_Index + (Integer A))] = FormOfSpells_SFXHitDur[(FormOfSpells_Index + (Integer A))]
      • -------- Manacosts are paid each Execution; Therefore MpS = Costs / Time --------
      • Set FormOfSpells_CostTrigger[(FormOfSpells_Index + 1)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_CostTrigger[(FormOfSpells_Index + 2)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_CostTrigger[(FormOfSpells_Index + 3)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_CostTrigger[(FormOfSpells_Index + 4)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 1)] = 2.50
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 2)] = 2.50
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 3)] = 2.50
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 4)] = 2.50
      • -------- If costs would drain it under this limit it will break --------
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 1)] = 20.00
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 2)] = 20.00
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 3)] = 20.00
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 4)] = 20.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 1)] = 200.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 2)] = 200.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 3)] = 250.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 4)] = 250.00
      • -------- If distance between Caster and Circle is bigger breaks on next intervale --------
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 1)] = 900.00
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 2)] = 900.00
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 3)] = 1100.00
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 4)] = 1100.00
      • -------- Conditions used to break up the Spell instantly --------
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 1)] = FoS Break Dead v Mana v Range <gen>
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 2)] = FoS Break Dead v Mana v Range <gen>
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 3)] = FoS Break Dead v Mana v Range <gen>
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 4)] = FoS Break Dead v Mana v Range <gen>
      • For each (Integer A) from 1 to FormOfSpells_Levels, do (Actions)
        • Schleifen - Actions
          • Set FormOfSpells_AttackType[(FormOfSpells_Index + (Integer A))] = Zaubersprüche
          • Set FormOfSpells_DamageType[(FormOfSpells_Index + (Integer A))] = Magie
      • -------- Beaware that DpS is Damage / Spell_Time --------
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 1)] = 17.50
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 2)] = 25.00
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 3)] = 40.00
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 4)] = 30.00
      • -------- Damage Structures take, default half --------
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 1)] = 8.75
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 2)] = 12.50
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 3)] = 20.00
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 4)] = 15.00
      • -------- If the conditions of the Choosen Trigger are true DamageSec is dealt. --------
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 1)] = FoS Action Filter Structure v Mech <gen>
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 2)] = FoS Action Filter Structure v Mech <gen>
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 3)] = FoS Action Filter Structure v Mech <gen>
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 4)] = FoS Action Filter Structure v Mech <gen>
      • -------- Overall Mod is damage mod from Caster only, For example Spellpower buffs etc --------
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 1)] = FoS Overall Mod Spellpower <gen>
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 2)] = FoS Overall Mod Spellpower <gen>
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 3)] = FoS Overall Mod Spellpower <gen>
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 4)] = FoS Overall Mod Spellpower <gen>
      • -------- How many targets are allowed to be hit in one intervale; 0 = unlimited --------
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 1)] = 0
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 2)] = 0
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 3)] = 0
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 4)] = 0
      • -------- The BuiltTime should be divedable without rest by choosen SpellTime. --------
      • -------- Duiring Builtup Only Update and BreakCondition are runed --------
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 1)] = 1.00
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 2)] = 1.00
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 3)] = 1.00
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 4)] = 1.00
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 1)] = 0.10
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 2)] = 0.10
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 3)] = 0.10
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 4)] = 0.10
      • -------- Action which fires as soon Spell Effects started --------
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 1)] = FoS Create AoE Indikator Distance Tag <gen>
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 2)] = FoS Create AoE Indikator Distance Tag <gen>
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 3)] = FoS Create AoE Indikator Distance Tag <gen>
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 4)] = FoS Create AoE Indikator Distance Tag <gen>
      • -------- Effect after an BuiltUp/Delay Time --------
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 1)] = FoS Create SFX <gen>
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 2)] = FoS Create SFX <gen>
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 3)] = FoS Create SFX <gen>
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 4)] = FoS Create SFX <gen>
      • -------- Duration after Building up --------
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 1)] = 120.00
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 2)] = 120.00
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 3)] = 120.00
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 4)] = 120.00
      • -------- Intervale after Buildingup --------
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 1)] = 0.50
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 2)] = 0.50
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 3)] = 0.50
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 4)] = 0.50
      • -------- ActionDelay allows you to use fast updates/Break calls (intervales), and slow costs/Action runs; only evey x time of intervale. --------
      • -------- 0 = always; 1 = every 2.time 2 = every 3.time .... --------
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 1)] = 0
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 2)] = 0
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 3)] = 0
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 4)] = 0
      • -------- How long it takes to kill the Grafic Container; aka play the death animation of SFX 0 --------
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 1)] = 1.50
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 2)] = 1.50
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 3)] = 1.50
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 4)] = 1.50
      • -------- This happens when the spell breaks. --------
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 1)] = FoS CleanOff Default <gen>
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 2)] = FoS CleanOff Default <gen>
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 3)] = FoS CleanOff Default <gen>
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 4)] = FoS CleanOff Default <gen>
      • -------- This happens every loop in the update Trigger.. --------
      • Set FormOfSpells_Update[(FormOfSpells_Index + 1)] = FoS Update Distance AoE Visibility <gen>
      • Set FormOfSpells_Update[(FormOfSpells_Index + 2)] = FoS Update Distance AoE Visibility <gen>
      • Set FormOfSpells_Update[(FormOfSpells_Index + 3)] = FoS Update Distance AoE Visibility <gen>
      • Set FormOfSpells_Update[(FormOfSpells_Index + 4)] = FoS Update Distance AoE Visibility <gen>
      • -------- Default owner matter if you set affects allies and foes. --------
      • Set FormOfSpells_DefaultOwner[FormOfSpells_Index] = Neutral feindlich
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 1)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 2)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 3)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 4)] = FoS Action Group Damage <gen>
      • -------- Can units be affected by multiple Fire Circles at the same time ? --------
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 1)] = False
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 2)] = False
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 3)] = False
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 4)] = True
      • -------- How long an unit stays unaffected if unstacking mod. --------
      • -------- Default is autocalced; the next intervale will affected it again. --------
      • For each (Integer A) from 1 to FormOfSpells_Levels, do (Actions)
        • Schleifen - Actions
          • Set FormOfSpells_RememberDur[(FormOfSpells_Index + (Integer A))] = (FormOfSpells_Intervale[(FormOfSpells_Index + (Integer A))] - 0.01)
      • -------- Which Group is used to calc stacking. --------
      • -------- Choose Spell__TargetGroup to use spell instance stacking checks and Use Spell__TargetGroup =true --------
      • Set FormOfSpells_Container[(FormOfSpells_Index + 1)] = CircleOfFire_Affected
      • Set FormOfSpells_Container[(FormOfSpells_Index + 2)] = CircleOfFire_Affected
      • Set FormOfSpells_Container[(FormOfSpells_Index + 3)] = CircleOfFire_Affected
      • Set FormOfSpells_Container[(FormOfSpells_Index + 4)] = CircleOfFire_Affected
      • Set Spell__UseTargetGroup = False
      • -------- An additional way to filter units., Currently Default CircleOfElements --------
      • Set Spell__Trigger_InRangeFilter = FoS Circle Default check <gen>
      • -------- Define Targets --------
      • Set Spell__Filter_AllowEnemy = True
      • Set Spell__Filter_AllowLiving = True
      • Set Spell__Filter_AllowHero = True
      • Set Spell__Filter_AllowNonHero = True
      • Set Spell__Filter_AllowAlly = False
      • Set Spell__Filter_AllowDead = False
      • Set Spell__Filter_AllowFlying = False
      • Set Spell__Filter_AllowMechanical = True
      • Set Spell__Filter_AllowStructure = True
      • Set Spell__Filter_AllowMagicImmune = False
      • -------- Keep it untouched in most cases --------
      • Set Spell__Duration = 99999.00
      • Set Spell__DurationPerLevel = 0.00
      • Set Spell__Time = 0.10
      • -------- ----- --------
      • -------- Don't touch below --------
      • -------- ----- --------
      • Custom script: set udg_FormOfSpells_HitBoth[udg_FormOfSpells_Index] = udg_Spell__Filter_AllowAlly and udg_Spell__Filter_AllowEnemy
      • Set Spell__Trigger_OnEffect = FormOfSpells Cast <gen>
      • Trigger - Run Spell System <gen> (ignoring conditions)
      • -------- Calc Index for next spell --------
      • Set FormOfSpells_Index = (FormOfSpells_Index + FormOfSpells_Levels)
      • Set FormOfSpells_Index = (FormOfSpells_Index + 1)




Form Of Spell Config change.jpg Fos Flow.jpg
BuiltUp.png FoS Loop.png


Currently most core stuff is in GUI.

This is the default OnEffect each Spell using this will execute.
  • FormOfSpells Cast
    • Events
    • Conditions
    • Actions
      • Custom script: set udg_AbilityId = GetSpellAbilityId()
      • -------- Save Used Data Index and Ability Index for this Spell Instance --------
      • Set FormOfSpells_x_IndexAbility_A[Spell__Index] = (Load 0 of AbilityId from Spell__Hash)
      • Set FormOfSpells_x_IndexAbility = FormOfSpells_x_IndexAbility_A[Spell__Index]
      • Set FormOfSpells_x_IndexData_A[Spell__Index] = (FormOfSpells_x_IndexAbility + Spell__Level)
      • Set FormOfSpells_x_IndexData = FormOfSpells_x_IndexData_A[Spell__Index]
      • -------- Reset Counters --------
      • Set FormOfSpells_x_ExecutionCount[Spell__Index] = 0
      • Set FormOfSpells_x_LoopCount[Spell__Index] = 0
      • -------- Fill DelayCounter --------
      • Set FormOfSpells_x_DelayCountDown[Spell__Index] = FormOfSpells_ActionDelay[FormOfSpells_x_IndexData]
      • -------- Create Grafic Container --------
      • Unit - Create 1 Spell__DummyType for Neutral extra at Spell__TargetPoint facing 270 degrees
      • Set FormOfSpells_x_SpellsDummy[Spell__Index] = (Last created unit)
        • -------- If there is nether Built Duration nor Duration the spell is instant. Save all that work. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • FormOfSpells_Duration[FormOfSpells_x_IndexData] Greater as 0.00
              • FormOfSpells_BuiltUpDuration[FormOfSpells_x_IndexData] Greater as 0.00
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FormOfSpells_BuiltUpDuration[FormOfSpells_x_IndexData] Smaller Equal 0.00
            • Then - Actions
              • Set Spell__Time = FormOfSpells_Intervale[FormOfSpells_x_IndexData]
              • Set Spell__Duration = FormOfSpells_Duration[FormOfSpells_x_IndexData]
              • Set Spell__Trigger_OnLoop = FormOfSpells Loop <gen>
            • Else - Actions
              • Set FormOfSpells_RemainingBuilt[Spell__Index] = FormOfSpells_BuiltUpDuration[FormOfSpells_x_IndexData]
              • Set Spell__Time = FormOfSpells_BuiltUpIntervale[FormOfSpells_x_IndexData]
              • Set Spell__Duration = (FormOfSpells_BuiltUpDuration[FormOfSpells_x_IndexData] + 1.00)
              • Set Spell__Trigger_OnLoop = FormOfSpells BuiltUP <gen>
          • Set Spell__StartDuration = True
        • Else - Actions
      • -------- Istant Action on cast --------
      • Trigger - Run FormOfSpells_CastAction[FormOfSpells_x_IndexData] (ignoring conditions)
This dynamicly calls the choosen triggers.
and does counting, this Counts should be pretty useful for spell creation.
FormOfSpells_x_DelayCountDown do action/cost only every x - loop
FormOfSpells_x_ExecutionCount How often action was executed
FormOfSpells_x_LoopCount Counts each loop
  • FormOfSpells Loop
    • Events
    • Conditions
    • Actions
      • Set FormOfSpells_x_LoopCount[Spell__Index] = (FormOfSpells_x_LoopCount[Spell__Index] + 1)
      • -------- Easy acces Data/Ability Index, --------
      • Set FormOfSpells_x_IndexData = FormOfSpells_x_IndexData_A[Spell__Index]
      • Set FormOfSpells_x_IndexAbility = FormOfSpells_x_IndexAbility_A[Spell__Index]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Evaluate FormOfSpells_BreakCondition[FormOfSpells_x_IndexData] conditions) Equal True
        • Then - Actions
          • Trigger - Run FormOfSpells_OnBreak[FormOfSpells_x_IndexData] (ignoring conditions)
          • Skip remaining actions
        • Else - Actions
      • Trigger - Run FormOfSpells_Update[FormOfSpells_x_IndexData] (ignoring conditions)
      • -------- Only do Actions, Costs ever x time of intervale if that is wanted. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_x_DelayCountDown[Spell__Index] Equal 0
        • Then - Actions
          • Set FormOfSpells_x_ExecutionCount[Spell__Index] = (FormOfSpells_x_ExecutionCount[Spell__Index] + 1)
          • Trigger - Run FormOfSpells_PreMain[FormOfSpells_x_IndexData] (ignoring conditions)
          • Trigger - Run FormOfSpells_MainAction[FormOfSpells_x_IndexData] (ignoring conditions)
          • -------- Remember for Stacking? --------
          • Trigger - Run FormOfSpells_SecondAction[FormOfSpells_x_IndexData] (ignoring conditions)
            • -------- Reload Countdown from Data --------
            • Set FormOfSpells_x_DelayCountDown[Spell__Index] = FormOfSpells_ActionDelay[FormOfSpells_x_IndexData]
        • Else - Actions
          • Set FormOfSpells_x_DelayCountDown[Spell__Index] = (FormOfSpells_x_DelayCountDown[Spell__Index] - 1)
The Dynamic Built UP Trigger
  • FormOfSpells BuiltUP
    • Events
    • Conditions
    • Actions
      • Set FormOfSpells_x_IndexData = FormOfSpells_x_IndexData_A[Spell__Index]
      • Set FormOfSpells_x_IndexAbility = FormOfSpells_x_IndexAbility_A[Spell__Index]
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Evaluate FormOfSpells_BreakCondition[FormOfSpells_x_IndexData] conditions) Equal True
        • Then - Actions
          • Trigger - Run FormOfSpells_OnBreak[FormOfSpells_x_IndexData] (ignoring conditions)
          • Skip remaining actions
        • Else - Actions
      • Trigger - Run FormOfSpells_Update[FormOfSpells_x_IndexData] (ignoring conditions)
      • Set FormOfSpells_RemainingBuilt[Spell__Index] = (FormOfSpells_RemainingBuilt[Spell__Index] - FormOfSpells_BuiltUpIntervale[FormOfSpells_x_IndexData])
      • -------- Built up is finished? --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_RemainingBuilt[Spell__Index] Smaller Equal 0.00
        • Then - Actions
          • -------- Builtup expired now start the effect, if there is duration. --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FormOfSpells_Duration[FormOfSpells_x_IndexData] Greater as 0.00
            • Then - Actions
              • Set Spell__Time = FormOfSpells_Intervale[FormOfSpells_x_IndexData]
              • Set Spell__Duration = FormOfSpells_Duration[FormOfSpells_x_IndexData]
              • Set Spell__Trigger_OnLoop = FormOfSpells Loop <gen>
            • Else - Actions
              • -------- Spare Time --------
              • Set Spell__Time = 999.00
              • Set Spell__Duration = 0.10
              • Set Spell__Trigger_OnLoop = NOTRIGGER
              • -------- Might choose differently in the BuiltFinAction --------
          • Trigger - Run FormOfSpells_BuiltFinishAction[FormOfSpells_x_IndexData] (ignoring conditions)
        • Else - Actions
  • FormOfSpells Remember
    • Events
    • Conditions
      • not FormOfSpells_DamageStacks[FormOfSpells_x_IndexData]
      • not (FormOfSpells_x_Affected is empty)
    • Actions
      • Custom script: local group g = CreateGroup()
      • Custom script: call GroupAddGroup ( udg_FormOfSpells_x_Affected, g)
      • -------- Save in Spell_i_TargetGroup ? --------
      • Custom script: if udg_FormOfSpells_Container[udg_FormOfSpells_x_IndexData] == udg_Spell__TargetGroup then
      • Custom script: call RememberGroup( g, udg_Spell_i_TargetGroup[udg_Spell__Index], udg_FormOfSpells_RememberDur[udg_FormOfSpells_x_IndexData])
      • Custom script: else
      • Custom script: call RememberGroup( g, udg_FormOfSpells_Container[udg_FormOfSpells_x_IndexData], udg_FormOfSpells_RememberDur[udg_FormOfSpells_x_IndexData])
      • Custom script: endif
      • Custom script: set g = null
JASS:
//This Functions starts an annonym timer to add a group to an other group for an specific amount of time.

function ForgetGroup takes nothing returns nothing
   local timer t = GetExpiredTimer()
   local integer tId = GetHandleId(t)
   local group temp = LoadGroupHandle(udg_Spell__Hash,tId,0)
   local group container = LoadGroupHandle(udg_Spell__Hash,tId,1)
   call GroupRemoveGroup (temp, container)
   call FlushChildHashtable(udg_Spell__Hash, tId)
   call DestroyTimer(t)
   call DestroyGroup(temp)
   set t = null
   set temp = null
   set container = null
endfunction
//Into should be a global group which is not destroyed
//While temp is a group which will be destroyed after duration ends.
function RememberGroup takes group temp, group into, real dur returns nothing
   local timer t
   //Is there duration? Is there a contained Unit?
   if dur > 0 and FirstOfGroup(temp) != null then
       set t = CreateTimer()
       call GroupAddGroup (temp , into)
       call SaveGroupHandle(udg_Spell__Hash,GetHandleId(t),0,temp)
       call SaveGroupHandle(udg_Spell__Hash,GetHandleId(t),1,into)
       call TimerStart(t, dur, false, function ForgetGroup)
   set t = null
   endif
endfunction
//===========================================================================
function InitTrig_FormOfSpells_Not_Twice takes nothing returns nothing
endfunction
This is how i suggest an simple Spell for on BuiltUPFinish or OnCast trigger without any intervalic behaviour. it is included in the map
  • FoS Simple Spell
    • Ereignisse
    • Bedingungen
    • Aktionen
      • -------- Easy access to datas, avoid inside code " index[index] " --------
      • Set FormOfSpells_x_IndexData = FormOfSpells_x_IndexData_A[Spell__Index]
      • Set FormOfSpells_x_IndexAbility = FormOfSpells_x_IndexAbility_A[Spell__Index]
      • -------- Use this as OnCast- /BuiltFinishAction --------
      • Trigger - Run FormOfSpells_PreMain[FormOfSpells_x_IndexData] (ignoring conditions)
      • Trigger - Run FormOfSpells_MainAction[FormOfSpells_x_IndexData] (ignoring conditions)
      • Trigger - Run FormOfSpells_SecondAction[FormOfSpells_x_IndexData] (ignoring conditions)
        • Trigger - Run FormOfSpells_OnBreak[FormOfSpells_x_IndexData] (ignoring conditions)

To the Action Triggers.
They are generally pretty small.
This is a MainAction its a simple one still pretty common:

  • FoS Action Group Damage
    • Events
    • Conditions
    • Actions
      • Trigger - Run FoS Load Damage <gen> (ignoring conditions)
      • Trigger - Run FormOfSpells_Targeting[FormOfSpells_x_IndexData] (ignoring conditions)
      • Einheitengruppe - Pick every unit in FormOfSpells_x_Affected and do (Actions)
        • Schleifen - Actions
          • Set Spell__InRangeUnit = (Picked unit)
          • Trigger - Run FoS deal damage <gen> (ignoring conditions)
As you might see it calls helper functions to do the job and keeping small.
To use this you have to think in actions working together.

Helper functions avoid to code stuff dozen times:
This one allows to calc damage for this damage doing
  • FoS Load Damage
    • Events
    • Conditions
    • Actions
      • Set FormOfSpells_x_Damage[1] = FormOfSpells_Damage[FormOfSpells_x_IndexData]
      • Set FormOfSpells_x_Damage[2] = FormOfSpells_Damage2[FormOfSpells_x_IndexData]
      • Trigger - Run FormOfSpells_DamageOverallMod[FormOfSpells_x_IndexData] (ignoring conditions)
      • -------- Backups --------
      • Set FormOfSpells_x_Damage[3] = FormOfSpells_x_Damage[1]
      • Set FormOfSpells_x_Damage[4] = FormOfSpells_x_Damage[2]
  • FoS Overall Mod Spellpower
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__Caster has an item of type Ring of superiority) Equal True
        • Then - Actions
          • Set FormOfSpells_x_Damage[1] = (FormOfSpells_x_Damage[1] x 1.25)
          • Set FormOfSpells_x_Damage[2] = (FormOfSpells_x_Damage[2] x 1.25)
        • Else - Actions
Targeting allow abstract choosing of TargetLocation, it is used by default group Damage triggers.
They load all units in range into FormOfSpells_x_Affected

Caster/Target/Spells Dummie are pretty much alike.
  • FoS Targeting Target
    • Events
    • Conditions
    • Actions
      • Einheitengruppe - Remove all units from FormOfSpells_x_Affected
      • Custom script: call MoveLocation(udg_FormOfSpells_x_DamagePoint, GetLocationX(udg_Spell__TargetPoint), GetLocationY(udg_Spell__TargetPoint))
      • -------- Get Group --------
      • Set Spell__InRangePoint = FormOfSpells_x_DamagePoint
      • Set Spell__InRangeMax = FormOfSpells_OnceMaxTarget[FormOfSpells_x_IndexData]
      • Set Spell__InRange = FormOfSpells_AoE[FormOfSpells_x_IndexData]
      • Einheitengruppe - Add all units of Spell__InRangeGroup to FormOfSpells_x_Affected
New feature of V2 is Actors which have an own Targeting System.
During Spell you create additional dummies which you add to the Actors of this spell instance and than can use in Target Actors to still using the default damaging triggers.
  • FoS Targeting Actors
    • Ereignisse
    • Bedingungen
    • Aktionen
      • Einheitengruppe - Remove all units from FormOfSpells_x_Affected
      • Einheitengruppe - Pick every unit in FormOfSpells_x_Actors[Spell__Index] and do (Actions)
        • Schleifen - Aktionen
          • Custom script: call MoveLocation(udg_FormOfSpells_x_DamagePoint, GetUnitX(GetEnumUnit()), GetUnitY(GetEnumUnit()) )
          • -------- Get Group --------
          • Set Spell__InRangePoint = FormOfSpells_x_DamagePoint
          • Set Spell__InRangeMax = FormOfSpells_OnceMaxTarget[FormOfSpells_x_IndexData]
          • Set Spell__InRange = FormOfSpells_AoE[FormOfSpells_x_IndexData]
          • Einheitengruppe - Add all units of Spell__InRangeGroup to FormOfSpells_x_Affected

  • FoS deal damage
    • Events
    • Conditions
    • Actions
      • -------- ---- --------
      • -------- Used by default Actions to deal damage --------
      • -------- ---- --------
      • Set Spell__InRangePoint = (Position of Spell__InRangeUnit)
      • -------- Use Secondary Damage? --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Evaluate FormOfSpells_DamageFilter[FormOfSpells_x_IndexData] conditions) Equal True
        • Then - Actions
          • Trigger - Run FormOfSpells_Damage2Mod[FormOfSpells_x_IndexData] (ignoring conditions)
          • -------- Damage or Heal? --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FormOfSpells_x_Damage[2] Greater as 0.00
            • Then - Actions
              • Spezialeffekt - Create a special effect attached to the FormOfSpells_SFXHit2Offset[FormOfSpells_x_IndexData] of Spell__InRangeUnit using FormOfSpells_SFXHit2[FormOfSpells_x_IndexData]
              • Einheit - Cause Spell__Caster to damage Spell__InRangeUnit, dealing FormOfSpells_x_Damage[2] damage of attack type FormOfSpells_AttackType[FormOfSpells_x_IndexData] and damage type FormOfSpells_DamageType[FormOfSpells_x_IndexData]
            • Else - Actions
              • -------- Do not heal unhurt units --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Leben of Spell__InRangeUnit) Kleiner als (Max. Leben of Spell__InRangeUnit)
                • Then - Actions
                  • Spezialeffekt - Create a special effect attached to the FormOfSpells_SFXHit2Offset[FormOfSpells_x_IndexData] of Spell__InRangeUnit using FormOfSpells_SFXHit2[FormOfSpells_x_IndexData]
                  • Einheit - Set life of Spell__InRangeUnit to ((Leben of Spell__InRangeUnit) - FormOfSpells_x_Damage[2])
                • Else - Actions
          • Custom script: call TimedGrafic( bj_lastCreatedEffect , udg_FormOfSpells_SFXHit2Dur[udg_FormOfSpells_x_IndexData] )
        • Else - Actions
          • Trigger - Run FormOfSpells_Damage1Mod[FormOfSpells_x_IndexData] (ignoring conditions)
          • -------- Damage or Heal? --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FormOfSpells_x_Damage[1] Greater as 0.00
            • Then - Actions
              • Spezialeffekt - Create a special effect attached to the FormOfSpells_SFXHitOffset[FormOfSpells_x_IndexData] of Spell__InRangeUnit using FormOfSpells_SFXHit[FormOfSpells_x_IndexData]
              • Einheit - Cause Spell__Caster to damage Spell__InRangeUnit, dealing FormOfSpells_x_Damage[1] damage of attack type FormOfSpells_AttackType[FormOfSpells_x_IndexData] and damage type FormOfSpells_DamageType[FormOfSpells_x_IndexData]
            • Else - Actions
              • -------- Do not heal unhurt units --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Leben of Spell__InRangeUnit) Kleiner als (Max. Leben of Spell__InRangeUnit)
                • Then - Actions
                  • Spezialeffekt - Create a special effect attached to the FormOfSpells_SFXHitOffset[FormOfSpells_x_IndexData] of Spell__InRangeUnit using FormOfSpells_SFXHit[FormOfSpells_x_IndexData]
                  • Einheit - Set life of Spell__InRangeUnit to ((Leben of Spell__InRangeUnit) - FormOfSpells_x_Damage[1])
                • Else - Actions
          • Custom script: call TimedGrafic( bj_lastCreatedEffect , udg_FormOfSpells_SFXHitDur[udg_FormOfSpells_x_IndexData] )
      • Custom script: call RemoveLocation(udg_Spell__InRangePoint)
      • -------- Load Backups --------
      • Set FormOfSpells_x_Damage[1] = FormOfSpells_x_Damage[3]
      • Set FormOfSpells_x_Damage[2] = FormOfSpells_x_Damage[4]

How Filters:

We are in GUI Spell System environment and we use therefore Spell_InRangeUnit
Spell_InRangePoint is outside of damage Step the position of the actor/damage center.
Inside damage Step its the damaging units position.
  • FoS Action Filter Structure v Mech
    • Events
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Spell__InRangeUnit is Ein Struct) Equal True
          • (Spell__InRangeUnit is Mechanisch) Equal True
    • Actions
Break Condition for Channeling Spells
  • FoS Break Channel v Mana
    • Events
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • Spell__Channeling Equal False
          • (Mana of Spell__Caster) Smaller Equal FormOfSpells_ManaCosts[FormOfSpells_x_IndexData]
    • Actions
      • -------- If the conditions return true the Spell ends instantly --------


This is still a prototype it works but might have many flaws.
So any kind of feedback or suggestion would be welcome, i think from this state on, it should be discussed public.
Is it useful? What could be done better?...

V2)
Insert FormOfSpells_Targeting array config,
allows abstract targetpoint setting
Current Ones are
  • Targeting Caster
  • Targeting Target
  • Targeting Dummy
  • Targeting Actors

Insert FormOfSpells_x_DamagePoint non Array:
it is moved around in targeting it should not be destroyed.
Its meant to be the center of the dmg Area currently not really good solved for actor based stuff but for others it works.​
Insert FormOfSpells_x_Affected is a non array variable
containing all targets found inside the targeting trigger, which is now used by default damaging Actions.​
Insert FormOfSpells_x_Actors - UnitGroup
, this group is generated the first time an Spell Index runs.
it is meant to be used, if an spell contains multiple Dummies doing something.
The default Spells Dummie is not part of it and has an own variable.​
Replaced Hardcoed RememberGroup Action with FormOfSpells_SeconAction.
To allow doing other stuff after the main action​
CostTrigger was renamed to preMainAction
Not every spell has constant costs, but might have use for an action before the MainAction which is not update.​

FoS Deal Damage:
now uses the Location Spell__InRangePoint to access the current Units Position instead of Spell__InRangeUnitPos to use for DamageFilters.​


Suggestions Collection

Show the change between one spell using this and without it.
Change Name.
Preload Subspells/ effect paths.
Feedback Collection

Not Intuitive
Hard to get used to.
Might be a good aid for GUI coding
Edit: There is currently a bug with the main sfx not beeing displayed. solved there were a bug with the imports beeing invalide, including the vexorian Dummy Unit Model which holds the grafic.
Edit: Added Images showing the Form of Spells Code Flow.
 

Attachments

  • FormOfSpells V2.w3x
    134.4 KB · Views: 63
Last edited:
I'm liking some of the approaches you have, but I don't understand much of it. The API would take a lot of getting used to, in so much that unless you were the one who wrote it, it won't be intuitive.

I like how you have a spell damage processor, but this part would have a much better home as an accessory to Damage Engine.

Ideally to showcase what this system does, what it improves, you should do a comparison showing how the code would look with and without the system.

It seems to have more features than I was expecting. I thought this might simplify things based on your description and the code was much longer than i expected.
 
How (What) about SpellClass (because the idea takes the form of a class or struct)?
Spell System already uses Struct allocation to handle different spell indices and types.

What I'd really like to know is how Tasyen's spells looked like with Spell System VS how they look now.

It seems the approach here is to assume spell level scaling is the same for all spells but allows other spells to otherwise break the rules by overriding them.

I get around the messy arrays per spell level by using a base + level * value which is one line instead of 4, and the base/value can be changed in the Config trigger.

What are the fundamentals of this system? What is the primary benefit? When would someone use this over just Spell System (what does it give them in addition)?

Based on what I've seen, you might want to do an "essentials" version of not just to serve as what the most basic building blocks of the system are. Right now, it's hard for me to grasp your initial process. Maybe if I understood the road you took i can understand the current state of this.

Edit: and if you want to incorporate Special Effects you should preload their string path. And make sure you're preloading any ability IDs you didn't send through Spell System Config <gen>
 
with base + level * perLevel one does only support linear scaling.
setting it with [abilityinde + level] one has free choice over the scaling.
(yes it tooks more space and often one wants only linear scaling or 1 levelup).

i completly admit that it is often completely overkill to have always set each level specific:
Set FormOfSpells_MainAction[(FormOfSpells_Index + 1)] = FoS Action Group Damage <gen>
Set FormOfSpells_MainAction[(FormOfSpells_Index + 2)] = FoS Action Group Damage <gen>
Set FormOfSpells_MainAction[(FormOfSpells_Index + 3)] = FoS Action Group Damage <gen>
Set FormOfSpells_MainAction[(FormOfSpells_Index + 4)] = FoS Action Group Damage <gen>​
but haven't yet an good general solution for that and per level only works for numbers and linear.


Form of spell's idea is like MyPad said to mimic object Editor's Spell section but using trigges -> beeing more complex, but the end result should be that one only picks FoS contained actions/Filters to get spells doing what one wants without having to touch the action/filter code and still allowing adding new mechanics.

I still got some older versions of the spells shown in Form of spells. this are kind of development steps:

This is a old state in which only 1 spell was done, but there already was the idea implemented to allow one to change dmg on cast depending on situations.
  • Fire Circle Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Skill Duration/Intervall --------
      • Set Spell__Ability = Fire Circle (Neutral feindlich)
      • Set Spell__Duration = 120.00
      • Set Spell__DurationPerLevel = 0.00
      • Set Spell__Time = 0.50
      • -------- Define Targets --------
      • Set Spell__Filter_AllowEnemy = True
      • Set Spell__Filter_AllowLiving = True
      • Set Spell__Filter_AllowHero = True
      • Set Spell__Filter_AllowNonHero = True
      • Set Spell__Filter_AllowAlly = False
      • Set Spell__Filter_AllowDead = False
      • Set Spell__Filter_AllowFlying = False
      • Set Spell__Filter_AllowMechanical = True
      • Set Spell__Filter_AllowStructure = True
      • -------- Fire Circle Data --------
      • -------- Grafic 0 = constant one should have an "stand"-animation; 1 displayed on hit --------
      • Set CircleOfFire_SFX[0] = war3mapImported\s_RunningFlame Aura.mdx
      • Set CircleOfFire_SFX[1] = Abilities\Spells\Other\ImmolationRed\ImmolationRedDamage.mdl
      • -------- Manacosts are paid each Intervale; Therefore MpS = Costs / Time --------
      • Set CircleOfFire_ManaCosts[1] = 2.50
      • Set CircleOfFire_ManaCosts[2] = 2.50
      • Set CircleOfFire_ManaCosts[3] = 2.50
      • Set CircleOfFire_ManaCosts[4] = 2.50
      • -------- If costs would drain it under this limit it will break --------
      • Set CircleOfFire_ManaBreakLimit[1] = 20.00
      • Set CircleOfFire_ManaBreakLimit[2] = 20.00
      • Set CircleOfFire_ManaBreakLimit[3] = 0.00
      • Set CircleOfFire_ManaBreakLimit[4] = 0.00
      • Set CircleOfFire_AoE[1] = 200.00
      • Set CircleOfFire_AoE[2] = 200.00
      • Set CircleOfFire_AoE[3] = 250.00
      • Set CircleOfFire_AoE[4] = 250.00
      • -------- Beaware that DpS is Damage / Spell_Time --------
      • Set CircleOfFire_Damage[1] = 17.50
      • Set CircleOfFire_Damage[2] = 25.00
      • Set CircleOfFire_Damage[3] = 37.50
      • Set CircleOfFire_Damage[4] = 25.00
      • -------- Damage Structures take, default half --------
      • Set CircleOfFire_StructMulti[1] = 0.50
      • Set CircleOfFire_StructMulti[2] = 0.50
      • Set CircleOfFire_StructMulti[3] = 0.50
      • Set CircleOfFire_StructMulti[4] = 0.50
      • -------- If distance between Caster and Circle is bigger breaks on next intervale --------
      • Set CircleOfFire_RangeBreak[1] = 900.00
      • Set CircleOfFire_RangeBreak[2] = 900.00
      • Set CircleOfFire_RangeBreak[3] = 1200.00
      • Set CircleOfFire_RangeBreak[4] = 1100.00
      • -------- Does the Circle stop if the caster dies --------
      • Set CircleOfFire_DeathBreak[1] = True
      • Set CircleOfFire_DeathBreak[2] = True
      • Set CircleOfFire_DeathBreak[3] = True
      • Set CircleOfFire_DeathBreak[4] = True
      • -------- Can units be affected by multiple Fire Circles at the same time ? --------
      • Set CircleOfFire_DamageStacks[1] = False
      • Set CircleOfFire_DamageStacks[2] = False
      • Set CircleOfFire_DamageStacks[3] = False
      • Set CircleOfFire_DamageStacks[4] = True
      • -------- Use TextTag, Aoe Indikator --------
      • Set CircleOfFire_ShowDistance = True
      • Set CircleOfFire_UseAoEIndikator = True
      • -------- Effect Stuff --------
      • Set Spell__Trigger_OnEffect = Fire Circle cast <gen>
      • Set Spell__Trigger_OnLoop = Fire Circle Loop <gen>
      • Set Spell__Trigger_InRangeFilter = Fire Circle check <gen>
      • Custom script: set udg_CircleOfFire_HitBoth = udg_Spell__Filter_AllowAlly and udg_Spell__Filter_AllowEnemy
      • Trigger - Run Spell System <gen> (ignoring conditions)
      • -------- Auto generate --------
      • Set CircleOfFire_Affected = CircleOfFire_Affected
  • Fire Circle check
    • Events
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Spell__InRangeUnit is in CircleOfFire_Affected) Equal False
          • CircleOfFire_DamageStacks[Spell__Level] Equal True
    • Actions
  • Fire Circle cast
    • Events
    • Conditions
    • Actions
      • -------- Makes it easy to add additional damage mods --------
      • Set Spell_TObject_Damage[Spell__Index] = CircleOfFire_Damage[Spell__Level]
      • -------- Inser here dmg mods, if you want them, an example is the disabled If else. --------
      • -------- If the spell is spoken by a Hero deal 25% more dmg. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__Caster is Ein Held) Equal True
        • Then - Actions
          • Set Spell_TObject_Damage[Spell__Index] = (Spell_TObject_Damage[Spell__Index] x 1.25)
        • Else - Actions
      • Set Spell_TObject_DamageSec[Spell__Index] = (Spell_TObject_Damage[Spell__Index] x CircleOfFire_StructMulti[Spell__Level])
      • Set Spell_TObject_Mana[Spell__Index] = CircleOfFire_ManaCosts[Spell__Level]
      • Set Spell_TObject_SFXPath[Spell__Index] = CircleOfFire_SFX[1]
      • -------- ---- --------
      • -------- Spells stuff begins --------
      • -------- ---- --------
      • Set Spell__StartDuration = True
      • Unit - Create 1 Spell__DummyType for Neutral extra at Spell__TargetPoint facing Vorgabe für Gebäude-Ausrichtung degrees
      • Set Spell_i_Target[Spell__Index] = (Last created unit)
      • Spezialeffekt - Create a special effect attached to the origin of (Last created unit) using CircleOfFire_SFX[0]
      • Animation - Change (Last created unit)'s size to ((CircleOfFire_AoE[Spell__Level] x 1.00)%, (CircleOfFire_AoE[Spell__Level] x 1.00)%, (CircleOfFire_AoE[Spell__Level] x 1.00)%) of its original size
      • Hashtabelle - Save Handle Of(Last created special effect) as 0 of Spell__Index in Spell__Hash
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CircleOfFire_UseAoEIndikator Equal True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CircleOfFire_HitBoth Equal True
            • Then - Actions
              • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_CircleOfFire_AoE[udg_Spell__Level], Player(PLAYER_NEUTRAL_AGGRESSIVE) )
            • Else - Actions
              • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_CircleOfFire_AoE[udg_Spell__Level], udg_Spell__CasterOwner)
          • Hashtabelle - Save Handle Of(Last created image) as 1 of Spell__Index in Spell__Hash
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CircleOfFire_ShowDistance Equal True
        • Then - Actions
          • Schwebender Text - Create floating text that reads (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) at Spell__TargetPoint with Z offset 120.00, using font size 14.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Custom script: if GetLocalPlayer() == udg_Spell__CasterOwner then
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , true)
          • Custom script: else
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , false)
          • Custom script: endif
          • Hashtabelle - Save Handle Of(Last created floating text) as 2 of Spell__Index in Spell__Hash
        • Else - Actions
  • Fire Circle Loop
    • Events
    • Conditions
    • Actions
      • Custom script: local group g
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • ((Mana of Spell__Caster) - Spell_TObject_Mana[Spell__Index]) smaller as CircleOfFire_ManaBreakLimit[Spell__Level]
              • (Distance between Spell__CastPoint and Spell__TargetPoint) greater as CircleOfFire_RangeBreak[Spell__Level]
              • And - All (Conditions) are true
                • Conditions
                  • (Spell__Caster is dead) Equal True
                  • CircleOfFire_DeathBreak[Spell__Level] Equal True
        • Then - Actions
          • Set Spell__Duration = 0.00
          • Spezialeffekt - Destroy (Load 0 of Spell__Index in Spell__Hash)
          • Unit - Add a 3.00 second Standard expiration timer to Spell__Target
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CircleOfFire_UseAoEIndikator Equal True
            • Then - Actions
              • Image - Destroy (Load 1 of Spell__Index in Spell__Hash)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CircleOfFire_ShowDistance Equal True
            • Then - Actions
              • Schwebender Text - Destroy (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.)
            • Else - Actions
          • Skip remaining actions
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CircleOfFire_ShowDistance Equal True
            • Then - Actions
              • Schwebender Text - Change text of (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.) to (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) using font size 14.00
            • Else - Actions
          • Unit - Set mana of Spell__Caster to ((Mana of Spell__Caster) - Spell_TObject_Mana[Spell__Index])
      • -------- Update Visibilty for indikator --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CircleOfFire_UseAoEIndikator Equal True
        • Then - Actions
          • Custom script: set udg_Player = GetLocalPlayer()
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Spell__TargetPoint is visible to Player) Equal True
            • Then - Actions
              • Image - Zeigen (Load 1 of Spell__Index in Spell__Hash)
            • Else - Actions
              • Image - Verbergen (Load 1 of Spell__Index in Spell__Hash)
        • Else - Actions
      • Set Spell__InRangePoint = Spell__TargetPoint
      • Set Spell__InRange = CircleOfFire_AoE[Spell__Level]
      • Einheitengruppe - Pick every unit in Spell__InRangeGroup and do (Actions)
        • Schleifen - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is a structure) Equal True
            • Then - Actions
              • Unit - Cause Spell__Caster to damage (Picked unit), dealing Spell_TObject_DamageSec[Spell__Index] damage of attack type spell and damage type magic
            • Else - Actions
              • Unit - Cause Spell__Caster to damage (Picked unit), dealing Spell_TObject_Damage[Spell__Index] damage of attack type spell and damage type magic
          • Spezialeffekt - Create a special effect attached to the chest of (Picked unit) using Spell_TObject_SFXPath[Spell__Index]
          • Custom script: call TimedGrafic( bj_lastCreatedEffect , 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CircleOfFire_DamageStacks[Spell__Level] Equal False
          • (Spell__InRangeGroup is empty) Equal False
        • Then - Actions
          • Custom script: set g = CreateGroup()
          • For each (Integer A) from 1 to Spell__InRangeCount, do (Actions)
            • Schleifen - Actions
              • Custom script: call GroupAddUnit (g, udg_Spell__InRangeUnits[bj_forLoopAIndex])
          • Custom script: call FireCircleRemember( g, udg_Spell_i_LastTime[udg_Spell__Index] - 0.03)
          • Custom script: set g = null
        • Else - Actions

in this version I created TObject Variables which took over spells specific array data into spell instance data.
the Config had no change but used different variables for each spell.
This contains only 2 spells cause 3./4. spells are not needed to understand what this version does.
  • Fire Circle Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Skill Duration/Intervall --------
      • Set Spell__Ability = Fire Circle (Neutral feindlich)
      • Set Spell__Duration = 120.00
      • Set Spell__DurationPerLevel = 0.00
      • Set Spell__Time = 0.10
      • -------- Define Targets --------
      • Set Spell__Filter_AllowEnemy = True
      • Set Spell__Filter_AllowLiving = True
      • Set Spell__Filter_AllowHero = True
      • Set Spell__Filter_AllowNonHero = True
      • Set Spell__Filter_AllowAlly = False
      • Set Spell__Filter_AllowDead = False
      • Set Spell__Filter_AllowFlying = False
      • Set Spell__Filter_AllowMechanical = True
      • Set Spell__Filter_AllowStructure = True
      • Set Spell__Filter_AllowMagicImmune = False
      • -------- Fire Circle Data --------
      • -------- Grafic 0 = constant one should have an "stand"-animation; 1 displayed on hit --------
      • -------- If you change the Models you might need to change the multiplier in "cast" and change the attachment point in "group action" --------
      • Set CircleOfFire_SFX[0] = war3mapImported\s_RunningFlame Aura.mdx
      • Set CircleOfFire_SFX[1] = Abilities\Spells\Other\ImmolationRed\ImmolationRedDamage.mdl
      • -------- Manacosts are paid each Intervale; Therefore MpS = Costs / Time --------
      • Set CircleOfFire_ManaCosts[1] = 2.50
      • Set CircleOfFire_ManaCosts[2] = 2.50
      • Set CircleOfFire_ManaCosts[3] = 2.50
      • Set CircleOfFire_ManaCosts[4] = 2.50
      • -------- If costs would drain it under this limit it will break --------
      • Set CircleOfFire_ManaBreakLimit[1] = 20.00
      • Set CircleOfFire_ManaBreakLimit[2] = 20.00
      • Set CircleOfFire_ManaBreakLimit[3] = 0.00
      • Set CircleOfFire_ManaBreakLimit[4] = 0.00
      • Set CircleOfFire_AoE[1] = 200.00
      • Set CircleOfFire_AoE[2] = 200.00
      • Set CircleOfFire_AoE[3] = 250.00
      • Set CircleOfFire_AoE[4] = 250.00
      • -------- Beaware that DpS is Damage / Spell_Time --------
      • Set CircleOfFire_Damage[1] = 17.50
      • Set CircleOfFire_Damage[2] = 25.00
      • Set CircleOfFire_Damage[3] = 37.50
      • Set CircleOfFire_Damage[4] = 25.00
      • -------- Damage Structures take, default half --------
      • Set CircleOfFire_StructMulti[1] = 0.50
      • Set CircleOfFire_StructMulti[2] = 0.50
      • Set CircleOfFire_StructMulti[3] = 0.50
      • Set CircleOfFire_StructMulti[4] = 0.50
      • -------- If distance between Caster and Circle is bigger breaks on next intervale --------
      • Set CircleOfFire_RangeBreak[1] = 900.00
      • Set CircleOfFire_RangeBreak[2] = 900.00
      • Set CircleOfFire_RangeBreak[3] = 1200.00
      • Set CircleOfFire_RangeBreak[4] = 1100.00
      • -------- Does the Circle stop if the caster dies --------
      • Set CircleOfFire_DeathBreak[1] = True
      • Set CircleOfFire_DeathBreak[2] = True
      • Set CircleOfFire_DeathBreak[3] = True
      • Set CircleOfFire_DeathBreak[4] = True
      • -------- Can units be affected by multiple Fire Circles at the same time ? --------
      • Set CircleOfFire_DamageStacks[1] = False
      • Set CircleOfFire_DamageStacks[2] = False
      • Set CircleOfFire_DamageStacks[3] = False
      • Set CircleOfFire_DamageStacks[4] = True
      • -------- The BuiltTime should be divedable without rest by choosen SpellTime. --------
      • -------- Duiring Builtup Only SFX 0, AoEIndikator and range check is applied --------
      • Set CircleOfFire_BuiltUpTime[1] = 1.00
      • Set CircleOfFire_BuiltUpTime[2] = 1.00
      • Set CircleOfFire_BuiltUpTime[3] = 1.00
      • Set CircleOfFire_BuiltUpTime[4] = 1.00
      • -------- Intervale after Buildingup --------
      • Set CircleOfFire_Intervale[1] = 0.50
      • Set CircleOfFire_Intervale[2] = 0.50
      • Set CircleOfFire_Intervale[3] = 0.50
      • Set CircleOfFire_Intervale[4] = 0.50
      • -------- Use TextTag, Aoe Indikator --------
      • Set CircleOfFire_ShowDistance = True
      • Set CircleOfFire_UseAoEIndikator = True
      • -------- Effect Stuff --------
      • Set Spell__Trigger_OnEffect = Fire Circle cast <gen>
      • Set Spell__Trigger_OnLoop = Circle BuiltUP <gen>
      • Set Spell__Trigger_InRangeFilter = Circle check <gen>
      • Custom script: set udg_CircleOfFire_HitBoth = udg_Spell__Filter_AllowAlly and udg_Spell__Filter_AllowEnemy
      • Trigger - Run Spell System <gen> (ignoring conditions)
  • Fire Circle cast
    • Events
    • Conditions
    • Actions
      • -------- Load Spell specific data into general data --------
      • -------- Makes it easier to add additional mods --------
      • -------- And Reusing the Loop for custom ones --------
      • -------- Depends on the model used, Models bigger than 100 take a number below 1 --------
      • Set ModelScaleMulti = 1.00
      • Set Spell_TObject_SFX = CircleOfFire_SFX[0]
      • Set Spell_TObject_Damage[Spell__Index] = CircleOfFire_Damage[Spell__Level]
      • -------- Inser here dmg mods, if you want them, an example is the disabled If else. --------
      • -------- If the spell is spoken by a Hero deal 25% more dmg. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__Caster is Ein Held) Equal True
        • Then - Actions
          • Set Spell_TObject_Damage[Spell__Index] = (Spell_TObject_Damage[Spell__Index] x 1.25)
        • Else - Actions
      • Set Spell_TObject_DamageSec[Spell__Index] = (Spell_TObject_Damage[Spell__Index] x CircleOfFire_StructMulti[Spell__Level])
      • Set Spell_TObject_AoEDamage[Spell__Index] = CircleOfFire_AoE[Spell__Level]
      • Set Spell_TObject_AoESec[Spell__Index] = CircleOfFire_RangeBreak[Spell__Level]
      • Set Spell_TObject_Mana[Spell__Index] = CircleOfFire_ManaCosts[Spell__Level]
      • Set Spell_TObject_ManaSec[Spell__Index] = CircleOfFire_ManaBreakLimit[Spell__Level]
      • Set Spell_TObject_DeathBreak[Spell__Index] = CircleOfFire_DeathBreak[Spell__Level]
      • Set Spell_TObject_GroupAction[Spell__Index] = Fire Circle Group Action <gen>
      • Set Spell_TObject_ContainerGroup[Spell__Index] = CircleOfFire_Affected
      • Set Spell_TObject_ShowDistance[Spell__Index] = CircleOfFire_ShowDistance
      • Set Spell_TObject_UseAoEIndikator[Spell__Index] = CircleOfFire_UseAoEIndikator
      • Set Spell_TObject_BuiltUpTime[Spell__Index] = CircleOfFire_BuiltUpTime[Spell__Level]
      • Set Spell_TObject_IntervaleEffect[Spell__Index] = CircleOfFire_Intervale[Spell__Level]
      • -------- ---- --------
      • -------- Spells stuff begins --------
      • -------- ---- --------
      • Set Spell__StartDuration = True
      • Unit - Create 1 Spell__DummyType for Neutral extra at Spell__TargetPoint facing Vorgabe für Gebäude-Ausrichtung degrees
      • Set Spell_i_Target[Spell__Index] = (Last created unit)
      • Spezialeffekt - Create a special effect attached to the origin of (Last created unit) using Spell_TObject_SFX
      • Animation - Change (Last created unit)'s size to ((Spell_TObject_AoEDamage[Spell__Index] x ModelScaleMulti)%, (Spell_TObject_AoEDamage[Spell__Index] x ModelScaleMulti)%, (Spell_TObject_AoEDamage[Spell__Index] x ModelScaleMulti)%) of its original size
      • Hashtabelle - Save Handle Of(Last created special effect) as 0 of Spell__Index in Spell__Hash
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_UseAoEIndikator[Spell__Index] Equal True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CircleOfFire_HitBoth Equal True
            • Then - Actions
              • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_Spell_TObject_AoEDamage[udg_Spell__Index], Player(PLAYER_NEUTRAL_AGGRESSIVE) )
            • Else - Actions
              • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_Spell_TObject_AoEDamage[udg_Spell__Index], udg_Spell__CasterOwner)
          • Hashtabelle - Save Handle Of(Last created image) as 1 of Spell__Index in Spell__Hash
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_ShowDistance[Spell__Index] Equal True
        • Then - Actions
          • Schwebender Text - Create floating text that reads (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) at Spell__TargetPoint with Z offset 120.00, using font size 14.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Custom script: if GetLocalPlayer() == udg_Spell__CasterOwner then
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , true)
          • Custom script: else
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , false)
          • Custom script: endif
          • Hashtabelle - Save Handle Of(Last created floating text) as 2 of Spell__Index in Spell__Hash
        • Else - Actions
  • Fire Circle Group Action
    • Events
    • Conditions
    • Actions
      • Einheitengruppe - Pick every unit in Spell__InRangeGroup and do (Actions)
        • Schleifen - Actions
          • Spezialeffekt - Create a special effect attached to the chest of (Picked unit) using CircleOfFire_SFX[1]
          • Custom script: call TimedGrafic( bj_lastCreatedEffect , 1.25 )
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is a structure) Equal True
            • Then - Actions
              • Unit - Cause Spell__Caster to damage (Picked unit), dealing Spell_TObject_DamageSec[Spell__Index] damage of attack type spell and damage type magic
            • Else - Actions
              • Unit - Cause Spell__Caster to damage (Picked unit), dealing Spell_TObject_Damage[Spell__Index] damage of attack type spell and damage type magic
  • Ice Circle Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Skill Duration/Intervall --------
      • Set Spell__Ability = Ice Circle
      • Set Spell__Duration = 120.00
      • Set Spell__DurationPerLevel = 0.00
      • Set Spell__Time = 0.10
      • -------- Define Targets --------
      • Set Spell__Filter_AllowEnemy = True
      • Set Spell__Filter_AllowLiving = True
      • Set Spell__Filter_AllowHero = True
      • Set Spell__Filter_AllowNonHero = True
      • Set Spell__Filter_AllowAlly = False
      • Set Spell__Filter_AllowDead = False
      • Set Spell__Filter_AllowFlying = False
      • Set Spell__Filter_AllowMechanical = True
      • Set Spell__Filter_AllowStructure = True
      • Set Spell__Filter_AllowMagicImmune = False
      • -------- Ice Circle Data --------
      • Set CircleOfIce_SlowSkill = Circle of Ice Slow
      • -------- If you change the Models you might need to change the multiplier in "cast" and the hit sfx is inside the slow spell --------
      • -------- Grafic 0 = constant one should have an "stand"-animation; --------
      • Set CircleOfIce_SFX[0] = war3mapImported\FrozenShell.MDX
      • -------- Manacosts are paid each Intervale; Therefore MpS = Costs / Time --------
      • Set CircleOfIce_ManaCosts[1] = 2.50
      • Set CircleOfIce_ManaCosts[2] = 2.50
      • Set CircleOfIce_ManaCosts[3] = 2.50
      • Set CircleOfIce_ManaCosts[4] = 2.50
      • -------- If costs would drain it under this limit it will break --------
      • Set CircleOfIce_ManaBreakLimit[1] = 20.00
      • Set CircleOfIce_ManaBreakLimit[2] = 20.00
      • Set CircleOfIce_ManaBreakLimit[3] = 20.00
      • Set CircleOfIce_ManaBreakLimit[4] = 20.00
      • Set CircleOfIce_AoE[1] = 200.00
      • Set CircleOfIce_AoE[2] = 225.00
      • Set CircleOfIce_AoE[3] = 250.00
      • Set CircleOfIce_AoE[4] = 300.00
      • -------- Beaware that DpS is Damage / Spell_Time --------
      • Set CircleOfIce_Damage[1] = 10.00
      • Set CircleOfIce_Damage[2] = 17.50
      • Set CircleOfIce_Damage[3] = 25.00
      • Set CircleOfIce_Damage[4] = 25.00
      • -------- Damage Structures take, default half --------
      • Set CircleOfIce_StructMulti[1] = 0.35
      • Set CircleOfIce_StructMulti[2] = 0.35
      • Set CircleOfIce_StructMulti[3] = 0.35
      • Set CircleOfIce_StructMulti[4] = 0.35
      • -------- If distance between Caster and Circle is bigger breaks on next intervale --------
      • Set CircleOfIce_RangeBreak[1] = 900.00
      • Set CircleOfIce_RangeBreak[2] = 1000.00
      • Set CircleOfIce_RangeBreak[3] = 1100.00
      • Set CircleOfIce_RangeBreak[4] = 1200.00
      • -------- Does the Circle stop if the caster dies --------
      • Set CircleOfIce_DeathBreak[1] = True
      • Set CircleOfIce_DeathBreak[2] = True
      • Set CircleOfIce_DeathBreak[3] = True
      • Set CircleOfIce_DeathBreak[4] = True
      • -------- Can units be affected by multiple Ice Circles at the same time ? --------
      • Set CircleOfIce_DamageStacks[1] = False
      • Set CircleOfIce_DamageStacks[2] = False
      • Set CircleOfIce_DamageStacks[3] = False
      • Set CircleOfIce_DamageStacks[4] = False
      • -------- The BuiltTime should be divedable without rest by choosen SpellTime. --------
      • -------- Duiring Builtup Only SFX 0, AoEIndikator and range check is applied --------
      • Set CircleOfIce_BuiltUpTime[1] = 1.00
      • Set CircleOfIce_BuiltUpTime[2] = 1.00
      • Set CircleOfIce_BuiltUpTime[3] = 1.00
      • Set CircleOfIce_BuiltUpTime[4] = 1.00
      • -------- Intervale --------
      • Set CircleOfIce_Intervale[1] = 0.50
      • Set CircleOfIce_Intervale[2] = 0.50
      • Set CircleOfIce_Intervale[3] = 0.50
      • Set CircleOfIce_Intervale[4] = 0.50
      • -------- Use TextTag, Aoe Indikator --------
      • Set CircleOfIce_ShowDistance = True
      • Set CircleOfIce_UseAoEIndikator = True
      • -------- Effect Stuff --------
      • Set Spell__Trigger_OnEffect = Ice Circle cast <gen>
      • Set Spell__Trigger_OnLoop = Circle BuiltUP <gen>
      • Set Spell__Trigger_InRangeFilter = Circle check <gen>
      • Custom script: set udg_CircleOfIce_HitBoth = udg_Spell__Filter_AllowAlly and udg_Spell__Filter_AllowEnemy
      • Trigger - Run Spell System <gen> (ignoring conditions)
  • Ice Circle cast
    • Events
    • Conditions
    • Actions
      • -------- Load Spell specific data into general data --------
      • -------- Makes it easier to add additional mods --------
      • -------- And Reusing the Loop for custom ones --------
      • -------- Depends on the model used, Models bigger than 100 take a number below 1 --------
      • Set ModelScaleMulti = 1.50
      • Set Spell_TObject_SFX = CircleOfIce_SFX[0]
      • Set Spell_TObject_Damage[Spell__Index] = CircleOfIce_Damage[Spell__Level]
      • -------- Inser here dmg mods, if you want them, an example is the disabled If else. --------
      • -------- If the spell is spoken by a Hero deal 25% more dmg. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__Caster is Ein Held) Equal True
        • Then - Actions
          • Set Spell_TObject_Damage[Spell__Index] = (Spell_TObject_Damage[Spell__Index] x 1.25)
        • Else - Actions
      • Set Spell_TObject_DamageSec[Spell__Index] = (Spell_TObject_Damage[Spell__Index] x CircleOfIce_StructMulti[Spell__Level])
      • Set Spell_TObject_AoEDamage[Spell__Index] = CircleOfIce_AoE[Spell__Level]
      • Set Spell_TObject_AoESec[Spell__Index] = CircleOfIce_RangeBreak[Spell__Level]
      • Set Spell_TObject_Mana[Spell__Index] = CircleOfIce_ManaCosts[Spell__Level]
      • Set Spell_TObject_ManaSec[Spell__Index] = CircleOfIce_ManaBreakLimit[Spell__Level]
      • Set Spell_TObject_DeathBreak[Spell__Index] = CircleOfIce_DeathBreak[Spell__Level]
      • Set Spell_TObject_GroupAction[Spell__Index] = Ice Circle Group Action <gen>
      • Set Spell_TObject_BuiltUpTime[Spell__Index] = CircleOfIce_BuiltUpTime[Spell__Level]
      • Set Spell_TObject_IntervaleEffect[Spell__Index] = CircleOfIce_Intervale[Spell__Level]
      • -------- If you want all Circle spells together check for stacking inser the same for all --------
      • Set Spell_TObject_ContainerGroup[Spell__Index] = CircleOfIce_Affected
      • Set Spell_TObject_ShowDistance[Spell__Index] = CircleOfIce_ShowDistance
      • Set Spell_TObject_UseAoEIndikator[Spell__Index] = CircleOfIce_UseAoEIndikator
      • -------- ---- --------
      • -------- Spells stuff begins --------
      • -------- ---- --------
      • Set Spell__StartDuration = True
      • Unit - Create 1 Spell__DummyType for Neutral extra at Spell__TargetPoint facing Vorgabe für Gebäude-Ausrichtung degrees
      • Set Spell_i_Target[Spell__Index] = (Last created unit)
      • Spezialeffekt - Create a special effect attached to the origin of (Last created unit) using Spell_TObject_SFX
      • Animation - Change (Last created unit)'s size to ((Spell_TObject_AoEDamage[Spell__Index] x ModelScaleMulti)%, (Spell_TObject_AoEDamage[Spell__Index] x ModelScaleMulti)%, (Spell_TObject_AoEDamage[Spell__Index] x ModelScaleMulti)%) of its original size
      • Hashtabelle - Save Handle Of(Last created special effect) as 0 of Spell__Index in Spell__Hash
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_UseAoEIndikator[Spell__Index] Equal True
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CircleOfIce_HitBoth Equal True
            • Then - Actions
              • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_Spell_TObject_AoEDamage[udg_Spell__Index], Player(PLAYER_NEUTRAL_AGGRESSIVE) )
            • Else - Actions
              • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_Spell_TObject_AoEDamage[udg_Spell__Index], udg_Spell__CasterOwner)
          • Hashtabelle - Save Handle Of(Last created image) as 1 of Spell__Index in Spell__Hash
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_ShowDistance[Spell__Index] Equal True
        • Then - Actions
          • Schwebender Text - Create floating text that reads (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) at Spell__TargetPoint with Z offset 120.00, using font size 14.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Custom script: if GetLocalPlayer() == udg_Spell__CasterOwner then
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , true)
          • Custom script: else
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , false)
          • Custom script: endif
          • Hashtabelle - Save Handle Of(Last created floating text) as 2 of Spell__Index in Spell__Hash
        • Else - Actions
  • Ice Circle Group Action
    • Events
    • Conditions
    • Actions
      • Unit - Add CircleOfIce_SlowSkill to DummyCaster
      • Unit - Set level of CircleOfIce_SlowSkill for DummyCaster to Spell__Level
      • Einheitengruppe - Pick every unit in Spell__InRangeGroup and do (Actions)
        • Schleifen - Actions
          • Unit - Order DummyCaster to Menschen-Zauberin - 'Slow' (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is a structure) Equal True
            • Then - Actions
              • Unit - Cause Spell__Caster to damage (Picked unit), dealing Spell_TObject_DamageSec[Spell__Index] damage of attack type spell and damage type magic
            • Else - Actions
              • Unit - Cause Spell__Caster to damage (Picked unit), dealing Spell_TObject_Damage[Spell__Index] damage of attack type spell and damage type magic
      • Unit - Remove CircleOfIce_SlowSkill from DummyCaster
  • Circle BuiltUP
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Distance between Spell__CastPoint and Spell__TargetPoint) greater as Spell_TObject_AoESec[Spell__Index]
              • And - All (Conditions) are true
                • Conditions
                  • (Spell__Caster is dead) Equal True
                  • Spell_TObject_DeathBreak[Spell__Index] Equal True
        • Then - Actions
          • Set Spell__Duration = 0.00
          • Spezialeffekt - Destroy (Load 0 of Spell__Index in Spell__Hash)
          • Unit - Add a 3.00 second Standard expiration timer to Spell__Target
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Spell_TObject_UseAoEIndikator[Spell__Index] Equal True
            • Then - Actions
              • Image - Destroy (Load 1 of Spell__Index in Spell__Hash)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Spell_TObject_ShowDistance[Spell__Index] Equal True
            • Then - Actions
              • Schwebender Text - Destroy (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.)
            • Else - Actions
          • Skip remaining actions
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Spell_TObject_ShowDistance[Spell__Index] Equal True
            • Then - Actions
              • Schwebender Text - Change text of (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.) to (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) using font size 14.00
            • Else - Actions
      • -------- Update Visibilty for indikator --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_UseAoEIndikator[Spell__Index] Equal True
        • Then - Actions
          • Custom script: set udg_Player = GetLocalPlayer()
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Spell__TargetPoint is visible to Player) Equal True
            • Then - Actions
              • Image - Zeigen (Load 1 of Spell__Index in Spell__Hash)
            • Else - Actions
              • Image - Verbergen (Load 1 of Spell__Index in Spell__Hash)
        • Else - Actions
      • Set Spell_TObject_BuiltUpTime[Spell__Index] = (Spell_TObject_BuiltUpTime[Spell__Index] - Spell_i_LastTime[Spell__Index])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_BuiltUpTime[Spell__Index] smaller equal 0.00
        • Then - Actions
          • -------- Builtup expired now start the effect --------
          • Set Spell__Time = Spell_TObject_IntervaleEffect[Spell__Index]
          • Set Spell__Trigger_OnLoop = Circle Loop <gen>
        • Else - Actions
  • Circle Loop
    • Events
    • Conditions
    • Actions
      • Custom script: local group g
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • ((Mana of Spell__Caster) - Spell_TObject_Mana[Spell__Index]) smaller as Spell_TObject_ManaSec[Spell__Index]
              • (Distance between Spell__CastPoint and Spell__TargetPoint) greater as Spell_TObject_AoESec[Spell__Index]
              • And - All (Conditions) are true
                • Conditions
                  • (Spell__Caster is dead) Equal True
                  • Spell_TObject_DeathBreak[Spell__Index] Equal True
        • Then - Actions
          • Set Spell__Duration = 0.00
          • Spezialeffekt - Destroy (Load 0 of Spell__Index in Spell__Hash)
          • Unit - Add a 3.00 second Standard expiration timer to Spell__Target
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Spell_TObject_UseAoEIndikator[Spell__Index] Equal True
            • Then - Actions
              • Image - Destroy (Load 1 of Spell__Index in Spell__Hash)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Spell_TObject_ShowDistance[Spell__Index] Equal True
            • Then - Actions
              • Schwebender Text - Destroy (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.)
            • Else - Actions
          • Skip remaining actions
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Spell_TObject_ShowDistance[Spell__Index] Equal True
            • Then - Actions
              • Schwebender Text - Change text of (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.) to (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) using font size 14.00
            • Else - Actions
          • Unit - Set mana of Spell__Caster to ((Mana of Spell__Caster) - Spell_TObject_Mana[Spell__Index])
      • -------- Update Visibilty for indikator --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_UseAoEIndikator[Spell__Index] Equal True
        • Then - Actions
          • Custom script: set udg_Player = GetLocalPlayer()
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Spell__TargetPoint is visible to Player) Equal True
            • Then - Actions
              • Image - Zeigen (Load 1 of Spell__Index in Spell__Hash)
            • Else - Actions
              • Image - Verbergen (Load 1 of Spell__Index in Spell__Hash)
        • Else - Actions
      • Set Spell__InRangePoint = Spell__TargetPoint
      • Set Spell__InRange = Spell_TObject_AoEDamage[Spell__Index]
      • Trigger - Run Spell_TObject_GroupAction[Spell__Index] (checking conditions)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Spell_TObject_DamageStacks[Spell__Index] Equal False
          • (Spell__InRangeGroup is empty) Equal False
        • Then - Actions
          • Custom script: set g = CreateGroup()
          • For each (Integer A) from 1 to Spell__InRangeCount, do (Actions)
            • Schleifen - Actions
              • Custom script: call GroupAddUnit (g, udg_Spell__InRangeUnits[bj_forLoopAIndex])
          • Custom script: call CircleRemember( g, udg_Spell_TObject_ContainerGroup[udg_Spell__Index], udg_Spell_i_LastTime[udg_Spell__Index] - 0.032)
          • Custom script: set g = null
        • Else - Actions
  • Circle check
    • Events
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Spell__InRangeUnit is in Spell_TObject_ContainerGroup[Spell__Index]) Equal False
          • Spell_TObject_DamageStacks[Spell__Index] Equal True
    • Actions

The now following version would be mostly like "form of spells" but more ugly and less finished, so skip it.

now i show the fire ring in its current form using form of spells.
The config: it defines data and logic, aftet this trigger the logic beeing used follows, except the system's core which is already uploaded in the 1.post.
  • Fire Circle Config
    • Ereignisse
      • Map initialization
    • Bedingungen
    • Aktionen
      • Set Spell__Ability = Fire Circle
      • Custom script: set udg_AbilityId = udg_Spell__Ability
      • Hashtabelle - Save FormOfSpells_Index as 0 of AbilityId in Spell__Hash
      • -------- Spells Level Amount --------
      • Set FormOfSpells_Levels = 4
      • -------- Variables with the name FormOfSpells_x are System variables and should not be written inside the configs --------
      • -------- Data which is 0/null does not have to be included. --------
      • -------- Fire Circle Data --------
      • For each (Integer A) from 1 to FormOfSpells_Levels, do (Actions)
        • Schleifen - Aktionen
          • Set FormOfSpells_SFX[(FormOfSpells_Index + (Integer A))] = war3mapImported\s_RunningFlame Aura.mdx
          • Set FormOfSpells_SFXScaling[(FormOfSpells_Index + (Integer A))] = 1.00
          • Set FormOfSpells_SFXHit[(FormOfSpells_Index + (Integer A))] = Abilities\Spells\Other\ImmolationRed\ImmolationRedDamage.mdl
          • Set FormOfSpells_SFXHitOffset[(FormOfSpells_Index + (Integer A))] = chest
          • Set FormOfSpells_SFXHitDur[(FormOfSpells_Index + (Integer A))] = 1.25
          • -------- Clone Hit1 --------
          • Set FormOfSpells_SFXHit2[(FormOfSpells_Index + (Integer A))] = FormOfSpells_SFXHit[(FormOfSpells_Index + (Integer A))]
          • Set FormOfSpells_SFXHit2Offset[(FormOfSpells_Index + (Integer A))] = FormOfSpells_SFXHitOffset[(FormOfSpells_Index + (Integer A))]
          • Set FormOfSpells_SFXHit2Dur[(FormOfSpells_Index + (Integer A))] = FormOfSpells_SFXHitDur[(FormOfSpells_Index + (Integer A))]
      • -------- PreMainAction is a good place for Costs. --------
      • Set FormOfSpells_PreMainAction[(FormOfSpells_Index + 1)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_PreMainAction[(FormOfSpells_Index + 2)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_PreMainAction[(FormOfSpells_Index + 3)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_PreMainAction[(FormOfSpells_Index + 4)] = FoS Costs Mana fix <gen>
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 1)] = 2.50
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 2)] = 2.50
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 3)] = 2.50
      • Set FormOfSpells_ManaCosts[(FormOfSpells_Index + 4)] = 2.50
      • -------- If costs would drain it under this limit it will break --------
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 1)] = 20.00
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 2)] = 20.00
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 3)] = 20.00
      • Set FormOfSpells_ManaLimit[(FormOfSpells_Index + 4)] = 20.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 1)] = 200.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 2)] = 200.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 3)] = 250.00
      • Set FormOfSpells_AoE[(FormOfSpells_Index + 4)] = 250.00
      • -------- If distance between Caster and Circle is bigger breaks on next intervale --------
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 1)] = 900.00
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 2)] = 900.00
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 3)] = 1100.00
      • Set FormOfSpells_RangeBreak[(FormOfSpells_Index + 4)] = 1100.00
      • -------- Conditions used to break up the Spell instantly --------
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 1)] = FoS Break Dead v Mana v Range <gen>
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 2)] = FoS Break Dead v Mana v Range <gen>
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 3)] = FoS Break Dead v Mana v Range <gen>
      • Set FormOfSpells_BreakCondition[(FormOfSpells_Index + 4)] = FoS Break Dead v Mana v Range <gen>
      • For each (Integer A) from 1 to FormOfSpells_Levels, do (Actions)
        • Schleifen - Aktionen
          • Set FormOfSpells_AttackType[(FormOfSpells_Index + (Integer A))] = Zaubersprüche
          • Set FormOfSpells_DamageType[(FormOfSpells_Index + (Integer A))] = Magie
      • -------- Beaware that DpS is Damage / Spell_Time --------
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 1)] = 17.50
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 2)] = 25.00
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 3)] = 40.00
      • Set FormOfSpells_Damage[(FormOfSpells_Index + 4)] = 30.00
      • -------- Damage Structures take, default half --------
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 1)] = 8.75
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 2)] = 12.50
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 3)] = 20.00
      • Set FormOfSpells_Damage2[(FormOfSpells_Index + 4)] = 15.00
      • -------- If the conditions of the Choosen Trigger are true DamageSec is dealt. --------
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 1)] = FoS Action Filter Structure v Mech <gen>
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 2)] = FoS Action Filter Structure v Mech <gen>
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 3)] = FoS Action Filter Structure v Mech <gen>
      • Set FormOfSpells_DamageFilter[(FormOfSpells_Index + 4)] = FoS Action Filter Structure v Mech <gen>
      • -------- Overall Mod is damage mod from Caster only, For example Spellpower buffs etc --------
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 1)] = FoS Overall Mod Spellpower <gen>
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 2)] = FoS Overall Mod Spellpower <gen>
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 3)] = FoS Overall Mod Spellpower <gen>
      • Set FormOfSpells_DamageOverallMod[(FormOfSpells_Index + 4)] = FoS Overall Mod Spellpower <gen>
      • -------- How many targets are allowed to be hit in one intervale; 0 = unlimited --------
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 1)] = 0
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 2)] = 0
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 3)] = 0
      • Set FormOfSpells_OnceMaxTarget[(FormOfSpells_Index + 4)] = 0
      • -------- The BuiltTime should be divedable without rest by choosen SpellTime. --------
      • -------- Duiring Builtup Only Update and BreakCondition are runed --------
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 1)] = 1.00
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 2)] = 1.00
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 3)] = 1.00
      • Set FormOfSpells_BuiltUpDuration[(FormOfSpells_Index + 4)] = 1.00
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 1)] = 0.10
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 2)] = 0.10
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 3)] = 0.10
      • Set FormOfSpells_BuiltUpIntervale[(FormOfSpells_Index + 4)] = 0.10
      • -------- Action which fires as soon Spell Effects started --------
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 1)] = FoS Create AoE Indikator Distance Tag <gen>
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 2)] = FoS Create AoE Indikator Distance Tag <gen>
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 3)] = FoS Create AoE Indikator Distance Tag <gen>
      • Set FormOfSpells_CastAction[(FormOfSpells_Index + 4)] = FoS Create AoE Indikator Distance Tag <gen>
      • -------- Where the dmg is dealt? --------
      • Set FormOfSpells_Targeting[(FormOfSpells_Index + 1)] = FoS Targeting Target <gen>
      • Set FormOfSpells_Targeting[(FormOfSpells_Index + 2)] = FoS Targeting Target <gen>
      • Set FormOfSpells_Targeting[(FormOfSpells_Index + 3)] = FoS Targeting Target <gen>
      • Set FormOfSpells_Targeting[(FormOfSpells_Index + 4)] = FoS Targeting Target <gen>
      • -------- Effect after an BuiltUp/Delay Time --------
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 1)] = FoS Create SFX <gen>
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 2)] = FoS Create SFX <gen>
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 3)] = FoS Create SFX <gen>
      • Set FormOfSpells_BuiltFinishAction[(FormOfSpells_Index + 4)] = FoS Create SFX <gen>
      • -------- Duration after Building up --------
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 1)] = 120.00
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 2)] = 120.00
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 3)] = 120.00
      • Set FormOfSpells_Duration[(FormOfSpells_Index + 4)] = 120.00
      • -------- Intervale after Buildingup --------
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 1)] = 0.50
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 2)] = 0.50
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 3)] = 0.50
      • Set FormOfSpells_Intervale[(FormOfSpells_Index + 4)] = 0.50
      • -------- ActionDelay allows you to use fast updates/Break calls (intervales), and slow costs/Action runs; only evey x time of intervale. --------
      • -------- 0 = always; 1 = every 2.time 2 = every 3.time .... --------
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 1)] = 0
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 2)] = 0
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 3)] = 0
      • Set FormOfSpells_ActionDelay[(FormOfSpells_Index + 4)] = 0
      • -------- How long it takes to kill the Grafic Container; aka play the death animation of SFX 0 --------
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 1)] = 1.50
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 2)] = 1.50
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 3)] = 1.50
      • Set FormOfSpells_DeathTime[(FormOfSpells_Index + 4)] = 1.50
      • -------- This happens when the spell breaks. --------
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 1)] = FoS CleanOff Default <gen>
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 2)] = FoS CleanOff Default <gen>
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 3)] = FoS CleanOff Default <gen>
      • Set FormOfSpells_OnBreak[(FormOfSpells_Index + 4)] = FoS CleanOff Default <gen>
      • -------- This happens every loop in the update Trigger.. --------
      • Set FormOfSpells_Update[(FormOfSpells_Index + 1)] = FoS Update Distance AoE Visibility <gen>
      • Set FormOfSpells_Update[(FormOfSpells_Index + 2)] = FoS Update Distance AoE Visibility <gen>
      • Set FormOfSpells_Update[(FormOfSpells_Index + 3)] = FoS Update Distance AoE Visibility <gen>
      • Set FormOfSpells_Update[(FormOfSpells_Index + 4)] = FoS Update Distance AoE Visibility <gen>
      • -------- Default owner matter if you set affects allies and foes. --------
      • Set FormOfSpells_DefaultOwner[FormOfSpells_Index] = Neutral feindlich
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 1)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 2)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 3)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_MainAction[(FormOfSpells_Index + 4)] = FoS Action Group Damage <gen>
      • Set FormOfSpells_SecondAction[(FormOfSpells_Index + 1)] = FormOfSpells Remember <gen>
      • Set FormOfSpells_SecondAction[(FormOfSpells_Index + 2)] = FormOfSpells Remember <gen>
      • Set FormOfSpells_SecondAction[(FormOfSpells_Index + 3)] = FormOfSpells Remember <gen>
      • Set FormOfSpells_SecondAction[(FormOfSpells_Index + 4)] = FormOfSpells Remember <gen>
      • -------- Can units be affected by multiple Fire Circles at the same time ? --------
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 1)] = False
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 2)] = False
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 3)] = False
      • Set FormOfSpells_DamageStacks[(FormOfSpells_Index + 4)] = True
      • -------- How long an unit stays unaffected if unstacking mod. --------
      • -------- Default is autocalced; the next intervale will affected it again. --------
      • For each (Integer A) from 1 to FormOfSpells_Levels, do (Actions)
        • Schleifen - Aktionen
          • Set FormOfSpells_RememberDur[(FormOfSpells_Index + (Integer A))] = (FormOfSpells_Intervale[(FormOfSpells_Index + (Integer A))] - 0.01)
      • -------- Which Group is used to calc stacking. --------
      • -------- Choose Spell__TargetGroup to use spell instance stacking checks and Use Spell__TargetGroup =true --------
      • Set FormOfSpells_Container[(FormOfSpells_Index + 1)] = CircleOfFire_Affected
      • Set FormOfSpells_Container[(FormOfSpells_Index + 2)] = CircleOfFire_Affected
      • Set FormOfSpells_Container[(FormOfSpells_Index + 3)] = CircleOfFire_Affected
      • Set FormOfSpells_Container[(FormOfSpells_Index + 4)] = CircleOfFire_Affected
      • Set Spell__UseTargetGroup = False
      • -------- An additional way to filter units., Currently Default CircleOfElements --------
      • Set Spell__Trigger_InRangeFilter = FoS Circle Default check <gen>
      • -------- Define Targets --------
      • Set Spell__Filter_AllowEnemy = True
      • Set Spell__Filter_AllowLiving = True
      • Set Spell__Filter_AllowHero = True
      • Set Spell__Filter_AllowNonHero = True
      • Set Spell__Filter_AllowAlly = False
      • Set Spell__Filter_AllowDead = False
      • Set Spell__Filter_AllowFlying = False
      • Set Spell__Filter_AllowMechanical = True
      • Set Spell__Filter_AllowStructure = True
      • Set Spell__Filter_AllowMagicImmune = False
      • -------- Keep it untouched in most cases --------
      • Set Spell__Duration = 99999.00
      • Set Spell__DurationPerLevel = 0.00
      • Set Spell__Time = 0.10
      • -------- ----- --------
      • -------- Don't touch below --------
      • -------- ----- --------
      • Custom script: set udg_FormOfSpells_HitBoth[udg_FormOfSpells_Index] = udg_Spell__Filter_AllowAlly and udg_Spell__Filter_AllowEnemy
      • Set Spell__Trigger_OnEffect = FormOfSpells Cast <gen>
      • Trigger - Run Spell System <gen> (ignoring conditions)
      • -------- Calc Index for next spell --------
      • Set FormOfSpells_Index = (FormOfSpells_Index + FormOfSpells_Levels)
      • Set FormOfSpells_Index = (FormOfSpells_Index + 1)
  • FoS Costs Mana fix
    • Ereignisse
    • Bedingungen
    • Aktionen
      • Unit - Set mana of Spell__Caster to ((Mana of Spell__Caster) - FormOfSpells_ManaCosts[FormOfSpells_x_IndexData])
  • FoS Break Dead v Mana v Range
    • Ereignisse
    • Bedingungen
      • Or - Any (Conditions) are true
        • Bedingungen
          • (Spell__Caster is dead) equal True
          • (Distance between Spell__CastPoint and Spell__TargetPoint) Greater as FormOfSpells_RangeBreak[FormOfSpells_x_IndexData]
          • (Mana of Spell__Caster) Kleiner equal FormOfSpells_ManaCosts[FormOfSpells_x_IndexData]
    • Aktionen
      • -------- If the conditions return true the Spell ends instantly --------
  • FoS Action Filter Structure v Mech
    • Ereignisse
    • Bedingungen
      • Or - Any (Conditions) are true
        • Bedingungen
          • (Spell__InRangeUnit is Ein Gebäude) equal True
          • (Spell__InRangeUnit is Mechanisch) equal True
    • Aktionen
  • FoS Overall Mod Spellpower
    • Ereignisse
    • Bedingungen
    • Aktionen
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__Caster has an item of type Ring der Ãœberlegenheit) equal True
        • Then - Actions
          • Set FormOfSpells_x_Damage[1] = (FormOfSpells_x_Damage[1] x 1.25)
          • Set FormOfSpells_x_Damage[2] = (FormOfSpells_x_Damage[2] x 1.25)
        • Else - Actions
  • FoS Create AoE Indikator Distance Tag
    • Ereignisse
    • Bedingungen
    • Aktionen
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_HitBoth[FormOfSpells_x_IndexAbility] equal True
        • Then - Actions
          • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_FormOfSpells_AoE[udg_FormOfSpells_x_IndexData], udg_FormOfSpells_DefaultOwner[udg_FormOfSpells_x_IndexAbility] )
        • Else - Actions
          • Custom script: call AoEIndikator(udg_Spell__TargetPoint, udg_FormOfSpells_AoE[udg_FormOfSpells_x_IndexData], udg_Spell__CasterOwner)
      • Set FormOfSpells_x_HasIndikator[Spell__Index] = True
      • Hashtabelle - Save Handle Of(Last created image) as 1 of Spell__Index in Spell__Hash
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__CasterOwner controller) equal Benutzer
        • Then - Actions
          • Schwebender Text - Create floating text that reads (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) at Spell__TargetPoint with Z offset 120.00, using font size 14.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
          • Custom script: if GetLocalPlayer() == udg_Spell__CasterOwner then
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , true)
          • Custom script: else
          • Custom script: call SetTextTagVisibility(bj_lastCreatedTextTag , false)
          • Custom script: endif
          • Set FormOfSpells_x_HasTexttag[Spell__Index] = True
          • Hashtabelle - Save Handle Of(Last created floating text) as 2 of Spell__Index in Spell__Hash
        • Else - Actions
  • FoS Targeting Target
    • Ereignisse
    • Bedingungen
    • Aktionen
      • Einheitengruppe - Remove all units from FormOfSpells_x_Affected
      • Custom script: call MoveLocation(udg_FormOfSpells_x_DamagePoint, GetLocationX(udg_Spell__TargetPoint), GetLocationY(udg_Spell__TargetPoint))
      • -------- Get Group --------
      • Set Spell__InRangePoint = FormOfSpells_x_DamagePoint
      • Set Spell__InRangeMax = FormOfSpells_OnceMaxTarget[FormOfSpells_x_IndexData]
      • Set Spell__InRange = FormOfSpells_AoE[FormOfSpells_x_IndexData]
      • Einheitengruppe - Add all units of Spell__InRangeGroup to FormOfSpells_x_Affected
  • FoS Create SFX
    • Ereignisse
    • Bedingungen
    • Aktionen
      • -------- Don't do shit --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_SFX[FormOfSpells_x_IndexData] Unequal <Leerer String>
        • Then - Actions
          • Set FormOfSpells_x_HasSFX[Spell__Index] = True
          • Animation - Change FormOfSpells_x_SpellsDummy[Spell__Index]'s size to ((FormOfSpells_AoE[FormOfSpells_x_IndexData] x FormOfSpells_SFXScaling[FormOfSpells_x_IndexData])%, (FormOfSpells_AoE[FormOfSpells_x_IndexData] x FormOfSpells_SFXScaling[FormOfSpells_x_IndexData])%, (FormOfSpells_AoE[FormOfSpells_x_IndexData] x FormOfSpells_SFXScaling[FormOfSpells_x_IndexData])%) of its original size
          • Spezialeffekt - Create a special effect attached to the origin of FormOfSpells_x_SpellsDummy[Spell__Index] using FormOfSpells_SFX[FormOfSpells_x_IndexData]
          • Hashtabelle - Save Handle Of(Last created special effect) as 0 of Spell__Index in Spell__Hash
        • Else - Actions
  • FoS CleanOff Default
    • Ereignisse
    • Bedingungen
    • Aktionen
      • Set Spell__Duration = 0.00
      • Unit - Add a FormOfSpells_DeathTime[FormOfSpells_x_IndexData] second Standard expiration timer to FormOfSpells_x_SpellsDummy[Spell__Index]
      • Set FormOfSpells_x_SpellsDummy[Spell__Index] = Keine Unit
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_x_HasSFX[Spell__Index] equal True
        • Then - Actions
          • Spezialeffekt - Destroy (Load 0 of Spell__Index in Spell__Hash)
        • Else - Actions
      • -------- Destroying null images can irritate the game. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_x_HasIndikator[Spell__Index] equal True
        • Then - Actions
          • Bild - Destroy (Load 1 of Spell__Index in Spell__Hash)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • FormOfSpells_x_HasTexttag[Spell__Index] equal True
        • Then - Actions
          • Schwebender Text - Destroy (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.)
        • Else - Actions
      • Einheitengruppe - Pick every unit in FormOfSpells_x_Actors[Spell__Index] and do (Actions)
        • Schleifen - Aktionen
          • Unit - Add a FormOfSpells_DeathTime[FormOfSpells_x_IndexData] second Standard expiration timer to (Picked unit)
          • Spezialeffekt - Destroy (Load 0 of (Key (Picked unit)) in Spell__Hash)
          • Einheitengruppe - Remove (Picked unit) from FormOfSpells_x_Actors[Spell__Index]
      • Set FormOfSpells_x_HasIndikator[Spell__Index] = False
      • Set FormOfSpells_x_HasTexttag[Spell__Index] = False
      • Set FormOfSpells_x_HasSFX[Spell__Index] = False
  • FoS Update Distance AoE Visibility
    • Ereignisse
    • Bedingungen
    • Aktionen
      • Schwebender Text - Change text of (Load 2 of Spell__Index in Spell__HashIf the label is not found, this function returns NULL.) to (String((Integer((Distance between Spell__CastPoint and Spell__TargetPoint))))) using font size 14.00
      • Custom script: set udg_Player = GetLocalPlayer()
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Spell__TargetPoint is visible to Player) equal True
        • Then - Actions
          • Bild - Zeigen (Load 1 of Spell__Index in Spell__Hash)
        • Else - Actions
          • Bild - Verbergen (Load 1 of Spell__Index in Spell__Hash)
  • FoS Action Group Damage
    • Ereignisse
    • Bedingungen
    • Aktionen
      • Trigger - Run FoS Load Damage <gen> (ignoring conditions)
      • Trigger - Run FormOfSpells_Targeting[FormOfSpells_x_IndexData] (ignoring conditions)
      • Einheitengruppe - Pick every unit in FormOfSpells_x_Affected and do (Actions)
        • Schleifen - Aktionen
          • Set Spell__InRangeUnit = (Picked unit)
          • Trigger - Run FoS deal damage <gen> (ignoring conditions)
 
Status
Not open for further replies.
Top