HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Weird ability Bug

06-11-2009, 01:16 PM#1
wraithseeker
Almost everything works fine and this is about to be released but I lost the verison which was unoptimized and works and so I seek help here. NewGen saves backups too many times....

When you pick those 3 Item types next to you, you gain some stats and ability bonus, cast backpack and the bonus remain but the ability does not?

Collapse JASS:
library CIS initializer Init requires Table, UnitProperties, AutoIndex

//! textmacro CheckAndApply takes VALUE
    if d.$VALUE$ != 0 then
        set $VALUE$[u] = $VALUE$[u] + d.$VALUE$
    endif
//! endtextmacro

//! textmacro CheckAndUnapply takes VALUE
    if d.$VALUE$ != 0 then
        set $VALUE$[u] = $VALUE$[u] + -1*d.$VALUE$
    endif
//! endtextmacro
    
private function UnitApplyItem takes unit u, bonus d returns nothing
    local integer i
    //! runtextmacro CheckAndApply("Str")
    //! runtextmacro CheckAndApply("Agi")
    //! runtextmacro CheckAndApply("Int")
    //! runtextmacro CheckAndApply("Damage")
    //! runtextmacro CheckAndApply("Armor")
    //! runtextmacro CheckAndApply("MaxLife")
    //! runtextmacro CheckAndApply("MaxMana")
    //! runtextmacro CheckAndApply("LifeRegen")
    //! runtextmacro CheckAndApply("ManaRegen")
    //! runtextmacro CheckAndApply("AttackSpeed")
    //! runtextmacro CheckAndApply("MoveSpeed")
    if d.Abilities[0] != 0 then
        set i = 0
        loop
            call UnitAddAbility(u, d.Abilities[i])
            call SetUnitAbilityLevel(u, d.Abilities[i], d.AbilityLevels[i])
            set i = i+1
            exitwhen d.Abilities[i] == 0 or i >= MAX_ABILITIES
        endloop
    endif
endfunction

private function UnitUnapplyItem takes unit u, bonus d returns nothing
    local integer i
    //! runtextmacro CheckAndUnapply("Str")
    //! runtextmacro CheckAndUnapply("Agi")
    //! runtextmacro CheckAndUnapply("Int")
    //! runtextmacro CheckAndUnapply("Damage")
    //! runtextmacro CheckAndUnapply("Armor")
    //! runtextmacro CheckAndUnapply("MaxLife")
    //! runtextmacro CheckAndUnapply("MaxMana")
    //! runtextmacro CheckAndUnapply("LifeRegen")
    //! runtextmacro CheckAndUnapply("ManaRegen")
    //! runtextmacro CheckAndUnapply("AttackSpeed")
    //! runtextmacro CheckAndUnapply("MoveSpeed")
    if d.Abilities[0] != 0 then
        set i = 0
        loop
            call UnitRemoveAbility(u, d.Abilities[i])
            set i = i + 1
            exitwhen d.Abilities[i] == 0 or i >= MAX_ABILITIES
        endloop
    endif
endfunction
    
private function UnitUnapplyAbilities takes unit u, bonus d returns nothing
    local integer i
    if d.Abilities[0] != 0 then
        set i = 0
        loop
            call UnitRemoveAbility(u, d.Abilities[i])
            set i = i + 1
            exitwhen d.Abilities[i] == 0 or i >= MAX_ABILITIES
        endloop
    endif
endfunction
        
private function UnitApplyAbilities takes unit u, bonus d returns nothing
    local integer i
    if d.Abilities[0] != 0 then
        set i = 0
        loop
            call UnitAddAbility(u, d.Abilities[i])
            call SetUnitAbilityLevel(u, d.Abilities[i], d.AbilityLevels[i])
            set i = i + 1
            exitwhen d.Abilities[i] == 0 or i >= MAX_ABILITIES
        endloop
    endif
endfunction
        
private function Check takes bonus d, unit u returns boolean
    local integer i = 0
    local integer array Items
    loop
        exitwhen i > 5
        set Items[i] = d.Items[i]
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if UnitHasItemOfType(u,Items[i]) then
            set Items[i] = 0
        endif
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if Items[i] != 0 then
            return false
        endif
        set i = i + 1
    endloop
    return true
endfunction

private function RecipeCheck takes bonus d, unit u returns boolean
    local integer i = 0
    local integer array Items
    local item array ItemRetrieve
    local integer it = 0
    local integer j = 0
    local boolean b = false
    loop
        exitwhen i > 5
        set Items[i] = d.Items[i]
        set i = i + 1
    endloop
    set i = 0
    loop
        set it = GetItemTypeId(UnitItemInSlot(u,i))
        loop
            if Items[j] == GetItemTypeId(GetManipulatedItem()) and it != 0 then
                set ItemRetrieve[j] = GetManipulatedItem()
                set Items[j] = 0
                set b = true
            elseif it == Items[j] and it != 0 then
                set ItemRetrieve[j] = UnitItemInSlot(u,i)
                set Items[j] = 0
            endif
            set j = j + 1
            exitwhen j > 5
        endloop
        set j = 0
        set i = i + 1
        exitwhen i > 5
    endloop
    set j = 0
    set i = 0
    loop
        if Items[i] != 0 then
            loop
                exitwhen j > 5
                set ItemRetrieve[j] = null
                set j = j + 1
            endloop
            return false
        endif
        set i = i + 1
        exitwhen i > 5
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if ItemRetrieve[i] != null then
            call RemoveItem(ItemRetrieve[i])
            set ItemRetrieve[i] = null
        endif
        set i = i + 1
    endloop
    call DestroyEffect(AddSpecialEffect(d.SFX,GetUnitX(u),GetUnitY(u)))
    call UnitAddItemById(u,d.result)
    return b
endfunction

private function BackCheck takes bonus d,unit u returns boolean
    local integer i = 0
    local integer array Items
    loop
        exitwhen i > 5
        set Items[i] = d.Items[i]
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if UnitHasItemOfType(u,Items[i]) then
            set Items[i] = 0
        endif
        set i = i + 1
    endloop
    set i = 0
    loop
        exitwhen i > 5
        if Items[i] != 0 then
            return false
        endif
        set i = i + 1
    endloop
    return true
endfunction

private function onPickup takes nothing returns nothing
    local item t = GetManipulatedItem()
    local bonus d = GetItemUserData(t)
    local unit u = GetTriggerUnit()
    local integer i = 0
    local integer r = 0
    local boolean UserItem = false
    if d != 0 then
        call UnitApplyItem(u,d)
        set UserItem = true
    endif
    set d = DataTable[GetItemTypeId(t)]
    if d > 0 then
        if not UserItem then
            call UnitApplyItem(u,d)
        endif
    endif
    loop
        exitwhen r >= d.Count
        set d = d.D[r]
        if Check(d,u) and d.COMBINED[GetUnitId(u)] == 0 then
            call UnitApplyItem(u,d)
            set d.COMBINED[GetUnitId(u)] = 1
        endif
        set r = r + 1
    endloop
    set r = 0
    loop
        exitwhen r >= d.RCount
        set d = d.R[r]
        if RecipeCheck(d,u) then
            call UnitApplyItem(u,d)
        endif
        set r = r + 1
    endloop
    set t = null
    set u = null
endfunction

private struct UnitAttach
    unit target
    timer t
    
static method create takes nothing returns UnitAttach
    local UnitAttach d = UnitAttach.allocate()
    set d.target = GetTriggerUnit()
    set d.t = NewTimer()
    return d
endmethod

method onDestroy takes nothing returns nothing
    call ReleaseTimer(.t)
endmethod

endstruct

private function SetCheck takes nothing returns nothing
    local UnitAttach c = GetTimerData(GetExpiredTimer())
    local integer r = 0
    local bonus d
    loop
        exitwhen r >= d.Count
        set d = d.D[r]
        if d.COMBINED[GetUnitId(c.target)] == 1 and not Check(d,c.target) then
            call UnitUnapplyItem(c.target,d)
            set d.COMBINED[GetUnitId(c.target)] = 0
        endif
        set r = r + 1
        call c.destroy()
    endloop
endfunction
 
private function onDrop takes nothing returns nothing
    local item t = GetManipulatedItem()
    local bonus d = GetItemUserData(t)
    local unit u = GetTriggerUnit()
    local boolean UserItem = false
    local UnitAttach c = UnitAttach.create()
    if d != 0 then
        call UnitUnapplyItem(u,d)
        set UserItem = true
    endif
    set d = DataTable[GetItemTypeId(t)]
    if d > 0 then
        if not UserItem then
        call UnitUnapplyItem(u,d)
        endif
    endif
    call BJDebugMsg("OnDrop Ran")
    call SetTimerData(c.t,c)
    call TimerStart(c.t,0.,false,function SetCheck)
    set u = null
    set t = null
endfunction

private interface face
    method OnMove takes unit target returns nothing defaults nothing
endinterface
struct backpack extends face
    integer array ItemType[6]
    integer array Charges[6]
    integer array UserData[6]    
    
static method create takes unit u returns backpack
    local backpack d = backpack.allocate()
    local backpack c
    local bonus a
    local bonus r
    local integer i = 0
    local item it
    local integer j = 0
    local boolean UserData = false
    loop
        exitwhen j >= bonus.Count
        set r = bonus.D[j]
        if BackCheck(r,u) then
            call UnitApplyItem(u,r)
            call UnitApplyAbilities(u,r)
            // here is the actual place where bonuses get applied
        endif
        set j = j + 1
    endloop
    loop
        set it = UnitItemInSlot(u, i)
        set d.ItemType[i] = GetItemTypeId(it)
        set d.Charges[i] = GetItemCharges(it)
        set d.UserData[i] = GetItemUserData(it)
        set c = DataTable[d.ItemType[i]]
        set a = GetItemUserData(it)
        if a != 0 then
            call UnitApplyItem(u,a)
            call RemoveItem(it)
            call UnitApplyAbilities(u,a)
            set UserData = true
        endif
        if not UserData then
            call UnitApplyItem(u,c)
            call RemoveItem(it)
            call UnitApplyAbilities(u,c)
        endif
        set i = i + 1
        exitwhen i > 5
    endloop
    if d.OnMove.exists then
        call d.OnMove(u)
    endif
    set it = null
    return d
endmethod
    implement AutoData
endstruct

function ActivateBackpack takes nothing returns nothing
    local unit target = GetTriggerUnit()
    local backpack d1
    local backpack d2 = backpack[target]
    local backpack d
    local integer i = 0
    local integer j = 0
    local item it
    local bonus a
    local bonus r
    local boolean done = false
    set d1 = backpack.create(target)
    if d2 != 0 then
        loop
            if d2.ItemType[i] != 0  then
                set it = UnitAddItemById(target, d2.ItemType[i])
                call SetItemCharges(it, d2.Charges[i])
                call SetItemUserData(it, d2.UserData[i])
                set d = DataTable[d2.ItemType[i]]
                call UnitUnapplyItem(target,d)
                call UnitApplyAbilities(target,d)
                endif
            set i = i + 1
            exitwhen i > 5
        endloop
            loop
            exitwhen j >= bonus.Count
            set r = bonus.D[j]
            if BackCheck(r,target) then
                call UnitUnapplyItem(target,r) // I unapplied everything
                call UnitApplyAbilities(target,r) // Applying ability back but NOT bonuses
            endif
            set j = j + 1
        endloop
        call d2.destroy()
    endif
    set backpack[target] = d1
    set it = null
endfunction

private function BackpackCondition takes nothing returns boolean
    return GetSpellAbilityId() == BackpackId
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
    call TriggerAddAction(t,function onPickup)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DROP_ITEM)
    call TriggerAddAction(t,function onDrop)
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function BackpackCondition))
    call TriggerAddAction(t,function ActivateBackpack)
endfunction

endlibrary

It's really hard to explain so here's the test map

http://www.thehelper.net/forums/show...27#post1050927
06-12-2009, 09:12 PM#2
Flame_Phoenix
I don't think many people will help you this way. A golden rule that I learned for myself is that when you go to a forum and ask for help, it is a bad idea to post the entire monster. Try reducing the problem as much as you can by using debbug messages and then post a small code containing the problem isolated.

This way (the way you are doing it) people will just get scared with the size of your code.
I saw your link, in both forums no one is aiding you.

If you can't find the problem using debbug messages, then I believe grimoire has a debugger for jass (if I am not mistaken) so you may want to use it.