HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Bug with IsUnitAlly?

11-07-2006, 08:59 PM#1
The_AwaKening
My code worked when I used IsPlayerAlly, but I changed to IsUnitAlly since it is simpler.

Collapse JASS:
function PurificationBool takes nothing returns boolean
    return IsUnitAlly(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit())) and IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)
endfunction

When using that condition in a group call, it is taking enemy units as well. Is there a bug with that code?

Edit:
I just tested with this instead
Collapse JASS:
function PurificationBool takes nothing returns boolean
    return not(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit()))) and IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)
endfunction
And it works just fine. Seems to me that IsUnitAlly is bugged in some cases maybe. I use IsUnitAlly in other codes and it works fine. Here is my entire code.
Collapse JASS:
function PurificationBool takes nothing returns boolean
    return not(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit()))) and IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)
endfunction

function HealGroup takes nothing returns nothing
    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIma\\AImaTarget.mdl",GetEnumUnit(),"chest"))
    call SetUnitState(GetEnumUnit(),UNIT_STATE_LIFE,GetUnitState(GetEnumUnit(),UNIT_STATE_LIFE)+500)
endfunction

function PurificationDone takes nothing returns nothing
 local item I = I2It(GetHandleInt(GetExpiredTimer(),"item"))
 local timer t=GetExpiredTimer()
    call SetItemDroppable(I,true)
    call FlushHandleLocals(t)
    call PauseTimer(t)        
    call DestroyTimer(t)
 set I=null
 set t=null
endfunction

function Trig_Purification_Actions takes nothing returns nothing
 local unit u=GetTriggerUnit()
 local item I
 local integer i=0
 local group g=CreateGroup()
 local boolexpr b=Condition(function PurificationBool)
 local timer t=CreateTimer()
    call TriggerSleepAction(.01)
    call GroupEnumUnitsInRect(g,GetPlayableMapRect(),b)
    call ForGroup(g,function HealGroup)
    call DestroyGroup(g)
    call DestroyBoolExpr(b)
    loop
        exitwhen i>5
        if GetItemTypeId(UnitItemInSlot(u,i))=='gopr' then
            set I = UnitItemInSlot(u,i)
            call SetItemDroppable(I,false)
            exitwhen true
        endif
        set i=i+1
    endloop
    call TimerStart(t,180,false,function PurificationDone)
    call SetHandleInt(t,"item",H2I(I))
 set I=null
 set g=null
 set b=null
 set u=null    
endfunction

//===========================================================================
function Trig_Purification_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A040'
endfunction

function InitTrig_Purification takes nothing returns nothing
    set gg_trg_Purification = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_Purification, Condition( function Trig_Purification_Conditions ) )
    call TriggerAddAction( gg_trg_Purification, function Trig_Purification_Actions )
endfunction

It works just fine as long as I use not(IsUnitEnemy). OH, and the event is set in another trigger.
11-08-2006, 02:00 AM#2
zen87
Collapse JASS:
function PurificationBool takes nothing returns boolean
    return IsUnitAlly(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit())) and IsUnitType(GetFilterUnit(),UNIT_TYPE_HERO)
endfunction

well it is not really a bug, you see, when you ,GetOwningPlayer(GetTriggerUnit()) what event are you atctually respand to the GetTriggerUnit ? you only can respand to FilterUnit but not the TriggerUnit in the other function... so just use IsPlayerAlly instead
11-08-2006, 02:40 AM#3
The_AwaKening
I don't think so. Why then would it work if I used

return not(IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit())))

That is pretty much the same thing. GetTriggerUnit() is a global and can pass between functions, and you would still need it in IsPlayerAlly.
11-08-2006, 02:45 AM#4
Naakaloh
Or set a unit as one of the BJ globals (bj_lastReplacedUnit or something) and then use that in place of TriggeringUnit().
11-08-2006, 02:49 AM#5
The_AwaKening
I think you're missing the point though. I really don't think the problem is with TriggerUnit because it works with IsUnitEnemy.

I have this working now anyway, but I still wonder why it was bugging out with the original code.
11-08-2006, 03:03 AM#6
Naakaloh
GetTriggerUnit() returns a value; it itself is not a variable; the function is not passed anywhere. As far as know it should work with GetTriggerUnit(), but if you try it with another option, and it works perhaps it shouldn't. Before rebuking any suggestions so frankly, it would be nice if you tried them and told us if they had an effect.

I personally have never had any problems with IsUnitAlly(), but then again, I have never used GetTriggerUnit() with it nor have I used returned the boolean without a if statement.

It would not be terribly surprising to me if it suffered the same issue as IsUnitType().
11-08-2006, 03:56 AM#7
PipeDream
I haven't tested but a quick glance at the assembly suggests Naakaloh is correct. IsUnitAlly, like IsUnitType, is implemented with an and'd bitmask. IsUnitEnemy works since it calls IsUnitAlly followed by a proper negation.
11-08-2006, 08:29 AM#8
Anitarf
If that is true, then just doing IsUnitAlly(...)==true should fix things, thus avoiding the extra function calls with IsUnitEnemy(). It's an easy test.
11-08-2006, 02:43 PM#9
BertTheJasser
If the GetTriggerUnit() would return null, is unit ally will return false, and IsUnitEnemy will return false aswell (I was told so by some allmighty guy). So this could be the reason for your behavior why it works your second way and not with is unit ally.
11-08-2006, 03:06 PM#10
Vexorian
It is good to know this some time before releasing a new optimizer version, [rant]shame on blizz for using ==1 instead of !=0 in the boolexpr handling.[/rant]

I certainly never bothered to research what natives have this issue. I guess it would be good to guess what functions use bitmasks to return.
11-08-2006, 06:43 PM#11
BertTheJasser
Maybe this is real idiotic question... but... Is it possible that the bug is only likely to happen when you use Conition() for a filterfunc or vice versa? I never had problems with picking units and I always look for the right type.
11-08-2006, 07:14 PM#12
shadow1500
Quote:
but... Is it possible that the bug is only likely to happen when you use Conition() for a filterfunc
Thats exactly what the problem is, as vexorian said, boolexpr use a different way for handling booleans so you get incorrect results. Condition is the only way to create code boolexprs, so its the only way you can cause this bug to happen.
11-09-2006, 03:43 PM#13
BertTheJasser
Using
A)
Collapse JASS:
local boolexpr b=Condition(function xxx)
B)
Collapse JASS:
local conditionfunc b=Condition(function xxx)
C)
Collapse JASS:
local boolexpr b=Filter(function xxx)
D)
Collapse JASS:
local filterfunc b=Filter(function xxx)
E)
Collapse JASS:
local conditionfunc b=Filter(function xxx)
F)
Collapse JASS:
local filterfunc b=Condition(function xxx)

Plx tell me which ones have a chance of a bug.
I didn't get it all.
11-09-2006, 03:56 PM#14
shadow1500
Quote:
boolexpr use a different way for handling booleans so you get incorrect results
Collapse JASS:
type conditionfunc extends boolexpr
type filterfunc extends boolexpr
All of them are boolexprs, so all of the have the bug.
11-09-2006, 04:24 PM#15
BertTheJasser
Omg sorry, have passed chemistry exam today. My mind is still not 100% online again.