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

[vJass] (System) CustomInventory

By far the biggest inventory system for Warcraft 3.
It's designed to have optional features, like FullScreenInventory-UI.

With a little bit of modification you can use this Inventory System in the normal Warcraft 3 Inventory too.

It is written in vJASS and has the following features:
- 12 Slot Equipment
- MPI
- Very flexible
- Easy to add bonuses to items
- Item Stacking
- Item Forging
- Item Sets (With bonuses)
- Inventory fixes warcraft 3 bugs (Double pickup bug)
- Fast
- Gives the ability to add your own areas with a little bit of code

A small note on the classes:

##############################################################################
# USER INTERFACE - CUSTOM WINDOW
##############################################################################
---------------
CWDestructable
---------------
It's an object that has an destructable for a local player.
(Such as icons, borders and more)

---------------
CWTrackable
---------------
This is basically an object that triggers player events for hovering the icons (CWDestructable).
Whenever an event occurs, it fires an action to the CustomWindow

---------------
CustomWindow
---------------
A collection of CWTrackable and CWDestructable. Every destructable will have an trackable object.
So whenever you hover over or click a trackable, this will be fired.
You will use this object to create hooks to the inventory system.

##############################################################################
# CUSTOM WINDOW - HOOK AND EXTENDING
##############################################################################

---------------
CIAll
---------------
This is a container object of items. It has conditions for pickup and drop and is the base
class for any container, like Slots, Potions, Equipment or even spell slots that you could create!
It has a variety of methods like adding, removing and checks and throws errors.

---------------
CIActions
---------------
This is a library which only use is to find out what the user wants to do. It supports up to 5
different steps which can be done in a row so if you need to build up something complicated here you go.
This action decides when to move, drop, pick and destroy items. It's bound to CIWindow and uses its
events to trigger / delegate events to the CISlots/CIEquips/CIPotions objects.

---------------
CIContent
---------------
This is a little help class for the CIActions object which puts a wrapper around the Equipment,
Potions and Slots. It will also update the camera.

---------------
CIWindow
---------------
This is the hook between CustomWindow, CIActions and the CustomInventory. It also provides
fake units to provide the Interface Functionality and delegates events to CIActions.

---------------
CISlots / CIEquips / CIPotions
---------------
The containers you see (Top left, top right and bottom left) are basically these objects.
They have special / unique conditions for pickup / drop and handle when to add or remove bonuses from the hero.

##############################################################################
# CUSTOM INVENTORY - CORE
##############################################################################

---------------
CIForging
---------------
This module forges items. You can combine any items and merge them to a bigger item. This will
always happen when your inventory updates.

---------------
CIStacking
---------------
You like items that can stack in your Inventory? Well this module is for you!
Create stackable items and make a maximum conditions. Item stacking is automatic, whenever
inventory updates.

---------------
CISet
---------------
Don't we all love this thing from World of Warcraft? Collecting items of a special set and
then get some bonus stuff once we have all of them. If you are cool, use this feature. It
even supports SET STACKING!

---------------
CIAttachment
---------------
Not done yet.

---------------
CIBonus
---------------
This is the hook between items and the unit state modifier library. You can use this module
to add and remove bonuses to the hero on the fly whenever needed.

---------------
CIError
---------------
Throw errors to the user whenever something bad happens.

---------------
CIEventHandler
---------------
Like every other Inventory system, we need some kind of hook for pickup/drop actions to
connect them with our CustomInventory. This will trigger the CustomInventory events.

---------------
CIEvents
---------------
Name may not be completely self-speaking, but this actually triggers the events on the item.
But only when the unit really has the item. (Safety layer)

---------------
CIItemDrop
---------------
This will allow pickup/drop actions of the items WITHOUT triggering the inventory events.
It will be required for many things so this module is a life safer!

---------------
CIItemInfo
---------------
Wouldn't it be cool if items could display what they are in a multiboard. Yes it would.
This module is exactly for that.

---------------
CIItemBoard
---------------
Yes, this is the multiboard which displays all the item statistics. It uses hooks to get
the attached events from the CUstomWindow.

---------------
CIItemProtection
---------------
Every item has states, like locked, owend, equiped and such. This module gives the ability
to change the states and make them available.

---------------
CIItemDest
---------------
Simple module for setting the destructable (icon) for the CustomWindow.

---------------
CIItemSeek
---------------
Module which is build to search and collect information about the inventory.
Find out how many items of which type you have that are not stacked, find out how many duplicated
items you have and even if you have errors in your inventory indexing.

---------------
CIItemSlot
---------------
Small module that adds classes to the items. You can only equip items with the right class
on the right positions.

---------------
CIItemEffect
---------------
This module allows to attach effects to an item wearer. Do whatever you want, but keep in mind
that one item has a maximum of 3 effects.

---------------
CIPowerup
---------------
Not done yet.

---------------
CISetup
---------------
Changes the area around the inventory to be black and create the UI for all players.


---------------
CustomItem
---------------
The item object itself. Will trigger and get triggered from all kind of sources.
Modules are completing the collection of members and methods.

---------------
CustomInventory
---------------
The main object. It forges, stacks, creates sets, triggers events, gets triggered and uses
optional modules to provide the full repository of features to the user.



-Fixed a bug found by Dr. Boom:
Dead units were able to change the inventory and caused bugs.
-Also added a little bit of documentation.


Keywords:
CustomInventory, Inventory, Custom, Anachron, FullScreen, Module, vJass, Stack, Forge, Combine, Set, Powerup, Drop, Equip, Equipment, Equip, System
Contents

CustomInventory - 0.2.2.6 (Map)

Reviews
18:27, 18th Feb 2010 The_Reborn_Devil: Ohsh- That describes pretty much what I'm thinking. My eyes were sore even before I was done reviewing half of the code. The code looks really good and I couldn't find just one little thing that would be...
Level 14
Joined
Mar 30, 2009
Messages
971
But really, how many people take profit from these updates? I guess 4-5?
i will! :D :D

What about changing the hero why cant i change it (im a noob pls teach me how)
if you have read the description then you should know that you HAVE TO know jass to be able to use this normally.

@offtopic:
i disagree with vercas cause it is not proper to mention illegal stuff at this site, it is improper and it is in violation of the site rules. i think you should also remove that link, be it in h4x0r language or not.
though i do agree with vercas, cause sweden is a damn welfare country :D, life in sweden is one of the best. and dude ive been to sweden too so i know whats it like. yes, games for you are 1.5 times more expensive than in the US and probably 10 times more expensive than in romania or here (estonia). i basically live in northern europe, but im still poor and with my funds i shouldnt even have the crappy computer i have. prices in sweden are higher than in other countries, but wages are way more higher yet and thats what matters. why do you think all those immigrants from around the world run to sweden when you have such high prices? if our family was to move to sweden id be swimming in money compared to the situation before. and that only thanks to the social benefits.
i would like to continue this discussion, but this here is not the right place for it. :)
 
Level 12
Joined
May 21, 2009
Messages
994
if our family was to move to sweden id be swimming in money compared to the situation before. and that only thanks to the social benefits.
i would like to continue this discussion, but this here is not the right place for it. :)

I'm really sorry to do this last off topic but, thats a big problem with people in greece or if you go to a more poor land than where I come from (Denmark). They always think we are rich and we got everything because we are from a 'rich' country. That is not necessarily true.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
something on-topic:
I have a map where players have to select a hero through a hero tavern.
Is it possible to create a fake inventory unit when the hero is created and use the hero+fake inventory unit for the system?
I tryed doing this:

JASS:
set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit()))), 'h000')
call CreateInventoryUI(GetSoldUnit(), fakeInv)

But it seems like it's not working. When I test it in-game I can't press escape to see the inventory for the hero thats being created from the tavern. Does the system need a hero created on init? Or am I doing something wrong?

this is the trigger I used instead of the test trigger:
  • Hero Selected
    • Events
      • Unit - A unit Sells a unit
    • Conditions
      • (Unit-type of (Selling unit)) Equal to SomeUnit
    • Actions
      • Custom script: local unit fakeInv = null
      • Set TempLoc = (Position of (Selling unit))
      • Unit - Remove (Selling unit) from the game
      • Unit - Move (Sold unit) instantly to TempLoc
      • Set HeroSpawnLoc[(Player number of (Owner of (Sold unit)))] = TempLoc
      • Set PlayerHero[(Player number of (Owner of (Sold unit)))] = (Sold unit)
      • Selection - Select (Sold unit) for (Owner of (Sold unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of (Sold unit)) Equal to Myhero1
        • Then - Actions
          • Custom script: set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit()))), 'h000')
          • Custom script: call CreateInventoryUI(GetSoldUnit(), fakeInv)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of (Sold unit)) Equal to Myhero2
            • Then - Actions
              • Custom script: set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit()))), 'h001')
              • Custom script: call CreateInventoryUI(GetSoldUnit(), fakeInv)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Unit-type of (Sold unit)) Equal to Myhero3
                • Then - Actions
                  • Custom script: set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit()))), 'h002')
                  • Custom script: call CreateInventoryUI(GetSoldUnit(), fakeInv)
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Unit-type of (Sold unit)) Equal to Myhero4
                    • Then - Actions
                      • Custom script: set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit()))), 'h003')
                      • Custom script: call CreateInventoryUI(GetSoldUnit(), fakeInv)
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (Unit-type of (Sold unit)) Equal to myhero5
                        • Then - Actions
                          • Custom script: set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit()))), 'h004')
                          • Custom script: call CreateInventoryUI(GetSoldUnit(), fakeInv)
                        • Else - Actions
      • Camera - Reset camera for (Owner of (Sold unit)) to standard game-view over 0.00 seconds
      • Custom script: call RemoveLocation (udg_TempLoc)
 
But it seems like it's not working. When I test it in-game I can't press escape to see the inventory for the hero thats being created from the tavern. Does the system need a hero created on init? Or am I doing something wrong?

Check the example. You have to set up fake hero types for the fake units for the inventory. Just check the loop.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Check the example. You have to set up fake hero types for the fake units for the inventory. Just check the loop.

I did that. Please check the edit in my post for the trigger I used to create fake hero types and create the UI with the sold unit + the fake hero.

EDIT: DOH >< forgot that in jass the index starts at 0 for players xD sry :p (I'm such a noob xD) changed it and works :)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
I don't know. Maybe GUI is the mistake.

no man it works ;D!
I was just a bit stupid xD I forgot that in jass the indexes start at 0 so I changed them to:

JASS:
set fakeInv = CreateInventoryUnit(Player(GetConvertedPlayerId(GetOwningPlayer(GetSoldUnit())) - 1), 'h000')

sry for the mistakes, just learning from them ;)

EDIT: b.t.w. have you found a way to create black fog over the inventory to cover it completely? :D Because I have no idea how to create something like that inside your system :S
I'm also trying to show a multiboard after a user pressed escape to close the inventory. I tryed doing this:

JASS:
private method onDestroy takes nothing returns nothing
        call DestroyMultiboard(bBoard)
        set bBoard = null
        if GetLocalPlayer() == Player(0) then
            call MultiboardDisplay(udg_Headquarters_multiboard, true)
        endif
    endmethod

but it didn't work ;( Now the multiboard of the inventory doesnt show because the multiboard I want to show just stays there xD. Did I put it at the wrong place in the code? Or am I failing ones again? :D When does this private method gets executed? :S
this is in the Board trigger btw xD
 
Last edited:
Level 14
Joined
Apr 20, 2009
Messages
1,543
the onDestroy is only called when you destroy the inventory.

Use the show/hide method inside CWInventoryWindow (At least I remember that name) to run code on show/hide actions.

there is no CWInventoryWindow.
CWDestructable, CWTrackable, CustomWindow and CWBorder are the ones existing and I cant find any show/hide methods inside them :S
 
CIContent

JASS:
public method show takes boolean bol returns nothing
            call FogModifierStop(.visible)
            call DestroyFogModifier(.visible)
            
            set .viewing = bol
            
            //call EnumDestructablesInRect(CI_UI_RECT, Condition(function thistype.checkDest), null)
                
            if bol then
                if GetLocalPlayer() == Player(.Player) then
                    set .camX = GetCameraTargetPositionX()
                    set .camY = GetCameraTargetPositionY()
                    set .camZ = GetCameraTargetPositionZ()
                    set .camDist = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE)
                endif
                
                set .visible = CreateFogModifierRect(Player(.Player), FOG_OF_WAR_VISIBLE, CI_UI_RECT, false, false)
                call .refresh()
                
                call PreventSpecificOrder(.inventory.getOwner(), "move", true)
                call PreventSpecificOrder(.inventory.getOwner(), "smart", true)
                
                static if LIBRARY_CIItemBoard then
                    call .inventory.showBoard(true)
                endif
            else
                set .visible = CreateFogModifierRect(Player(.Player), FOG_OF_WAR_MASKED, CI_UI_RECT, false, false)
                
                if GetLocalPlayer() == Player(.Player) then
                    call SetCameraPosition(.camX, .camY)
                    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 305., 0)
                    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, .camDist, 0)
                endif
                
                call ClearAllSpecificOrderPrevention(.inventory.getOwner())
                
                static if LIBRARY_CIItemBoard then
                    call .inventory.showBoard(false)
                endif
            endif
            
            call FogModifierStart(.visible)
        endmethod

You can use this to hook a show/hide action for the inventory of a player.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
CIContent

JASS:
public method show takes boolean bol returns nothing
            call FogModifierStop(.visible)
            call DestroyFogModifier(.visible)
            
            set .viewing = bol
            
            //call EnumDestructablesInRect(CI_UI_RECT, Condition(function thistype.checkDest), null)
                
            if bol then
                if GetLocalPlayer() == Player(.Player) then
                    set .camX = GetCameraTargetPositionX()
                    set .camY = GetCameraTargetPositionY()
                    set .camZ = GetCameraTargetPositionZ()
                    set .camDist = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE)
                endif
                
                set .visible = CreateFogModifierRect(Player(.Player), FOG_OF_WAR_VISIBLE, CI_UI_RECT, false, false)
                call .refresh()
                
                call PreventSpecificOrder(.inventory.getOwner(), "move", true)
                call PreventSpecificOrder(.inventory.getOwner(), "smart", true)
                
                static if LIBRARY_CIItemBoard then
                    call .inventory.showBoard(true)
                endif
            else
                set .visible = CreateFogModifierRect(Player(.Player), FOG_OF_WAR_MASKED, CI_UI_RECT, false, false)
                
                if GetLocalPlayer() == Player(.Player) then
                    call SetCameraPosition(.camX, .camY)
                    call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, 305., 0)
                    call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, .camDist, 0)
                endif
                
                call ClearAllSpecificOrderPrevention(.inventory.getOwner())
                
                static if LIBRARY_CIItemBoard then
                    call .inventory.showBoard(false)
                endif
            endif
            
            call FogModifierStart(.visible)
        endmethod

You can use this to hook a show/hide action for the inventory of a player.

thanks ones again, it works ;D!
I still have one question, I guess it will be my last ;)

How do I call the command to destroy the inventory for a player?

I have a repicking trigger for hero's but I'm not quite sure how to destroy the inventory. Now whenever I repick a hero I have 2 inventory's of 2 hero's (which one of them is removed. Which also means the fakeinv unit still exists) for 1 player... that kind of bugs the inventory xD Does the fake inventory unit get removed whenever the inventory gets destroyed?

P.S. hope I'm not bothering you too much with questions :S
 
Last edited:
thanks ones again, it works ;D!
I still have one question, I guess it will be my last ;)

How do I call the command to destroy the inventory for a player?

I have a repicking trigger for hero's but I'm not quite sure how to destroy the inventory. Now whenever I repick a hero I have 2 inventory's of 2 hero's (which one of them is removed. Which also means the fakeinv unit still exists) for 1 player... that kind of bugs the inventory xD Does the fake inventory unit get removed whenever the inventory gets destroyed?

P.S. hope I'm not bothering you too much with questions :S
Not possible, you can manipulate the system a bit (tweak) and change the units for the inventory dummy + hero, so that it will work like that. (Remember to DESTROY all the items before changing the units)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Not possible, you can manipulate the system a bit (tweak) and change the units for the inventory dummy + hero, so that it will work like that. (Remember to DESTROY all the items before changing the units)

JASS:
  private static method hook_ReplaceUnitBJ takes unit whichUnit, integer newUnitId, integer unitStateMethod returns nothing
        set removing[getIndex(whichUnit)] = true
    endmethod
    //Intercepts whenever RemoveUnit or ReplaceUnitBJ is called and sets a flag.

does this mean I can call ReplaceUnitBJ to replace the hero that is used for the inventory with another hero? :D
And does this also count for the fake inventory unit? (It doesn't matter for the fake inventory unit because I already found a way to replace that. But for the hero I haven't found a way yet :p)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Nope, that is from another code that I did not write.

If you are not familiar with vJass, I would not use this system.

However, the CIContent includes the hero and the fakehero unit (saved) and you could write methods by yourself to change them.

I'm still learning, and I will not quit untill I have fixed this ;)
thanks for all your help.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Yes, I would say check the CIContent struct.
Don't forget that you will need to destroy the inventory of the unit as well!

JASS:
call CustomInventory.load(GetHandleId(theUnit))

And then create a new one.

You don't need to destroy the CIContent (The window), but you should replace the dummy unit.

I recreated the dummy by making the fakeinv variable global. That seems to work. Now the only trouble I'm having is recreation of the inventory of the unit. I'll try the best I can, I think I'll get it to work ;)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
a little question: when the inventory of the unit is destroyed you can still press escape to see the inventory? Because it seems like I have to disable that untill the player has picked his new hero.. :S
This is what happens:

a hero has been picked -> the inventory is created for that hero.
the player types -repick -> the inventory of the hero gets destroyed and the fake inventory unit gets removed.

the player presses escape without having a new hero -> gives the autoindex error for removed or decayed units. (problem #1) I know why it gives that error message... But what I found strange is that: how can a player press escape to see the inventory when the inventory is destroyed :S?

the player picks a second hero -> inventory is created for the hero with a fake inventory unit

the player presses escape while having the new hero -> The inventory does show for maybe half a second and then gets hided. (problem #2) I have no idea why this happens :S


I used debugmessages to find out if the handleId of the destroyed inventory is the same as the one being created but the handleId is the same so that couldn't be the problem :(

as what I had assumed:
call CustomInventory.load(GetHandleId(theUnit)) will destroy the inventory of the unit right :S?

then why can a player still press escape after it gets destroyed :S?
I also noticed that .inventory becomes 2 when the second inventory gets created. Does this mean that the player now has 2 inventory's?
How do I make sure that the first inventory gets completely removed?

I'm trying to understand it but it still is a bit too hard for me ><
Maybe it's better if I find someone who knows vJass better then I do and helps me to solve this.
This is too much time consuming for you and for me :p
 
Last edited:
call CustomInventory.load(GetHandleId(theUnit)) will destroy the inventory of the unit right :S?
No, it just loads the inventory.

You should really translate the actions.

JASS:
call CustomInventory.load(GetHandleId(theUnit)).destroy()
this destroys it.

then why can a player still press escape after it gets destroyed :S?
I also noticed that .inventory becomes 2 when the second inventory gets created. Does this mean that the player now has 2 inventory's?
How do I make sure that the first inventory gets completely removed?
Check above, this should be fixed when inventory is destroyed.

By the way, I stopped mapping, I am really sorry but I don't offer that much help anymore.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
No, it just loads the inventory.

You should really translate the actions.

JASS:
call CustomInventory.load(GetHandleId(theUnit)).destroy()
this destroys it.


Check above, this should be fixed when inventory is destroyed.

By the way, I stopped mapping, I am really sorry but I don't offer that much help anymore.


thanks man, I appreciate everything you did for me :)
I hope this will solve my problem. If it does I will stop asking these questions. I have already asked enough xD

and thanks for your time man :)
 
i mean if you put something from the inventory to your equipment and put it back o your inventory. so i can add other item abilitys to the unit.
Oh well then use the set itemobj.onPickAct = funcion. (Inside the function you do the stuff). Don't forget that the onDropAct should remove the abilities.
 
Level 1
Joined
Jul 4, 2010
Messages
2
Hey guys i want to use this inventory System for my ORPG but everytime i save the map i got the error Unable to find textmacro "optional" can someone say me what to do?
 
Level 17
Joined
Jun 9, 2007
Messages
2,493
Yes, can you guys please actually read the readme?

I think the reason to why people does not read it is becouse it is named readme...
And that is just stupid.
Make a huge bolded red text in the description and tell them to read the readme.
Most people just avoid reading stuff becouse they are lazy or just think that it is some trash.
There should be a rule about reading the readme before asking a question actually.. Not to sound rude or something.. but it should be obvious to read the readme.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
The map won't launch every time I start it. I launch it on v1.24 does it have anything to do with my version.
Yes, can you guys please actually read the readme?

I am not complaining that I can't use your system in my own map. The problem is that I can't test yours.

I have done what you said in the readme downloaded JASSNewGen 5d and then opened it but every time I test YOUR map the loading screen won't launch and I return to the main screen as if the map doesn't exist.

Your help please.

<< EDIT >>

I don't know how it worked. It seems it won't launch because the file was in many sub-folders and the path was too long to find, but I am not sure if this is the reason or not. Anyway thanks. I hope you finish this system.

Here are my comments/bugs in the systems:

1) In the black area where the GUI is, when I press the cancel button (click on the ground) it opens the inventory.
2) Sometimes when I click on an empty square in the inventory it selects the one that is below,above, right or left of it.

Other than that the system is good.

(+ rep)
 
Last edited:
Top