[JASS] New errors/bugs

Level 29
Joined
Jul 29, 2007
Messages
5,174
Well, I changed my shooting system and also created a new spell and they both have all kind of weird errors that just can't be true.

I searched for any mistakes because I know that the WE is a noobish thing and it creates tons of new errors when it gets a real error but I couldn't find anything.

Here are both of the scripts

Shooting
JASS:
function Shoot_Con takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction
function TimerActions takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit summon = GetHandleUnit(t, "summon" )
    local integer i = GetHandleInt(t, "i" )
    local real a = GetUnitFacing(summon) * bj_DEGTORAD
    local real x = GetUnitX(summon) + 20 * Cos(a)
    local real y = GetUnitY(summon) + 20 * Sin(a)    
    // start of summon height               
    local real height = GetHandleReal(t, "height")
    local real distance = GetHandleReal(t, "distance")
    local real currentheight = GetUnitFlyHeight(summon)
    call SetUnitFlyHeight(summon, currentheight+height/(distance/10))
    // end of summon height 
    call SetUnitPosition( summon, x, y )
    if i >= 100 then
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        call KillUnit(summon)
    else
        call SetHandleInt(t, "i", i + 1)
    endif
    set t = null
    set summon = null
endfunction
function Shoot takes nothing returns nothing
    local timer t = CreateTimer()
    local unit u = GetTriggerUnit()
    local real a = GetUnitFacing(u) * bj_DEGTORAD
    local real x = GetUnitX(u) + 50 * Cos(a)
    local real y = GetUnitY(u) + 50 * Sin(a)
    local integer i = 0
    local unit summon = CreateUnit(GetOwningPlayer(u), 'h000', x, y, GetUnitFacing(u))
    // start of target location height check
    local location oldloc = Location(x,y)
    local location loc = GetSpellTargetLoc()
    local real oldx = GetLocationX(loc)
    local real oldy = GetLocationY(loc)
    local real oldheight = GetLocationZ(oldloc)
    local real height = GetLocationZ(loc)
    local real distance = DistanceBetweenPointsXY(oldx,oldy,x,y)
    set height = height-oldheight
    call SetHandleReal(t, "height", height)
    call SetHandleReal(t, "distance", distance)
    // end of target location height check  
    call SetHandleHandle( t, "summon", summon )
    call SetHandleInt( t, "i", i )
    call TimerStart( t, 0.02, true, function TimerActions )
    set t = null
    set u = null
    set summon = null
    set oldloc = null
    set loc = null
endfunction

//===========================================================================
function InitTrig_Shooting_System takes nothing returns nothing
    set gg_trg_Shooting_System = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Shooting_System, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Shooting_System, Condition( function Shoot_Con ) )
    call TriggerAddAction( gg_trg_Shooting_System, function Shoot )
endfunction

Lightning Storm
JASS:
function Trig_LightningStorm_Cons takes nothing returns boolean
    return GetSpellAbilityId() == 'A002'
endfunction
function TimerActionsLightningStorm takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = GetHandleUnit(t, "caster")
    local real oldx = GetHandleReal(t, "x")
    local real oldy = GetHandleReal(t, "y") 
    local location oldloc = Location(oldx,oldy)
    local location loc = PolarProjectionBJ(oldloc, GetRandomReal(0, 350.00), GetRandomReal(0, 359.00))
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local unit lightningbolt = CreateUnit(GetOwningPlayer(u), 'h002', x, y, 0)
    local integer i = GetHandleInt(t, "i")
    call UnitDamagePoint(u, 0, 50, x, y, 100, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_LIGHTNING, WEAPON_TYPE_WHOKNOWS)
    call UnitApplyTimedLife( 0.50, 'BTLF', lightningbolt )
    if i >= 10 then
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    else
        call SetHandleInt(t, "i", i + 1)
    endif
    set t = null
    set u = null
    set lightningbolt = null
    set oldloc = null
    set loc = null
endfunction
function Trig_LightningStorm_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local location loc = GetSpellTargetLoc()
    local real x = GetLocationX(loc)
    local real y = GetLocationY(loc)
    local timer t = CreateTimer()
    local integer i = 0
    local integer int = 0 
    call SetHandleInt(t, "i", i)
    call SetHandleHandle(t, "caster", u)
    call SetHandleReal(t, "x", x)
    call SetHandleReal(t, "y", y)
    loop
        exitwhen int > 5
        call CreateNUnitsAtLoc( 1, 'h001', GetOwningPlayer(GetTriggerUnit()), PolarProjectionBJ(GetRectCenter(GetPlayableMapRect()), GetRandomReal(0, 300.00), GetRandomReal(0, 359.00)), bj_UNIT_FACING )
        call UnitApplyTimedLife( 30, 'BTLF', GetLastCreatedUnit() )
        set int = int+1
    endloop
    call TimerStart(t, 3, true, function TimerActionsLightningStorm)
    set u = null
    set loc = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Lightning_Storm takes nothing returns nothing
    set gg_trg_LightningStorm = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_LightningStorm, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_LightningStorm, Condition( function Trig_LightningStorm_Cons ) )
    call TriggerAddAction( gg_trg_LightningStorm, function Trig_LightningStorm_Actions )
endfunction


The lightning storm just basicly makes a few dummies that look like clouds, and then every 3 seconds create a dummy unit at a random place near the target area that looks like lightning and damages the area he was created in.
 
Level 6
Joined
Dec 31, 2005
Messages
712
I copied the codes to JassCraft and got the errors:

In Shooting:
1. You didn't pass all the parameters to SetUnitFlyHeight: SetUnitFlyHeight( unit, height, rate).

In Storm:
1. You swapped the first and the last parameters in UnitApplyTimedLife. The unit should come first and the time last.
2. You did number 1 twice o/

I think that's all. Though I don't think the shooting will work xD
Good luck

EDIT
Just a hint, in instead of using CreateNUnitsAtLoc, use CreateUnit:

native CreateUnit takes player id, integer unitid, real x, real y, real face returns unit

Besides using coordinates, it's a native, far better than CreateNUnitsAtLoc. This way you will also avoid using PolarProjectionBJ...

But remember that CreateUnit(...) does not use GetLastCreatedUnit()!! you have to set a variable or use it directly in the next function, like:

call UnitApplyTimedLife( CreateUnit( blah ), 'BTLF', 30 )
 
Last edited:
Level 6
Joined
Dec 31, 2005
Messages
712
A spelling mistake at function createfirebolts: You wrote "ablevle" when you gt the level of the ability.

And You use GetHandleHandle to set a unit at the same function. You should use GetHandleUnit.

And, man... Whats that?

JASS:
endloopgger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_NewTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(gg_trg_NewTrigger, Condition(function Trig_NewTrigger_Conditions))
    call TriggerAddAction(gg_trg_NewTrigger, function Trig_NewTrigger_Actions)
endfunction

What's endloopgger? xD
Maybe you wrote an endloop over the CreateTrigger()...
 
Level 6
Joined
Dec 31, 2005
Messages
712
It took me some days to find this out, but I reached this equation.

Every equation for an arc comes from this basic equation:

y = ax² + bx + c

Where y can be the height and x anything else.
I made an equation assuming y is the height and x is the time the unit is "flying", so the distance is determined by any other equation.

If you want me to demonstrate the formula, ask me to make a picture because I think it would be impossible to understand as text xD

y = (4h/-t²)x² + (4h/t)x

Where:
h = Maximum height reached
t = Time from the starting position to the end
x = Time elapsed since the movement started.

It will give the height y at x th second.

As it's an arc, the first (0 second) and the last positions (t seconds) should be height = 0. So:

First position:
y = (4h/-t²).0² + (4h/t).0 = 0

Last position:
y = (4h/-t²). + (4h/t).t
y = 4h/-1 + 4h
y = -4h + 4h = 0

try it:
JASS:
function ArcPosition takes real h, real t, real x returns real
    return ((4*h)/-t*t)*x + ((4*h)/t)*x
endfunction

function TimerActions takes nothing returns nothing
 local timer T = GetExpiredTimer()
 local real Time = GetHandleReal(T, "time")
    call SetUnitFlyHeight( Unit, ArcPosition( 200, 2, t ) )
    // The unit will reach 200 height and reach its destination in 2 seconds
    call SetHandleReal( T, "time", Time + 0.02 )
    // Assuming the timer has a 0.02 expiration time
endfunction
According to my notes, that's it...

Offtopic
Icons are changing at Hive Workshop o/
 
Last edited:
Level 6
Joined
Dec 31, 2005
Messages
712
I don't know the really meanings of a, b and c either. I can guess, but I'd better don't trust so much on my guessing xD

My equation come from this:

y = ax² + bx + c
x will be the current time and y the current height.
The Max height (H) will be given by the user, as well as the total time of the movement (T).

The arc will cross the y axis at the point (0, c). So, as the arc for a jump MUST cross the point (0, 0), c = 0.

The y of the vertex of the arc (highest point of the arc) is the maximum height (H), and is defined by -∆/4a.

∆ is defined by b² - 4ac. I found out that c = 0, so ∆ = b².

This way, H = -b²/4a.

Next, the x of the vertex is defined by -b/2a. As it's an arc steady movement, the x of the arc will obviously be the middle way of the movement, I mean, T/2, being T the total time of the movement (user defined).

So: -b/2a = T/2. Dray it as two fractions, and multiplying in cross we'll have -2b = 2aT. Divide that by -2, and the result: b = -aT.

We've discovered 'c' and half of 'b', as we still use 'a' to discover 'b', what we don't know yet. Now we need 'a'.

H is -b²/4a, as I've stated. As we've found out that b = -aT we can swap 'b' in the max height equation, having -(-aT)²/4a.

H = -(-aT)²/4a
H = -[a²]T²/4[a]
H = -aT²/4 Multiplying by 4
4H = -aT² Dividing by -T²
4H/-T² = a

We got the equation of 'a', now let's finish 'b':

b = -aT Put the 'a' equation
b = -(4H/[-T²]).[T]
b = -4H/-T
b = 4H/T

Result:
a = 4H/-T²
b = 4H/T
c = 0

y = 4Hx/-T² + 4Hx/T

As you see, I didn't use any of the "definitions" of each part of the equation. I just used all the equations I knew xD

And for your spell, I think the exitwhen should be when u == null, and not g.
Also, instead of GetUnitsInRangeOfLocMatching, try using EnumUnitsInRange. It uses coordinates and is a native:

native GroupEnumUnitsInRange takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing

The units will be added to whichGroup.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
I don't think so, because you literally overwrite "u" by the new FirstOfGroup unit. When the loop ends, FirstOfGroup() will be null (as the unitgroup is null), thus "u" will automatically be nulled.

Which brings me to the question:
Someone told me that if I do:
JASS:
set locvar = GetUnitLoc(or something like that)
// Do stuff with the loc
set locvar = GetUnitLoc(another unit)
// Do more stuff
call RemoveLocation(locvar)
then the second point will be removed, although the first point I used will still leak... Why's that?
Edit: Yeah, the same guys told me that it had something to do with the way locations are "created", but I'd like to know a more specific reason to why it actually leaks.
Edit 2: And I'm sorry for hijacking this thread with that question :)
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
You need to remove location each time
You should null the variable at bottom of function not inside
... oh a Just as Eleandor said (damn you)
 
Level 6
Joined
Dec 31, 2005
Messages
712
You should use like that:

JASS:
function Parabula takes real H, real T, real x returns real
    return ((4*H)/-(T*T))*(x*x) + ((4*H)/T)*x
endfunction

function TimerActions takes nothing returns nothing
 local timer T = GetExpiredTimer()
 local unit U = GetHandleUnit(T, "Unit")
 local real x = GetHandleInt(U, "x")
 local real y = Parabula( 500, 2, x )
    call SetUnitFlyHeight( U, y, 0 ) // I think that using 0 will make it instant
    call SetHandleReal( U, "x", x + 0.02 )
 set T = null
 set U = null
endfunction

I'm quite sure it's this way and it works xD
Can't check it right now since I'm not home, and this keyboard is crappy \o/

And the equation does work:

x = 0:
-500*0² + 1000*0 = 0

x = 2:
-500*2² + 1000*2 = 0

x = 1
-500*1 + 1000*1 = 500 (middle way == max height)

About the locations, I learned that each function that returns a location creates the handle, so you'll need to destroy it o_O
But I learned thought other people who may be wrong also xD

Offtopic: sorry for any possible missing lettrs, this keyboard is CRAP xD
And you can call me just Hossomi, as evyone in everywhere does xDDD
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
JASS:
function TimerActionsG takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit whichUnit = GetHandleUnit(t, "whichUnit")
    local real speed = GetHandleReal(t, "speed")
    local real a = GetHandleReal(t, "angle")
    local real time = GetHandleReal(t, "time")
    local real gravity = GetHandleReal(t, "gravity")
    local real vstart = GetHandleReal(t, "vstart")
    local real x = GetUnitX(whichUnit) + speed * Cos(a)*0.02 // Use normal speeds like 600 instead of 30000
    local real y = GetUnitY(whichUnit) + speed * Sin(a)*0.02
    local real height = time*(vstart-0.5*gravity*time)
    call SetUnitPosition(whichUnit, x, y)
    call SetUnitFlyHeight(whichUnit, height, 0.)
    call SetHandleReal( t, "time", time + 0.02 )
    if height <= 0. then
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        call SetUnitFlyHeight(whichUnit, 0., 0.)
    endif
    set t = null
    set whichUnit = null
    endfunction
function ArcStart takes unit whichUnit, real speed, real angle, real totaltime, real maxheight  returns nothing
    local timer t = CreateTimer()
    local real a = angle*bj_DEGTORAD
    local real time = 0
    local real gravity = (2*maxheight)/(totaltime*totaltime)
    call SetHandleReal(t, "vstart",0.5*gravity*totaltime )  
    call SetHandleReal(t, "gravity", gravity)
    call SetHandleHandle(t, "whichUnit", whichUnit)
    call SetHandleReal(t, "speed", speed)
    call SetHandleReal(t, "angle", a)
    call SetHandleReal(t, "time", time)
    call TimerStart(t, 0.02, true, function TimerActionsG)
    set t = null
endfunction

I just learned how to use handle vars
 
Level 6
Joined
Dec 31, 2005
Messages
712
If I'm fine today Need_O2, I think your function will never reach the max height.
If I call
call ArcStart( U, 100, 0, 2.0, 500 )

Calculations will be:
Gravity = 2*500/2² = 250
vstart = 0.5*250*2 = 250

So, when time == 1:
height = 1*(250 - 0.5*250*1) = 125

From now on, height will only decrease...
But it's an arc anyway xD
 
Level 6
Joined
Dec 31, 2005
Messages
712
Note that the unit will hit only one unit in the group, and this considering that FirstOfGroup does not return whichUnit...
And, ANYWAY, you kill whichUnit xD :
JASS:
if u != null and u != whichUnit then
  call KillUnit(whichUnit)
endif

The function EnumUnitsInRange uses RADIUS, so 50 will be the radius, creating a circle of 100 diameter.

And a boolexpr is a Boolean Expression, returned by the function Condition( function Whatever ).
It's just like you add a condition:
JASS:
function MyCondition takes nothing returns boolean
    return <blah>
endfunction

function Dunno takes nothing returns nothing
    call GroupEnumUnitsInRange( g, x, y, r, Condition( function MyCondition ) )
endfunction
 
Top