• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Can you fix my leaks?

Status
Not open for further replies.
Level 10
Joined
Dec 13, 2008
Messages
222
This is my new spell. It leaks like hell. Can someone help me. (it mustbe done in JASS not vJASS)

It creates 3 orbs which spin around caster and damage units when they come into collision with them. Then, orb destroys itself, deals damage and heals caster.

Pls, help... :S

JASS:
function Trig_Jiriki_2_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A03D'
endfunction

function OrbDamage takes unit orb1, unit orb2, unit orb3, integer level, unit u  returns nothing
    local location p
    local unit target
    local group g
    
    set p = GetUnitLoc (orb1)
    set g = GetUnitsInRangeOfLocAll(75.00, p)
    if orb1 != null then
    loop
       set target = FirstOfGroup(g)
       exitwhen target == null
       call GroupRemoveUnit(g,target)

       if (IsPlayerEnemy(GetOwningPlayer(orb1), GetOwningPlayer(target)) and (not(IsUnitType(target, UNIT_TYPE_STRUCTURE))) and (IsUnitAliveBJ (target))) then  
          call CreateNUnitsAtLoc( 1, 'h00L', GetOwningPlayer(orb1), p, 0.00 )
          call UnitAddAbilityBJ( 'A01W', GetLastCreatedUnit() )
          call SetUnitAbilityLevelSwapped( 'A01W', GetLastCreatedUnit(), 25 + 25*level - 1 )
          call IssueTargetOrderBJ( GetLastCreatedUnit(), "attackonce", target )
          call AddSpecialEffectLoc ("Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl", p)
          call DestroyEffect( GetLastCreatedEffectBJ() )
          call UnitApplyTimedLifeBJ( 1.00, 'BTLF', GetLastCreatedUnit() )
          call KillUnit( orb1 )
          call GroupClear( g )
          call SetUnitState( u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_LIFE) + 25 + 25*level  )
       endif
    endloop
    endif

    set p = GetUnitLoc (orb2)
    set g = GetUnitsInRangeOfLocAll(75.00, p)
    if orb2 != null then
    loop
       set target = FirstOfGroup(g)
       exitwhen target == null
       call GroupRemoveUnit(g,target)

       if (IsPlayerEnemy(GetOwningPlayer(orb2), GetOwningPlayer(target)) and (not(IsUnitType(target, UNIT_TYPE_STRUCTURE))) and (IsUnitAliveBJ (target))) then  
          call CreateNUnitsAtLoc( 1, 'h00L', GetOwningPlayer(orb2), p, 0.00 )
          call UnitAddAbilityBJ( 'A01W', GetLastCreatedUnit() )
          call SetUnitAbilityLevelSwapped( 'A01W', GetLastCreatedUnit(), 25 + 25*level - 1 )
          call IssueTargetOrderBJ( GetLastCreatedUnit(), "attackonce", target )
          call AddSpecialEffectLoc ("Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl", p)
          call DestroyEffect( GetLastCreatedEffectBJ() )
          call UnitApplyTimedLifeBJ( 1.00, 'BTLF', GetLastCreatedUnit() )
          call KillUnit( orb2 )
          call GroupClear( g )
          call SetUnitState( u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_LIFE) + 25 + 25*level  )
       endif
    endloop
    endif

    set p = GetUnitLoc (orb3)
    set g = GetUnitsInRangeOfLocAll(75.00, p)
    if orb3 != null then
    loop
       set target = FirstOfGroup(g)
       exitwhen target == null
       call GroupRemoveUnit(g,target)

       if (IsPlayerEnemy(GetOwningPlayer(orb3), GetOwningPlayer(target)) and (not(IsUnitType(target, UNIT_TYPE_STRUCTURE))) and (IsUnitAliveBJ (target))) then  
          call CreateNUnitsAtLoc( 1, 'h00L', GetOwningPlayer(orb3), p, 0.00 )
          call UnitAddAbilityBJ( 'A01W', GetLastCreatedUnit() )
          call SetUnitAbilityLevelSwapped( 'A01W', GetLastCreatedUnit(), 25 + 25*level - 1 )
          call IssueTargetOrderBJ( GetLastCreatedUnit(), "attackonce", target )
          call AddSpecialEffectLoc ("Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl", p)
          call DestroyEffect( GetLastCreatedEffectBJ() )
          call UnitApplyTimedLifeBJ( 1.00, 'BTLF', GetLastCreatedUnit() )
          call KillUnit( orb3 )
          call GroupClear( g )
          call SetUnitState( u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_LIFE) + 25 + 25*level  )
       endif
    endloop
    endif

    call RemoveLocation(p) 
    set target = null
    set orb1 = null
    set orb2 = null
    set orb3 = null
    call DestroyGroup(g)

endfunction

function OrbCircle takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = GetHandleUnit(t, "u")
    local integer level = GetHandleInt(t, "level")
    local unit orb1 = GetHandleUnit(t, "orb1")
    local unit orb2 = GetHandleUnit(t, "orb2")
    local unit orb3 = GetHandleUnit(t, "orb3")
    local location p 
    local real ang1 = GetHandleReal (t, "ang1")
    local real ang2 = GetHandleReal (t, "ang2")
    local real ang3 = GetHandleReal (t, "ang3")
    local location loc1
    local location loc2
    local location loc3
    local integer steps = GetHandleInt(t, "steps")

    set p = GetUnitLoc(u)    
    set ang1 = ang1 + 10.00
    if ang1 == 360.00 then
    set ang1 = 0
    endif
    call SetHandleReal(t, "ang1", ang1)
    set loc1 = PolarProjectionBJ(p, 100.00, ang1)  

    set p = GetUnitLoc(u)
    set ang2 = ang2 + 10.00
    if ang2 == 360.00 then
    set ang2 = 0
    endif
    call SetHandleReal(t, "ang2", ang2)
    set loc2 = PolarProjectionBJ(p, 100.00, ang2)    

    set p = GetUnitLoc(u)
    set ang3 = ang3 + 10.00
    if ang3 == 360.00 then
    set ang3 = 0
    endif
    call SetHandleReal(t, "ang3", ang3)
    set loc3 = PolarProjectionBJ(p, 100.00, ang3)
    
    if orb1 != null then
    call SetUnitPositionLoc( orb1, loc1)
    endif
    
    if orb2 != null then
    call SetUnitPositionLoc( orb2, loc2)
    endif
   
    if orb3 != null then
    call SetUnitPositionLoc( orb3, loc3)
    endif

    call OrbDamage(orb1, orb2, orb3, level, u)
    
    call RemoveLocation(p) 
    call RemoveLocation(loc1)
    call RemoveLocation(loc2)
    call RemoveLocation(loc3)
        
    set steps = steps - 1
    if (steps == 0 or (orb1==null and orb2==null and orb3==null)) then
        call RemoveUnit( orb1 )
        call RemoveUnit( orb2 )
        call RemoveUnit( orb3 )
        set orb1 = null
        set orb2 = null
        set orb3 = null
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    endif

    set orb1 = null
    set orb2 = null
    set orb3 = null

endfunction

function CreateOrbs takes unit u, integer level, real duration returns nothing
    local unit orb1
    local unit orb2
    local unit orb3
    local location p = GetUnitLoc(u)
    local real ang1 = 120.00
    local real ang2 = 240.00
    local real ang3 = 360.00
    local location loc1 = PolarProjectionBJ(p, 100.00, ang1)
    local location loc2 = PolarProjectionBJ(p, 100.00, ang2)
    local location loc3 = PolarProjectionBJ(p, 100.00, ang3)
    local timer t = CreateTimer()
    local integer steps = 375
         
    call CreateNUnitsAtLoc( 1, 'h01M', GetOwningPlayer(u), loc1, 0.00 )
    call UnitApplyTimedLifeBJ( 15.00, 'BTLF', GetLastCreatedUnit() )
    set orb1 = GetLastCreatedUnit()

    call CreateNUnitsAtLoc( 1, 'h01M', GetOwningPlayer(u), loc2, 0.00 )
    call UnitApplyTimedLifeBJ( 15.00, 'BTLF', GetLastCreatedUnit() )
    set orb2 = GetLastCreatedUnit()
   
    call CreateNUnitsAtLoc( 1, 'h01M', GetOwningPlayer(u), loc3, 0.00 )
    call UnitApplyTimedLifeBJ( 15.00, 'BTLF', GetLastCreatedUnit() )
    set orb3 = GetLastCreatedUnit()

    call SetHandleHandle (t,"orb1",orb1)
    call SetHandleHandle (t,"orb2",orb2)
    call SetHandleHandle (t,"orb3",orb3)
    call SetHandleHandle (t,"u", u)
    call SetHandleReal(t, "ang1", ang1)
    call SetHandleReal(t, "ang2", ang2)
    call SetHandleReal(t, "ang3", ang3)
    call SetHandleInt(t, "level", level)
    call SetHandleInt(t, "steps", steps)

    call TimerStart(t, 0.04, true, function OrbCircle)

    call RemoveLocation(p) 
    call RemoveLocation(loc1)
    call RemoveLocation(loc2)
    call RemoveLocation(loc3)
    
    set orb1 = null
    set orb2 = null
    set orb3 = null 
  
endfunction

function Trig_Jiriki_2_Actions takes nothing returns nothing
    local unit u = GetSpellAbilityUnit()
    local integer level = GetUnitAbilityLevelSwapped('A03D', u)
    local real duration = 15.00

    call CreateOrbs(u, level, duration)
    set u = null

endfunction

//===========================================================================
function InitTrig_Jiriki_2 takes nothing returns nothing
    set gg_trg_Jiriki_2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Jiriki_2, EVENT_PLAYER_UNIT_SPELL_FINISH )
    call TriggerAddCondition( gg_trg_Jiriki_2, Condition( function Trig_Jiriki_2_Conditions ) )
    call TriggerAddAction( gg_trg_Jiriki_2, function Trig_Jiriki_2_Actions )
endfunction
 
Level 8
Joined
May 21, 2008
Messages
218
You need this function

JASS:
loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        if ( Trig_Damage_Detection_Copy_Func001Func001C() ) then
            if ( Trig_Damage_Detection_Copy_Func001Func001Func002C() ) then
                if ( Trig_Damage_Detection_Copy_Func001Func001Func002Func002C() ) then
                    if ( Trig_Damage_Detection_Copy_Func001Func001Func002Func002Func002C() ) then
                        if ( Trig_Damage_Detection_Copy_Func001Func001Func002Func002Func002Func002C() ) then
                            if ( Trig_Damage_Detection_Copy_Func001Func001Func002Func002Func002Func002Func001C() ) then
                                call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_001" )
                                return
                            else
                            endif
                        else
                        endif
                    else
                    endif
                else
                endif
            else
            endif
        else
        endif
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop

By the way, that's called Karma
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
@ Zypher: I wonder what are you trying to do with that suggestion... It doesn't have any use, just spams messages... -.-

Yea... I was thinking "wtf is he talking about?".

Anyway, you leak a ton of pointers that reference the locations and groups you destroy.

JASS:
local location l = some_location // this means that "l" points to that location, "l" is NOT the location

....

call RemoveLocation(l); // removes the location, NOT the pointer
set l = null // this nulls the pointer

// same goes for groups and any type you need to destroy, since they are all pointers
// (includes units, but you usually won't want to destroy them)

And just to show you what it does (if you understand this, of course :p)
Code:
typedef struct
{
    float x,y,z;
} loc, *Location;

Location CreateLocation(float x,float y,float z)
{
    Location l = new loc;
    l->x = x;
    l->y = y;
    l->z = z;
    return l;
}
void RemoveLocation(Location l)
{
    delete l;
}

// somewhere in the code

Location l = CreateLocation(5.4,30,495.123);
...
RemoveLocation(l);
l = NULL;
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Probably c++, it seems.

But in warcraft 3 locations don't have a Z coordinate... At least, I'm pretty sure they don't "store" it anywhere.

native GetLocationZ takes location whichLocation returns real


Unless warcraft actually searches for the Z according to the X/Y, I'd say locations have a Z.

And yes that was C++.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,191
Locations do not store a Z I believe.
They store an X and Y and probably generate the Z on demand by getting terane height at that specific point.

This explains why there is no "set location Z" and why the Z updates if you move the location. It also is logical as nothing seems to use a Z value that takes a location. Still it is illogical why blizzard did not include a GetZ which takes the x and y directly, afterall they do that for locations. Also people say the Z returned is inaccurate, again probably a shortcut used to fetch it on demand and not store it.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
That's correct. The Z you get is probably a linear interpolation between the height of the 3 nearest terrain grid "points".

The Location constructor only takes x and y coordinates, no Z coordinates. I guess blizzard did not include a Z coordinate on points because it wasn't needed. And frankly, it isn't needed either in warcraft. Everything in warcraft 3, after all, is done only using X and Y coordinates.

Even something like "flying height" doesn't really have a gameplay function, and the "height" of the unit is simply calculated by getting the height of the terrain + the flying height.
 
Level 14
Joined
Nov 18, 2007
Messages
816
Okay,
1.) you leak a ton of groups.
2.) you destroy timers
3.) you dont nullify all local handles that are destroyed later on.
4.) you dont indent (properly).
5.) you use BJs where natives would be far more efficient (IsUnitAliveBJ(), UnitApplyTimedLifeBJ(), CreateNUnitsAtLoc(), GetLastCreatedUnit(), GetUnitAbilityLevelSwapped(),...)
6.) most balancing related values are hardcoded
7.) you use I2H() (LHV)
8.) you use RemoveUnit()
9.) I must have overlooked something. Oh, yeah, you use locations.

Off-Topic: Warcraft 3 is written in C for the most part, iirc.
 
Level 14
Joined
Nov 18, 2007
Messages
816
2.) Use TimerUtils. If you cant use the vJass version, convert it to Jass.
4.) look up "indentation" in a dictionary, maybe even google for it. Im sure youll find a good explanation for it.
6.) things like duration should be in constant functions at the top of this script.
7.) Random bugs, even handle stack corruption.
8.) Kill + hide units.
 
Level 8
Joined
May 21, 2008
Messages
218
You were trying to help, I know, but it just takes more skill. So, I gave you reputation for trying to help.

Your a funny one. For everyone that didn't understand, he made a damage system and tried to submit it. It was completely useless, all it did is spam messages. He was trying to make fun of the hive and he knows it. I posted back that code because it was completely useless. Click the link in his signature to see it ofr yourself. That's also why I mentioned karma at the bottom of the code. That's why I laughed when he repped me.

Edit: he repped me again...lol...at least he's generous.
 
Level 10
Joined
Dec 13, 2008
Messages
222
Thanks Deaod, it really helped me, but I have one more question, what is the best function for creating units and getting last created unit? (without vJASS)

@Zypher: At that time even knew less GUI and JASS than now. Consider that silly system as a failure because I was serious when I was making it. *ashamed*
 
Status
Not open for further replies.
Top