System ItemCombiners

SerraAvenger

Cuz I can
Reaction score
234
This Contains the three systems
-Item Doubler
-Item Combiner
-Item Stacker

All the three systems share this:
-> If you use them, put a "Special Thanks to Cpt.DaveyJones / SerraAvenger" in your map
-> You can easily add Itemtypes that will be used by the respective system wiht one liners ( but in custom script )
-> The systems are very efficient, especially at searching the items in the list
-> They don't affect items not in the list
-> They all require JassPack NewGen
-> They all only require one trigger
-> None of them Requieres a lot of JASS - experience
-> You can add items to the lists during the game ( normally this isn't required but just in case you want to do something like that, like allowing certain doublings only after a certain point has reached )
-> The '' in the code are important. If you don't use them, It won't work at all.
-> There is no warranty that the code works. I have proved the used algorithms to work during a three hour test with random integers, so the only things that might not work are the effective code that replaces the items etc.
Although I tested it on a small range of items, I don't know if it will work in 100% of the cases.
For any bugs / Comments / Help, please pm me. Thanks.

Item Doubler*
-Description
Whenever a unit picks up one item of a certain list and has a second of it in it's inventory, both items will be removed and a certain item will be added.
-How to install
*Create a trigger called "WeaponDoubler"
*Convert the trigger to custom code ( if you don't know how you'll surely find an explanation in this forum )
*Overwrite the auto-generated text with the text "WeaponDoubler 1.6" from the attachments
-How to create a new "Recipe"

*Get any trigger that fires at the moment you want to create the new recipe. Preferably one that only fires once, otherwise it will only decrease the performance.
*Now add a custom script action to it. In the Apearing textbox you enter:
JASS:
call NewDoublingRecipe( '*²' , '*³' )

*² : The ItemId* of the item you want to be doubled
*³ : The ItemId* of the item you want as result
*Now after the trigger fired for the first time, the new recipe will be ready!

ItemCombiner
-Description
If a unit buys a unit of a certain list and has two specific items in it's inventory ( either of them can need a certain number of charges, too ), the two items and the sold unit will be removed and the buying unit will get a certain item.
-How to install
*Create a trigger called "Combiner"
*Convert the trigger to custom code ( if you don't know how you'll surely find an explanation in this forum )
*Overwrite the auto-generated text with the text "Item Combiner" from the attachments
-How To Create a New "Recipe"
*Creating Combining Recipes is a bit more Complex then Creating Doubling Recipes. First of all. you'll need to create a unit that will represent the recipe.
Give it the model none.mdl and the abilities "Invulnerability" and "Locust". Set it's gold cost and Point value to the gold cost of the recipe. Change it's description and name according to the recipe it represents and make the shop you want to sell the recipe selling that unit.
*Get the trigger that you want to create the recipe
*Afterwards, you need to decide wether or not one of your items needs a certain number of charges. If Yes:
*Add a custom script action to it. In the appearing field you enter:
JASS:
call NewCombineRecipeCharges( '' , '' , '' , , '' )

*Now between the first '' you enter the UnitId* of the recipe unit you just created.
*Between the second pair of ' you enter the ItemId* of the first item you need for the recipe. That is, the one of which you don't need a certain number of charges.
*Between the third pair of ', you enter the ItemId* of the second item, the one that needs a certain number of charges. Right after the comma, you put in the number of charges you need.
*In the last pair of ', you write the ItemId* of the item you want to create after the recipe has took place.
*Now Your code should look like this:
JASS:

call NewCombineRecipeCharges( 'h00E','I007' , 'I005' , 4  , 'I009' )


If Not:
*Add a custom script action to it. In the appearing field you enter:
Code:
call NewCombineRecipe( '' , '' , '' , '' )
*Now between the first '' you enter the UnitId* of the recipe unit you just created.
*Between the second pair of ' you enter the ItemId* of the first item you need for the recipe.
*Between the third pair of ', you enter the ItemId* of the second item you need for the recipe.
*In the last pair of ', you write the ItemId* of the item you want to create after the recipe has took place.


ItemStacker
Description
Whenever a unit picks up an item of a certain list and has another item of the same type as that item in it's inventory, the items will stack in one pile. The respective charges will be added up. The system goes as far as that you can specify the maximum number of charges per pile. If you don't want a limit, simply enter 999 as maximum ( or something hihger )
How to Install
*Create a trigger called "ItemStacker"
*Convert the trigger to custom code ( if you don't know how you'll surely find an explanation in this forum )
*Overwrite the auto-generated text with the text "Item Stacker" from the attachments
How to create a "Recipe"

*Go to the trigger that shall create the recipe and add a custom code action to it.
*In the appearing textbox, enter or copy the following text: ( warning, case sensitive!):
JASS:

call NewStackableItem( '' , )

*Now in the first field, enter the ItemId* of the Item you want to be stacked. In the second field, enter the maximum number of charges per stack. That's it!


*To get the ItemId of an item simply scroll to the item in the Object Editor, and then press "ctrl + d". At the previous place of the name, four or eight letters will appear. Use the first four. Same for Units.

I allready added a system similiar to this. The respective thread can now be removed.

In the attachments you can find a demo map with all three systems implemented.

HF GL! And for any problems with implementing you can simply ask in this thread.

Code:
ItemDoubler
JASS:

globals
    integer NumDoublings = -1
    integer array DoublingEduct
    integer array DoublingProduct
endglobals


function GetDoublingNum takes integer tosearch returns integer
    local integer low = 0
    local integer high = NumDoublings
    local integer mid
    loop
        exitwhen low > high
        set mid = ( low + high ) / 2
        if DoublingEduct[ mid ] > tosearch then
            set high = mid - 1
        elseif DoublingEduct[ mid ] < tosearch then
            set low = mid + 1
        else
            return mid
        endif
    endloop
    return -1
endfunction


function SortNewDoublingRecipe takes nothing returns nothing
    local integer loopIndicator
    
    local integer key
    local integer lock
    
    set key = DoublingEduct[NumDoublings]
    set lock = DoublingProduct[NumDoublings]
    set loopIndicator = NumDoublings
    loop
        
        exitwhen loopIndicator < 1 or DoublingEduct[loopIndicator-1] < key
        
        set DoublingEduct[loopIndicator] = DoublingEduct[loopIndicator-1]
        set DoublingProduct[loopIndicator] = DoublingProduct[loopIndicator-1]
        
        set loopIndicator = loopIndicator - 1
        
    endloop
    
    set DoublingEduct[loopIndicator] = key
    set DoublingProduct[loopIndicator] = lock
endfunction


function Doubler takes nothing returns nothing
    
    local integer slotIndicator = 0
    local integer lastField = NumDoublings
    local integer nextstep = 0
    local integer lim = NumDoublings
    
    local item trigItem = GetManipulatedItem()
    local integer itemID = GetItemTypeId( trigItem )
    local integer recipeID = GetDoublingNum( itemID )
    
    local item slotItem  = null
    local boolean preceed = true
    
    
    local string productName
    local item product
    
    local unit trigUnit = GetTriggerUnit()
    local player trigplayer = GetOwningPlayer( trigUnit )
    
    if recipeID != -1 then
        
        
        loop
            if slotIndicator > 5 then
                set preceed = false
                exitwhen true
            endif
            
            set slotItem = UnitItemInSlot( trigUnit , slotIndicator )
            exitwhen slotItem != trigItem and GetItemTypeId( slotItem ) == itemID
            
            set slotIndicator = slotIndicator + 1
        endloop
        
        
        if preceed then
            set product = CreateItem( DoublingProduct[ recipeID ] , GetUnitX( trigUnit ), GetUnitY( trigUnit ) )
            set productName = GetItemName( product )
            call RemoveItem( slotItem )
            call DisplayTextToPlayer( trigplayer , 0 , 0 , "You combined two |cff5555ff" + GetItemName( trigItem ) + "s|r to a |cff55ff55" + productName + "|r. Gratulations!" )
            call RemoveItem( trigItem )
            call UnitAddItem( trigUnit,  product )
        endif
    endif
    
    set trigUnit = null
    set trigItem = null
    set slotItem = null
    set product = null
    set productName = null
    set slotIndicator = 0
    set lastField = 0
endfunction


function NewDoublingRecipe takes integer EductId, integer ProductId returns nothing
    set NumDoublings = NumDoublings + 1
    set DoublingEduct[ NumDoublings ] = EductId
    set DoublingProduct[ NumDoublings ] = ProductId
    call SortNewDoublingRecipe()
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_WeaponDoubler takes nothing returns nothing
    local integer playerIndicator = 11
    set gg_trg_WeaponDoubler = CreateTrigger()
    
    loop
        exitwhen playerIndicator < 0
        
        call TriggerRegisterPlayerUnitEvent(gg_trg_WeaponDoubler, Player( playerIndicator ) , EVENT_PLAYER_UNIT_PICKUP_ITEM, null )
        set playerIndicator = playerIndicator - 1
    endloop
    
    
    
    call TriggerAddAction(gg_trg_WeaponDoubler, function Doubler )
    set playerIndicator = 0
    
    
endfunction
ItemCombiner
JASS:

library Combiner

globals
    integer array CombineEduct1
    integer array CombineEduct2
    integer array CombineEduct2Charges
    integer array CombineId
    integer array RecipeNumber
    integer array CombineProduct
    integer NumRecipes = -1
endglobals


function GetRecipeNum takes integer toSearch returns integer
    local integer low = 0
    local integer high = NumRecipes
    local integer mid
    loop
        exitwhen low > high
        set mid = ( low + high ) / 2
        if CombineId[ mid ] > toSearch then
            set high = mid - 1
        elseif CombineId[ mid ] < toSearch then
            set low = mid + 1
        else
            return RecipeNumber[ mid ]
        endif
    endloop
    return -1
endfunction

function Trig_Combiner_Actions takes nothing returns nothing
    local unit soldUnit = GetSoldUnit()
    
    local unit buyUnit  = GetBuyingUnit()
    local player buyPlayer = GetOwningPlayer( buyUnit )
    local integer buyPlayerID = GetPlayerId( buyPlayer )
    
    local integer soldUnitID  = GetUnitTypeId( soldUnit )
    local integer recipeId    = GetRecipeNum( soldUnitID )
    local integer recipePrice = GetUnitPointValueByType( soldUnitID )
    
    local real Dummy1
    local real Dummy2
    
    local item educt1
    local item educt2
    local integer educt2charges
    local item product
    
    local integer loopIndicator
    
    local item array inventoryItem
    local integer array inventoryItemID
    
    local boolean preceed = true
    if recipeId != -1 then
        
        call RemoveUnit( soldUnit )
        
        set loopIndicator = 0
        loop
            exitwhen loopIndicator > 5
            
            set inventoryItem[ loopIndicator ] = UnitItemInSlot( buyUnit , loopIndicator )
            set inventoryItemID[ loopIndicator ] = GetItemTypeId( inventoryItem[ loopIndicator ] )
            
            set loopIndicator = loopIndicator + 1
        endloop
        
        set loopIndicator  = 0
        loop
            if loopIndicator > 5 then
                set preceed = false
                exitwhen true
            elseif CombineEduct1[ recipeId ] == inventoryItemID[ loopIndicator ] then
                set educt1 = inventoryItem[ loopIndicator ]
                exitwhen true
            endif
            set loopIndicator = loopIndicator + 1
        endloop
        
        if preceed then
            set loopIndicator = 0
            if  CombineEduct2Charges[recipeId] != 0 then
                loop
                    set educt2charges = GetItemCharges( inventoryItem[ loopIndicator ] )
                    if loopIndicator > 5 then
                        set preceed = false
                        exitwhen true
                    elseif ( CombineEduct2[ recipeId ] == inventoryItemID[ loopIndicator ] ) and ( CombineEduct2Charges[ recipeId ] <= educt2charges ) then
                        set educt2 = inventoryItem[ loopIndicator ]
                        
                        exitwhen true
                    endif
                    set loopIndicator = loopIndicator + 1
                endloop
                
                if preceed then
                    call RemoveItem( educt1 )
                    if educt2charges == CombineEduct2Charges[ recipeId ] then
                        call RemoveItem( educt2 )
                    else
                        call SetItemCharges( educt2 , educt2charges - CombineEduct2Charges[ recipeId ] )
                    endif
                    
                    set product = CreateItem( CombineProduct[ recipeId ] , GetUnitX( buyUnit ), GetUnitY( buyUnit ) )
                    call DisplayTextToPlayer( buyPlayer , 0 , 0 , "|cff80ff80Combining completed sucessfully|r" )
                    call UnitAddItem( buyUnit, product )
                    
                else
                    call DisplayTextToPlayer( buyPlayer , 0 , 0 , "|cffFF3333You don't have enough charges on your item!|r" )
                    call SetPlayerState( buyPlayer , PLAYER_STATE_RESOURCE_GOLD , GetPlayerState( buyPlayer, PLAYER_STATE_RESOURCE_GOLD ) + recipePrice )
                endif
            else
                
                loop
                    if loopIndicator > 5 then
                        set preceed = false
                        exitwhen true
                    elseif CombineEduct2[ recipeId ] == inventoryItemID[ loopIndicator ] then
                        set educt2 = inventoryItem[ loopIndicator ]
                        exitwhen true
                    endif
                    set loopIndicator = loopIndicator + 1
                endloop
                
                if preceed then
                    call RemoveItem( educt1 )
                    call RemoveItem( educt2 )
                    set product = CreateItem( CombineProduct[ recipeId ] , GetUnitX( buyUnit ), GetUnitY( buyUnit ) )
                    call DisplayTextToPlayer( buyPlayer , 0 , 0 , "|cff80ff80Combining completed sucessfully|r" )
                    call UnitAddItem( buyUnit, product )
                else
                    call DisplayTextToPlayer( buyPlayer , 0 , 0 , "|cffFF3333Combination did not work...|r" )
                    call SetPlayerState( buyPlayer , PLAYER_STATE_RESOURCE_GOLD , GetPlayerState( buyPlayer, PLAYER_STATE_RESOURCE_GOLD ) + recipePrice )
                endif
            endif
        else
            call DisplayTextToPlayer( buyPlayer , 0 , 0 , "|cffFF3333Combination did not work...|r" )
            call SetPlayerState( buyPlayer , PLAYER_STATE_RESOURCE_GOLD , GetPlayerState( buyPlayer, PLAYER_STATE_RESOURCE_GOLD ) + recipePrice )
            
            
        endif
        
        
    endif
    
    
    
endfunction






function SortNewCombineRecipe takes nothing returns nothing
    local integer loopIndicator = NumRecipes
    local integer key  = CombineId[ NumRecipes ]
    local integer lock = NumRecipes
    
    loop
        exitwhen loopIndicator < 1 or CombineId[ loopIndicator - 1] < key
        
        set CombineId[ loopIndicator ] = CombineId[ loopIndicator - 1 ]
        set RecipeNumber[ loopIndicator ] = RecipeNumber[ loopIndicator - 1 ]
        
        set loopIndicator = loopIndicator - 1
    endloop
    
    
    set CombineId[ loopIndicator ] = key
    set RecipeNumber[ loopIndicator ] = lock
    
    set key = 0
    set loopIndicator = 0
    set lock = 0
endfunction



function NewCombineRecipe takes integer recipeid, integer educt1id, integer educt2id , integer productid returns nothing
    set NumRecipes = NumRecipes + 1
    set CombineEduct1[ NumRecipes ] = educt1id
    set CombineEduct2[ NumRecipes ] = educt2id
    set CombineEduct2Charges[ NumRecipes ] = 0
    set CombineProduct[ NumRecipes ] = productid
    set CombineId[ NumRecipes ] = recipeid
    
    call SortNewCombineRecipe( )
    
endfunction

function NewCombineRecipeCharges takes integer recipeid, integer educt1id, integer educt2id , integer educt2charges, integer productid returns nothing
    set NumRecipes = NumRecipes + 1
    set CombineEduct1[ NumRecipes ] = educt1id
    set CombineEduct2[ NumRecipes ] = educt2id
    set CombineEduct2Charges[ NumRecipes ] = educt2charges
    set CombineProduct[ NumRecipes ] = productid
    set CombineId[ NumRecipes ] = recipeid
    
    call SortNewCombineRecipe( )
    
endfunction

//==== Init Trigger NewTrigger ====
function InitTrig_Combiner takes nothing returns nothing
    local integer playerIndicator = 15
    
    set gg_trg_Combiner = CreateTrigger()
    loop
        exitwhen playerIndicator < 0
        call TriggerRegisterPlayerUnitEvent(gg_trg_Combiner, Player( playerIndicator ) , EVENT_PLAYER_UNIT_SELL , null )
        set playerIndicator = playerIndicator - 1
    endloop
    call TriggerAddAction(gg_trg_Combiner, function Trig_Combiner_Actions)
endfunction
endlibrary
ItemStacker
JASS:
globals
    integer NumStackable = - 1
    integer array StackableItemID
    integer array MaxStack
endglobals


function GetStackableId takes integer tosearch returns integer
    local integer low = 0
    local integer high = NumStackable
    local integer mid
    loop
        exitwhen low > high
        set mid = ( low + high ) / 2
        if StackableItemID[ mid ] > tosearch then
            set high = mid - 1
        elseif StackableItemID[ mid ] < tosearch then
            set low = mid + 1
        else
            return mid
        endif
    endloop
    return -1
endfunction

function SortNewStackable takes nothing returns nothing
    local integer key  = StackableItemID[ NumStackable ]
    local integer lock = MaxStack[ NumStackable ]
    local integer loopIndicator = NumStackable
    
    loop
        exitwhen loopIndicator < 1 or StackableItemID[ loopIndicator - 1 ] < key
        set StackableItemID[ loopIndicator ] = StackableItemID[ loopIndicator - 1 ]
        set MaxStack[ loopIndicator ] = MaxStack[ loopIndicator - 1 ]
        set loopIndicator = loopIndicator - 1
    endloop
    
    set StackableItemID[ loopIndicator ] = key
    set MaxStack[ loopIndicator ] = lock
    
endfunction

function NewStackableItem takes integer itemid, integer maxstack returns nothing
    set NumStackable = NumStackable + 1
    set StackableItemID[ NumStackable ] = itemid
    set MaxStack[ NumStackable ] = maxstack
    call SortNewStackable()
endfunction

function StackCharges takes nothing returns nothing
    local item trigItem = GetManipulatedItem()
    local integer trigItemID = GetItemTypeId( trigItem )
    local integer trigItemCharges = GetItemCharges( trigItem )
    local integer stackableID = GetStackableId( trigItemID )
    local unit trigUnit = GetTriggerUnit()
    
    local item slotItem
    local integer slotCharges
    local integer newCharges
    local integer loopIndicator = 0
    if stackableID != -1 then
        loop
            if loopIndicator > 5 then
                call SetItemCharges( trigItem, trigItemCharges )
                exitwhen true
            endif
                           
            set slotItem = UnitItemInSlot( trigUnit, loopIndicator )
            if GetItemTypeId( slotItem ) == trigItemID and trigItem != slotItem then
                set slotCharges = GetItemCharges( slotItem )
                set newCharges = slotCharges + trigItemCharges
                if newCharges <= MaxStack[ stackableID ] then
                    call SetItemCharges( slotItem , newCharges )
                    call RemoveItem( trigItem )
                    exitwhen true
                else
                    call SetItemCharges( slotItem, MaxStack[ stackableID ] )
                    set trigItemCharges = trigItemCharges - ( MaxStack[ stackableID ] - slotCharges )
                endif
            endif
            set loopIndicator = loopIndicator + 1
        endloop
    endif
    set trigItem = null
    set trigUnit = null
    set slotItem = null
endfunction


function InitTrig_ItemStacker takes nothing returns nothing
    local integer playerIndicator = 11
    set gg_trg_ItemStacker = CreateTrigger()
    
    loop
        exitwhen playerIndicator < 0
        
        call TriggerRegisterPlayerUnitEvent(gg_trg_ItemStacker, Player( playerIndicator ) , EVENT_PLAYER_UNIT_PICKUP_ITEM, null )
        set playerIndicator = playerIndicator - 1
    endloop
    
    
    
    call TriggerAddAction(gg_trg_ItemStacker, function StackCharges )
    set playerIndicator = 0
    
endfunction
 

Attachments

  • Item Stacker.txt
    3.6 KB · Views: 272
  • ItemDoubler v1.6.txt
    3.9 KB · Views: 249
  • ItemSystems.w3x
    32.3 KB · Views: 281
  • ItemCombiner.txt
    7.9 KB · Views: 302

SerraAvenger

Cuz I can
Reaction score
234
Please post the full code.. or the map atleast <.<

I posted the map. I'll post the code soon, just that it are more then 450 lines of code and I don't think anyone would like to read it in his browser anyway. ; )
 

SerraAvenger

Cuz I can
Reaction score
234
Bump

Fixed a bug in the ItemCombiner that ignored players 13 and higher when selling the recipe
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top