HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Callbacks

07-15-2006, 03:54 AM#1
karukef
With all the talk of extending and object orienting the JASS, I thought I'd give just one example of what my JassPreProcessor currently does.

Take a look at this interesting line of code:

Collapse JASS:
    call ForGroup(selected_targets, jpp_callback ABIL_EmeraldSpiritsTargetEnum(source, actual_damage))

It does something that is not possible in JASS, that is it calls a function with arguments for each unit in a group.
Normally, this would read:

Collapse JASS:
    set SomeGlobalVar = source
    set SomeOtherGlobal = actual_damage
    call ForGroup(selected_targets, function ABIL_EmeraldSpiritsTargetEnum)

As most Jassers are aware of, callback functions such as the one ForGroup take no arguments meaning arguments must be passed by global variables (or *shudder* gamecache).

This is very inconvenient and extremely bad programming practice.

So, one of the new features of my JPP (jass preprocessor) is to turn:
Collapse JASS:
jpp_callback ABIL_EmeraldSpiritsTargetEnum takes unit source, integer damage returns nothing
    call DebugMsg(GetUnitName(source) + " damages " + GetUnitName(GetEnumUnit()) + ", Damage = " + I2S(damage))
endfunction

function ABIL_EmeraldSpirits takes group targets returns nothing
    call ForGroup(targets, jpp_callback ABIL_EmeraldSpiritsTargetEnum(source, actual_damage))
endfunction

automatically into this in the war3map.j:

Collapse JASS:
function ABIL_EmeraldSpiritsTargetEnum takes nothing returns nothing
    local unit source = jpp_cb0
    local integer damage = jpp_cb1
    call DebugMsg(GetUnitName(source) + " damages " + GetUnitName(GetEnumUnit()) + ", Damage = " + I2S(damage))
endfunction

function ABIL_EmeraldSpirits takes group targets returns nothing
    set jpp_cb0 = source
    set jpp_cb1 = actual_damage
    call ForGroup(selected_targets, function ABIL_EmeraldSpiritsTargetEnum)
endfunction


It will of course declare globals of correct types and insert it into the globals section of war3map.j.

Simple and Effective!
07-15-2006, 04:03 AM#2
PipeDream
Good job. "This is very inconvenient and extremely bad programming practice." is a little dramatic.
07-15-2006, 04:33 AM#3
karukef
Quote:
Originally Posted by PipeDream
Good job. "This is very inconvenient and extremely bad programming practice." is a little dramatic.

Well, it may not be very inconvenient. Of course, setting some global variables before calling a callback is only a line or two. But it IS extremely bad programming practice, that's for sure :)
07-15-2006, 04:38 AM#4
DioD
For group global less

Collapse JASS:
    loop
        set GFilter = FirstOfGroup(ToDamage)
        exitwhen GFilter == null
        call GroupRemoveUnit(ToDamage,GFilter)        
        if not IsUnitInGroup(GFilter,Group) and IsUnitEnemy(GFilter,GetOwningPlayer(Caster)) then
            call UnitDamageTarget(Caster,GFilter,Damage,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
            call GroupAddUnit(Group,GFilter)
        endif
    endloop

It used for wave damaging and will damage unit only a time

Your "code" is useless
07-15-2006, 04:40 AM#5
Alevice
Not when callback functions are used in more places than just at for groups.
07-15-2006, 05:11 AM#6
PipeDream
Pontificate, v.
1. To express opinions or judgments in a dogmatic way.
2. Beg to be moderated with reckless abandon
07-15-2006, 06:49 AM#7
karukef
Quote:
Originally Posted by DioD
Your "code" is useless

If you do not see its immense usefullness I can't help you :)

Btw, PipeDream, care to explain the meaning of your last post to those of us, including me, who just don't understand what on earth it is you are saying?
07-15-2006, 07:53 AM#8
Mezzer
Seems ok, you should tell Vex about your precompiler, he's been meaning to do the same in his set JASS=JASS+1 thread
07-15-2006, 02:39 PM#9
Alevice
Quote:
Originally Posted by karukef
If you do not see its immense usefullness I can't help you :)

Btw, PipeDream, care to explain the meaning of your last post to those of us, including me, who just don't understand what on earth it is you are saying?

I think it was addressed to DioD in a "keep your mouth shut" way. Or so I say.
07-15-2006, 03:55 PM#10
Vexorian
hmn diod, yes but no.

That works, but is slower than a for group and it gets rid of the group, so if you want to keep the group after the iteration, you have to either clone the group before doing so or keep adding units to another group and work arounds like that.

jpp_callback seems like bad syntax.

Quote:
This is very inconvenient and extremely bad programming practice.

Why should it be a bad programming practice?


Quote:
Not when callback functions are used in more places than just at for groups.
Preprocessor seems to be ready only for ForGroup. Hard to adapt for other things anyways
07-15-2006, 04:01 PM#11
Vexorian
Quote:
jpp_callback seems like bad syntax.

Hard to remember I say, if you find the function keyword and then the function name is followed by the ( operator then it is easy to identify a callback
07-15-2006, 06:27 PM#12
karukef
First, jpp_callback does not work just for ForGroup. It works for every callback and can be used in any imaginable circumstance where one normally would set global variables.

As for syntax, I could make the callback function use the normal function signature, process every callback call and then seek out the functions that are being used as callbacks and modify them like you suggest. I chose jpp_callback as a special keyword because I want to make it as obvious as possible that something different is going on. Magic preprocessing should be clearly visible in the sourcecode.

As for why it is bad programming practice to set some global variables and then call a function that read those variables vs passing those same variables through the normal function calling syntax consists of several reasons: It makes the syntax less complex making it easier to use, read and maintain, it removes the need to manage a large amount of global variables and concentrates all the "extra work" needed get arguments into callbacks into one single line.
07-15-2006, 08:23 PM#13
Vexorian
I can't think on callbacks that would use more than 3 variables, and for them I could use bj variables, they are always there. But well it is an annoyance and it is unconfortable but not a bad programming practice.

Quote:
I chose jpp_callback as a special keyword because I want to make it as obvious as possible that something different is going on
It would seem pretty obvious to me.

--
Quote:
First, jpp_callback does not work just for ForGroup. It works for every callback and can be used in any imaginable circumstance where one normally would set global variables.

And that is ForGroup and ForForce, but ForForce is like incredibly useless anyways.
07-15-2006, 09:02 PM#14
Alevice
What about timers, trigger conditions, etc? Unless those aren't callbacks...
07-15-2006, 09:04 PM#15
Vexorian
How exactly would you apply global variables there?