HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Jass Problem( me again sorry)

02-01-2008, 05:42 AM#1
shadowange1
First off sorry for posting my spells too much, but iamm trying to learn jass fast so i am making spells i need with it fast.

This spell creates fire balls around the caster and rotates them around him for a given time. When the fire balls crash into an enemy the deal damage to that unit. This part works fine.
The part i am having a problem with is that when they finally hit something the effect never goes away it stays there where it hits them forever. In other words it never gets destroyed.

Also if anyone can give me tips on how to optimize my code plz do so. It will be greatly appreciated.

Also i need a question answered.
I have just found out if you try to destroy a local that does not point to anything the code will stop there. Is this true?
Hidden information:
Collapse JASS:
function Trig_Flame_Shield_Conditions takes nothing returns boolean
    if (GetSpellAbilityId() == 'A03O') then
        return true
    endif
    return false
endfunction

function Trig_Flame_Shield_Actions takes nothing returns nothing
    local effect e1
    local effect e2
    local effect e3
    local group g = CreateGroup()//main group that will be made to check if a collision has occured
    local group g2 = CreateGroup()//Filter group to get out unwanted units
    local unit cas = GetSpellAbilityUnit()
    local unit tar
    local unit f
    local real range//used to calculate where points are
    local real ang1 =GetRandomReal(0.00, 360.00)
    local real ang2 =GetRandomReal(0.00, 360.00)
    local real ang3 =GetRandomReal(0.00, 360.00)
    local real x
    local real y
    local real unitx=GetUnitX(cas)
    local real unity=GetUnitY(cas)
    local real d =(I2R(GetHeroStatBJ(bj_HEROSTAT_INT, cas, true)))//damage done
    local integer a1 = 0//is a check to see if fireball has hit anything
    local integer a2 = 0
    local integer a3 = 0
    local integer i = 0
    loop
        exitwhen i==1000//counter used to make the loop happen a certain amount of times
        set unitx=GetUnitX(cas)
        set unity=GetUnitY(cas)
        if (a1 == 0 ) then
            set range=250.
            set x =((Cos(ang1)*range)+unitx)//sets x point of fireball
            set y =((Sin(ang1)*range)+unity)//sets y point of fireball
            set e1=AddSpecialEffect( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnBirthMissile.mdl",x , y )//adds special effect to point
            set g =CreateGroup()
            set g2=CreateGroup()
            call GroupEnumUnitsInRange(g, x, y, 50, null)//gets group within special effect
            set g2 = Trig_CopyGroup(g)//copies group in order to filter
            loop//loop to filter units
                set f=FirstOfGroup(g2)
                exitwhen f==null
                if ( (IsUnitType(f, UNIT_TYPE_STRUCTURE)==true) or (IsUnitDeadBJ(f)==true) or (IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)==true) or (IsUnitAlly(f, GetOwningPlayer(cas))==true)) then
                    call GroupRemoveUnit( g, f )
                endif
            call GroupRemoveUnit(g2,f)
            endloop
            set tar = FirstOfGroup(g)//sets target to a unit in the group if any
            if (tar==null) then
                call DoNothing(  )
            else//damages the unit if there is one
                call UnitDamageTargetBJ( cas, tar, d, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC )
                set a1=1
                call DestroyEffectBJ(e1)//destroys the effect that got collided
            endif
        set ang1=ang1+.2//inc angle
        set f =null
        set tar =null
        call DestroyGroup(g)
        call DestroyGroup(g2)
        endif
        if (a2 == 0 ) then
            set range=350.
            set x =((Cos(ang2)*range)+unitx)
            set y =((Sin(ang2)*range)+unity)
            set e2=AddSpecialEffect( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnBirthMissile.mdl",x , y )
            set g =CreateGroup()
            set g2=CreateGroup()
            call GroupEnumUnitsInRange(g, x, y, 50, null)
            set g2 = Trig_CopyGroup(g)
            loop
                set f=FirstOfGroup(g2)
                exitwhen f==null
                if ( (IsUnitType(f, UNIT_TYPE_STRUCTURE)==true) or (IsUnitDeadBJ(f)==true) or (IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)==true) or (IsUnitAlly(f, GetOwningPlayer(cas))==true)) then
                    call GroupRemoveUnit( g, f )
                endif
            call GroupRemoveUnit(g2,f)
            endloop
            set tar = FirstOfGroup(g)
            if (tar==null) then
                call DoNothing(  )
            else
                call UnitDamageTargetBJ( cas, tar, d, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC )
                set a2=1
                call DestroyEffectBJ(e2)
            endif
        set f =null
        set tar =null
        set ang2=ang2+.15
        call DestroyGroup(g)
        call DestroyGroup(g2)
        endif
        if (a3 == 0 ) then
            set range=450.
            set x =((Cos(ang3)*range)+unitx)
            set y =((Sin(ang3)*range)+unity)
            set e3=AddSpecialEffect( "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnBirthMissile.mdl",x , y )
            set g =CreateGroup()
            set g2=CreateGroup()
            call GroupEnumUnitsInRange(g, x, y, 50, null)
            set g2 = Trig_CopyGroup(g)
            loop
                set f=FirstOfGroup(g2)
                exitwhen f==null
                if ( (IsUnitType(f, UNIT_TYPE_STRUCTURE)==true) or (IsUnitDeadBJ(f)==true) or (IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)==true) or (IsUnitAlly(f, GetOwningPlayer(cas))==true)) then
                    call GroupRemoveUnit( g, f )
                endif
            call GroupRemoveUnit(g2,f)
            endloop
            set tar = FirstOfGroup(g)
            if (tar==null) then
                call DoNothing(  )
            else
                call UnitDamageTargetBJ( cas, tar, d, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC )
                set a3=1
                call DestroyEffectBJ(e3)
            endif
        set ang3=ang3+.07
        set f =null
        set tar =null
        call DestroyGroup(g)
        call DestroyGroup(g2)
        endif
        call TriggerSleepAction( .01 )//waits time so that the object can appear to be moving changing this will decrease or increase movement spee ie .05 will be faster speed 
        call DestroyEffectBJ(e1)
        call DestroyEffectBJ(e2)
        call DestroyEffectBJ(e3)
        set i=i+1//increments loop by 1
    endloop
    set cas = null
endfunction

//===========================================================================
function InitTrig_Flame_Shield takes nothing returns nothing
    set gg_trg_Flame_Shield = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Flame_Shield, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Flame_Shield, Condition( function Trig_Flame_Shield_Conditions ) )
    call TriggerAddAction( gg_trg_Flame_Shield, function Trig_Flame_Shield_Actions )
endfunction


The Trig_CopyGroup() function works fine so thats not the issue.

Added some comments in first part since it jsut repeats that should say what im doing.
@PipeDream sorry for not commenting but im use to looking at long lists of code with out them >.<
02-01-2008, 06:02 AM#2
PipeDream
Quote:
I have just found out if you try to destroy a local that does not point to anything the code will stop there. Is this true?

Attempting to read a variable (including trying to destroy it) which has not been written stops execution. I wrote a couple tools for detecting when this can happen / does happen, the most usable is in the Jass NewGen pack over in the tools section.

Your code is too complicated for me to go through it line by line. I suggest splitting it into functions or at least commenting it. Otherwise after 6 months you will look at this code and go "Wha?".
02-01-2008, 08:43 AM#3
shadowange1
Okay im a dumbdonkey i figured out my problem after i read PipeDreams post 4 times over lol. When units got hit the effect got destroyed twice. This caused the problem but now its fixed =).

Expand JASS:

However can anyone help me optimize code?
that is point to tuts or other threads.
Also im a nub so is there anyway i could get a native list of like all the gui things?
02-01-2008, 03:01 PM#4
chobibo
Get Jass NewGen pack, it's packed with a complete function lists which can be accessed through TESH.
02-01-2008, 05:31 PM#5
Blue_Jeans
I will also advise you to get JASS NewGen pack. Additionally, I can help you recode your JASS, although I can't point you to tutorials. I've gathered what I know from bits and pieces everywhere. If you do get JASS NewGen, then I think Cohadar wrote something on optimization somewhere here.

I'll be waiting for your reply if you want my help.

Edit: Just briefly looking at your code, I'm not entirely why you are looping 1000 times. Also, like PipeDream said, you really ought to make some separate functions to do specific things. The one that really comes to mind is one to filter your units in the groupl. You can make a simple, yet moderate improvement on execution if you change your if(a2 == 0 )then and if(a3 == 0 )then into elseif's. This way, when a condition is met, the rest of the if's are not even tested. As your code is this huge mess, I'm not sure that changing them to elseif will not affect functionality. At a glance it appeared it would not.

Lastly, from the a1,a2,a3 statements, all that appears to change are a few numbers. If this is the case, we can entirely redo you trigger and make it vastly more efficient. Again, get back to me.

Edit2: Oh, the effects aren't destroyed because of the TriggerSleepAction(.01), I am pretty sure.
02-01-2008, 06:15 PM#6
shadowange1
The spell is fixedin functionality.Ty i will try the Genpack but i changed the loop to 100 times to make it last the 23 seconds i desired. and the a1,a2,a3 are unts that i change to 1 if the fireball has exploded so it no longer calculates or makes the effect again. sort of like a check to where 0=true,1=false, but i think it should be other way around in real code.

Oh a quick question if i make my own functions can they take and return things because ive tried making them but i always get a scripting error.
02-01-2008, 06:43 PM#7
Blue_Jeans
Ooh... sorry to be the one to tell you this, mate, but looping 100 times doesn't equal 23 seconds... it will last longer on laggy computers, which can cause desyncs depending on what happens afterward, or what you do with the unit.
You need to have a timer that executes every .05 seconds or so for 23 seconds. You would decrease the repetition time for a smoother feel, increasing it for a rougher feel, but it's less resource intensive.
Collapse JASS:
function DamageMultiplier takes integer level returns real
    return level * 1.8
endfunction
Hope that example helps you create custom functions. One reason that you might fail with them is because if you have code such as ForGroup(g,DamageMultiplier()), you cannot 'send' the function parameters.

Do you want my in-depth help or not? I need to know so I can organize my time.
02-01-2008, 07:24 PM#8
zen87
just some addon to make things run faster =\

Collapse JASS:
constant function DamageMultiplier takes integer level returns real
    return level * 1.8
endfunction
02-01-2008, 07:26 PM#9
Pyrogasm
Quote:
Originally Posted by shadowange1
Also im a nub so is there anyway i could get a native list of like all the gui things?
There's an online list at the main sourceforge page... http://jass.sourceforge.net/doc
02-01-2008, 09:17 PM#10
Blue_Jeans
Quote:
Originally Posted by zen87
just some addon to make things run faster =\

Collapse JASS:
constant function DamageMultiplier takes integer level returns real
    return level * 1.8
endfunction

I purposely left off constant... lol. This was just an example, I didn't want him to think you had to write constant every time. Actually, there are far better techniques than this example to do a damage multiplier, but it was the only function I'd ever written that I had where I took and returned things... it seems the more I use structs/handle systems the less I use these sort of functions.
02-02-2008, 12:05 AM#11
Pyrogasm
Adding "constant" doesn't make it any faster or slower. All it does is place a few restrictions on the function and allows it to be inlined by Vexorian's Map Optimizer.
02-02-2008, 12:35 AM#12
Malf
It gets inlined without the need of Map Optimizer :P

So something like this:

Collapse Before Compiling:
constant function DamagePerLevel takes integer i returns real
    return 40+(i*50)
endfunction

function Pwn takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit t = GetSpellTargetUnit()
local integer level = GetUnitAbilityLevel(u,'XXXX')
    call UnitDamageTarget(u,t,DamagePerLevel(level),true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
    set u = null
    set t = null
endfunction
Collapse Compiled Code:
function Pwn takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit t = GetSpellTargetUnit()
local integer level = GetUnitAbilityLevel(u,'XXXX')
    call UnitDamageTarget(u,t,40+(level*50),true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
    set u = null
    set t = null
endfunction
02-02-2008, 01:25 AM#13
Pyrogasm
Only with NewGen.