Quote from: rvonsonsnadtz on October 14, 2012, 09:45:56 AM
Well, it haven't been much time since my last post, and syntax-writing have started to take over my GUI-usage more and more. But I got a question I want answered; How do I pick units in a line (for creating a trigger-based spell like shockwave or similar). I have before used a number of rects to simulate the line-effect, but is there a better way, then I am interested in hearing it.
Well, you seem to read my mind

Right now I'm working in a code to group units in a line. And yes you can avoid rects, in fact rects is not the proper way. You can do this process in code as follows:
- define the cast point and final point with X,Y coordinates
- set the middle point (with average formula 0.5*(x1+x2) )
- group units in range with center in the middle point
- Measure the angle between the cast point and the unit, if it doesn't differ much from the original angle (you set that parameter) then add it to the destination group
- Repeat until covers all thew units in the initail range[/i]
If you're a little patient I'm gonna finish this code very quickly (I have the algorithm almost done)
QuoteAnd a little of-topic question; a quite long time ago, I read a topic about vJass and its strengths against normal GUI, and one particular thing I remembered was that someone mentioned another way to fire of triggers rather than the way triggers runs of in the GUI that was more efficient, but I can't recall how nor where I read it. Someone who knows anything about it?
Definitely!!!
the problem with GUI is that you generate one trigger and every conditional create a new function which trigger ANOTHER function. Check this example:
[trigger]Untitled Trigger 001
Events
Unit - A unit Finishes casting an ability
Conditions
(Ability being cast) Equal to Animate Dead
Actions
Unit - Create 1 Footman for Player 1 (Red) at (Position of (Triggering unit)) facing Default building facing degrees
-------- Etc, etc, etc... --------
[/trigger]
This GUI viewed as jass looks like this:
function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AUan' ) ) then
return false
endif
return true
endfunction
function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
call CreateNUnitsAtLoc( 1, 'hfoo', Player(0), GetUnitLoc(GetTriggerUnit()), bj_UNIT_FACING )
// Etc, etc, etc...
endfunction
//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
set gg_trg_Untitled_Trigger_001 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_FINISH )
call TriggerAddCondition( gg_trg_Untitled_Trigger_001, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunctionAs you can see, this code is too long in all the terms possible and that's because GUI puts a lot "just in case" code which in most of the situations is inefficient as hell. In the triggering part is the same: you register the event (Unit finish casting an ability) then you set a WHOLE FUNCTION just to check the spell type and then it runs another function to run the script.
In fact the question is: couldn't we do this in only one function? and the answer is YES: Let's optimize.
function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
local location L // I define a local variable so this code doesn't leak a location
if GetSpellAbilityId() == 'AUan' then
set L = GetUnitLoc(GetTriggerUnit())
call CreateNUnitsAtLoc( 1, 'hfoo', Player(0), L, bj_UNIT_FACING )
call RemoveLocation(L) // removes the location
endif
set L = null //
return false // set it so nothing will run after this function, we3 don't need it :)
endfunction
//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
set gg_trg_Untitled_Trigger_001 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_FINISH )
call TriggerAddCondition( gg_trg_Untitled_Trigger_001, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
endfunctionHere I merged the action inside the condition, doing this gives you an advantage: conditions are faster than actions. I added some code to remove the location leak in the original code. Let's optimize more, doing some vJASS:
scope TestTrigger initializer init
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == 'AUan' then
call CreateUnit( Player(0), 'hfoo', GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), bj_UNIT_FACING )
// Add more things to do...
endif
return false // set it so nothing will run after this function, we3 don't need it :)
endfunction
//===========================================================================
private function init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_FINISH )
call TriggerAddCondition( t, Condition( function Conditions ) )
set t = null // to free handle counter
endfunction
endscopeNow this code is totally efficient, it DOES NOT use locations anymore and it has a nicer presentation and readability. I've set the trigger as a local variable so it doesn't interfere with other code making it totally MUI (multi unit instanceable).
I hope with this live example you can see the advantage of jass and vJASS in triggering terms.