I think that the biggest difference between an intermediate coder and a good one is the ability to structure and design their code properly.
1) You don't need to inline the TriggerRegisterAnyUnitEventBJ, it's perfectly fine to use as speed is unimportant during initialisation and it looks cleaner to have only three lines of code.
2) Why do you use triggeractions? Especially as a condition-action type. You should change it to a triggercondition.
3) You don't need to set your variables before the line that checks if the ability is cast your ability. You set index to zero, and num_dummies to something. You set two things on every single ability that is cast. That's inefficient and irrelevant.
4) You divide 360 by 12. It should be divided by how many dummy units there will be.
5) You shouldn't be converting degrees to radians, and vice versa so much. Just use radians throughout the entire code, and convert to degrees only for unit facing.
6) Function arguments should have more meaningful names. "a", "p", and "u" do not tell the user anything. "angle", "owningPlayer", and "sourceUnit" do though.
7) Relating to point 5, if you removed the line that started the MovingFlames function, you will relise you create the dummy units in a completely wrong coordinate.
8) You should store functions that are called frequently into variables. In the OnCast function, you call GetTriggerUnit() up to 36 times.
9) Why do you actually use GetTriggerUnit() in your CreateStruct function? Why not use the unit argument you have.
10) Rather than using a function, why not just use the struct's create method? It looks far neater and organised.
11) The timer period (0.03) should be a configurable constant real global.
12) Rather than having an instance for each dummy unit, have it all in one. It is more efficient as you are calling the callback function only once compared to twelve times.
13) Rather than checking the distance between the dummy and the source unit, have a variable ("distanceRemaining"?) that decrements. Once that variable hits 0 (or 70), that is when you consider the ability 'done'.
14) Indent properly.
15) You leak a group. You never DestroyGroup on tempgroup. Infact, you shouldn't even be using dynamic groups. Use a global group as you only do everything instantly. (What's that bj group that Bribe suggests to use O_O?)
16) Your GroupEnum function is completely pointless. It's equivalent to a BJ function.
17) Rather than declaring another local Flames variable inside AOE_Expr, just use Flames.FInteger directly. So "Flames.FInteger.Caster".
18) You can privatise the Flames struct. You can move AOE_Expr under the Flames struct or use a keyword. Although I'd advise doing the former.
19) Move the DamageUnits inside of the AOE_Expr. No need for to enumerate the units and then apply a ForGroup. Just do everything inside the enumeration.
20) Relating to number 8, you can store GetEnumUnit() into a local variable.
21) Why do you use a loop to knock the target unit back? It's all instant, just set the unit's X/Y in two function lines, rather than this loop nonsense.
22) Store the AOE of the ability as a struct member so you don't call it every 0.03 seconds.
23) What's up with decreasing the height of the unit by 33.33 every second? If you're going to decrease height, make the rate a configurable constant global.
24) All your configurable functions should be constant. DAMAGE, NUM_DUMMIES, etc.