• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] On my course from GUI to JASS

Status
Not open for further replies.
Level 3
Joined
Dec 24, 2009
Messages
22
Hey and thanks for stopping by,
I would like to have your guidance. Yeah, seriously, I'm stuck.

So I intends to create an orb coming out from a character, it'll go to that person desired location( target point of ability being cast ) and it will explode in the area even if there's nothing there. Like a grenade but I would like to try it on my own way to determine whether I can create something based on my knowledge about JASS so far. :goblin_wtf:


So anyway here is my code, I don't know what I should do with it anymore. I'm stunned.

JASS:
function Trig_A_Jass_Condition takes nothing returns boolean
    return GetSpellAbilityId() == 'A007'
endfunction   

function T_SfxExp takes nothing returns string
    return "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
endfunction


function Trig_A_Jass_Actions takes nothing returns nothing
    local unit cas = GetTriggerUnit()
    local location casp = GetUnitLoc(cas)
    local location casloc = GetSpellTargetLoc()
    local unit L
    local real RDist = DistanceBetweenPoints( casp, casloc )
    local real MRDist
    local effect LE
    
    call CreateNUnitsAtLoc( 1, 'h005', GetOwningPlayer(cas), casp, 0.00)
    set L = GetLastCreatedUnit()
    call IssuePointOrderLoc( L, "move", casloc)
    
    loop
        set MRDist = DistanceBetweenPoints( GetUnitLoc(L), casloc)
        exitwhen MRDist < 50.00
        if MRDist < 50.00 then         
            call UnitDamagePointLoc( L, 0.00, 50.00, casloc, 500, ATTACK_TYPE_SIEGE, DAMAGE_TYPE_SONIC) 
            call KillUnit(L)
            call AddSpecialEffectLoc( T_SfxExp(), casloc)
            set LE = GetLastCreatedEffectBJ()
            call DestroyEffect(LE)             
        endif
    endloop
    
    set L = null
    set casp = null
    set casloc = null
    set RDist = 0.00
    set MRDist = 0.00
    set LE = null
    set cas = null
endfunction

//=================================================================
function InitTrig_A_Jass takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( t, function Trig_A_Jass_Actions )
    call TriggerAddCondition( t, Condition(function Trig_A_Jass_Condition))
endfunction



And the outcome was against my expectation of course. The projectile did come out and goes to the location but it didn't explode or anything. It just stands there doing nothing, more like a torchlight since my model brightens it surrounding.
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
I find it nice that you are trying to pick up JASS.

For now, I'll just note a few things.

Coordinates!
In JASS, we use coordinates. Nobody ever uses locations.
It is true that you need 2 coordinate variables for each location, but it handles everything way smoother (and you can easily calculate everything you need with 2 coordinates, while otherwise they have to be extracted from the location).

If you see a 'red function' (if you're using JNGP at least), that means you'll have to change it (there are a few exceptions, but in most cases they're bad).
(These are BJ's by the way).
"CreateNUnitsAtLoc" is completely redundant. "CreateUnit" is way more efficient (also uses coordinates).
CreateNUnitsAtLoc:
JASS:
function CreateUnitAtLocSaveLast takes player id, integer unitid, location loc, real face returns unit
    if (unitid == 'ugol') then
        set bj_lastCreatedUnit = CreateBlightedGoldmine(id, GetLocationX(loc), GetLocationY(loc), face)
    else
        set bj_lastCreatedUnit = CreateUnitAtLoc(id, unitid, loc, face)
    endif

    return bj_lastCreatedUnit
endfunction

function CreateNUnitsAtLoc takes integer count, integer unitId, player whichPlayer, location loc, real face returns group
    call GroupClear(bj_lastCreatedGroup)
    loop
        set count = count - 1
        exitwhen count < 0
        call CreateUnitAtLocSaveLast(whichPlayer, unitId, loc, face)
        call GroupAddUnit(bj_lastCreatedGroup, bj_lastCreatedUnit)
    endloop
    return bj_lastCreatedGroup
endfunction

CreateUnit:
JASS:
call CreateUnit( Player(0), 'h005', x, y, 0. )
If you're not using JNGP, you should definitely download it. It will help you so much in your quest to learn JASS.
You can CTRL-click on any BJ to see what the actual function looks like. Often they can be shortened by a great deal.


Here's another thing that can shorten your code.
What you did:
JASS:
local effect LE
call AddSpecialEffectLoc( T_SfxExp(), casloc)
set LE = GetLastCreatedEffectBJ()
call DestroyEffect(LE)

What's better:
JASS:
call DestroyEffect( AddSpecialEffect( T_SfxExp(), x, y ) )
No need for the local variables.
This time I used the one with coordinates again, because locations aren't necessary :)


"Distance Between Points" thing:
The formula to calculate distances between locations looks like this:
JASS:
local real distance = SquareRoot( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) )

Now, when you're comparing distances, you do not need the square root. It becomes:
JASS:
if (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) > radius*radius
In your case, 'radius' is 50. So you might as well write 2500. there.



Why it doesn't work

You're ordering the unit to move somwewhere, then instantly after that you check whether he's already arrived.
Not only that, you check whether he's arrived a thousand times in less than a second. This is really, really bad.
A loop doesn't 'wait', it runs really fast. The unit probably didn't even move before the trigger just crashed due to an infinite loop.

In JASS, we use timers. We don't order the unit to move, we make him move! :)
Set up a timer, create a hashtable (global variable) and save all data in it.
Then run the timer
JASS:
call TimerStart( t, 0.03125, true, function moveUnit )
(0.03125 is 1/32 by the way).

In the fuction "moveUnit" (or whatever you wish to call it), you reload all data from the hashtable and make the unit move with
JASS:
set x = x + MOVE_SPEED * Cos( facing * 0.017453292 )
set y = y + MOVE_SPEED * Sin( facing * 0.017453292 )

call SetUnitX( unit, x )
call SetUnitY( unit, y )
We add ' * 0.017453292 ' because the function "Cos" needs an angle in radians (the facing of a unit is in degrees).
You can also use bj_DEGTORAD if you'd like.

Then compare the distances as said before :)
Don't forget to clean the hashtable when all is said and done.
 
Status
Not open for further replies.
Top