1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Travel to distant realms and encounter scenes unknown to the common folk. The Greatest of Adventures is upon us with the 8th Cinematic Contest. Join in on a fun ride.
    Dismiss Notice
  5. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  6. The Secrets of Warcraft 3 have revealed interesting works. The RESULTS for Abelhawk's Mini-Mapping Contest #15 have come out!
    Dismiss Notice
  7. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  8. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  9. Night Rider gained several songs for his journey. The poll for the 12th Music Contest has started. Check it out!
    Dismiss Notice
  10. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  11. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[GUI Friendly] Item Fusion Shop

Submitted by Tasyen
This bundle is marked as approved. It works and satisfies the submission rules.
Item Fusion Shop is a System to register item merging to get another, in most cases better, item. That item merging is often used in AoS (moba) maps.
The Item merging is not done automatically when an unit pickups all mats. No the user has to order the merging inside Item Fusion shop, which looks and feels like visiting a warcraft 3 shop. If an item has many upgrades the shop gets a page conrol allowing to change the currently shown 9 upgrade options.
Upgrade options display the requiered mats and the gold to instantly buy it.
(in 1.6 and below that was done by using stock amount of the item).
(Int 2.0.2 the gold cost are added as suffix to the headline of the upgrade option)​


V2.0.2a Requiers warcraft 3 1.29+ (cause of dynamic Abilities)
V1.6 can be used with warcraft 3 versions having hashtables.



  • Uses the default Warcraft 3 UI.
    Each Player has its own dynamic shop.
    Shows upgrades of items.
    Or even upgrades of upgrades, when wanted.​
    Fuses items only on user order.
    Shop supports considing a Bagpack.
    Bagpack accessability is frequently rechecked during shoping.​
    Uses Rects to define Shoping Zones, each ShopZone can exclude a playergroup from using it.
    Autogenerates Requiered Mat lists for registered Fusions.
    Given Item Stats are on default taken from the field description of the fusion result.

    • Make sure you set the Option "File - preferences - Create Unknown Variables".
    • Copy The Ability "IFS - Select Hero".
    • > "ItemFusionShop - Show Upgrades"
    • > "ItemFusionShop - Page Next"
    • > "ItemFusionShop - Page Previous"
    • > All of the "ItemFusionShop - Button" 1 to 9
    • Copy The "ItemFusionShop" Unit.
    • Copy the Folder "Item Fusion Shop"
    • Check out the Configer below Triggers, to complet missing links and fill the database.
    • To let units open the Item fusion shop checkout the Demo Map only folder.
      • If you get an error, you might need to make sure that the mapheader contains an valid function.

  • After item fusion was successfuly installed in your map, you have to save gold costs of items beeings used as mats. And you have to register all builtways you wana have.

    Gold Costs are saved as integer on:
    inside: udg_IFShop_Table
    MainKey: itemType
    SecKey: 0
    There is also a GUI Wrapper trigger doing the gold saving, checkout the demo map if you wana use it.
    Each Builtway is one upgrade option.

    Recommented generation is function IFShopAddFusion.

    Code (vJASS):

    function IFShopAddFusion takes integer fusion, integer mat0, integer mat1, integer mat2, integer mat3, integer mat4, integer mat5, integer mat6 returns boolean
     

    There is also a GUI wrapper Trigger in the demo map.

    Important: Do start saving your item data after you executed Item fusion shop once (which is on default done inside the demo maps Init General), the first execution of Item fusion shop will create shops, hashtable and Events.

    Now you also need to setup ways to open the shop. Then players can use it in the game.

    after item fusion shop was executed the first time it morphs its action from initializing to open shop. Based on the current Event from which you execute Item Fusion shop it will call function IFShopShow with different values.

    • Effect of Ability: Triggering Unit is used as shopper, upgrades are shown of the current spellTarget - item, if there is none all upgrades of all items in the units inventories are shown.
    • Gain item: The unit gaining the item is the shopper and upgrades of the gained items are shown.
    • Enter Region: The unit entering is the shopper and all registered upgrades are shown.
    Before executing Item fusion Shop to open the shop you can set IFShop_Shopper_Bagpack[0] to define the bagpack of the shopping.

    If you are using jass you could also use this function to open Item fusion shop for an unit/player.
    Code (vJASS):

    function IFShopShow takes integer playerIndex, unit shopper, unit bagpack, integer itemType returns nothing
    //       GUI playerIndex; 1 = red
    //       this will show the shop the owner of shopper
    //       itemType = 0, will add all Ugrades of all items in the inventories of shopper and bagpack
    //       itemType = -1 all Plans are added to the shop.
     



  • Code (vJASS):

    //Item Fusion Shop 2.0.2
    //By Tasyen
    //============

    //Item fusion shop is a Recipe System showing possible upgrades of an item inside the Warcraft basic user interface.
    //The system calculates the needed gold cost and regards items already obtained by the hero and its bagpack, if wanted.
    //This way the player gets control over the fusions he want to do and it feels like visiting a shop in basic Warcraft 3.

    //============
    //   API Fusion Creation
    //============
    //    function IFShopAddFusion takes integer fusion, integer mat0, integer mat1, integer mat2, integer mat3, integer mat4, integer mat5, integer mat6 returns boolean
    //       Creates a Fusion with Mat 0 to 6 returns.
    //       You need to set all mats, with a ItemTypeId or 0 for not needed.
    //       Auto generates a Requier String List

    //   function IFShopAddMat takes integer mat, integer plan returns nothing
    //       Adds a Material component to the plan
    //       expects ItemTypeId
    //       after beeing done with AddMats one can "call IFShopUpdateReqStrings(plan)" to generate a requier list.

    //   function IFShopAddMatEx takes integer mat returns nothing
    //       Wraper function for IFShopAddMat for the Last register Plan

    //   function IFShopCreate takes integer fusion returns boolean
    //       Creates a Fusion without material

    //   function IFShopSetItemStringList takes integer itemType, string text returns nothing
    //       Write only the content
    //       On default one does not need to call that one.
    //       Requier Lists are autogenerated and Gives List are using the Object Field Description of the fusion result.

    //============
    //   API Show Shop
    //============
    //   function IFShopIsInShopZone takes unit u returns boolean
    //       Checks if the unit is inside an BuyZone which his owner can use.
    //        This should be used before calling IFShopShow, but is not requiered.

    //   function IFShopShow takes integer playerIndex, unit shopper, unit bagpack, integer itemType returns nothing
    //       this will show the shop the owner of shopper
    //       itemType = 0, will add all Ugrades of all items in the inventories of shopper and bagpack
    //       itemType = -1 all Plans are added to the shop.
    //============
    // API   for getting fusions (not needed on default usage)
    //============
    //   function IFShopCalcCost takes integer playerIndex, unit shopper, unit bagpack returns nothing
    //       calcs the goldcosts regarding owned items from the two units.
    //       into udg_IFShop_Shop_Avaible_Fuse_Costs
    //       you should fill the list with IFShopGetPossibleFusions before using this.

    //   function IFShopResetPossibleFusion takes integer playerIndex returns nothing
    //       Resets the listvariables at playerIndex.

    //   function IFShopGetPossibleFusions takes integer itemType, integer playerIndex returns nothing
    //       Loads all upgrades of the itemType into udg_IFShop_Shop_Avaible_Fuse_plans, udg_IFShop_Shop_Avaible_Fusions
    //       MPI based access udg_IFShop_Shop_Avaible_Fuse_First,udg_IFShop_Shop_Avaible_Fuse_Last
    //       udg_IFShop_ShowMaxUpgrades enables to show itemtypes upgrade's upgrade...,

    //   function IFShopGetAllFusions takes integer playerIndex, integer start returns nothing
    //       Loads all Plans registered for that player, starting from Plan start.
    //============

    // The intervale in which the System rechecks Bagpack useability
    // Every x seconds useability of Bagpack is rechecked.
    // Lower numbers are more accurate but more costly.
    constant function IFShopTimerIntervale takes nothing returns real
       return 0.4
    endfunction

    //how many items can a shop contain?
    //keep max player amount * this smaller than 32k (JASS_MAX_ARRAY_SIZE)
    //this system uses GUI PlayerIds therefore the 0 IFShopPlayerShopSize block is not used.
    constant function IFShopPlayerShopSize takes nothing returns integer
       return 500
    endfunction

    //this are the number of Items each page contains
    //setting this to something higher than 9 is not working (2 pagecontrol +1 target control) (Wc3 V1.28.5)
    //Each PageEntry needs 1 Ability beeing its button.
    constant function IFShopPageSize takes nothing returns integer
       return 9
    endfunction

    //Strings used by this system, one could change them to change results a bit.
    function IFShopInitStrings takes nothing returns nothing
       set udg_IFShop_Strings[0] = "\n\n|cffffA000Requiers|r:" //Requiers Word
       set udg_IFShop_Strings[1] = "\n  "       //Prefix for each Mat in the Requiers List beeing autogenerated
      set udg_IFShop_Strings[2] = "|cffffA000Gives|r:\n"   //Start of the builtInfo part, builtInfo uses item description of the fusion result.
       set udg_IFShop_Strings[3] = "\n\n|cffffA000Replaces|r:" //If a fusion needs only one Mat, this is used instead of Requiers.
       set udg_IFShop_Strings[4] = " - " //Prefix GoldCost Number
       set udg_IFShop_Strings[5] = " "+GetLocalizedString("GOLD") //Sufix GoldCost Number
       set udg_IFShop_Strings[6] = "x " //2x Axe, written after the number

       set udg_IFShop_Strings[7] = "|cffffff00Singpleplayer Info|r: " //Duplicat - Warning Prefix
       set udg_IFShop_Strings[8] = " amount of builtways: " //Duplicat - Warning Sufix
      set udg_IFShop_Strings[9] = "|cffff0000Error|r:|nIFShopPlayerShopSize limit was exceeded." //Warning IFShopPlayerShopSize exceeded

    endfunction

    //============
    //System constants
    //============
    //hashtable saved:
    //============
    //   Normal items (itemCode 'I000'):
    //============
    //   +side   = beeing material in plan
    //   0          = Goldvalue
    //   -side    = built ways
    //   0 = Granted Powers List as Text
    //============
    //   Item Handle
    //============
    //   0 = true -> Is already used in current calculation

    //============
    //   plans
    //============
    //   0    = -1 easy identyfier
    //   0   = Requiered Item List as Text
    //   1    = result
    //   2    = Mat amount
    //   3+    = Mats
    //============

    //The OrderId of select ShopTarget.
    constant function IFShopSelectShopTarget takes nothing returns integer
       return 852566
    endfunction

    constant function IFShopAbiltiyIdSellItems takes nothing returns integer
       return 'Asid'
    endfunction

    constant function IFShopTableResult takes nothing returns integer
       return 1
    endfunction

    constant function IFShopTablePlan takes nothing returns integer
       return 0
    endfunction

    constant function IFShopTableMatAmount takes nothing returns integer
       return 2
    endfunction

    constant function IFShopTableMatStart takes nothing returns integer
       return 3
    endfunction

    //Is this buildway already registered?
    function IFShopIsBuiltWay takes integer itemType, integer plan returns boolean
       local integer index = 0
       local integer ancestor
       //find next free ancestor spot
       loop
           set index = index -1
           set ancestor = LoadInteger(udg_IFShop_Table,itemType,index)
           exitwhen ancestor == 0
           if ancestor == plan then
               return true
           endif
       endloop
       return false
    endfunction

    //Returns the already existing amount of builtways for an item
    function IFShopGetBuiltWayCount takes integer itemType returns integer
       local integer index = 0
       //find next free ancestor spot
       loop
           set index = index -1
           exitwhen not HaveSavedInteger(udg_IFShop_Table,itemType,index)
       endloop
       return - (index + 1)
    endfunction

    //Remember that this item can be built by this plan.
    //Builtways are saved at the -Side.
    function IFShopAddBuiltWay takes integer itemType, integer plan returns nothing
       local integer index = 0
       if plan == 0 then
           return
       endif
       //find next free ancestor spot
       loop
           set index = index -1
           exitwhen not HaveSavedInteger(udg_IFShop_Table,itemType,index)
       endloop
       call SaveInteger(udg_IFShop_Table, itemType, index, plan)
    endfunction

    //Remebers that this item is used in plan as material
    //Beeing Material is at the +Side.
    function IFShopMatIsUsedInPlan takes integer itemType, integer plan returns nothing
       local integer index = 0
       if plan == 0 then
           return
       endif
       //find next free ancestor spot
       loop
           set index = index +1
           //Already know this mat can be used in this plan?
           if LoadInteger(udg_IFShop_Table,itemType,index) == plan then
               return
           endif
           exitwhen not HaveSavedInteger(udg_IFShop_Table,itemType,index)
       endloop
       call SaveInteger(udg_IFShop_Table, itemType, index, plan)
    endfunction

    //Updates the Requier string List also merges same mats as one strong with 2x Blade
    //On Default everytime you use IFShopAddFusion
    function IFShopUpdateReqStrings takes integer plan returns nothing
       local integer Loop_A = 0
       local integer matCount = LoadInteger(udg_IFShop_Table, plan, IFShopTableMatAmount())
       local integer array matTypes       //the types found
       local integer array matTypesAmount //Amount of items of type[index] found
       local integer matTypesCount = 0       //size of matTypes & matTypesAmount
       local string text = ""
       local integer itemType
       local boolean isNew
       loop
           exitwhen matCount == -1
           set itemType = LoadInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+matCount)
           set Loop_A = matTypesCount
           set isNew = true
           loop
               exitwhen Loop_A == 0
               if matTypes[Loop_A] == itemType then
                   set isNew = false
                   set matTypesAmount[Loop_A] = matTypesAmount[Loop_A] + 1
                   exitwhen true
               endif

               set Loop_A = Loop_A -1
           endloop
           if isNew then
               set matTypesCount = matTypesCount + 1
               set matTypesAmount[matTypesCount] = 1
               set matTypes[matTypesCount] = itemType
           endif
           set matCount = matCount - 1
       endloop

       loop
           exitwhen matTypesCount == 0
           if matTypesAmount[matTypesCount] > 1 then
             set text = text + udg_IFShop_Strings[1]+ I2S(matTypesAmount[matTypesCount]) + udg_IFShop_Strings[6] +GetObjectName(matTypes[matTypesCount])
           else
               set text = text + udg_IFShop_Strings[1]+GetObjectName(matTypes[matTypesCount])
           endif
           set matTypesCount = matTypesCount - 1
       endloop
       call SaveStr(udg_IFShop_Table, plan, 0, text)
    endfunction

    function IFShopSetItemStringList takes integer itemType, string text returns nothing
       call SaveStr(udg_IFShop_Table, itemType, 0, text)
    endfunction


    //The most important API action
    //It creates an new way to built an Fusion.
    //taking up to 7 mats as argument ( this is not the max limit)
    //function IFShopAddFusion takes integer fusion, integer plan, integer mat0, integer mat1, integer mat2, integer mat3, integer mat4, integer mat5, integer mat6 returns boolean
    function IFShopAddFusion takes integer fusion, integer mat0, integer mat1, integer mat2, integer mat3, integer mat4, integer mat5, integer mat6 returns boolean
       local integer amount = -1
       local integer plan
       local item i
       set udg_IFShop_Item_List_Fusions_Last = udg_IFShop_Item_List_Fusions_Last + 1
       set plan = udg_IFShop_Item_List_Fusions_Last

       if not HaveSavedString (udg_IFShop_Table, fusion, 0) then
           set i = CreateItem(fusion,0,0)
           call SaveStr(udg_IFShop_Table, fusion, 0, BlzGetItemDescription(i))
           call RemoveItem(i)
           set i = null
       endif

       //PrintOut multiple Builtways in Single player, might be an possible error.
       if bj_isSinglePlayer then
           if IFShopGetBuiltWayCount(fusion) != 0 then
             call DisplayTimedTextToPlayer( GetLocalPlayer(),0,0, 30, udg_IFShop_Strings[7]+GetObjectName(fusion) + udg_IFShop_Strings[8] +I2S(IFShopGetBuiltWayCount(fusion)+1) )
           endif
       endif
       call IFShopAddBuiltWay(fusion, plan)

       //Save Fusion and plan
       call SaveInteger( udg_IFShop_Table, plan, IFShopTableResult(), fusion)
       call SaveInteger( udg_IFShop_Table, plan, IFShopTablePlan(), -1 )


       //Check for Mats and save them at nearest slot
       if( mat0 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat0)
           call IFShopMatIsUsedInPlan(mat0, plan)
       endif
       if( mat1 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat1)
           call IFShopMatIsUsedInPlan(mat1, plan)
       endif
       if( mat2 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat2)
           call IFShopMatIsUsedInPlan(mat2, plan)
       endif
       if( mat3 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat3)
           call IFShopMatIsUsedInPlan(mat3, plan)
       endif
       if( mat4 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat4)
           call IFShopMatIsUsedInPlan(mat4, plan)
       endif
       if( mat5 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat5)
           call IFShopMatIsUsedInPlan(mat5, plan)
       endif
       if( mat6 != 0) then
           set amount = amount + 1
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat6)
           call IFShopMatIsUsedInPlan(mat6, plan)
       endif

       call SaveInteger( udg_IFShop_Table, plan, IFShopTableMatAmount(), amount)

       call IFShopUpdateReqStrings(plan)
       return true
    endfunction

    //Adds material to plan.
    function IFShopAddMat takes integer mat, integer plan returns nothing
       local integer amount
       //Ignore calls with no ItemType
       if(   mat != 0 and plan != 0) then
           set amount = LoadInteger(udg_IFShop_Table, plan, IFShopTableMatAmount())+1
           call SaveInteger( udg_IFShop_Table, plan, IFShopTableMatAmount(), amount)
           call SaveInteger(udg_IFShop_Table, plan, IFShopTableMatStart()+amount,  mat)
           call IFShopMatIsUsedInPlan(mat, plan)
       endif
    endfunction

    //Add an material to the last created plan
    function IFShopAddMatEx takes integer mat returns nothing
       call IFShopAddMat(mat, udg_IFShop_Item_List_Fusions_Last)
    endfunction

    //Creates an fusion without mats.
    function IFShopCreate takes integer fusion returns boolean

       //PrintOut multiple Builtways in Single player, might be an possible error.
       if bj_isSinglePlayer then
           if IFShopGetBuiltWayCount(fusion) != 0 then
             call DisplayTimedTextToPlayer( GetLocalPlayer(),0,0, 30, udg_IFShop_Strings[7]+GetObjectName(fusion) + udg_IFShop_Strings[8] +I2S(IFShopGetBuiltWayCount(fusion)+1) )
           endif
       endif
       //Inc Pool Size
       set udg_IFShop_Item_List_Fusions_Last = udg_IFShop_Item_List_Fusions_Last + 1
       call IFShopAddBuiltWay(fusion, udg_IFShop_Item_List_Fusions_Last)
       //Save ItemTypes and mat amount
       call SaveInteger( udg_IFShop_Table, udg_IFShop_Item_List_Fusions_Last, IFShopTableResult(), fusion)
       call SaveInteger( udg_IFShop_Table, udg_IFShop_Item_List_Fusions_Last, IFShopTableMatAmount(), -1)
       call SaveStr( udg_IFShop_Table, udg_IFShop_Item_List_Fusions_Last, 0, "")
       return true
    endfunction

    //Updates the shop for this Player.
    //Uses GUI Indexing Red = 1 blue = 2
    function IFShopUpdate takes integer playerIndex returns nothing
       local integer Loop_A
       local integer Loop_A_End
       local integer itemType
       local integer counter = 0
       local player p = Player(playerIndex - 1)
       local string text
       //Clear Shop
       set Loop_A = IFShopPageSize()
       loop
           exitwhen Loop_A <= 0
           //call SetPlayerAbilityAvailable(p, udg_IFShop_Page_Skill_Button[Loop_A], false)
           call UnitRemoveAbility(udg_IFShop_Shop[playerIndex],udg_IFShop_Page_Skill_Button[Loop_A])
           set Loop_A = Loop_A - 1
       endloop


       call UnitRemoveAbility( udg_IFShop_Shop[playerIndex] , IFShopAbiltiyIdSellItems()  )
       call UnitAddAbility(  udg_IFShop_Shop[playerIndex] , IFShopAbiltiyIdSellItems() )

       //Is Multipaging needed?
       if( udg_IFShop_Page_Max[playerIndex] > 0) then
           //Get Current-Page ItemTypes
         set   Loop_A = ( udg_IFShop_Shop_Avaible_Fuse_First[playerIndex] + ( IFShopPageSize() * udg_IFShop_Page_Current[playerIndex] ) )
           set Loop_A_End = Loop_A + (IFShopPageSize()-1)
           if  Loop_A_End > udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] then
               set Loop_A_End = udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]
           endif
           //Add Page Controll
           call UnitAddAbility(  udg_IFShop_Shop[playerIndex] ,udg_IFShop_Page_Skill_Next )
           call UnitAddAbility(  udg_IFShop_Shop[playerIndex] ,udg_IFShop_Page_Skill_Previous )
       else
           //Remove Page Controll
           call UnitRemoveAbility( udg_IFShop_Shop[playerIndex], udg_IFShop_Page_Skill_Next )
            call UnitRemoveAbility( udg_IFShop_Shop[playerIndex], udg_IFShop_Page_Skill_Previous )
           //Get ItemTypes
           set Loop_A = udg_IFShop_Shop_Avaible_Fuse_First[playerIndex]
           set Loop_A_End = udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]
       endif
       set counter = 1
       loop
           exitwhen Loop_A > Loop_A_End
           set itemType = udg_IFShop_Shop_Avaible_Fusions[Loop_A]

           if GetLocalPlayer() == p then
               if LoadInteger(udg_IFShop_Table, udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A], IFShopTableMatAmount()) == 0 then
                   if HaveSavedString(udg_IFShop_Table, itemType, 0) then //Has Gained Effect String List?
                     set text = udg_IFShop_Strings[2]+ LoadStr(udg_IFShop_Table, itemType, 0) + udg_IFShop_Strings[3] + LoadStr(udg_IFShop_Table, udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A], 0)
                   else
                     set text = BlzGetAbilityExtendedTooltip(itemType,1) + udg_IFShop_Strings[3] + LoadStr(udg_IFShop_Table, udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A], 0)
                   endif
               else
                   if HaveSavedString(udg_IFShop_Table, itemType, 0) then
                     set text = udg_IFShop_Strings[2]+ LoadStr(udg_IFShop_Table, itemType, 0) + udg_IFShop_Strings[0] + LoadStr(udg_IFShop_Table, udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A], 0)
                   else
                     set text = BlzGetAbilityExtendedTooltip(itemType,1) + udg_IFShop_Strings[0] + LoadStr(udg_IFShop_Table, udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A], 0)
                   endif
               endif
           
               call BlzSetAbilityExtendedTooltip(udg_IFShop_Page_Skill_Button[counter], text,1)
               if udg_IFShop_Shop_Avaible_Fuse_Costs[Loop_A] > 0 then
                 call BlzSetAbilityTooltip(udg_IFShop_Page_Skill_Button[counter],    BlzGetAbilityTooltip(itemType,1) + udg_IFShop_Strings[4]+I2S(udg_IFShop_Shop_Avaible_Fuse_Costs[Loop_A]) + udg_IFShop_Strings[5],1)
               else
                   call BlzSetAbilityTooltip(udg_IFShop_Page_Skill_Button[counter],    BlzGetAbilityTooltip(itemType,1) ,1)
               endif
               call BlzSetAbilityIcon(udg_IFShop_Page_Skill_Button[counter], BlzGetAbilityIcon(itemType))

           endif
           //call SetPlayerAbilityAvailable(p, udg_IFShop_Page_Skill_Button[counter], true)
           call UnitAddAbility(udg_IFShop_Shop[playerIndex],udg_IFShop_Page_Skill_Button[counter])
           set counter = counter + 1
           set Loop_A = Loop_A + 1
       endloop

       set p = null
    endfunction

    //When one deselects the shop hide it.
    function IFShopHide takes nothing returns nothing
       local integer playerIndex = GetPlayerId( GetOwningPlayer(GetTriggerUnit()) ) + 1
       //Clear and Hide Shop
       call UnitRemoveAbility( udg_IFShop_Shop[playerIndex] , IFShopAbiltiyIdSellItems()  )
       call ShowUnit(GetTriggerUnit(),false)
       set udg_IFShop_Is_Shopping[playerIndex] = false
       set udg_IFShop_Shopper_Count = udg_IFShop_Shopper_Count - 1
       //If none is shopping disable Backpack loop checking.
       if(udg_IFShop_Shopper_Count == 0) then
           call PauseTimer( udg_IFShop_Bagpack_Timer )
       endif
    endfunction

    function IFShopPageControl takes integer spell, integer playerIndex returns nothing
       if( spell == udg_IFShop_Page_Skill_Next ) then
           set udg_IFShop_Page_Current[playerIndex] = ( udg_IFShop_Page_Current[playerIndex] + 1 )
           //Return to Page 0?
           if ( udg_IFShop_Page_Current[playerIndex] > udg_IFShop_Page_Max[playerIndex]) then
               set udg_IFShop_Page_Current[playerIndex] = 0
           endif
       else
           //Previous Page.
           set udg_IFShop_Page_Current[playerIndex] = ( udg_IFShop_Page_Current[playerIndex] - 1 )
           //Return to max Max?
           if ( udg_IFShop_Page_Current[playerIndex] < 0) then
               set udg_IFShop_Page_Current[playerIndex] = udg_IFShop_Page_Max[playerIndex]
           endif
       endif
       call IFShopUpdate(playerIndex)
    endfunction

    //Checks if the unit is inside an BuyZone whiche his owner can use.
    // This should be used before calling IFShopShow
    function IFShopIsInShopZone takes unit u returns boolean
       local real x = GetUnitX(u)
       local real y = GetUnitY(u)
       local integer Loop_A=0
       //loop All Registere Buyzones.
       loop
            exitwhen Loop_A > udg_IFShop_Buy_Zones_Last
           //Is Shopper inside BuyZone and is his owner allowed to use it? yes = true
          if ( RectContainsCoords(udg_IFShop_Buy_Zones[Loop_A], x,y) and not (IsPlayerInForce ( GetOwningPlayer (u), udg_IFShop_Buy_Zones_Excluded[Loop_A] )) ) then
               return true
           endif
            set Loop_A = Loop_A + 1
       endloop
       return false
    endfunction

    function IFShopIsBagpackUseable takes unit shopper, unit bagpack returns boolean
       //Developer don't want Bagpack?
       if not(udg_IFShop_Bagpack_Enabled[GetPlayerId(GetOwningPlayer(shopper))+1])then
           return false
       endif
       //null Pointer?
       if GetUnitTypeId (bagpack) == 0 then
           return false
       endif
       //Bagpack is dead?
       if IsUnitType(bagpack, UNIT_TYPE_DEAD) then
           return false
       endif
       //In Range Check?
       if not IsUnitInRange(shopper, bagpack, udg_IFShop_Bagpack_Hero_Max_Distan) then
           return false
       endif
       return true
    endfunction

    //Helper Function
    //Saves old Custom Value and loads into the stack
    function IFShopCheckAndMarkItem takes item mat, integer itemType returns boolean
       //Filters other Item Types, Marked Items and Not existing items
       if(itemType != GetItemTypeId(mat) or HaveSavedBoolean(udg_IFShop_Table, GetHandleId(mat),0) or mat == null ) then
           return false
       endif

       //Inser into Item stack and  Mark it.
       set udg_IFShop_Item_Stack_Last = ( udg_IFShop_Item_Stack_Last + 1 )
       set udg_IFShop_Item_Stack[udg_IFShop_Item_Stack_Last] = mat
       call SaveBoolean(udg_IFShop_Table, GetHandleId(mat),0, true)
       return true
    endfunction

    //Resets the found itemTypes stack for this player.
    //Playerindexes are in this system overall GUI-Like
    //But if you do not use the shops you don't have care about that.
    function IFShopResetPossibleFusion takes integer playerIndex returns nothing
       set udg_IFShop_Shop_Avaible_Fuse_First[playerIndex] = ( IFShopPlayerShopSize() * playerIndex )
       set udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] = ( udg_IFShop_Shop_Avaible_Fuse_First[playerIndex] - 1 )
       set udg_IFShop_Page_Max[playerIndex] = 0
       set udg_IFShop_Page_Current[playerIndex] = 0
    endfunction

    function IFShopGetPossibleFusions takes integer itemType, integer playerIndex returns nothing
       local integer Loop_B = 1
       local integer Loop_A = 0
       local integer plan
       local integer pageMembersReamining = IFShopPageSize()
      local integer counter = ( udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] - udg_IFShop_Shop_Avaible_Fuse_First[playerIndex]) +1
       local boolean skip

       //Loop the Material of current Fusion
       loop
           //Exceeds Players Array Size? yes -> stop. Should normally not happen.
           if ( counter >= IFShopPlayerShopSize() ) then
               //show Stacksize to small only in singleplayer.
               if bj_isSinglePlayer then
                   call DisplayTimedTextToPlayer( GetLocalPlayer(),0,0, 30, udg_IFShop_Strings[9] )
               endif
               return
           endif
           set plan = LoadInteger(udg_IFShop_Table, itemType, Loop_B)
           set skip = false
           exitwhen plan == 0
           //filter out duplicates.
           set Loop_A = udg_IFShop_Shop_Avaible_Fuse_First[playerIndex]
           loop
               exitwhen Loop_A > udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] or skip
               if plan == udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A] then
                   set skip = true
               endif
               set Loop_A = Loop_A +1
           endloop
           // if no duplicate load it in.
           if not skip then
               set udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] = ( udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] + 1 )
             set udg_IFShop_Shop_Avaible_Fusions[udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]] = LoadInteger(udg_IFShop_Table, plan, IFShopTableResult())
           
               set udg_IFShop_Shop_Avaible_Fuse_plans[udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]] = plan
               set counter = counter + 1
               set pageMembersReamining = pageMembersReamining - 1
               //Is a new Page needed?
               if pageMembersReamining == -1 then
                   set udg_IFShop_Page_Max[playerIndex] = udg_IFShop_Page_Max[playerIndex] + 1
                   set pageMembersReamining = IFShopPageSize() - 1
               endif
               //Find Upgrade's Upgrades?
               if udg_IFShop_ShowMaxUpgrades[playerIndex] then
                 call IFShopGetPossibleFusions(udg_IFShop_Shop_Avaible_Fusions[udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]],playerIndex)
               endif
           endif
           set Loop_B = Loop_B + 1
       endloop
    endfunction

    function IFShopGetAllFusions takes integer playerIndex, integer start returns nothing
       local integer plan = start
       local integer result
      local integer counter = ( udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] - udg_IFShop_Shop_Avaible_Fuse_First[playerIndex]) +1
       local integer pageMembersReamining = IFShopPageSize()
       //Loop the Material of current Fusion
       loop
           //Exceeds Players Array Size? yes -> stop. Should normally not happen.
           if ( counter >= IFShopPlayerShopSize() ) then
               //show Stacksize to small only in singleplayer.
               if bj_isSinglePlayer then
                   call DisplayTimedTextToPlayer( GetLocalPlayer(),0,0, 30, udg_IFShop_Strings[9] )
               endif
               return
           endif
           set result = LoadInteger(udg_IFShop_Table, plan, IFShopTableResult())
           exitwhen result == 0
           set udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] = ( udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] + 1 )
           set udg_IFShop_Shop_Avaible_Fusions[udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]] = result
       
           set udg_IFShop_Shop_Avaible_Fuse_plans[udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]] = plan
           set counter = counter + 1
           set pageMembersReamining = pageMembersReamining - 1
           //Is a new Page needed?
           if pageMembersReamining == -1 then
               set udg_IFShop_Page_Max[playerIndex] = udg_IFShop_Page_Max[playerIndex] + 1
               set pageMembersReamining = IFShopPageSize() - 1
           endif
           set plan = plan + 1
       endloop

    endfunction

    function IFShopCheckInventory takes unit u, integer itemType returns boolean
       local integer Loop_B = 0
       //Checks Full Inventory
       loop
           exitwhen Loop_B == bj_MAX_INVENTORY
           if IFShopCheckAndMarkItem(UnitItemInSlot(u, Loop_B), itemType) then
               return true
           else
               set Loop_B = Loop_B + 1
           endif
       endloop
       return false
    endfunction

    function IFShopInventorySlotBased takes unit first, unit second, integer itemType returns boolean
       local integer Loop_B = 0
       //Checks Shopper Bagpacks Items in turns.
       loop
           exitwhen Loop_B == bj_MAX_INVENTORY
           if IFShopCheckAndMarkItem(UnitItemInSlot(first, Loop_B), itemType) then
               return true
           endif
           if IFShopCheckAndMarkItem(UnitItemInSlot(second, Loop_B), itemType) then
               return true
           endif
           set Loop_B = Loop_B + 1
       endloop
       return false
    endfunction

    //Unmarks Items starting from start and setting size to the approached amount
    function IFShopUnmarkMats takes integer start returns nothing
       local integer Loop_A = start
       loop
           exitwhen Loop_A > udg_IFShop_Item_Stack_Last
           call RemoveSavedBoolean(udg_IFShop_Table, GetHandleId(udg_IFShop_Item_Stack[Loop_A]),0)
           set Loop_A = Loop_A +1
       endloop
       set udg_IFShop_Item_Stack_Last = start - 1
    endfunction

    function IFShopGetSubFusions takes integer playerIndex, unit shopper, unit bagpack, integer plan returns integer
       local integer Loop_A = IFShopTableMatStart()
       local integer Loop_B = -1
       local integer subChoosen = Loop_B
       local integer subCurrent
       local integer subChoosenGold
       local integer subCurrentGold
       local integer costs = 0
       local integer unmarkStart
       local integer itemType
       local boolean matAvailable
       local integer subChoosenTry
       loop
           set itemType = LoadInteger(udg_IFShop_Table, plan, Loop_A )
           exitwhen itemType == null
           set matAvailable = false
           //Followng Defines the Order of accessing the inventories.
           //Is No Bagpack used or not allowed? yes -> simply check the Shopper.
           if not(   udg_IFShop_Shop_Bagpack_Accessable[playerIndex] ) then
               set matAvailable = IFShopCheckInventory(shopper,itemType)
           else
               //Check Inventories in Turns?
               if udg_IFShop_Bagpack_Pick_SlotBased then
                   //In Turns; Start with who?
                   if udg_IFShop_Bagpack_Shopper_First then
                       set matAvailable = IFShopInventorySlotBased(shopper,bagpack,itemType)
                   else
                       set matAvailable = IFShopInventorySlotBased(bagpack,shopper,itemType)
                   endif
               else
                   //Slotbased
                   //Start with Shopper?
                   if udg_IFShop_Bagpack_Shopper_First then
                       set matAvailable = IFShopCheckInventory(shopper,itemType)
                       //Still missing?
                       if not (matAvailable) then
                           set matAvailable = IFShopCheckInventory(bagpack,itemType)
                       endif
                   else
                       set matAvailable = IFShopCheckInventory(bagpack,itemType)
                       if not (matAvailable) then
                           set matAvailable = IFShopCheckInventory(shopper,itemType)
                       endif
                   endif
               endif
           endif
       
           //Mat unavaible?
           if not (matAvailable) then
               //Is Mat a Fusion? yes -> search for sub Material; Recursiv
               //Fusionitems have numbers saved in the -side aka built ways
               if(LoadInteger(   udg_IFShop_Table, itemType, -1) != 0) then
                   //Remember Index from where to unmark.
                 //Without this sets the loop below won't work in recursion, why ever i had them before at the local init but it didn't work.
                   set unmarkStart = udg_IFShop_Item_Stack_Last+1
                   set subChoosenGold = 99999
                   set Loop_B = -1
                   //Loop all Builtways of this item and choose the cheapest.
                   loop
                       set subCurrent = LoadInteger(udg_IFShop_Table,itemType,Loop_B)
                       exitwhen  subCurrent == 0
                       call IFShopUnmarkMats(unmarkStart)
                       set subCurrentGold = IFShopGetSubFusions(playerIndex, shopper, bagpack, subCurrent )
                       //Calced one Cheaper then cheapest?
                       if subCurrentGold < subChoosenGold then
                           set subChoosenTry = Loop_B
                           set subChoosen = subCurrent
                           set subChoosenGold = subCurrentGold
                       endif
                   
                       set Loop_B = Loop_B - 1
                   endloop
                   //mark + Load choosen items again
                   //if was not found on last try
                   if subChoosenTry != Loop_B + 1 then
                       call IFShopUnmarkMats(unmarkStart)
                       call IFShopGetSubFusions(playerIndex, shopper, bagpack, subChoosen )
                   endif
                   set costs = costs + subChoosenGold
               else
                   //No Fusion; Increment Gold if wanted.
                   set costs = costs + LoadInteger(udg_IFShop_Table, itemType, 0)
               endif
           endif
           set Loop_A = Loop_A + 1
       endloop

       return costs
    endfunction

    //This is called to calculate Gold Costs of all avaibleFusions for this player.
    function IFShopCalcCost takes integer playerIndex, unit shopper, unit bagpack returns nothing
       local integer Loop_A = udg_IFShop_Shop_Avaible_Fuse_First[playerIndex]
       call IFShopUnmarkMats(0)
       //loop all Upgrade Options
       loop
           exitwhen Loop_A > udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex]
         set udg_IFShop_Shop_Avaible_Fuse_Costs[Loop_A] = IFShopGetSubFusions(playerIndex,shopper,bagpack,udg_IFShop_Shop_Avaible_Fuse_plans[Loop_A])
           call IFShopUnmarkMats(0)
           set Loop_A = Loop_A + 1
       endloop
    endfunction

    function IFShopTimerAction   takes nothing returns nothing
       local integer playerIndex = 1
       local boolean isAvaible=false
       //loop all Players
       loop
           exitwhen playerIndex >  bj_MAX_PLAYERS
           if udg_IFShop_Is_Shopping[playerIndex] and udg_IFShop_Bagpack_Enabled[playerIndex] then
             set isAvaible = IFShopIsBagpackUseable (udg_IFShop_Shop_Shopper[playerIndex],udg_IFShop_Shop_Shopper_Bagpack[playerIndex])
               //Bagpack accessability Changed?
               if udg_IFShop_Shop_Bagpack_Accessable[playerIndex] != isAvaible then
                   //Access Changed Recalc Gold Costs.
                   set udg_IFShop_Shop_Bagpack_Accessable[playerIndex] = isAvaible
                  call IFShopCalcCost(playerIndex,udg_IFShop_Shop_Shopper[playerIndex],udg_IFShop_Shop_Shopper_Bagpack[playerIndex])
                   call IFShopUpdate(playerIndex)
               endif
           endif
       set playerIndex = playerIndex + 1
       endloop  
    endfunction

    function IFShopShow takes integer playerIndex, unit shopper, unit bagpack, integer itemType returns nothing
       local integer Loop_A = 0
       set udg_IFShop_Shop_Bagpack_Accessable[playerIndex] = IFShopIsBagpackUseable(shopper,bagpack)
       //IFShopGetPossibleFusions only if not the same as last try or it is 0 aka whole inventory?
       if udg_IFShop_Shop_LastTry[playerIndex] != itemType or itemType == 0 or itemType == -1 then
           set udg_IFShop_Shop_LastTry[playerIndex] = itemType
           call IFShopResetPossibleFusion(playerIndex)
           //specific item
           if itemType > 0 then
               call IFShopGetPossibleFusions(itemType,playerIndex)
           elseif itemType == 0 then //all upgrades of carried Items
               //Non specific item show all avaible Upgrades of all items in shopper's and bagpack's inventory
               //Load Inventory
               set Loop_A = 0
               //Hero
               loop
                   exitwhen Loop_A == bj_MAX_INVENTORY
                   set itemType =  GetItemTypeId(UnitItemInSlot(shopper, Loop_A))
                   if itemType != 0 then
                       call IFShopGetPossibleFusions(itemType,playerIndex)
                   endif
                   set Loop_A = Loop_A + 1
               endloop
               //bagpack exists?
               if    GetUnitTypeId(bagpack) != 0 and udg_IFShop_Bagpack_Enabled[playerIndex] then
                   //Bagpack
                   set Loop_A = 0
                   loop
                       exitwhen Loop_A == bj_MAX_INVENTORY
                       set itemType = GetItemTypeId( UnitItemInSlot(bagpack, Loop_A))
                       if itemType != 0 then
                           call IFShopGetPossibleFusions(itemType,playerIndex)
                       endif
                       set Loop_A = Loop_A + 1
                   endloop
               endif
           elseif itemType == -1 then //all plans registered
               call IFShopGetAllFusions(playerIndex, 1)
           endif
       endif

       //Does an Upgrade Exist?
       if( udg_IFShop_Shop_Avaible_Fuse_Last[playerIndex] >= udg_IFShop_Shop_Avaible_Fuse_First[playerIndex] ) then
           set udg_IFShop_Shopper_Count = udg_IFShop_Shopper_Count + 1
           //First Player Shopping? start Periodic check.
           if( udg_IFShop_Shopper_Count ==1 and udg_IFShop_Bagpack_Enabled[playerIndex]) then
               call TimerStart ( udg_IFShop_Bagpack_Timer, IFShopTimerIntervale(), true, function IFShopTimerAction)
           endif
           //Save Current Shopping Situation
           set udg_IFShop_Is_Shopping[playerIndex] = true
            set udg_IFShop_Shop_Shopper[playerIndex] = shopper
            set udg_IFShop_Shop_Shopper_Bagpack[playerIndex] = bagpack
           call IFShopCalcCost(playerIndex,shopper,bagpack)
           //Inser upgrade Options and Open Shop
           call ShowUnit( udg_IFShop_Shop[playerIndex],true )
           call SetUnitX(udg_IFShop_Shop[playerIndex], GetUnitX(shopper))
           call SetUnitY(udg_IFShop_Shop[playerIndex], GetUnitY(shopper))
           call IFShopUpdate(playerIndex)
           call SelectUnitForPlayerSingle( udg_IFShop_Shop[playerIndex], Player(playerIndex - 1) )
           //Make Shop target Shopper.
         call IssueNeutralTargetOrderById( Player(playerIndex - 1), udg_IFShop_Shop[playerIndex], IFShopSelectShopTarget() , shopper)
       else
           //No Upgrades avaible Reselect Shopper.
           call SelectUnitForPlayerSingle( shopper, GetOwningPlayer(shopper) )
       endif
    endfunction

    function IFShopShowGUI takes nothing returns nothing
       local integer itemType
       local integer eid = GetHandleId(GetTriggerEventId())
       local unit shopper

       if eid == GetHandleId(EVENT_PLAYER_UNIT_SPELL_EFFECT) or eid == GetHandleId(EVENT_UNIT_SPELL_EFFECT) then
           set itemType = GetItemTypeId(GetSpellTargetItem())
           set shopper = GetTriggerUnit()
       elseif eid == GetHandleId(EVENT_PLAYER_UNIT_PICKUP_ITEM) or eid == GetHandleId(EVENT_UNIT_PICKUP_ITEM) then
           set itemType = GetItemTypeId(GetManipulatedItem())
           set shopper = GetTriggerUnit()
       else
           set itemType = 0
           set shopper = udg_IFShop_Shop_Shopper[0]
       endif
       if IFShopIsInShopZone(GetTriggerUnit()) then
           call IFShopShow(GetConvertedPlayerId(GetOwningPlayer(shopper)), shopper, udg_IFShop_Shop_Shopper_Bagpack[0], itemType)
       endif
       set udg_IFShop_Shop_Shopper_Bagpack[0] = null
       set shopper = null
    endfunction

    function IFShopDoFusion takes integer spell, integer playerIndex returns nothing
       local integer Loop_A = IFShopPageSize()
       local integer Loop_A_End
       local integer Loop_B = 0
       local integer itemType
       local integer indexInShop = 0

       local unit bagpack = udg_IFShop_Shop_Shopper_Bagpack[playerIndex]
       local unit shopper = udg_IFShop_Shop_Shopper[playerIndex]
       call IFShopUnmarkMats(0)
       loop
           exitwhen Loop_A <= 0
           //Was this one bought?
           if ( udg_IFShop_Page_Skill_Button[Loop_A] == spell) then
             set indexInShop = udg_IFShop_Shop_Avaible_Fuse_First[playerIndex] + ( IFShopPageSize() * udg_IFShop_Page_Current[playerIndex] ) + Loop_A -1
               set itemType = udg_IFShop_Shop_Avaible_Fuse_plans[indexInShop]
               exitwhen true
           endif
           set Loop_A = Loop_A - 1
       endloop
       //Enough Gold?
      if( GetPlayerState( Player(playerIndex - 1), PLAYER_STATE_RESOURCE_GOLD) >= udg_IFShop_Shop_Avaible_Fuse_Costs[indexInShop] )then
         call AdjustPlayerStateBJ( ( -1 * udg_IFShop_Shop_Avaible_Fuse_Costs[indexInShop] ), Player(playerIndex - 1), PLAYER_STATE_RESOURCE_GOLD )
           // Collect avaible Fusion-Material
           call IFShopGetSubFusions(playerIndex, shopper, bagpack, itemType)
           //Destory Found material
           loop
               exitwhen Loop_B > udg_IFShop_Item_Stack_Last
               call RemoveSavedBoolean(udg_IFShop_Table, GetHandleId(udg_IFShop_Item_Stack[Loop_B]),0)
               call RemoveItem( udg_IFShop_Item_Stack[Loop_B] )
               set Loop_B = Loop_B + 1
           endloop
           //Create Fusion
           set itemType = udg_IFShop_Shop_Avaible_Fusions[indexInShop]
           call UnitAddItemByIdSwapped( itemType, shopper )
           call DestroyEffect( AddSpecialEffectTarget(udg_IFShop_Fusion_SFX_Path, shopper, "origin") )
       
           call IFShopHide()
           //continue Shopping, with gained Fusion?
           if udg_IFShop_Continue_After_Fusion[playerIndex] then
               call IFShopShow (playerIndex, shopper, bagpack, itemType)
           else
               call SelectUnitForPlayerSingle( shopper, GetTriggerPlayer() )
           endif
       else
           call StartSoundForPlayerBJ(GetTriggerPlayer() ,udg_IFShop_Sound_No_Gold)
       endif

       set shopper = null
       set bagpack = null
    endfunction

    //When an shop casts a spell
    function IFShopCast takes nothing returns nothing
       local integer playerIndex = GetPlayerId(GetTriggerPlayer()) + 1
       local integer spell = GetSpellAbilityId()
       //Next Page used?
       if (spell == udg_IFShop_Page_Skill_Next or spell == udg_IFShop_Page_Skill_Previous) then
           call IFShopPageControl(spell, playerIndex)
       else
           call IFShopDoFusion(spell, playerIndex)
       endif
    endfunction

    //Creates all needed stuff.
    function IFShopInit takes nothing returns nothing
       local trigger switchPage =CreateTrigger()
       local trigger hideShops =CreateTrigger()
       local integer playerIndex = 0
       local integer skillLoop
       local unit shop
       // Basic Setup

       set udg_IFShop_Shopper_Count = 0
       set udg_IFShop_Table = InitHashtable()
       call TriggerAddAction( switchPage, function IFShopCast )
       call TriggerAddAction(hideShops, function IFShopHide)

       //Loop all Players;
       loop
           exitwhen playerIndex == bj_MAX_PLAYERS
           //Is Playing? Is User?
         if ( GetPlayerSlotState(Player(playerIndex)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(playerIndex)) == MAP_CONTROL_USER  ) then
               //Create Shops, Register: Page Controll, Shop Closing
             set shop = CreateUnit( Player(playerIndex), udg_IFShop_Shop_UnitType, GetStartLocationX(playerIndex), GetStartLocationY(playerIndex), 270.0)
               call UnitAddAbility(shop, udg_IFShop_Page_Skill_Next)
               call UnitAddAbility(shop, udg_IFShop_Page_Skill_Previous)
               call UnitAddAbility(shop, udg_IFShop_Page_Skill_Select)
               set skillLoop = IFShopPageSize()
               loop
                   exitwhen skillLoop <= 0
                   call UnitAddAbility(shop, udg_IFShop_Page_Skill_Button[skillLoop])
                   set skillLoop = skillLoop - 1
               endloop
               call SetUnitPathing( shop, false )
           
               call TriggerRegisterUnitEvent( switchPage, shop, EVENT_UNIT_SPELL_CAST )
               call TriggerRegisterUnitEvent( hideShops, shop, EVENT_UNIT_DESELECTED )
               set udg_IFShop_Shop[playerIndex+1] = shop
           endif
           set playerIndex = playerIndex + 1
       endloop
       set shop = null
       call TriggerClearActions(gg_trg_Item_Fusion_shop)
       call IFShopInitStrings()
       call TriggerAddAction(gg_trg_Item_Fusion_shop, function IFShopShowGUI)
    endfunction

    //===========================================================================
    function InitTrig_Item_Fusion_shop takes nothing returns nothing
       set gg_trg_Item_Fusion_shop = CreateTrigger(  )
       call TriggerAddAction( gg_trg_Item_Fusion_shop, function IFShopInit )
    endfunction
     



  • Changelog

    V2.0.2a
    Fixed usage for warcraft 3 1.31+​
    V2.0.2
    Item FusionShop now uses dynamic Abilities instead of powerup - items.
    Removes the need of additional items created for Item Fusion Shop.
    lost the stock amount as gold feature.
    Gold costs are now added as suffix to the items tooltip.​
    Requierment Lists for fusions are now autogenerated.
    Gain Lists are on default the object Field description of the item one gains from a fusion.
    Installing should be now more easy.
    GUI shop opening is now done by executing Item Fusion shop trigger (after it was executed once to setup it).
    Item fusion shop can now add all registered Fusions into the shop by calling IFShopShow wit itemType = -1
    Various code improvements.​
    old Changes

    V1.6)
    One can now show all available upgrades of items in inventories ( shopper + backpack)
    the demo spell shows now this behaviour by casting it on the hero himself.​
    It is now possible to show max upgrade level of items.
    default off.​
    The GUI registering trigger now cleans off fusion result/fake.
    The Fusion Init now starts itself at 0.00 to allow printing out error messages.
    the Entries per page are now changeable inside the jass code.
    cleans now the bought plan instantly.
    fixed a bug with using an material multiple times in one built when jumping tier levels -> took less gold if wanted.​
    V1.5
    Reworked the system, it now performs better with big itempools.
    fixed a bug in which a more expensive built way was choosen
    the primary key for fusion-Plans is now the itemTypeId (tech info).
    takes only 1 Hashtable.​
    V1.3a
    Insert "return true" at the end of function CreateFusion()​
    V1.3
    Material-Amount was registered with 1 too much.
    Option: Start with Bagpack/Shopper for Material finding
    Option: Check Material Slot/Inventory based
    Default: Shopper & Inventory-Based
    Renamed some Variables​
    V1.2a/b
    Insert the Option to exclude a Player Group from a Buyzone
    Changed Blues Hero to blademaster
    Replaced Some BJ-functions
    Break out of loops is now done with exitwhen (true)
    Optimized the calculation time of function BuyFusion dramatically​
    V1.2
    Now in Jass
    Gold Costs are saved in another Hashtabel
    Moved not configerable basic setup into Item Fusion shop Code.
    Added an Option: Show further Upgrades after Fusing
    Fixed 2 buggs with Multi-Page​
    V1.1d
    Custom Value of Items are now correctly restored
    Insert 2 Global Constants (One is the OrderID from select Shopper the other makes it easier to find a not used Custom Value)
    Not selected Units won't Open the Shop anymore
    Added a Blue Player with a own horse.
    Altered the Get Bagpack Trigger showing how to use with 2 MPI Heroes.
    Reordered the Init General Trigger
    Inserter a break in IsInShopzone
    Insert a Variable for the Show Upgrade Spell​
    V1.1c
    Systems Prefix: IFS -> IFShop
    Some Names were shortend to accept the new Prefix
    Added a New Item to the Demo Map: Built to Many. It shows the Multi paging.​
    V1.1b
    Uses Blizzard's Function: StartSoundForPlayerBJ​
    V1.1a
    The "No-Gold" Sound is now played only on the Local PC.
    V1.1
    Added the Feature: "Multiple Pages", the Page-Control is only Shown if needed.
    Now Prices will be updated in Real time, if the accessablity of the used backpack changes; Frequenz 2,5 Hz.
    Now the Shopper is always The "Shown"-Target of the Shop, this Requiers the "Pick User Button" to be shown in the Shop, as the in the map contained ability does.
    Some Code updates
    Demo Map-Text updated.

    V1.0a
    Outsourced IFS_Shopper_Bagpack into the new Trigger IFS getBagpack
    -> this allows easier Customizing and less touching of the System.
    Changed the Trigger Order, to simplfy Importing.
    Added a New Variable IFS_Sound_No_Gold, is set in IFS Init General



Previews
Contents

Item Fusion Shop 1.6 (Map)

Item Fusion Shop 2.0.2ab (Map)

Reviews
KILLCIDE
The system seemed small at first, but as I began to read the code and see the mechanics, I began to see the entirety of the system. I rather like how you managed to get this to work with the WC3 interface. The movement between pages and the...
  1. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,494
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20

    Needs Fixed

    • loc as a variable name is way too generic
    • IFS - Show Upgrade should be stored into a configurable variable
    • loc2 as a variable name is way too generic
    • It should be mentioned that the custom value of item's is manipulated by this system
    • Boolean as a variable name is way too generic
    • Sell Items, Page_Skill_Next, & Page_Skill_Previous should be stored into configurable variables

    Suggestions

    • Documentation for the Basic Setup variables in Init General would be appreciated. As of right now, I have no idea what they mean, especially Fusions_Last
    • In the player group loop in IFS Init General, I would store (Picked player) and (Last created unit) into variables
    • I would avoid using (Integer A) because it might clash with other user's maps, and it is also slower
    • I would add an
      exitwhen (true)
      in the for loop inside IFS shopper is in Shopzone. It seems useless to be continuing the loop if you already found that it's in one of the regions
    • Does the preplaced backpack unit work for all players? Do they only have to place one of these backpack units down or must they place one for each player?
    • In Show Upgrades Spell, you store (Triggering unit) into a variable, but you don't use it
    • Error messages should only be shown locally
    • LoadIntegerBJ()
      ->
      LoadInteger()
    • Instead of setting loop integers to an arbitary value that will exit the loop, make use of the
      exitwhen (true)
      operator

    Status


    Awaiting Update
     
  2. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    Thanks for your Feedback.

    It is not mentioned cause the System should restore the current custom value after usage. Currently In Version 1.1c it does not restore it cause of a simple misstake.
    Its used and needed in the Triggers called.
    Sell Items is the basic Ability of market which can't be modyfied at all, so I don't see any value in giving it a variable.
    Page_Next/Previous are allready variable based.

    In the demo Map the packhorse is used by all Units. But this kind of Bagpack finding, in a own trigger, was choosen to allow free customizing.

    Uploaded Version 1.1d
     
  3. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,494
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    I'm referring to here: Set IFS_Index_Player = (Player number of (Owner of (Triggering unit)))

    If you are storing them into the variables, then you aren't using them in the code correctly. There are parts of the code where you refer to the actual ability in the Object Editor instead of the variable.
     
  4. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    You are right i did this. Currently i converting this to jass which is more suited, will be released as soon as it works as intended and fills the JAPG.
    IFShop 1.1d was a hotfix.
     
  5. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,494
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    Sighh... why do you decide that AFTER I review it >.>
     
  6. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    Uploaded Version 1.2.
     
  7. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,494
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    Meh I'm going to have to throw this at the bottom of the moderation list for now unless another reviewer comes by. There are other submissions we must go to, and I was expecting to keep reviewing this from the GUI version. Since you decided to convert it to JASS after I did my review, I'm going to have to review it all over again.

    Feel free to keep updating it if you find any bugs. For now, please get rid of the unnecessary BJs and use
    exitwhen true
    to exit a loop instead of setting the loop integer to some arbitarily large value.
     
  8. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    Edit: Updated to Version 1.2b.
     
    Last edited: May 2, 2017
  9. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,494
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20

    Needs Fixed


    • Missing return inside function CreateFusion

    Suggestions


    • Nothing

    Status


    Awaiting Update
     
  10. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    updated to 1.3a
     
  11. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,494
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    The system seemed small at first, but as I began to read the code and see the mechanics, I began to see the entirety of the system. I rather like how you managed to get this to work with the WC3 interface. The movement between pages and the combination of items feel smooth. The only con I can see is some inefficiency in the code and the rather large learning curve. Fortunately though, the system isn't periodic, so I can't imagine this causing any issues. I sort of don't feel like taking the time to re-read your code again given that it was originally in GUI, so I'm going to trust that the JASS is okay.

    Needs Fixed

    • Nothing

    Suggestions

    • I would highly appreciate it if you can leave some documentation in your code. The logics make sense to you because you made it, but you must consider that the Reviewers and Moderators just see this as arbitary code.
    • I would make use of
      bj_MAX_PLAYER_SLOTS
      instead of using random numbers like 11 or 16

    Status


    Approved
     
  12. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    Added some Documentation to the Code uploaded on Hive. (Not in the Map)
    Fixed a Error in "IFS Add Item" on Hive showing an old version. (was correct in the map)


    Edit: Updated to 1.5.
    This patch overworked the System overall, improving performance on big itempools by presaving connections between Plans, Fusions and Mats which takes away alot of calcing power during game time.
    Edit: Updated to 1.6.
    1.6 improves 1.5 and adds new features:
    setting items per page
    showing upgrades of upgrades.
    improved error messages for registering fusions
    show upgrades for any item hold by shopper and bagpack.
     
    Last edited: Jul 27, 2017
  13. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,213
    Resources:
    16
    Tools:
    2
    Maps:
    2
    Spells:
    7
    Tutorials:
    4
    JASS:
    1
    Resources:
    16
    Updatet to V2.0.2.
    Uses the new natives to changes abilities to manage the shop and show upgrade options.
    Previoulsy each upgrade option was one powerup item which bloated object Editor alot.
    Various improvements: performance, naming, copyability and useability.