HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Why doesnt this Jass script work?

02-24-2007, 05:02 AM#1
Tiku
Im sorta new at JASS not really too new but im having a couple of problems with this script....

Collapse JASS:
function Trig_Frost_Mine_Conditions takes nothing returns boolean
    if ( not ( GetUnitTypeId(GetDyingUnit()) == 'n001' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Frost_Mine_Func001001002 takes nothing returns boolean
    return ( IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT) != true )
endfunction

function Trig_Frost_Mine_Func001A takes nothing returns nothing
    call PauseUnitBJ( true, GetEnumUnit() )
    call AddSpecialEffectTarget( "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl", GetEnumUnit(), "origin" ) 
    call PolledWait( 7.00 )
    call PauseUnitBJ( false, GetEnumUnit() )
    call DestroyEffectBJ(GetLastCreatedEffectBJ())
endfunction

function Trig_Frost_Mine_Actions takes nothing returns nothing
    local location loc = GetUnitLoc(GetDyingUnit())
    local effect se
      call AddSpecialEffectLocBJ( loc, "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl" )
      set se = GetLastCreatedEffectBJ()
      call ForGroupBJ( GetUnitsInRectMatching(GetPlayableMapRect(), Condition(function Trig_Frost_Mine_Func001001002)), function Trig_Frost_Mine_Func001A )
      call PolledWait( 2.0 )
      call DestroyEffectBJ( se )
      set se = null
      set loc = null   
endfunction

//===========================================================================
function InitTrig_Frost_Mine takes nothing returns nothing
    set gg_trg_Frost_Mine = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Frost_Mine, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Frost_Mine, Condition( function Trig_Frost_Mine_Conditions ) )
    call TriggerAddAction( gg_trg_Frost_Mine, function Trig_Frost_Mine_Actions )
endfunction


Basically its my custom "Freeze" spell...
The mine is suppose to explode then all the units nearby get frozen =P
It works by pausing and unpausing the units.... but when the units pause, they wont unpause after the Polled time... =/ and ive tried "messing around" with some of the script to see whats messing it up...

Im not sure if its Messed up or its just not written correctly...
Please help =]
02-24-2007, 08:03 AM#2
Pyrogasm
Hows about we learn how to optimize, ok?

Take, for example, your first function:
Collapse JASS:
function Trig_Frost_Mine_Conditions takes nothing returns boolean
    if ( not ( GetUnitTypeId(GetDyingUnit()) == 'n001' ) ) then
        return false
    endif
    return true
endfunction
Firstly, you're using GetDyingUnit(). While that's well and good, GetTriggerUnit() is always faster; use that instead. The next thing we notice is that it's using an If statement in a condition that returns a boolean... Now, if we know that return <statement> returns either "true" or "false", wouldn't it just be a lot simpler to write:
Collapse JASS:
function Trig_Frost_Mine_Conditions takes nothing returns boolean
   return GetUnitTypeId(GetTriggerUnit()) == 'n001'
endfunction

Next (switching to the actions), you've got a local location and some SFX BJ's. Locations = slow, so you'll want to use local reals X and Y whenever you can (though sometimes you need a location). So, we'll create a unit variable and have these lines now:
Collapse JASS:
local unit U = GetTriggerUnit()
local real X = GetUnitX(U)
local real Y = GetUnitY(U)

If we change that, now we've got to change our SFX actions and remove those BJ's because there's usually a native for them. In this case, we can eliminate one line of code by directly setting the effect when it's declared like this: local effect se = AddSpecialEffect("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", X, Y). Alternatively, if the effect is able to be destroyed when it's created and still play its animation, you can use this: call DestroyEffect(AddSpecialEffect("Model file", X, Y))
Alltogether, the actions now look like this:
Collapse JASS:
function Trig_Frost_Mine_Actions takes nothing returns nothing
    local unit U = GetTriggerUnit()
    local real X = GetUnitX(U)
    local real Y = GetUnitY(U)
    local effect se = AddSpecialEffect("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", X, Y)
        call ForGroupBJ( GetUnitsInRectMatching(GetPlayableMapRect(), Condition(function Trig_Frost_Mine_Func001001002)), function Trig_Frost_Mine_Func001A )
        call PolledWait( 2.0 )
        call DestroyEffect(se)
    set se = null
    set U = null 
endfunction

Moving on to the line call ForGroupBJ( GetUnitsInRectMatching(GetPlayableMapRect(), Condition(function Trig_Frost_Mine_Func001001002)), function Trig_Frost_Mine_Func001A )... Once again, we can remove the BJ function and instead of replacing it with a new one, create a loop work-around that works just fine. Basically, we pick every unit we want in a group, then initiate a loop in which we set a variable to the first one of the group, do some actions with it, remove it from the group, and then loop over again until there are no more units in the group. Here's what that looks like:
Collapse JASS:
loop
    set U = FirstOfGroup(G) //U being the unit variable and G being our group
    exitwhen U == null //So we can exit when the group is empty
    //Do some stuff with U
    GroupRemoveUnit(G, U) //Removing it from the group
endloop

To apply this, we'll first need to get our group. We'll use the GroupEnumUnitsInRange() native for this, which picks units that match a condition in a radius of Z from X and Y values. Our X and Y values are already present, our radius will be whatever you want (you made it affect every unit on the map; I'll say the radius is 300), and our condition (otherwise known as a boolexpr filter; here is an explaination of one) is function Trig_Frost_Mine_Func001001002. Before using GroupEnumUnitsInRange(), you must create a group. Thus, we will now have to add the following line to a variable declaration: local group G = CreateGroup().

After straigtening out the group mess, we'll need another unit variable U2, in this instance, and an application of the loop mentioned above. So let's just change the instances of GetEnumUnit() and mush the whole thing together. Now it'll look like this:
Collapse JASS:
function Trig_Frost_Mine_Actions takes nothing returns nothing
    local unit U = GetTriggerUnit()
    local real X = GetUnitX(U)
    local real Y = GetUnitY(U)
    local effect se = AddSpecialEffect("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", X, Y)
    local group G = CreateGroup()
    local unit U2
        call GroupEnumUnitsInRange(G, X, Y, 300.00, Conditon(function Trig_Frost_Mine_Func001001002))
        loop
            set U2 = FirstOfGroup(G) //This MUST be before the exitwhen, else the loop will instantly end
            exitwhen U2 == null
            call PauseUnitBJ( true, GetEnumUnit() )
            call AddSpecialEffectTarget( "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl", GetEnumUnit(), "origin" )
            call PolledWait( 7.00 )
            call PauseUnitBJ( false, GetEnumUnit() )
            call DestroyEffectBJ(GetLastCreatedEffectBJ())
            call GroupRemoveUnit(G, U2)
        endloop
        call PolledWait( 2.0 )
        call DestroyEffect(se)
    set se = null
    set U = null
    call DestroyGroup(G)
    set G = null
    set U2 = null
endfunction

Immediately you should notice that the loop will now wait 7.00 seconds before switching to the next unit, that there are a few BJ's in there, and that "LastCreatedEffectBJ()" won't return the correct value. To fix the waiting problem we simply remove the wait, add those units to another unit group, add the wait back in after the loop, and loop once again through the second group to unpause/remove the effects. It's now going to look something like this:
Collapse JASS:
function Trig_Frost_Mine_Actions takes nothing returns nothing
    local unit U = GetTriggerUnit()
    local real X = GetUnitX(U)
    local real Y = GetUnitY(U)
    local effect se = AddSpecialEffect("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", X, Y)
    local group G = CreateGroup()
    local unit U2
    local group G2 = CreateGroup()
        call GroupEnumUnitsInRange(G, X, Y, 300.00, Conditon(function Trig_Frost_Mine_Func001001002))
        loop
            set U2 = FirstOfGroup(G)
            exitwhen U2 == null
            call PauseUnit(U2, true)
            call AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl", U2, "origin")
            call GroupAddUnit(G2, U2)
            call GroupRemoveUnit(G, U2)
        endloop
        call PolledWait(7.00)
        loop
            set U2 = FirstOfGroup(G2)
            exitwhen U2 == null
            call PauseUnit(U2, false)
            call DestroyEffect(GetLastCreatedEffectBJ())
            call GroupRemoveUnit(G2, U2)
        endloop
        call PolledWait(2.0)
        call DestroyEffect(se)
    set se = null
    set U = null
    call DestroyGroup(G)
    set G = null
    set U2 = null
    call DestroyGroup(G2)
    set G2 = null
endfunction

Once again, there is a problem with the SFX. I personally would have just made a dummy spell based off of storm bolt that had the freezing breath art as a buff for the stun, which would have eliminated any need for waits, SFX, and/or pausing units... but we can do it the hard way. For this, we will need a local integer I and a local effect array SFX.

We're going to increment I with every iteration of the first loop, then set SFX's index equal to I each time. Next, we'll loop through all indexes of SFX until we've reached our last one. Here's how we'll go about doing this:
Collapse JASS:
function Trig_Frost_Mine_Actions takes nothing returns nothing
    local unit U = GetTriggerUnit()
    local real X = GetUnitX(U)
    local real Y = GetUnitY(U)
    local effect se = AddSpecialEffect("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", X, Y)
    local group G = CreateGroup()
    local unit U2
    local group G2 = CreateGroup()
    local integer I = 0
    local effect array SFX
        call GroupEnumUnitsInRange(G, X, Y, 300.00, Conditon(function Trig_Frost_Mine_Func001001002))
        loop
            set U2 = FirstOfGroup(G)
            exitwhen U2 == null
            set I = I+1
            call PauseUnit(U2, true)
            set SFX[i] = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl", U2, "origin")
            call GroupAddUnit(G2, U2)
            call GroupRemoveUnit(G, U2)
        endloop
        call PolledWait(7.00)
        set I = 0
        loop
            set U2 = FirstOfGroup(G2)
            exitwhen U2 == null
            set I = I+1
            call DestroyEffect(SFX[i]) //We know it will destroy every effect because each time I was incremented in the above loop, a unit was passed from G to G2
            set SFX[i] = null
            call PauseUnit(U2, false)
            call DestroyEffect(GetLastCreatedEffectBJ())
            call GroupRemoveUnit(G2, U2)
        endloop
        call DestroyEffect(se)
    set se = null
    set U = null
    call DestroyGroup(G)
    set G = null
    set U2 = null
    call DestroyGroup(G2)
    set G2 = null
endfunction

Notice that I removed the call PolledWait( 2.0 ). This is because there was a 7 second wait above it, and it doesn't matter when you destroy the effect, just as long as it gets done (unless you need to stop its animation or something funky like that). The last thing to notice is that while the units are paused, they will still move and look less "frozen". To fix this, we'll just add in the line SetUnitTimeScale(), which changes a unit's animation speed. All put together and given nice, orderly names, the code would look like this:
Collapse JASS:
function Trig_Frost_Mine_Conditions takes nothing returns boolean
   return GetUnitTypeId(GetTriggerUnit()) == 'n001'
endfunction

function Trig_Frost_Mine_Filter takes nothing returns boolean
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT) == false
endfunction

function Trig_Frost_Mine_Actions takes nothing returns nothing
    local unit U = GetTriggerUnit()
    local real X = GetUnitX(U)
    local real Y = GetUnitY(U)
    local effect se = AddSpecialEffect("Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", X, Y)
    local group G = CreateGroup()
    local unit U2
    local group G2 = CreateGroup()
    local integer I = 0
    local effect array SFX
        call GroupEnumUnitsInRange(G, X, Y, 300.00, Conditon(function Trig_Frost_Mine_Filter))
        loop
            set U2 = FirstOfGroup(G)
            exitwhen U2 == null
            set I = I+1
            call PauseUnit(U2, true)
            call SetUnitTimeScale(U2, 0.00)
            set SFX[i] = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl", U2, "origin")
            call GroupAddUnit(G2, U2)
            call GroupRemoveUnit(G, U2)
        endloop
        call PolledWait(7.00)
        set I = 0
        loop
            set U2 = FirstOfGroup(G2)
            exitwhen U2 == null
            set I = I+1
            call DestroyEffect(SFX[i])
            set SFX[i] = null
            call PauseUnit(U2, false)
            call SetUnitTimeScale(U2, 1.00)
            call DestroyEffect(GetLastCreatedEffectBJ())
            call GroupRemoveUnit(G2, U2)
        endloop
        call DestroyEffect(se)
    set se = null
    set U = null
    call DestroyGroup(G)
    set G = null
    set U2 = null
    call DestroyGroup(G2)
    set G2 = null
endfunction

Whew... hope that helps
02-24-2007, 08:14 AM#3
darkwulfv
*Gaping Jaw*

For christ's sake Pyrogasm... You completely... Wow.

+Rep for you!
02-24-2007, 08:20 AM#4
Pyrogasm
Quote:
Jumpin' Jesus Christ on a Pogo Stick!
That took me... 2 1/2 hours I think? I started typing soon after he posted that.

You should take a look at some of Moyack's responses sometimes... he tends to do this too.

And seeing a trigger as screwed up as that was, in a thread asking for help... I just couldn't resist.

EDIT: ROFLS "Ninja-Style Kick-ass!" <3
02-24-2007, 08:25 AM#5
darkwulfv
*requests rep for pwnsome rep phrase*

Well, he now has a fully fixed trigger and knows some extra things. If I felt like being so helpful I could pull this off... But damn, 2 1/2 hours?
02-24-2007, 08:46 AM#6
The)TideHunter(
Very nice answer.
I surpose you gave me rep for the answer i gave, so its only fair you recieve rep in return.

GJ.

EDIT: Offtopic: Ouch, you need 3 rep for your blue rep.
02-24-2007, 08:49 AM#7
Pyrogasm
Quote:
*Thanks Pyrogasm for repping me for pwnsome rep phrase*
Fix'd.
2 1/2 hours give-or take. I'm not sure if that's actually a good time increment because I was doing other stuff at the time

The)TideHunter( I tend to rep people for being helpful even if I'm not involved in the conversation

Edit: So... a blue on is 120, is it? I thought it was around 100. So close...
02-24-2007, 02:16 PM#8
Tiku
Omg pyrogasm you deserve 10,000,000 rep for that
but i can only rep you with 1 =[

Thanks so frikken much, wow im still amazed! =]
02-25-2007, 12:01 AM#9
Pyrogasm
But does it work?...