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

Item Recipe System v 1.1.1.0

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
i know there are some other recipe systems out there but i decided to make a very easy to use system in vJass. all you have to do is something like this.
This example creates one item from 3 items. updated map has 2 recipes now one adds 2 items w same type the other does not.

note: disAssemble works but if u have 2 recipes that make the same item then it will only disAssemble to the last created recipe

JASS:
library ItemRecipeSystem /* by deathismyfriend version 1.1.1.0
================================ Requirements =================================
               Requires JNGP 
    */uses Table, /* [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url] by bribe
    *      Alloc  * [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-alloc-alternative-221493/[/url] by nestharus

*************************************************************************************
*
*   Used to easily create item recipes.
*
************************************************************************************
*
*   Installing
*       STEP 1: Install JNGP first if you dont have JNGP.
*       STEP 2: Install Table by bribe the link is above.
*       STEP 3: Install Alloc by nestharus the link is above. You may be able to use some other alloc systems.
*       STEP 4: Copy and paste this library to your map.
*
************************************************************************************
*
*       Description
*       -----------------------
*           This is a very easy recipe system it only requires you to make recipes by using the create function.
*           After that it checks for a recipe everytime an item is picked up or bought or when u enter a rect decided by the user.
*           Allows you to set a rect if u want to use the enter rect / region event.
*           Note: removes the items and adds the new item to the unit when the last item needed for the recipe is picked up by the unit.
*
*       Capabilities
*       -----------------------
*           
*           Allows the user to easily create an item recipe.  
*               -   example as done in map  -  local RecipeList data = RecipeList.create( 'ratc', 'rat6', 'rat9', 0, 0, 0, 'I000', true)
*               -   this recipe only uses 3 items. 
*
******************************************************************************************************************************************************************************************************

/ ******************************************************************************************************************************************************************************************************
/ *
/ *       CREATORS / DESTRUCTORS
/ *       -----------------------
/ *
/ ******************************************************************************************************************************************************************************************************
/ *     
/ *     struct Recipe extends array
/ *  
/ *         static method create takes integer i1, integer i2, integer i3, integer i4, integer i5, integer i6, integer itmToBeMade, boolean createOnPickup returns thistype
/ *             -   this is all you need to create an itemRecipe. If you do not want a 6 item recipe just put in a 0 for the integers.
/ *             -   If you want to make a recipe that you need to go in a region to make then set pickupRecipe to false.
/ *
/ *         method destroy takes nothing returns nothing
/ *             -   to destroy an item recipe if wanted. just store the struct into an integer variable to destroy the item Recipe
/ *     
/ *         static method disAssemble takes item itm, unit u returns nothing
/ *             -   u can use this to disAssemble an item made through a recipe
/ *
/ *
/ *         METHODS
/ *         -------
/ *
/ *         method RequireCharges takes integer itemId, integer charges returns nothing
/ *             -   This allows u to make item recipes require charges.
/ *             -   It takes the item id and the number of charges you want it to have.
/ *
/ *         static method forceRecipe takes unit u returns nothing
/ *             -   allows u to force a recipe for when a unit enters region or some other event of ur choice
/ *
/ *         static method forceRecipeByItem takes unit u, integer itemTypeId returns nothing
/ *             -   this allows for specific recipes to be made in specific rects.
/ *             -   note: use a special item for the itemTypeId 
/ *
/ *         static method disable takes nothing returns nothing
/ *             -   pauses the recipe system
/ *            
/ *         static method enable takes nothing returns nothing
/ *             -   resumes the recipe system
/ * 
/ *       
/ *         private static method turnOffOtherSystems takes nothing returns nothing
/ *             -   add systems to turn off when the recipe system is running
/ *        
/ *         private static method turnOnOtherSystems takes nothing returns nothing
/ *             -   the systems u turned off in the above method turn them on here
/ *
/ ********************************************************************************************************************************/    

    globals
        private Table disAssembleTable
        private integer array structArray
        private integer array regId
    endglobals
    
    struct Recipe extends array
        implement Alloc

        private static rect recipeRect
        private static integer tempR
        
        private static method turnOffOtherSystems takes nothing returns nothing
        endmethod
        
        private static method turnOnOtherSystems takes nothing returns nothing
        endmethod
        
        private static integer index = 0
        private static boolean combineItems = true
        private integer i1
        private integer i2
        private integer i3
        private integer i4
        private integer i5
        private integer i6
        private integer charges1
        private integer charges2
        private integer charges3
        private integer charges4
        private integer charges5
        private integer charges6
        private integer itmToBeMade
        private integer ttlItemsForRecipe
        private boolean pickup
        private boolean charges
        
        private static method checkingRecipes takes integer id, unit u, boolean pick returns nothing
            local thistype this
            local region reg
            local integer array i
            local integer array charges
            local integer ttlItemsUnitHas = 0
            local boolean b
            local item array itm
            local boolean array isItm
            local integer L = 1
            local integer L1 = 1 // used to check through the recipes tht go w that specific item
            local integer L2 = 1
            local integer r = 1 // used for removing items from the slots
            if combineItems then
                call thistype.turnOffOtherSystems()
                loop
                    exitwhen L1 > index
                    set this = structArray[L1]
                    if this.pickup == pick then
                        set i[1] = this.i1
                        set i[2] = this.i2
                        set i[3] = this.i3
                        set i[4] = this.i4
                        set i[5] = this.i5
                        set i[6] = this.i6
                        set charges[1] = this.charges1
                        set charges[2] = this.charges2
                        set charges[3] = this.charges3
                        set charges[4] = this.charges4
                        set charges[5] = this.charges5
                        set charges[6] = this.charges6
                        set isItm[1] = false
                        set isItm[2] = false
                        set isItm[3] = false
                        set isItm[4] = false
                        set isItm[5] = false
                        set isItm[6] = false
                        set ttlItemsUnitHas = 0
                        loop
                            exitwhen L > 6
                            set itm[L] = UnitItemInSlot( u, (L - 1))
                            loop
                                exitwhen L2 > 6
                                if isItm[L2] == false then
                                    if itm[L] != null and GetItemTypeId( itm[L]) == i[L2] then
                                        if this.charges then
                                            if GetItemCharges( itm[L]) >= charges[L] then
                                                set isItm[L2] = true
                                                set ttlItemsUnitHas = ttlItemsUnitHas + 1
                                            endif
                                        else
                                            set isItm[L2] = true
                                            set ttlItemsUnitHas = ttlItemsUnitHas + 1
                                        endif
                                        exitwhen isItm[L2]
                                    endif
                                endif
                            set L2 = L2 + 1
                            endloop
                            set L2 = 1
                            set L = L + 1
                        endloop
                        if ttlItemsUnitHas == this.ttlItemsForRecipe then
                            loop
                                exitwhen r > 6
                                if isItm[r] then
                                    call RemoveItem( itm[r])
                                endif
                                set itm[r] = null
                                set r = r + 1
                            endloop
                            call UnitAddItemById( u, this.itmToBeMade)
                        endif
                    endif
                    set L1 = L1 + 1
                endloop
                call thistype.turnOnOtherSystems()
            endif
        endmethod
        
        static method forceRecipe takes unit u returns nothing
            local integer L = 0
            loop
                exitwhen L > 5
                call thistype.checkingRecipes( GetItemTypeId( UnitItemInSlot( u, L)), u, false)
                set L = L + 1
            endloop
            set u = null
        endmethod
        
        static method forceRecipeByItem takes unit u, integer itemTypeId returns nothing
            local integer L = 0
            loop
                exitwhen L > 5
                if GetItemTypeId( UnitItemInSlot( u, L)) == itemTypeId then
                    call thistype.checkingRecipes( itemTypeId, u, false)
                endif
                set L = L + 1
            endloop
            set u = null
        endmethod
        
        method RequireCharges takes integer itemId, integer charges returns nothing
            if this.i1 != 0 and this.i1 == itemId then
                set this.charges1 = charges
            elseif this.i2 != 0 and this.i2 == itemId then
                set this.charges2 = charges
            elseif this.i3 != 0 and this.i3 == itemId then
                set this.charges3 = charges
            elseif this.i4 != 0 and this.i4 == itemId then
                set this.charges4 = charges
            elseif this.i5 != 0 and this.i5 == itemId then
                set this.charges5 = charges
            elseif this.i6 != 0 and this.i6 == itemId then
                set this.charges6 = charges
            endif
            set this.charges = true
        endmethod
        
        static method disAssemble takes item itm, unit u returns nothing
            local thistype this = disAssembleTable[ GetItemTypeId( itm)]
            set combineItems = false
            call thistype.turnOffOtherSystems()
            call RemoveItem( itm)
            call UnitAddItemById( u, this.i1)
            call UnitAddItemById( u, this.i2)
            call UnitAddItemById( u, this.i3)
            call UnitAddItemById( u, this.i4)
            call UnitAddItemById( u, this.i5)
            call UnitAddItemById( u, this.i6)
            call thistype.turnOnOtherSystems()
            set combineItems = true
        endmethod
        
        static method disable takes nothing returns nothing
            set combineItems = false
        endmethod
        
        static method enable takes nothing returns nothing
            set combineItems = true
        endmethod
        
        static method create takes integer id1, integer id2, integer id3, integer id4, integer id5, integer id6, integer itmToBeMade, boolean createOnPickup returns thistype
            local thistype this = thistype.allocate()
            local integer array i
            local integer L = 0
            set this.i1 = id1
            set this.i2 = id2
            set this.i3 = id3
            set this.i4 = id4
            set this.i5 = id5
            set this.i6 = id6
            set this.itmToBeMade = itmToBeMade
            set this.pickup = createOnPickup
            set this.charges = false
            set i[0] = id1
            set i[1] = id2
            set i[2] = id3
            set i[3] = id4
            set i[4] = id5
            set i[5] = id6
            set this.ttlItemsForRecipe = 0
            set disAssembleTable[itmToBeMade] = this
            set index = index + 1
            set structArray[index] = this
            set this.ttlItemsForRecipe = 0
            loop
                exitwhen L > 5
                if i[L] != 0 then
                    set this.ttlItemsForRecipe = this.ttlItemsForRecipe + 1
                endif
                set L = L + 1
            endloop
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            local integer L = 1
            loop
                exitwhen L > index
                if structArray[ L] == this then
                    set structArray[ L] = structArray[index]
                    set index = index - 1
                endif
                set L = L + 1
            endloop
            call this.deallocate()
        endmethod
        
        private static method recipeCheck takes nothing returns boolean
            call thistype.checkingRecipes(GetItemTypeId(GetManipulatedItem()), GetTriggerUnit(), true)
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            set disAssembleTable = Table.create()
            call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_PICKUP_ITEM)
            call TriggerAddCondition( t, function thistype.recipeCheck)
            set t = null
        endmethod
    
    endstruct

endlibrary


version 1.1.1.0
mad changes purge suggested.​
version 1.1.0.0
Added the ability to make items require charges
Updated API​
version 1.0.9.1
added ability to make specific items in specific rects
note: u will need a condtion in the trigger u make and also a special item( an item not used in other recipes) for this to work​
version 1.0.9.0
got rid of rects and added a method to call for when a player wants to force a recipe to be created​
version 1.0.5.0
fixed a bug w owned rects​
version 1.0.4.5
you can now have regions w different owners​
version 1.0.4.2
fixed a bug w unit enters region event​
version 1.0.4.1
added ability for multiple regions​
version 1.0.4.0
got rid of unused Tables
now works completely although i will hopefully be changing it back to tables if i could find a viable way of storing itemTypeIds into tables​
version 1.0.3.0
works with unit enters region event.
Only downside is that to create a recipe it needs one more arguement​
version 1.0.2.0
fixed the bug with not working when 2 items of same type r being added in a recipe​
version 1.0.1.0
added a method to turn other systems on or off when needed
this is to be used when u have a system that fires w the event EVENT_PLAYER_UNIT_DROP_ITEM​
version 1.0.0.7
added a pause and resume for the system​
version 1.0.0.5
now can disAssemble items made through recipes​
version 1.0.0.1
corrected indentation again lol​
version 1.0.0.0
first version released​


Keywords:
item, recipe, system, item recipe, item recipe system, deathismyfriend, dimf, vJass, easy to use GUI
Contents

system spell damage damager (Map)

Reviews
11:30, 3ndth Sep 2015 This resource has been set to Need Fix by BPower. Reason: The system completely bugs when having an ingredient of a recipe multiple times in your inventory. This bug was reported multiple times in the thread and I could...

Moderator

M

Moderator

11:30, 3ndth Sep 2015

This resource has been set to Need Fix by BPower.

Reason:
The system completely bugs when having an ingredient of a recipe multiple times in your inventory.
This bug was reported multiple times in the thread and I could reproduce it within 1 minute, hence I
have the impression you didn't even care fixing it.

There is more I want to mention. ( link )

15:11, 19th Jul 2013
PurgeandFire: The required changes were made. Approved.
 
Review:
  • In the method "recipeCheck", you don't really need the locals. You can inline it all to one line:
    JASS:
    call thistype.checkingRecipes(GetItemTypeId(GetManipulatedItem()), GetTriggerUnit(), true)
  • You have "index" to keep track of the number of recipes. However, if someone destroys a recipe, then the index needs to be decremented. Otherwise it isn't properly giving how many recipes there are.
  • In a similar way, you have "structArray[index]". Since you don't change index and you don't adjust structArray when an instance is destroyed, it will loop through deallocated instances. If someone wants to destroy a recipe, this system will still loop through it as if it isn't destroyed. To fix this, you have to implement either a stack or a linked list.
  • The methods "pause" and "resume" are a bit oddly named. I'd go with enable and disable. Better yet:
    JASS:
    static method enable takes boolean flag returns nothing 
        set combineItems = flag
    endmethod
    That method is more modular.
  • In the method "disassemble", you can inline "id" since you only use it once.
  • In the method "disassemble", you don't need to set itm to null. Arguments/parameter variables don't need to be nulled.

Right now the system is OK. I'll approve it if you make the changes above. Coding-wise, it isn't the most optimized/efficient way. Right now you have to do the same thing 6 times over and over because you are using 6 variables. There is a better implementation where you make a separate struct for the items, and you can have the charges and whatnot as a member. You would sort it into a list, and then instead of repeating the same thing 6 times, you would iterate through the list. However, it is up to you whether you want to change it to fit that.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Back in my day you actually had to upload a gameplay picture to get a resource approved..
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
the pictured text is better for systems IMO. i dont like seeing an item in an inventory and having it mean anything. Same with my item drop system. do i put an item on the ground ? it looks like an item again.

The title bar is for the name of the system, not the picture.

Atleast just show a before with like a string and stick and an after with a bow. :\
 
Can you provide me with a test map so i can see exactly what is going on ? Thanks
I can't sorry, I found another system that do job (for now, code isn't really so good, so I will code one at the end when it become problem).

But if needed I will try to recreate same problem.
Just try to create recipe with line of code.
Then place those components and recipes on the ground (let's say you want to have 2 or more of those crafted items).
Check what is going on with items in inventory when you start collecting items.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Alloc should be listed as requirement. ( not commented out )

disAssemble is actually written disassemble.

A module initializer would be better to ensure the Table is allocated right in time.

RequireCharges should be requireCharges ( public API should follow our code convention, the JPAG )

Why do you null a unit handle, which is past over as a function argument?

local region reg!!! Why is this in method checkingRecipes?
Or local boolean b. Seriously check your code properly.

Rule out the problem mentioned in the thread comments by -Kobas- and msongyboi.
Then i can re-approve the system.
 
Top