HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

This doesn't work.

09-13-2007, 12:34 AM#1
~Void~
Why does this not work? It all runs fine except the part where the dummies actually cast polymorph. I use a modified custom version of polymorph but it has the same order string so... I've tried to make the code easy to go through for you.

Collapse JASS:
//===========================================================================
//=======================Shepherding by ~Void~===============================
//===========================================================================




constant function Shep_ID takes nothing returns integer
    return 'A000' //Rawcode of the ability being cast
endfunction

constant function Shep_Dummy takes nothing returns integer
    return 'h000' //Rawcode of the dummy unit
endfunction

constant function Shep_Range1 takes nothing returns integer
    return 300 //The first number in formula for spell radius: Shep_Range1 + (abilitylevel * Shep_Range2)
endfunction

constant function Shep_Range2 takes nothing returns integer
    return 100 //The multiplier for the spell level in formula for spell radius: Shep_Range1 + (abilitylevel * Shep_Range2)
endfunction

//===========================================================================
//===========================================================================

function Trig_Shepherding_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    return true
endfunction

//===========================================================================

function Shep_Conditions takes nothing returns boolean
    local unit filt = GetFilterUnit()
    return ( filt != GetTriggerUnit() ) and( GetUnitTypeId(filt) != Shep_Dummy())  //makes sure the caster doesn't get polymorphed.
endfunction

//===========================================================================

function Shep_Dummy_Create takes nothing returns nothing  //creates the dummy and orders it to poly the picked unit
    local unit temp
    call CreateNUnitsAtLoc( 1, Shep_Dummy(), Player(PLAYER_NEUTRAL_PASSIVE), GetSpellTargetLoc(), bj_UNIT_FACING ) 
    set temp = GetLastCreatedUnit()
    call UnitApplyTimedLifeBJ( 1.00, 'BTLF', temp )
    call IssueTargetOrderBJ( temp, "polymorph", GetEnumUnit() )
    set temp = null
endfunction

//===========================================================================

function Trig_Shepherding_Actions takes nothing returns nothing
    local unit cast = GetTriggerUnit()
    local location targ = GetSpellTargetLoc() 
    local integer abil = GetUnitAbilityLevelSwapped(Shep_ID(),cast)
    call ForGroupBJ( GetUnitsInRangeOfLocMatching( (Shep_Range1() + ( Shep_Range2() * I2R(abil))), targ, Condition(function Shep_Conditions)), function Shep_Dummy_Create )
endfunction
     
//===========================================================================
//===========================================================================

function InitTrig_Shepherding takes nothing returns nothing
    set gg_trg_Shepherding = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Shepherding, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Shepherding, Condition( function Trig_Shepherding_Conditions ) )
    call TriggerAddAction( gg_trg_Shepherding, function Trig_Shepherding_Actions )
endfunction

09-13-2007, 01:33 AM#2
TaintedReality
Collapse JASS:
function Shep_Dummy_Create takes nothing returns nothing  //creates the dummy and orders it to poly the picked unit
    local unit temp
    call CreateNUnitsAtLoc( 1, Shep_Dummy(), Player(PLAYER_NEUTRAL_PASSIVE), GetSpellTargetLoc(), bj_UNIT_FACING ) 
    set temp = GetLastCreatedUnit()
    call UnitApplyTimedLifeBJ( 1.00, 'BTLF', temp )
    call IssueTargetOrderBJ( temp, "polymorph", GetEnumUnit() )
    set temp = null
endfunction

I'm thinking it's the GetSpellTargetLoc on the 2nd line of that function. I don't think it carries over for some reason. Doesn't really make sense, but try storing that to a global variable to transfer it through. Oh another thing, the UnitApplyTimedLife might have too short of a time (depending on how your dummy unit is set up). Try increasing it to 2 seconds.

And...that is some ugly ass code, to put it nicely =D. BJ's all over, leaking locations, it almost looks like it was just converted from GUI.

Since I'm not really confident in my answer - where exactly was the problem? Did the dummy units never spawn, or did the spell just not get cast?
09-13-2007, 03:37 AM#3
Pyrogasm
No, TaintedReality, that is the error.

Now that we've found it, you should learn to optimize:

Since we know that the "return" keyword is used to return a boolean statement, you can simply replace this:
Collapse JASS:
function Trig_Shepherding_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    return true
endfunction
With this:
Collapse JASS:
function Trig_Shepherding_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Shep_Id()
endfunction

This function leaks a unit variable:
Collapse JASS:
function Shep_Conditions takes nothing returns boolean
    local unit filt = GetFilterUnit()
    return ( filt != GetTriggerUnit() ) and( GetUnitTypeId(filt) != Shep_Dummy())  //makes sure the caster doesn't get polymorphed.
endfunction
To fix this, we'll simply have to use a boolean variable to store what would normally be returned by the return, like so:
Collapse JASS:
function Shep_Conditions takes nothing returns boolean
    local unit filt = GetFilterUnit()
    local boolean b = (filt != GetTriggerUnit()) and(GetUnitTypeId(filt) != Shep_Dummy())  //makes sure the caster doesn't get polymorphed.
    set filt = null
    return b
endfunction

Now, you should notice that this is still inefficient because it calls 2 function calls that could be avoided by using global variables. There is no need to create our own (which you could easily do), as we can just use these two variables from Blizzard.j: bj_ghoul[300] and bj_meleeTwinkedHeroes[300]:
Collapse JASS:
function Shep_Conditions takes nothing returns boolean
    local unit filt = GetFilterUnit()
    local boolean b = (filt != bj_ghoul[300]) and(GetUnitTypeId(filt) != bj_meleeTwinkedHeroes[300])  //makes sure the caster doesn't get polymorphed.
    set filt = null
    return b
endfunction
//...
function Trig_Shepherding_Actions takes nothing returns nothing
    local location targ = GetSpellTargetLoc() 
    local integer abil
    set bj_ghoul[300] = GetTriggerUnit() //Just use these variables here, no need to have a local and global that point the same thing
    set abil = GetUnitAbilityLevelSwapped(Shep_ID(),bj_ghoul[300])
    set bj_meleeTwinkedHeroes[300] = Shep_Dummy()
    call ForGroupBJ( GetUnitsInRangeOfLocMatching( (Shep_Range1() + ( Shep_Range2() * I2R(abil))), targ, Condition(function Shep_Conditions)), function Shep_Dummy_Create )
endfunction

Next, the Trig_Shepherding_Actions function has a fair amount of BJs and a leak that should be fixed like so:
Collapse JASS:
function Trig_Shepherding_Actions takes nothing returns nothing
    local location targ = GetSpellTargetLoc() 
    local group g = CreateGroup()
    set bj_ghoul[300] = GetTriggerUnit()
    set bj_meleeTwinkedHeroes[300] = Shep_Dummy()

    call GroupEnumUnitsInRangeOfLoc(g, targ, Shep_Range1()+(Shep_Range2()*GetUnitAbilityLevel(bj_ghoul[300], Shep_ID()), Condition(function Shep_Conditions))
    call ForGroup(g, function Shep_Dummy_Create)

    call DestroyGroup(g)
    call RemoveLocation(targ)
    set g = null
    set targ = null
endfunction

Last, we can see that we should remove the usage of locations and instead use x/y values. To do this (and to fix the problem you had before), we'll have to replace the ForGroup call with this simple workaround:
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
In application, you're going to do this:
Collapse JASS:
function Trig_Shepherding_Actions takes nothing returns nothing
    local location targ = GetSpellTargetLoc() 
    local group g = CreateGroup()
    local real x = GetLocationX(targ)
    local real y = GetLocationY(targ)
    local unit u
    local unit temp
    set bj_ghoul[300] = GetTriggerUnit()
    set bj_meleeTwinkedHeroes[300] = Shep_Dummy()

    call GroupEnumUnitsInRange(g, x, y, Shep_Range1()+(Shep_Range2()*GetUnitAbilityLevel(bj_ghoul[300], Shep_ID())), Condition(function Shep_Conditions))
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null //This also removes a minor leak
  
        set temp = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), bj_meleeTwinkedHeroes[300], x, y, 0.00)
        call UnitApplyTimedLife(temp, 'BTLF', 1.00)
        call IssueTargetOrder(temp, "polymorph", u)

        call GroupRemoveUnit(g, u)
    endloop

    call DestroyGroup(g)
    call RemoveLocation(targ)
    set g = null
    set targ = null
    set temp = null
endfunction


All together, it should look like this:
Collapse JASS:
//===========================================================================
//=======================Shepherding by ~Void~===============================
//===========================================================================




constant function Shep_ID takes nothing returns integer
    return 'A000' //Rawcode of the ability being cast
endfunction

constant function Shep_Dummy takes nothing returns integer
    return 'h000' //Rawcode of the dummy unit
endfunction

constant function Shep_Range1 takes nothing returns integer
    return 300 //The first number in formula for spell radius: Shep_Range1 + (abilitylevel * Shep_Range2)
endfunction

constant function Shep_Range2 takes nothing returns integer
    return 100 //The multiplier for the spell level in formula for spell radius: Shep_Range1 + (abilitylevel * Shep_Range2)
endfunction

//===========================================================================
//===========================================================================

function Trig_Shepherding_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == Shep_ID()
endfunction

//===========================================================================

function Shep_Conditions takes nothing returns boolean
    local unit filt = GetFilterUnit()
    local boolean b = (filt != bj_ghoul[300]) and(GetUnitTypeId(filt) != bj_meleeTwinkedHeroes[300])  //makes sure the caster doesn't get polymorphed.
    set filt = null
    return b
endfunction

//===========================================================================

function Trig_Shepherding_Actions takes nothing returns nothing
    local location targ = GetSpellTargetLoc() 
    local group g = CreateGroup()
    local real x = GetLocationX(targ)
    local real y = GetLocationY(targ)
    local unit u
    local unit temp
    set bj_ghoul[300] = GetTriggerUnit()
    set bj_meleeTwinkedHeroes[300] = Shep_Dummy()

    call GroupEnumUnitsInRange(g, x, y, Shep_Range1()+(Shep_Range2()*GetUnitAbilityLevel(bj_ghoul[300], Shep_ID())), Condition(function Shep_Conditions))
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null //This also removes a minor leak
  
        set temp = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), bj_meleeTwinkedHeroes[300], x, y, 0.00)
        call UnitApplyTimedLife(temp, 'BTLF', 1.00)
        call IssueTargetOrder(temp, "polymorph", u)

        call GroupRemoveUnit(g, u)
    endloop

    call DestroyGroup(g)
    call RemoveLocation(targ)
    set g = null
    set targ = null
    set temp = null
endfunction

//===========================================================================
//===========================================================================

function InitTrig_Shepherding takes nothing returns nothing
    set gg_trg_Shepherding = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Shepherding, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Shepherding, Condition( function Trig_Shepherding_Conditions ) )
    call TriggerAddAction( gg_trg_Shepherding, function Trig_Shepherding_Actions )
endfunction
09-13-2007, 04:56 AM#4
Jazradel
Variables in functions which return something don't need to be nulled, I thought.
09-13-2007, 05:08 AM#5
Pyrogasm
The variable that's returned doesn't need to be nulled. Others do:
Collapse JASS:
//Good:
function SomeFunc takes nothing returns unit
    local real PlayerInt = GetRandomInt(0, 15)
    local unit U = CreateUnit(Player(PlayerInt), 'h000', 0.00, 0.00, 0.00)
    return U
endfunction

//Bad:
function SomeFunc takes nothing returns integer
    local real PlayerInt = GetRandomInt(0, 15)
    local unit U = CreateUnit(Player(PlayerInt), 'h000', 0.00, 0.00, 0.00)
    return PlayerInt
endfunction

//Good:
function SomeFunc takes nothing returns integer
    local real PlayerInt = GetRandomInt(0, 15)
    local unit U = CreateUnit(Player(PlayerInt), 'h000', 0.00, 0.00, 0.00)
    set U = null
    return PlayerInt
endfunction
09-14-2007, 11:22 PM#6
~Void~
Thanks pyro, but it still doesn't sheep them. O_o
09-14-2007, 11:29 PM#7
Pyrogasm
Does it error?

Edit:
Try changing this: set temp = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), bj_meleeTwinkedHeroes[300], x, y, 0.00) to this:
Collapse JASS:
local player p
set bj_ghoul[300] = GetTriggerUnit()
set P = GetOwningPlayer(bj_ghoul[300])
//...
set temp = CreateUnit(p, bj_meleeTwinkedHeroes[300], x, y, 0.00)
//...
set p = null //Just null it, you can't destroy players.

And/Or changing the timed life time to to 2.00 seconds.
Or it could be that the dummy unit does not have the ability... or that the dummy has no mana and the polymorph costs mana... or you forgot to remove tech requirements from polymorph.