• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Disable Item Drop while on Cooldown

Status
Not open for further replies.
Level 6
Joined
Aug 4, 2012
Messages
193
I try to make the item undroppable when the item is on cooldown, when the item is used, Avatar is activated, if a unit drops the item when Avatar is activated, the unit size will not returns to normal when the item effect ends. Please help me to fix this.

JASS:
function Avatar_Conditions takes nothing returns boolean
    return(GetItemTypeId(GetManipulatedItem())=='I001')
endfunction

function Avatar_Finish takes item Avatar returns nothing
    call SetItemDroppable(Avatar,true)
endfunction

function Avatar_Actions takes nothing returns nothing
    local item Avatar=GetManipulatedItem()
    local timer AvatarCD=CreateTimer()
    call SetItemDroppable(Avatar,false)
    call TimerStart(AvatarCD,10,false,function Avatar_Finish)
endfunction

function InitTrig_Avatar takes nothing returns nothing
    set gg_trg_Avatar=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Avatar,EVENT_PLAYER_UNIT_USE_ITEM)
    call TriggerAddCondition(gg_trg_Avatar,Condition(function Avatar_Conditions))
    call TriggerAddAction(gg_trg_Avatar,function Avatar_Actions)
endfunction
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Here, though it feels like the Hashtable is wasted. If you're reaching the Hashtable limit, you could always use Table or TimerUtils but that will require JNGP.

Here's the code (with easy configuration):
JASS:
constant function Avatar_Cooldown takes nothing returns real
    return 15.0
endfunction

constant function Avatar_ItemId takes nothing returns integer
    return 'I000'
endfunction

function Trig_Avatar_TimerExpire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    call SetItemDroppable(LoadItemHandle(udg_Avatar_Hash, id, 0), true)
    call DestroyTimer(t)
    set t = null
endfunction

function Trig_Avatar_Main takes nothing returns boolean
    local item it = GetManipulatedItem()
    local timer t
    if GetItemTypeId(it) == Avatar_ItemId() then
        call SetItemDroppable(it, false)
        set t = CreateTimer()
        call TimerStart(t, Avatar_Cooldown(), false, function Trig_Avatar_TimerExpire)
        call SaveItemHandle(udg_Avatar_Hash, GetHandleId(t), 0, it)
        set t = null
    endif
    set it = null
    return false
endfunction

//===========================================================================
function InitTrig_Avatar takes nothing returns nothing
    set gg_trg_Avatar = CreateTrigger(  )
    set udg_Avatar_Hash = InitHashtable()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Avatar, EVENT_PLAYER_UNIT_USE_ITEM )
    call TriggerAddCondition( gg_trg_Avatar, function Trig_Avatar_Main)
endfunction
 

Attachments

  • Avatar.w3x
    17.1 KB · Views: 94
Level 6
Joined
Aug 4, 2012
Messages
193
Does this requires JNGP? What is Hashtable limit?

call TriggerAddCondition( gg_trg_Avatar, function Trig_Avatar_Main)

I believe this should be action, right?
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Does this requires JNGP? What is Hashtable limit?

call TriggerAddCondition( gg_trg_Avatar, function Trig_Avatar_Main)

I believe this should be action, right?

No, it doesn't require JNGP. You can only use 255 (or 256?) Hashtables per map. My suggested code above uses one Hashtable but you can actually use a generic Hashtable for this operation because I don't see a way it will conflict other Hashtables.

Putting the actions in the Conditions is faster than separating a Condition and an action because it doesn't create a separate thread (someone correct me if I'm wrong)

I'm more surprised that you haven't downloaded the demo yet.
 
Level 6
Joined
Aug 4, 2012
Messages
193
Actually, I did downloaded the demo, and I have actually tried to import the code. I believe this is a glitch, maybe?

BUT, when i was trying to save using normal World Editor, I got an error, I've tried to check and notice that issue I mentioned.

However, even though I've change the "Condition" to "Action", which allows me to save in World Editor, but Warcraft 3 just refuse to start the map.

If the limit is 255, then it shouldn't be my concern because so far I haven't use hashtable exceed 100 yet.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Actually, I did downloaded the demo, and I have actually tried to import the code. I believe this is a glitch, maybe?

BUT, when i was trying to save using normal World Editor, I got an error, I've tried to check and notice that issue I mentioned.

However, even though I've change the "Condition" to "Action", which allows me to save in World Editor, but Warcraft 3 just refuse to start the map.

If the limit is 255, then it shouldn't be my concern because so far I haven't use hashtable exceed 100 yet.
Well that's the problem. Why did you change the code? And what's the error you're getting?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
My suggested code above uses one Hashtable but you can actually use a generic Hashtable for this operation because I don't see a way it will conflict other Hashtables.
As long as the parent and child keys are from the came key source it will not conflict. There are dozens of ways to use hashtables which have different parent and child key sources so can conflict.

laserdemon I recommend you read up about local variables. This will help you understand why your initial solution did not work. The handle for the item was not being passed to the timeout function because it was in a local variable so was lost at function return.

On another note you also leaked a timer and possibly a handle id.
 
Level 6
Joined
Aug 4, 2012
Messages
193
Will this works?

JASS:
function Avatar_Conditions takes nothing returns boolean
    return(GetItemTypeId(GetManipulatedItem())=='I001')
endfunction

function Avatar_Finish takes item Avatar returns nothing
    call DestroyTimer(GetExpiredTimer())
    call SetItemDroppable(Avatar,true)
endfunction

function Avatar_Actions takes nothing returns item
    local item Avatar=GetManipulatedItem()
    local timer AvatarCD=CreateTimer()
    call SetItemDroppable(Avatar,false)
    call TimerStart(AvatarCD,10,false,function Avatar_Finish)
    set AvatarCD=null
    return Avatar
endfunction

function InitTrig_Avatar takes nothing returns nothing
    set gg_trg_Avatar=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Avatar,EVENT_PLAYER_UNIT_USE_ITEM)
    call TriggerAddCondition(gg_trg_Avatar,Condition(function Avatar_Conditions))
    call TriggerAddAction(gg_trg_Avatar,function Avatar_Actions)
endfunction
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Will this works?
No because it will throw a syntax error.
Code:
function Avatar_Finish takes item Avatar returns nothing
     call DestroyTimer(GetExpiredTimer())
     [U]call SetItemDroppable([B]Avata[/B]r,true)[/U]
endfunction
There is no item variable named "Avatar" in that scope. Please make yourself familiar with what a local variable is.

There will also probably be a thread crash or other error.
Code:
[U]function Avatar_Actions takes nothing returns [B]item[/B][/U]
     local item Avatar=GetManipulatedItem()
     local timer AvatarCD=CreateTimer()
     call SetItemDroppable(Avatar,false)
     call TimerStart(AvatarCD,10,false,function Avatar_Finish)
     set AvatarCD=null
     [U]return Avatar[/U]
endfunction

function InitTrig_Avatar takes nothing returns nothing
     set gg_trg_Avatar=CreateTrigger()
     call TriggerRegisterAnyUnitEventBJ(gg_trg_Avatar,EVENT_PLAYER_UNIT_USE_ITEM)
     call TriggerAddCondition(gg_trg_Avatar,Condition(function Avatar_Conditions))
     [U]call TriggerAddAction(gg_trg_Avatar,[B]function Avatar_Actions[/B])[/U]
endfunction
Action functions should not return anything.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Ahh I see the problem. In that line, it should be be
TriggerAddCondition(gg_trg_Avatar, Condition(function Trig_Avatar_Main))

But why did it work for me?? very weird but it must have been JNGP.

Yes, JassHelper automatically adds the "Condition()" stuff around functions. It was a hobby project, so a lot of lazy stuff got thrown in there.
 
Status
Not open for further replies.
Top