• 🏆 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!

(system) [vJASS] Smart Inventory v0.0.1

Smart Inventory !
Version : 0.0.1
Credits Distribution : None
External Requirements : None
==========================================
THIS SYSTEM DOES NOT AFFECT ANY OF YOUR ITEMS
UNLESS YOU REGISTER THEM!!
==========================================

Documentation
A smart system that allows you to very easily register item types into it to utilize them in game.

Aspects
Stacking Inventory
Item Subicons (Set a different item in the shop but getting a different when you buy!)
Stacking Items (With a configurable amount of stacks for each!)
Item Droppable Cooldown (Uniquely configurable for each, makes them undroppable when you use them for a set amount of time.)
You think it looks simple but it's not :p
These aspects are normally not included with your Wc3 :p

How to register items:

  • Template GUI
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- For a non stackable item --------
      • Custom script: call PreloadItem('I000', 'I001', false, 0, false, 0)
      • -------- 'I000' and 'I001' are our pair types. - false is a flag for stackability - 0 is the number of stacks it can have --------
      • -------- false flags it as droppable when used and 0 marks the cooldown time if it was flagged true --------
      • -------- =================== --------
      • -------- For a stackable item (Like potions) --------
      • Custom script: call PreloadItem('I002', 'I003', true, 10, true, 2)
      • -------- Now we flagged it as stackable with up to 10 stacks and undroppable when used for 2 seconds. --------
JASS:
function Trig_Template_Actions takes nothing returns nothing
    local boolean IsStackable = false
    local boolean HasCooldown = false
    local real cooldown = 0
    local integer MaxCharges = 0
    call PreloadItem('I000', 'I001', IsStackable, MaxCharges, HasCooldown, cooldown)
    //////////////////====================================================================
    set IsStackable = true
    set MaxCharges = 10
    set HasCooldown = true
    set cooldown = 2.0
    call PreloadItem('I002', 'I003', IsStackable, MaxCharges, HasCooldown, cooldown)
    ///////////===========================================================================
    set IsStackable = true
    set MaxCharges = 3
    set HasCooldown = true
    set cooldown = 10.0
    call PreloadItem('I004', 'I005', IsStackable, MaxCharges, HasCooldown, cooldown)
    ///////////===========================================================================
    set IsStackable = true
    set MaxCharges = 50
    set HasCooldown = false
    set cooldown = 0
    call PreloadItem('I006', 'I007', IsStackable, MaxCharges, HasCooldown, cooldown)
    //It doesn't matter in which order we put the raw codes
    //If you are able to read some basic jass go to our main code and
    //see how i preload the Demo Icons
    //It's very simple and easy to do
    //Roam for a function called PreloadItems
endfunction

//===========================================================================
function InitTrig_Template_JASS takes nothing returns nothing
    set gg_trg_Template_JASS = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Template_JASS, function Trig_Template_Actions )
endfunction

Map Code Bellow :

Library
JASS:
library subitems initializer init

globals
    private timer eTim = CreateTimer ( )
endglobals    

///============== EXTRA FUNCTIONS ===================\\\


private function ItemCount takes unit u, integer id returns integer
    local integer i = 0
    local integer count = 0
    loop
    exitwhen i == bj_MAX_INVENTORY
        if GetItemTypeId(UnitItemInSlot(u, i)) == id then
            set count = count + 1
        endif
        set i = i + 1
    endloop
    return count
endfunction  

///////////////////===================================\\\\\\\\\\\\\\\\\\

private struct cool
    integer id
    unit u
    real time = 0
    item i
endstruct


private struct Item
    integer a
    integer b
    integer charges = 0
    real cooldown = 0
    boolean charged
    boolean hascooldown
    static integer max = 0
    private static integer total = 0
    private static Item array arr
    private static timer tim = CreateTimer( )
    static method create takes integer a, integer b, boolean flag, integer c, boolean hc, real cd returns Item
        local Item that = Item.allocate()
        set that.a = a
        set that.b = b
        set that.charges=c
        if that.charges > 99 then
            set that.charges = 99 //Just in case..
        endif    
        set that.charged = flag
        set that.hascooldown = hc
        set that.cooldown = cd
        set Item.max = Item.max + 1
        return that
    endmethod
    
    static method GetCopy takes integer a returns integer
        local Item that
        local integer i = 0
        loop
        exitwhen i > Item.max
            set that = i
            if that.a == a then
                return that.b
            elseif that.b == a then
                return that.a
            endif
            set i = i + 1
        endloop
        return 0
    endmethod
    
    static method IsStackable takes integer a returns boolean
        local Item that
        local integer i = 0
        loop
        exitwhen i > Item.max
            set that = i
            if (that.a == a) or (that.b == a) then
                return that.charged
            endif
            set i = i + 1
        endloop
        return false
    endmethod  
    
    static method HasCooldown takes integer a returns boolean
        local Item that
        local integer i = 0
        loop
        exitwhen i > Item.max
            set that = i
            if (that.a == a) or (that.b == a) then
                return that.hascooldown
            endif
            set i = i + 1
        endloop
        return false
    endmethod     
    
    static method MaxCharges takes integer a returns integer
        local Item that
        local integer i = 0
        loop
        exitwhen i > Item.max
            set that = i
            if (that.a == a) or (that.b == a) then
                return that.charges
            endif
            set i = i + 1
        endloop
        return 0
    endmethod
    
    static method GetCooldown takes integer id returns real
        local Item that
        local integer i = 0
        local real cd = 0
        loop
        exitwhen i > Item.max
            set that = i
            if (that.a == id) or (that.b == id) then
                set cd = that.cooldown
            endif
            set i = i + 1
        endloop
        return cd
    endmethod    
    
    static method AddCooldown takes unit u, item i returns cool
        local cool down = cool.create()
        local integer id = GetItemTypeId(i)
        local integer w = 0
        local item k
        set down.u = u
        set down.i = i
        set down.time = Item.GetCooldown(id)
        loop
        exitwhen w == bj_MAX_INVENTORY
            set k = UnitItemInSlot(u, w)
            if GetItemTypeId(k) == id then
                call SetItemDroppable(k, false)
            endif
            set w = w + 1
        endloop
        set k = null
        if Item.total == 0 then
            call TimerStart(Item.tim, .50, true, function Item.Tick)
            //I suggest you keep the interval to this
            //JASS is fragile, threads crash if you push them too much
        endif    
        set Item.total = Item.total + 1
        set Item.arr[Item.total-1] = down
        return down
    endmethod
    
    static method Tick takes nothing returns nothing
        local cool down
        local integer i = 0
        local integer w = 0
        local item k
        loop
        exitwhen i >= Item.total
            set down = Item.arr[i]
            if down.time > 0 then
                set down.time = down.time - .50
                set w = 0
                loop
                exitwhen w == bj_MAX_INVENTORY
                    set k = UnitItemInSlot(down.u, w)
                    if GetItemTypeId(k) == GetItemTypeId(down.i) then
                        call SetItemDroppable(k, false)
                    endif
                    set w = w + 1
                endloop
            else    
                set w = 0
                loop
                exitwhen w == bj_MAX_INVENTORY
                    set k = UnitItemInSlot(down.u, w)
                    if GetItemTypeId(k) == GetItemTypeId(down.i) then
                        call SetItemDroppable(k, true)
                    endif
                    set w = w + 1
                endloop
                set k = null
                set down.u = null
                set down.i = null
                set Item.total = Item.total - 1
                set Item.arr[i] = Item.arr[Item.total]
                call down.destroy()
            endif    
            set i = i + 1
        endloop
        if Item.total == 0 then 
            call PauseTimer(Item.tim)
        endif
    endmethod    
endstruct    
            
private function Stack takes unit u, integer ID, integer ch returns nothing
    local integer i = 0
    local item array items
    local item k
    local boolean exit = false
    local integer c = 0
    local integer w = 0
    local integer q = 0
    local integer mc = Item.MaxCharges(ID)
    //Got any better ideas?
    loop
    exitwhen i == bj_MAX_INVENTORY
        set k = UnitItemInSlot(u, i)
        set items[i] = null
        if GetItemTypeId(k)==ID then
            set c = GetItemCharges(k)
            if (c+ch)<=mc then
                set items[i] = k
                set q = q + 1
            else
                set w = w + 1
            endif    
        endif
        set i = i + 1
    endloop
         
    /////////////////////////////////////////////
    ///Setting charges on weird case scenarios///
    /////////////////////////////////////////////
    set i = 0
    set c = 0
    if q>0 then
        loop
        exitwhen (i == bj_MAX_INVENTORY) or (c>0)
            set k = UnitItemInSlot(u, i)
            if k == items[i] then
                set c = GetItemCharges(k)
                call SetItemCharges(k, (c+ch))
            endif
         set i = i + 1
         endloop
     else
         if UnitInventoryCount(u)==bj_MAX_INVENTORY then
             set k = CreateItem(Item.GetCopy(ID), GetUnitX(u), GetUnitY(u))
         else    
             set k = CreateItem(ID, GetRectMaxX(bj_mapInitialPlayableArea)-50, GetRectMaxY(bj_mapInitialPlayableArea)-50)
             call SetItemCharges(k, ch)
             call UnitAddItem(u, k)
         endif    
      endif            
      set w = 0
      loop
      exitwhen w == bj_MAX_INVENTORY
         set items[w] = null
         set w = w + 1
      endloop
      set k = null
endfunction

private function Replace takes nothing returns nothing
    local item i = GetManipulatedItem()
    local integer it = GetItemTypeId(i)
    local integer copy = Item.GetCopy(it)
    local boolean b = Item.IsStackable(it)
    local integer c = GetItemCharges(i)
    local unit u
    if copy == 0 then
        set i = null
        return
    else
        set u = GetTriggerUnit()
        if b then
            if (ItemCount(u, copy)>0) then
                call Stack(u, copy, c)
                set i = null
                set u = null
                return
            endif
        endif    
        if UnitInventoryCount(u)==bj_MAX_INVENTORY then
            set i = CreateItem(it, GetUnitX(u), GetUnitY(u))   
        else
            set i = UnitAddItemById(u, copy)
            call SetItemCharges(i, c)
        endif
    endif
    set i = null
    set u = null
endfunction

private function EnumReplace takes nothing returns nothing
    local item i = GetEnumItem()
    local integer id = Item.GetCopy(GetItemTypeId(i))
    local real x = GetItemX(i)
    local real y = GetItemY(i)
    local integer c = GetItemCharges(i)
    call RemoveItem(i)
    set i = CreateItem(id, x, y)
    call SetItemCharges(i, c)
    set i = null
endfunction    

private function EnumCheck takes nothing returns boolean
    return (GetItemType(GetFilterItem()) != ITEM_TYPE_POWERUP) and (Item.GetCopy(GetItemTypeId(GetFilterItem()))>0) 
endfunction

private function EnumStart takes nothing returns nothing
    call EnumItemsInRect(bj_mapInitialPlayableArea, Condition(function EnumCheck), function EnumReplace)
endfunction  

private function OnUse takes nothing returns nothing
    if Item.HasCooldown(GetItemTypeId(GetManipulatedItem())) then
       call Item.AddCooldown(GetTriggerUnit(), GetManipulatedItem())
    endif
endfunction    

//=========================================================================================================================
private function Cond2 takes nothing returns boolean
    local real r = 0
    if (GetItemType(GetManipulatedItem()) != ITEM_TYPE_POWERUP) then
        set r = TimerGetRemaining(eTim)
        if r == 0 then
            set r = .07
        endif
        call PauseTimer(eTim)
        call TimerStart(eTim, r, false, function EnumStart)
    endif
    return false
endfunction

private function Cond3 takes nothing returns boolean
    return GetItemType(GetManipulatedItem()) == ITEM_TYPE_POWERUP
endfunction

private function PreloadItems takes nothing returns nothing
    //DEMO
    //In case you want to use this instead of calling a function to register your item types, read the lines above and 
    //Do the exact same thing in this block
    //===============================================================
    //call Item.create('I000', 'I001', false, 0, false, 0)
    //call Item.create('I002', 'I003', true, 10, true, 2)
    //===============================================================
    //These two calls are an example of how to instantly preload your items inside this block
    //We give the pair of items in first and second arguments, then we give the flag of stackability (potions, etc.) and the maximum amount of charges
    //Locking used items for a duration --->
    //4th argument marks the item as undroppable when used
    //5th argument gives the cooldown for the item
    //Let's assume 'I005' is a healing potion and 5 is it's cooldown, the item gets locked for 5 seconds, becoming undroppable :)
endfunction   
    
function PreloadItem takes integer a, integer b, boolean s, integer c, boolean hc, real cd returns nothing
    call Item.create(a, b, s, c, hc, cd)
    //A function that can be accessed from outside
endfunction    

private function init takes nothing returns nothing
    local trigger t = CreateTrigger ( )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_PICKUP_ITEM )
    call TriggerAddCondition(t, Condition(function Cond3))
    call TriggerAddAction( t, function Replace )
    set t = CreateTrigger ()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_USE_ITEM )
    call TriggerAddAction( t, function OnUse )
    set t = CreateTrigger ()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DROP_ITEM )
    call TriggerAddCondition( t, Condition(function Cond2))
    call PreloadItems()
    set t = null
endfunction

endlibrary
That's it!!

I'm looking forward to some judging and feedback
The damn heat is killing me =P

Keywords:
system, item, items, inventory, super, vjass, jass
Contents

Just another Warcraft III map (Map)

Reviews
Bribe: This is ready to be approved, but there are some O(N) searches that you could eliminate by using a Table. There is one in-game quirk and that is the item is still allowed to be purchased/picked up even if it won't fit in the inventory...

Moderator

M

Moderator

Bribe:

This is ready to be approved, but there are some O(N) searches that you could eliminate by using a Table.

There is one in-game quirk and that is the item is still allowed to be purchased/picked up even if it won't fit in the inventory (dropped at the feet of the hero). It would be more seemless if it simply rejected the purchase and left the item in the shop, or left the item back on the ground where it was originally from.
 
Level 7
Joined
Jun 6, 2010
Messages
224
Forgot to mention
To register and stack inventory and items, you need a copy of your items made in the object editor, flagged as power up, use automatically when acquired, perishable and with no item abilities.

That's it!

If you got confused open the object editor and see how i did it.
 
Level 6
Joined
Nov 3, 2008
Messages
117
Ok Feedback.

1. I don't get why you use 2 different items. Ok the buy a item and get a different item is useful, but why you replace it when an item is dropped. On the one hand it looks weird and on the other its kinda nonsense (in my opinion)
2. I'd say your Cooldown thingy is useless since warcraft allready supports non-droppable items with cooldown. Cons of your system are that you don't see any cooldown on the item, you dont get an error message.

More later

Edit: Would be glad to have ya back in wc3 mapping scene -> Anachron
 
Level 7
Joined
Jun 6, 2010
Messages
224
Ok Feedback.

1. I don't get why you use 2 different items. Ok the buy a item and get a different item is useful, but why you replace it when an item is dropped. On the one hand it looks weird and on the other its kinda nonsense (in my opinion)
2. I'd say your Cooldown thingy is useless since warcraft allready supports non-droppable items with cooldown. Cons of your system are that you don't see any cooldown on the item, you dont get an error message.

More later

Edit: Would be glad to have ya back in wc3 mapping scene -> Anachron


1st: You can't buy an item from shop if your inventory is full. The first item is powerup, it means you can pick it anyways no matter the size of inventory

2nd: What? You make any sense? Do you have any idea what kind of abuse you can do by giving an item with cooldown to other units? Let's say an item with avatar, use item, then drop it, pick it use it then drop it. See what happens. No, blizzard doesn't provide us with timed un-droppable cooldown.

@Anachron
What difference does it make? The struct is private.
 
Level 2
Joined
Aug 17, 2010
Messages
10
Ok Feedback.

1. I don't get why you use 2 different items. Ok the buy a item and get a different item is useful, but why you replace it when an item is dropped. On the one hand it looks weird and on the other its kinda nonsense (in my opinion)
2. I'd say your Cooldown thingy is useless since warcraft allready supports non-droppable items with cooldown. Cons of your system are that you don't see any cooldown on the item, you dont get an error message.

i just tested it and i'm glad to actually see a working item system

basically if you played dota, when you buy an item from shop and want to make a recipe, and your inventory is full and that item you bought matches the recipee combination, the combination gets completed!

i think he replaces items that he drops so they got back into their 'POWER UP'stage so he can pick them again with full inventory.

Also what you say in no.2 doesn't exist man... Yes you can change an item's attribute to droppable/undroppable in the object editor but you can't toggle it in game, what he did in the system was to make items undroppable after he uses them until the item's cooldown vanishes.

This system deserves a 5/5
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
2nd: What? You make any sense? Do you have any idea what kind of abuse you can do by giving an item with cooldown to other units? Let's say an item with avatar, use item, then drop it, pick it use it then drop it. See what happens. No, blizzard doesn't provide us with timed un-droppable cooldown.

just tried it with kelens dagger of escape and 2 palas
I picked up the item
blinked
item had cooldown
dropped it
picked it up with other pala
item had cooldown again

I remember that things were not like that but that was long long time ago
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
no you didn't
Propably you made the item perishable

I didn't but made the item perishable? :ugly:
no I did it (testet it) but I didn't make it perishable

i just did

congratulations
want a screenshot? or a demo map?

to prove what?
that I didn't have a fatal error while testing it?
sure
go ahead and show me a screenshot/demo map of exactly what I did without fatal error :p

I attached my own testmap so you can see that I'm not talking trash
 

Attachments

  • Avatar Item.w3x
    12.4 KB · Views: 167
Level 7
Joined
Jun 6, 2010
Messages
224
oh gosh are you trying to annoy me or you're just clumpsy?
The item's cooldown group is not even related to the ability's cooldown. It's related with "BLINK"

Do you have any idea about object data or you're just throwing around random shit talk?

Let me post you your deserved reply with your own map working avatar.

HERE
How does this happen then?

clipboardoj.jpg


Maybe i should also give you a lesson for warcraft native ability functions.
When casting an ability like windwalk, avatar, metamorphosis
The map creates a handle, a timer with a resolution that is calculated by the ability's duration and cooldown.
the raw code of the ability = 'A000'
It creates an object called A000
that object has some returning methods like . A000.cool1 (cooldown)
The timer grabs these objects, if it returns null while it's supposed to return a real , you will have a runtime error.

Before even thinking of talking about programming, i suggest you get your brain loaded with some proper information then start a proper debate.
 

Attachments

  • Avatar Item CORRECT VERSION.w3x
    12.4 KB · Views: 119
hmmm.... looks good and useful, though somehow it needs lots of item registration and object data... anyways, inventory and equipment systems are never for lazy persons...

one question though, can we remove the item that is power-up? as I have read that is only for you to still be able to buy items when inventory is full, so if we dont want that can we remove it?
 
Level 7
Joined
Jun 6, 2010
Messages
224
well you gotta test it in the map :)
You can stack potions to a configurable max stack when you preload it.
Let's say you want your Healing Salve to stack 66 times
You preload it, make it stackable, and set its stacks to 66.

Each time you get 1 healing salve, it will stack to a current stack in your inventory.
:p
Space conserving!

Also if you didn't notice, you can make an item undroppable for a duration.
Like using a Scroll of Teleport, and it got a cooldown of 15 seconds, you can preload it and set it undroppable and set it's cooldown to 15.
When you use it, it will be undroppable for 15 seconds. Same as it's stacks.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
oh gosh are you trying to annoy me or you're just clumpsy?
The item's cooldown group is not even related to the ability's cooldown. It's related with "BLINK"

Do you have any idea about object data or you're just throwing around random shit talk?

Let me post you your deserved reply with your own map working avatar.

HERE
How does this happen then?

clipboardoj.jpg


Maybe i should also give you a lesson for warcraft native ability functions.
When casting an ability like windwalk, avatar, metamorphosis
The map creates a handle, a timer with a resolution that is calculated by the ability's duration and cooldown.
the raw code of the ability = 'A000'
It creates an object called A000
that object has some returning methods like . A000.cool1 (cooldown)
The timer grabs these objects, if it returns null while it's supposed to return a real , you will have a runtime error.

Before even thinking of talking about programming, i suggest you get your brain loaded with some proper information then start a proper debate.

actually I was talking about fatal errors and about that you can't use avatar properly as an item
apparently you got me all wrong :grin:
but since pictures say more than 1000 words you might get this one (and yes, it was done with your perfect test map)
 

Attachments

  • FATAL_ERROR.jpg
    FATAL_ERROR.jpg
    37.7 KB · Views: 113
well you gotta test it in the map :)
You can stack potions to a configurable max stack when you preload it.
Let's say you want your Healing Salve to stack 66 times
You preload it, make it stackable, and set its stacks to 66.

Each time you get 1 healing salve, it will stack to a current stack in your inventory.
:p
Space conserving!

Also if you didn't notice, you can make an item undroppable for a duration.
Like using a Scroll of Teleport, and it got a cooldown of 15 seconds, you can preload it and set it undroppable and set it's cooldown to 15.
When you use it, it will be undroppable for 15 seconds. Same as it's stacks.

well, the only why I said that I have no use for it now is because I'm working on an rpg which uses The_Witcher's equip system and I would not put any usable items, even potions will be triggered...

but this will surely come handy for some other things I might work on especially the undroppable while cooling down and the stacking since I can configure what items will stack and how many (the current one I use in my hero arena stacks all charged items and all items has the same max)...
 
Level 7
Joined
Jun 6, 2010
Messages
224
actually I was talking about fatal errors and about that you can't use avatar properly as an item
apparently you got me all wrong :grin:
but since pictures say more than 1000 words you might get this one (and yes, it was done with your perfect test map)

the error only occurs with invalid data returned and 'IF' the item does not exist in the memory.

While the item (with the avatar) is still in your inventory and you cast it, you get no fatal errors.

instead of posting screenshots without a statement, submit some valid explanation to : Why the hell that item crashed my game?
 
Level 5
Joined
Oct 24, 2007
Messages
90
Great system, might use it in my map. However, I found a minor bug when fooling around with it a bit. Yeah, I am bored. For example, you have a full stack of some item; the rest of your inventory is full. You buy another item of the one you have full stack on. It drops to the ground (it's supposed to happen, I know). You drop the full stack, and pick the other dropped item up, then pick the stack. Nothing. Pick it again: it comes into your inventory as just 1 item. It sounds too improbable to happen while somebody is playing normally, but it's worth mentioning. It basically turns a stack of 50 of potion of clarity, for example, into 1. :O

EDIT: It happens every time you attempt to pick a stack twice which doesn't fit in your inventory anymore. It's not so improbable anymore, I guess.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
subitems

Bad name for a library.

function PreloadItem takes integer a, integer b, boolean s, integer c, boolean hc, real cd returns nothing

Poor naming convention to say the least. Looking at the code, it does nothing. I have to read the description, which should be extraneous, not a requirement.

loop and exitwhen conventionally are indented on different lines. Not sure why you are having it like this but all scopes in JASS are properly supposed to be four spaces unindented from their content items.

THIS SYSTEM DOES NOT AFFECT ANY OF YOUR ITEMS
UNLESS YOU REGISTER THEM!!

Lots of work to put on the users to register every single item, but why not.

'I000', 'I001'... why are there two rawcodes? What's the second for?

This is probably going to end up approved one day. I just am missing a couple of things...

Why two timers?

Why PauseTimer right before TimerStart?
 
Top