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

TasItemshop

Introduction

TasItemShop is a Frame-UI System for Warcraft 3 V1.31 or higher. The System's purpose is to have shops that can sell/fuse more items than the ones Warcraft 3 nativly provides. In the same time more accessable with search&filter features.​
Shops are still meant to be units in this system.​

Features

Shows current buyable Items in a scrollable list of Buttons.​
Customizeable to some degree, without touching the system's code (might require some fdf knowhow).​
Can be used by any amount of players at the same time. Each with their own shoping.​
Supports Items crafted by fusing other items.​
Complete fusions - pays for missing items, if the shop can sell the material.​
Can disable the usage of other players items as fusion material.(You have to handle item ownership using SetItemPlayer, this feature can be disabled)​
Can Defuse items.​
Can Sell Items to a Shop.​
Multiple Units can contribute materials for a ItemFusion.​
Has Reference Buttons to show upgrades, materials, current items in inventory and your shoppers.​
Item Reference Buttons can be left clicked, to navigate the shop.​
Item Reference Buttons can be right clicked to quick buy it.​
Items can be filtered by categories. (There can be upto 31 categories)​
Supports multicategory in which items have to fullfill all selected categories.​
Item can be searched by name or parts of their name.​
item Infos are taken from Object Editor.​
Can have different Shops with different prices and itempools.​
Such Shops are setuped by Unitcode and have either a White- or BlackList.​
Shops can have Gold/Lumber cost factors for anything or/and different price factors for specific items.​
Can be feed by GUI. (Some features are code only)​
^^ The GUI part can be removed quite simple, if not wanted.​
Works during Game Pause (Sadly not the quick buying with right clicks).​
Can Undo all Buys/Fusions/Sells/Defusions done aslong the TasItemShop was not closed. Undo gives you back the gold/Lumber, items used and removes the gained items. (Undo can be disabled) (When this feature is enabled material-Items are not removed until the Undo becomes unuseable)​
Abilities/Buffs can change the prices in TasItemShop.​
Can sell you any items not added to the item shop, but can navigated to (has to be enabled, connected with ignoring what shops can sell/craft).​
Can Set ShortCuts for buyable Items on a Player base (this can be done by user and by Code)​
Makes your map some kb heavier and adds several hundreds of lines to your map script.​

How to install?

First you have to export and import the Files in the demo map (using the export all Files function can bug in older Editor Versions).​
war3mapImported\TasItemShop.fdf​
war3mapImported\TasItemShop.toc​
war3mapImported\TasButtonList.fdf​
the model in the demo (by abfal), if you want to use it​
Now you copy Item Shop UI (trigger editor) into your map​
if all worked, you can now use it.​

How to use!

After it was added into your map you first have to tell it which unitTypes are used as shops and what they (not) sell/craft. You also should setup Fusions and categories.​
When you setuped all the shops, buyable items,fusions and categories you are done.​
You also have to inspect and maybe change the most top functions right below the configs in the System's code which can be treated as part of the user setup.​
local function UserInit() (in vjass this function is in a seperate script file and is independent)​
local function IsValidShopper(player, shop, unit, range)​
local function CostModifier(gold, lumber, itemCode, buyer, shop, shopObject)​
For code examples download the map or scroll down.​
When a shopping is started the current buyable options are loaded into the UI, based on the current visited shop.​
When your map hides the Frame "ConsoleUIBackdrop" then you should change the parent used for TasItemShopUI.Frames.ParentSuper. When TasItemShop is used in Reforged, on default, "ConsoleUIBackdrop" is used to make the box be useable outside of the 4:3 Screen.​

ShopUnits

TasItemShop has Shops in BlackList and Shops in WhiteList mode. The difference between these is the items they can sell/craft.​
Shops without custom data and BlackList based shops use the TasItemShop item array (BUY_ABLE_ITEMS). The Blacklist mode takes away options from the common buy options when using the shop. While WhiteList shops don't care about that list at all and sell only what one set up for them.​

Fusion Limitations

Fusions done by TasItemShop can only be done inside the shop. There is no fusing by holding all the items.​
An Fused Item can only be built by one way. One can not setup 2 ways to get the ultimate sword, there can only be one.​
Materials are absolute, there is no replacement or equal substitute item. Although they can be replaced by gold/lumber, if the shop can sell them.​
Fusion do not care about charges​

GUI

Lua

vjass


The GUI part is the same for the Lua and vjass version. If you only want to use TasItemShop with GUI don`t forget to inspect and change the config to your bidding, which is shown in the start of the vjass/Lua tab.

This Trigger is the GUI init it evokes the other ItemShop GUI init Triggers. It is quite important that you create categories before you try to use them onto an item.
  • ItemshopGUI Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Trigger - Run ItemshopGUI Init Cats <gen> (ignoring conditions)
      • Trigger - Run ItemshopGUI Init Fusions <gen> (ignoring conditions)
      • Trigger - Run ItemshopGUI Init Haggle Skills <gen> (ignoring conditions)
      • Trigger - Run ItemshopGUI Init Items <gen> (ignoring conditions)
      • Trigger - Run ItemshopGUI Init Shop <gen> (ignoring conditions)
Define 2 Haggle-Effects. Being turned into a frog by a shadow hunter spell will make shopping much more expensive.
Having the Haggle-Skill reduces the prices by 20%.
  • ItemshopGUI Init Haggle Skills
    • Events
    • Conditions
    • Actions
      • -------- With the Haggle skill you have to pay 20% less --------
      • Set TasItemShop_Skill = Haggling
      • Set TasItemShop_Gold = 0.80
      • Set TasItemShop_Lumber = 0.80
      • Set TasItemShop_LumberAdd = 0.00
      • Set TasItemShop_GoldAdd = 0.00
      • Trigger - Run TasItemShopHaggle (ignoring conditions)
      • -------- With the Hex buff you have pay 3 times as much --------
      • Set TasItemShop_Buff = Hexerei
      • Set TasItemShop_Gold = 3.00
      • Set TasItemShop_Lumber = 3.00
      • Trigger - Run TasItemShopHaggle (ignoring conditions)
This trigger defines Goblin-Shop as a TasItemShop. It is an expensive shop which takes 20% more Gold&Lumber. It is a Blacklist shop which excludes Kelens Dagger and Crown of the Kings, if they are part of the common sellable item pools.
  • ItemshopGUI Init Shop
    • Events
    • Conditions
    • Actions
      • Set TasItemShop_Unit = Goblin-Laden
      • -------- general cost Factor, 1.0 = 100%. 1,2 = 120% costs --------
      • Set TasItemShop_Gold = 1.20
      • Set TasItemShop_Lumber = 1.20
      • -------- false = disallow mentioned items --------
      • -------- true = allow only the mentioned items --------
      • Set TasItemShop_WhiteList = False
      • -------- Mat[0] is not supported --------
      • Set TasItemShop_Mats[1] = Kelens Dolch des Entkommens
      • Set TasItemShop_Mats[2] = Krone der Könige +5
      • Trigger - Run TasItemShopCreateShop (ignoring conditions)
Add this 2 Items to common buyable pool
  • ItemshopGUI Init Items
    • Events
    • Conditions
    • Actions
      • -------- Add Sengklinge as MyItemShopCat to the common buyable Pool --------
      • Set TasItemShop_Item = Sengklinge
      • Set TasItemShop_Category = MyItemShopCat
      • Trigger - Run TasItemShopAdd (ignoring conditions)
      • -------- Add Frostwache as MyItemShopCat & MyItemShopCat2 to the common buyable Pool --------
      • Set TasItemShop_Item = Frostwache
      • Set TasItemShop_Category = (MyItemShopCat + MyItemShopCat2)
      • Trigger - Run TasItemShopAdd (ignoring conditions)
Define 2 new Fusions.
  • ItemshopGUI Init Fusions
    • Events
    • Conditions
    • Actions
      • -------- Mat[0] is not supported --------
      • Set TasItemShop_Item = Frostwache
      • Set TasItemShop_Mats[1] = Frostkugel
      • Set TasItemShop_Mats[2] = Klauen des Angriffs +15
      • Trigger - Run TasItemShopFusion (ignoring conditions)
      • Set TasItemShop_Item = Sengklinge
      • Set TasItemShop_Mats[1] = Feuerkugel
      • Set TasItemShop_Mats[2] = Klauen des Angriffs +15
      • Trigger - Run TasItemShopFusion (ignoring conditions)
Creates 2 categories and safes their value into custom variables. This variables are required to add items later with these categories.
  • ItemshopGUI Init Cats
    • Events
    • Conditions
    • Actions
      • -------- Add a new category --------
      • Set TasItemShop_Text = GUI
      • Set TasItemShop_Icon = ReplaceableTextures\CommandButtons\BTNDranaiAkama.blp
      • Trigger - Run TasItemShopCategory (ignoring conditions)
      • -------- TasItemShop_Category contains the new category's value --------
      • -------- Save it into an custom variable of your choice. You need it to set the categories of items. --------
      • Set MyItemShopCat = TasItemShop_Category
      • -------- Add another category --------
      • Set TasItemShop_Text = GUI2
      • Set TasItemShop_Icon = ReplaceableTextures\CommandButtons\BTNAcolyte.blp
      • Trigger - Run TasItemShopCategory (ignoring conditions)
      • -------- This is a different category safe it in a different variable --------
      • Set MyItemShopCat2 = TasItemShop_Category
With V4A one can set current ShortCut for a player with GUI triggers. This trigger sets the default ShortCuts for all players. Humans have different ones than non Hummans.
Beaware that in the Lua version you can not do that before 0.01s seconds passed.
  • ItemshopGUI Init ShortCuts
    • Events
      • Time - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • -------- Do that after 0.01s --------
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • -------- The playre for which you want to set Shortcuts --------
          • Set TasItemShop_Player = (Picked player)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Race of (Picked player)) Equal to Human
            • Then - Actions
              • -------- Mat[0] is not supported --------
              • Set TasItemShop_Mats[1] = Gürtel der Gigantenkraft +6
              • Set TasItemShop_Mats[2] = Krone der Könige +5
              • Set TasItemShop_Mats[3] = Klauen des Angriffs +15
            • Else - Actions
              • Set TasItemShop_Mats[1] = Medaillon des Mutes
              • Set TasItemShop_Mats[2] = Ring des Schutzes +3
              • Set TasItemShop_Mats[3] = Sobi-Maske
          • Trigger - Run TasItemShopShortCuts (ignoring conditions)
      • -------- You could clear the ShortCutList by setting [1] to no Item Type --------

Config

At the top of the TasItemShop after "do" you find the config for various settings. This settings except for BUY_ABLE_ITEMS & Haggle_Skills. Should not be changed later on. These settings define Size, Position, button amount & enables features, some are constantly read some only when the UI is created. If you want to use the system with GUI only you should remove all data from BUY_ABLE_ITEMS and remove all content from local function UserInit() which is also found a little bit below the other config.​
Normaly in Lua one has to use FourCC when mentioning a Object Editor Objectcode. TasItemShop API functions handle that four you.​
Lua:
-- A list of items buyable, you could just smack in all your buyAble TasItems here.
-- Or use TasItemShopAdd(itemCode, category) inside local function UserInit()
-- This List is used by shops without custom data or by BlackList Shops
local BUY_ABLE_ITEMS = {'bgst', 'ciri', 'belv', 'hval', 'hcun', 'mcou', 'ckng', 'rat9', 'ratf', 'rst1', 'rin1', 'rag1', 'cnob', 'rat6', 'rlif'
,'ajen', 'clfm', 'ward', 'kpin', 'lgdh', 'rde4', 'pmna', 'rhth', 'ssil', 'spsh', 'lhst', 'afac', 'sbch', 'brac', 'rwiz', 'crys', 'evtl', 'penr'
,'prvt', 'rde3', 'bspd', 'gcel', 'rde2', 'clsd', 'dsum', 'stel', 'desc', 'modt', 'ofro', 'thdm', 'hlst', 'mnst', 'pghe', 'pgma', 'pnvu', 'pres'
,'ankh', 'shas', 'stwp', 'ofir', 'oli2', 'odef', 'oven', 'oslo', 'ocor', 'shtm', 'I001', 'klmm', 'crdt'
}

local Haggle_Skills = {
    -- skill, GoldBase, Lumberbase, GoldAdd, LumberAdd
    -- add is added per Level of that skill to Base. The current Cost is than multiplied by that Factor.
    --{FourCC('A000'), 0.8, 0.8, 0.0, 0.0}
}

-- position of the custom UI
-- it can leave the 4:3 Screen but you should checkout the start of function TasItemShopUI.Create
local xPos = 0.0
local yPos = -0.02
local posPoint = FRAMEPOINT_TOPRIGHT
local posScreenRelative = true --(true) repos to the screenSize, when the resolution mode changes the box will move further in/out when using a right or Left point.
-- It is advised to posScreenRelative = false when posPoint does not include Left or Right
-- with posScreenRelative = false xPos and yPos are abs coords, to which posPoint of the Shop UI is placed to.

-- position of Item toolTips, this does not affect the tooltips for Categories or Users.
-- comment out toolTipPosPointParent, if you want a specific position on screen.
-- with toolTipPosPoint & toolTipPosPointParent are toolTipPosX & toolTipPosY relative offsets.
-- The position is a bit wierd, the position is not the box but the Extended Tooltip Text, the Header has a height of ~0.052.

local toolTipPosX = 0.0
local toolTipPosY = -0.052
local toolTipPosPoint = FRAMEPOINT_TOPRIGHT
local toolTipPosPointParent = FRAMEPOINT_BOTTOMRIGHT
local toolTipSizeX = 0.2 -- only content
local toolTipSizeXBig = 0.3 -- only content
local toolTipLimitBig = 300 -- When a TooltipText Contains this amount or more of Chars it will use toolTipSizeXBig

-- this can be used to change the visual ("EscMenuControlBackdropTemplate") ("TasItemShopRaceBackdrop")
local boxFrameName = "TasItemShopRaceBackdrop"
local boxButtonListFrameName = "EscMenuControlBackdropTemplate"
local boxRefFrameName = "EscMenuControlBackdropTemplate"
local boxCatFrameName = "EscMenuControlBackdropTemplate"
local boxUndoFrameName = "TasItemShopRaceBackdrop"
local boxDefuseFrameName = "TasItemShopRaceBackdrop"
local buttonListHighLightFrameName = "TasItemShopSelectedHighlight"
local boxFrameBorderGap = 0.0065
local boxButtonListBorderGap = 0.0065 -- does nothing right now
local boxRefBorderGap = 0.0065
local boxCatBorderGap = 0.0055
local boxUndoBorderGap = 0.0045
local boxDefuseBorderGap = 0.0045
local boxSellBorderGap = 0.0045
local buttonListButtonGapCol = 0.001
local buttonListButtonGapRow = 0.005
-- material control
local flexibleShop = false -- (true) can sell items not added to the shop. This includes items reached over RefButtons and material for autocompletion. I don't know that item, but your description is enough. I craft it, no problem.
local sharedItems = false -- (false) can only fuse material owned by neutral passive (default) or oneself. The code handling that is in TasItemFusion.
local canProviderGetItem = true -- (true) when the mainShopper's inventory is full, try to give the other matieral provider the item
local canUndo = true -- (true) There is an Undo Button which allows to Revert BuyActions done in this shopping. A shopping ends when the UI is closed, changing current shop counts as closed.
local canDefuse = true -- (true) There is a Defuse Button which allows to defuse FusionItems hold.
local DefuseButtonIcon = "ReplaceableTextures\\CommandButtons\\BTNdemolish"
local DefuseButtonIconDisabled = getDisabledIcon(DefuseButtonIcon)
local canSellItems = true -- (true)
local SellFactor = 0.75
local SellUsesCostModifier = true
local SellButtonIcon = "ReplaceableTextures\\CommandButtons\\BTNReturnGoods"
local SellButtonIconDisabled = getDisabledIcon(SellButtonIcon)

local MainUserTexture = "ui\\widgets\\console\\human\\commandbutton\\human-multipleselection-border"
local MainItemTexture = "ui\\widgets\\console\\human\\commandbutton\\human-multipleselection-border"

local shopRange = 900 -- the max distance between shop and Shoper, this can be overwritten by shopObject.Range.
local updateTime = 0.4 -- how many seconds pass before a new update is applied. update: search new shopers, validat current shopers and update UI.
-- Titel-text in the reference Boxes
local textUpgrades = "COLON_UPGRADE" --tries to localize on creation
local textMats = "SCORESCREEN_TAB3"
local textInventory = "INVENTORY"
local textUser = "USER"
local textCanNotBuyPrefix = "Can not buy: "
local textCanNotBuySufix = "OUTOFSTOCKTOOLTIP"
local textNoValidShopper = "No valid Shoper"
local textUndo = "Undo: "
local textUnBuyable = "xxxxxxx"
local textDefuse = "Defuse:"
local textSell = "Sell:"
local textQuickLink = "ShortCuts:"
local categoryModeTextAnd = "ui\\widgets\\battlenet\\bnet-mainmenu-friends-disabled"
local categoryModeTextOr = "Or"
local categoryModeIconOr = "ui\\widgets\\battlenet\\bnet-mainmenu-friends-up"
local categoryModeIconAnd = "And"

local quickLinkKey = OSKEY_LSHIFT  -- nil will prevent the user from changing shortcuts. can also be commented out
-- how many refButtons, refButtons have pages, if needed.
-- A feature is disabled with a counter smaller than 1.
local refButtonCountMats = 4 -- materialRefs.
local refButtonCountUp = 4 -- possible upgrades of the current Selected
local refButtonCountInv = 6 -- inventory items, this system allows an unitgroup to provide items, if you don't use that feature only upto 6 makes sense.
local refButtonCountUser = 6 -- References to the shopping Units/material provider.
local refButtonCountQuickLink = 4 -- User SelectAble Shortcuts
local refButtonSize = 0.02
local refButtonGap = 0.003
local refButtonPageSize = 0.012
local refButtonPageRotate = true --(true) swap to first page when going above last page, and swap to last page when going down first Page
local refButtonPageUp = "ReplaceableTextures\\CommandButtons\\BTNReplay-SpeedUp"
local refButtonPageDown = "ReplaceableTextures\\CommandButtons\\BTNReplay-SpeedDown"
local refButtonBoxSizeY = 0.047

-- LayoutType alters the position of buttons
-- (0) the buy button is at the bottom between buttonList and buybutton the refBoxes are placed
-- (1) the buy button is below the buttonList below it are the refButtons
-- (2) the buy button is below the buttonList, the RefButtons are at the bottom outside of the Box
-- (3) the buy button is below the buttonList, the RefButtons are left outside of the Box they are also from top to bottom
local LayoutType = 0


-- (true) right clicking an refInventoryButton in the UI will sell the item
-- (false) right clicking it will buy it again.
local inventoryRightClickSell = true
local inventoryShowMainOnly = true --(false) show all items currently useable

local userButtonOrder = false -- (true) Creates any UnitTargetOrder Event enables right clicking Units in the world to swap main shoppers.
local doubleClickTimeOut = 2.0 -- amount of seconds a doppleclick inside the Buttonlist counts as Buying

-- model displayed when buy request was started.
--local spriteModel = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl" -- in 1.31 the coins are black only.
--local spriteModel = "Abilities\\Weapons\\RockBoltMissile\\RockBoltMissile.mdl"
--local spriteModel = "Abilities\\Weapons\\BansheeMissile\\BansheeMissile.mdl"
--local spriteModel = "Abilities\\Spells\\Other\\GeneralAuraTarget\\GeneralAuraTarget.mdl"
local spriteModel = "war3mapImported\\BansheeMissile.mdx" --by abfal, (no sound).
local spriteScale = 0.0006 -- The scale has to fit the used model. if you use non-UI models use a low scale, 0.001 or below.
local spriteAnimationIndex = 1 -- 1 = death animation

local buttonListRows = 5
-- buttonListCols has a strong impact on the xSize of this UI. make sure that refButtons of one type fit into this.
local buttonListCols = 3

-- this will not change the size of the Buttons, nor the space the text can take
-- true = Show
-- false = hide
local buttonListShowGold = true
local buttonListShowLumber = true
local buyButtonShowGold = true
local buyButtonShowLumber = true

-- which button is used inside the ButtonList? Enable one block and disable the other one

local buttonListButtonName = "TasButtonSmall"
local buttonListButtonSizeX = 0.1
local buttonListButtonSizeY = 0.0325

-- "TasButtonGrid" are smaller, they don't show the names in the list
--local buttonListButtonName = "TasButtonGrid"
--local buttonListButtonSizeX = 0.064
--local buttonListButtonSizeY = 0.0265

--local buttonListButtonName = "TasButton"
--local buttonListButtonSizeX = 0.2
--local buttonListButtonSizeY = 0.0265

local categoryButtonSize = 0.019

In Lua most setup is done in the local function UserInit() of TasItemShop. Here one should define categories, fusions, shops.
Probably you should use functions of this Lua api:
Lua:
--[[
TasItemSetCategory(itemCode, category)
TasItemShopAdd(itemCode, category)
TasItemShopAddCategory(icon, text)
 define a new Category, should be done before the UI is created.
 Returns the value of the new category
TasItemShopUIShow(player, shop, shopperGroup[, mainShoper])
    TasItemShopUIShow(player) hides the shop for player
    shopperGroup are all units providing items, if you use nil the current shoppergroup remains intact. When giving something else the group contains only mainShoper.
    mainShoper is the unit consider for haggel and gains the items. If you gave a group then you can skip mainShoper then a random is taken.
    with player and shop the shoppers are kept but the shop updates.
    Beaware that this System does only update on user input it will not check distance/live or anything.
TasItemShopUIShowSimple(player, shop, mainShoper)
TasItemShopCreateShop(unitCode, whiteList, goldFactor, lumberFactor, goldFunction, lumberFunction)
TasItemShopAddShop(unitCode, ...)
 adds data for that specific shop
TasItemShopGoldFactor(unitCode, factor, ...)
    sets the goldFactor for that shop to the given data
TasItemShopLumberFactor(unitCode, factor, ...)
    lumberFactor ^^
TasItemShopAddHaggleSkill(skill, goldBase[, lumberBase, goldAdd, lumberAdd])
    adds a new Skill which will affect the costs in TasItemShop.
TasItemShopUI.SetQuickLink(player, itemCode)
    add/remove itemCode from quickLink for player
--]]
Demo map Example of local function UserInit()
Lua:
-- This runs right before the actually UI is created.
-- this is a good place to add items, categories, fusions shops etc.
local function UserInit()
    -- this can all be done in GUI aswell, enable the next Line or remove all Text of this function if you only want to use GUI
    --if true then return end

    -- define Categories: Icon, Text
    -- the Categories are displayed in the order added.
    -- it is a good idea to save the returned Value in a local to make the category setup later much easier to understand.
    -- you can only have 31 categories
    local catDmg = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNSteelMelee", "COLON_DAMAGE")
    local catArmor = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNHumanArmorUpOne", "COLON_ARMOR")
    local catStr = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNGauntletsOfOgrePower", "STRENGTH")
    local catAgi = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNSlippersOfAgility", "AGILITY")
    local catInt = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNMantleOfIntelligence", "INTELLECT")
    local catLife = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNPeriapt", "Life")
    local catLifeReg = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNRegenerate", "LifeRegeneration")
    local catMana = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNPendantOfMana", "Mana")
    local catManaReg = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNSobiMask", "ManaRegeneration")
    local catOrb = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNOrbOfDarkness", "Orb")
    local catAura = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNLionHorn", "Aura")
    local catActive = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNStaffOfSilence", "Active")
    local catPower = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNControlMagic", "SpellPower")
    local catCooldown = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNHumanMissileUpOne", "Cooldown")
    local catAtkSpeed = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNHumanMissileUpOne", "Attackspeed")
    local catMress = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNRunedBracers", "Magic-Resistence")
    local catConsum = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNPotionGreenSmall", "ConsumAble")
    local catMoveSpeed = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNBootsOfSpeed", "COLON_MOVE_SPEED")
    local catCrit = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNCriticalStrike", "Crit")
    local catLifeSteal = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNVampiricAura", "Lifesteal")
    local catEvade = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNEvasion", "Evasion")
 
    -- setup custom shops
    -- custom Shops are optional.
    -- They can have a White or Blacklist of items they can(n't) sell and have a fixed cost modifier for Gold, Lumber aswell as a function for more dynamic things for Gold and Lumber.
    local shopObject
    -- 'n000' can only sell this items (this items don't have to be in the pool of items)
    shopObject = TasItemShopAddShop('n000', 'hlst', 'mnst', 'pghe', 'pgma', 'pnvu', 'pres', 'ankh', 'stwp', 'shas')
    -- enable WhiteListMode
    shopObject.Mode = true
    -- 'n001' can't sell this items (from the default pool of items)
    shopObject = TasItemShopAddShop('n001', 'hlst', 'mnst', 'pghe', 'pgma', 'pnvu', 'pres', 'ankh', 'stwp', 'shas')
    -- enable BlackListMode
    shopObject.Mode = false
    -- create an shopObject for 'ngme', has to pay 20% more than normal, beaware that this can be overwritten by GUI Example
    shopObject = TasItemShopCreateShop('ngme', false, 1.2, 1.2
    -- custom gold Cost function
        ,function(itemCode, cost, client, shop) return cost end
    -- custom lumber Cost function
        ,function(itemCode, cost, client, shop) return cost end
    )
    --'I002' crown +100 was never added to the database but this shop can craft/sell it.
    shopObject = TasItemShopAddShop('n002', 'ckng', 'I001', 'I002', 'arsh')
    shopObject.Mode = true
 

    -- Define skills/Buffs that change the costs in the shop
    -- cursed Units have to pay +25%
    TasItemShopAddHaggleSkill(FourCC('Bcrs'), 1.25, 1.25)

    -- define Fusions
    -- result created by 'xxx', 'xx' , 'x'...
    -- item can only be crafted by one way
    -- can add any amount of material in the Lua version
    TasItemFusionAdd('bgst', 'rst1', 'rst1')
    TasItemFusionAdd('ciri', 'rin1', 'rin1')
    TasItemFusionAdd('belv', 'rag1', 'rag1')
    TasItemFusionAdd('hval', 'rag1', 'rst1')
    TasItemFusionAdd('hcun', 'rag1', 'rin1')
    TasItemFusionAdd('mcou', 'rst1', 'rin1')
    TasItemFusionAdd('ckng', 'cnob', 'cnob')
    TasItemFusionAdd('rat9', 'rat6', 'rat6')
    TasItemFusionAdd('ratf', 'rat9', 'rat9')
    TasItemFusionAdd('rde4', 'rde3')
    TasItemFusionAdd('rde3', 'rde2')
    TasItemFusionAdd('rhth', 'prvt')
    TasItemFusionAdd('pmna', 'penr')
    TasItemFusionAdd('arsh', 'rde3', 'rde2')

    TasItemFusionAdd('lhst', 'sfog')

    -- crown of Kings + 50
    TasItemFusionAdd('I001', 'ckng', 'ckng', 'ckng', 'ckng', 'ckng', 'ckng', 'bgst', 'bgst', 'ciri', 'ciri', 'belv', 'belv', 'cnob', 'cnob')
    -- crown of Kings + 100, this is a joke you can not craft it because it was not added to buyAble Items
    TasItemFusionAdd('I002', 'I001', 'I001')

    -- define item Categories
    -- uses the locals from earlier.
    -- An item can have multiple categories just add them together like this: catStr + catAgi + catInt
 
    TasItemSetCategory('rst1', catStr)
    TasItemSetCategory('bgst', catStr)
    TasItemSetCategory('rin1', catInt)
    TasItemSetCategory('ciri', catInt)
    TasItemSetCategory('rag1', catAgi)
    TasItemSetCategory('belv', catAgi)

    TasItemSetCategory('I001', catStr + catAgi + catInt)

    TasItemSetCategory('ckng', catStr + catAgi + catInt)
    TasItemSetCategory('mcou', catStr + catInt)
    TasItemSetCategory('hval', catStr + catAgi)
    TasItemSetCategory('hcun', catAgi + catInt)
    TasItemSetCategory('cnob', catStr + catAgi + catInt)

    TasItemSetCategory('rat9', catDmg)
    TasItemSetCategory('rat6', catDmg)
    TasItemSetCategory('ratf', catDmg)
 
    TasItemSetCategory('rlif', catLifeReg)

    TasItemSetCategory('ajen', catAura + catAtkSpeed + catMoveSpeed)
    TasItemSetCategory('clfm', catAura + catDmg)
    TasItemSetCategory('ward', catAura + catDmg)
    TasItemSetCategory('kpin', catAura + catManaReg)
    TasItemSetCategory('lgdh', catAura + catMoveSpeed + catLifeReg)
    TasItemSetCategory('rde4', catArmor)
    TasItemSetCategory('pmna', catMana)
    TasItemSetCategory('rhth', catLife)
    TasItemSetCategory('ssil', catActive)
    TasItemSetCategory('lhst', catAura + catArmor)
    TasItemSetCategory('afac', catAura + catDmg)
    TasItemSetCategory('sbch', catAura + catDmg)
    TasItemSetCategory('sbch', catAura + catLifeSteal)
    TasItemSetCategory('brac', catMress)
    TasItemSetCategory('spsh', catMress + catActive)
    TasItemSetCategory('rwiz', catManaReg)
    TasItemSetCategory('crys', catActive)
    TasItemSetCategory('evtl', catEvade)
    TasItemSetCategory('penr', catMana)
    TasItemSetCategory('prvt', catLife)
    TasItemSetCategory('rde3', catArmor)
    TasItemSetCategory('bspd', catMoveSpeed)
    TasItemSetCategory('gcel', catAtkSpeed)
    TasItemSetCategory('rde2', catArmor)
    TasItemSetCategory('clsd', catActive)
    TasItemSetCategory('dsum', catActive + catMoveSpeed)
    TasItemSetCategory('stel', catActive + catMoveSpeed)
    TasItemSetCategory('desc', catActive + catMoveSpeed)
    TasItemSetCategory('ofro', catDmg + catOrb)
    TasItemSetCategory('modt', catLifeSteal + catOrb)
    TasItemSetCategory('thdm', catActive)
    TasItemSetCategory('hlst', catActive + catConsum + catLifeReg)
    TasItemSetCategory('mnst', catActive + catConsum + catManaReg)
    TasItemSetCategory('pghe', catActive + catConsum)
    TasItemSetCategory('pgma', catActive + catConsum)
    TasItemSetCategory('pnvu', catActive + catConsum)
    TasItemSetCategory('pres', catActive + catConsum)
    TasItemSetCategory('ankh', catConsum)
    TasItemSetCategory('stwp', catActive + catConsum + catMoveSpeed)
    TasItemSetCategory('shas', catActive + catConsum + catMoveSpeed)
    TasItemSetCategory('ofir', catOrb + catDmg)
    TasItemSetCategory('oli2', catOrb + catDmg)
    TasItemSetCategory('odef', catOrb + catDmg)
    TasItemSetCategory('oven', catOrb + catDmg)
    TasItemSetCategory('oslo', catOrb + catDmg)
    TasItemSetCategory('ocor', catOrb + catDmg)
    TasItemSetCategory('shtm', catActive)
end
This function belongs to the setup and is quite important. It allows or disallows units currently using a shop and with that also providing material.
Lua:
local function IsValidShopper(player, shop, unit, range)
    if not IsUnitOwnedByPlayer(unit, player) then
        --print("IsUnitOwnedByPlayer")
        return false
    end
    if UnitInventorySize(unit) < 1 then
        --print("UnitInventorySize")
        return false
    end
    if IsUnitType(unit, UNIT_TYPE_DEAD) then
        --print("UNIT_TYPE_DEAD")
        return false
    end
    if IsUnitPaused(unit) then
        --print("IsUnitPaused")
        return false
    end
    if IsUnitHidden(unit) then
        --print("IsUnitHidden")
        return false
    end
    if IsUnitIllusion(unit) then
        --print("IsUnitIllusion")
        return false
    end
    if not IsUnitInRange(shop, unit, range) then
        --print("not IsUnitInRange")
        return false
    end
    return true
end
CostModifier is a function which kinda belongs to the system but still might be a place one want to change to affect all prices in all TasItemShops.
Lua:
local function CostModifier(gold, lumber, itemCode, buyer, shop, shopObject)
    -- this function is called for each Button that shows costs in the shop UI and right before buying the item.
    -- Beaware that this function is also called in a async manner -> no sideeffects or state changes.
    -- buyer got the Haggling skill?
    local level, skill
    for i, v in ipairs(Haggle_Skills) do
        skill = v[1]
        level = GetUnitAbilityLevel(buyer, skill)
        if level > 0 then
            gold = gold * (v[2] + v[4]*level)
            lumber = lumber * (v[3] + v[5]*level)
        end
    end

    if shopObject then
        gold = gold * shopObject.GoldFactor[itemCode]
        lumber = lumber * shopObject.LumberFactor[itemCode]
        if shopObject.Gold then
            gold = shopObject.Gold(itemCode, gold, buyer, shop)
        end
        if shopObject.Lumber then
            lumber = shopObject.Lumber(itemCode, lumber, buyer, shop)
        end
 
    end
    return math.floor(gold), math.floor(lumber)
end
This functions is used to choose the parent (layer) which is used by TasItemShop. This is important to be able to leave the 4:3 Screen.
Even if you use this in reforged it might be a good choice to use the else path. Because as Child of "ConsoleUIBackdrop" TasItemShop will be below the default UI.
Lua:
local function GetParent()
    local parent
    if TasItemShopUI.IsReforged then
        parent = BlzGetFrameByName("ConsoleUIBackdrop", 0)
    else
        CreateLeaderboardBJ(bj_FORCE_ALL_PLAYERS, "title")
        parent = BlzGetFrameByName("Leaderboard", 0)
        BlzFrameSetSize(parent, 0, 0)
        BlzFrameSetVisible(BlzGetFrameByName("LeaderboardBackdrop", 0), false)
        BlzFrameSetVisible(BlzGetFrameByName("LeaderboardTitle", 0), false)
    end
    return parent
end

Config

In the vjass version most of the config is inside the global block of TasItemShop upto to a line which reads // Config End.​
With the values in config you can alter some rules, features, position, size and appearance of TasItemShop. Even if you only want to use GUI you should checkout & maybe change these value to your will.​
JASS:
globals
// Config Start
public real xPos = 0.0
public real yPos = -0.02
public framepointtype posPoint = FRAMEPOINT_TOPRIGHT
public boolean posScreenRelative = true //(true) repos to the screenSize, when the resolution mode changes the box will move further in/out when using a right or Left point.
// It is advised to posScreenRelative = false when posPoint does not include Left or Right
// with posScreenRelative = false xPos and yPos are abs coords, to which posPoint of the Shop UI is placed to.

// position of Item toolTips, this does not affect the tooltips for Categories or Users.
// toolTipPosPointParent = null, if you want a specific position on screen.
// with toolTipPosPoint & toolTipPosPointParent are toolTipPosX & toolTipPosY relative offsets.
// The position is a bit wierd, the position is not the box but the Extended Tooltip Text, the Header has a height of ~0.052.
public real toolTipPosX = 0.0
public real toolTipPosY = -0.052
public framepointtype toolTipPosPoint = FRAMEPOINT_TOPRIGHT
public framepointtype toolTipPosPointParent = FRAMEPOINT_BOTTOMRIGHT
//public framepointtype toolTipPosPointParent = null
public real toolTipSizeX = 0.2 // only content
public real toolTipSizeXBig = 0.3 // only content
public real toolTipLimitBig = 300 // When a TooltipText Contains this amount or more of Chars it will use toolTipSizeXBig

// this can be used to change the visual ("EscMenuControlBackdropTemplate") ("TasItemShopRaceBackdrop")
public string boxFrameName = "TasItemShopRaceBackdrop"
public string boxButtonListFrameName = "EscMenuControlBackdropTemplate"
public string boxRefFrameName = "EscMenuControlBackdropTemplate"
public string boxCatFrameName = "EscMenuControlBackdropTemplate"
public string boxUndoFrameName = "TasItemShopRaceBackdrop"
public string boxDefuseFrameName = "TasItemShopRaceBackdrop"
public string buttonListHighLightFrameName = "TasItemShopSelectedHighlight"
public real boxFrameBorderGap = 0.0065
public real boxButtonListBorderGap = 0.0065 // does nothing right now
public real boxRefBorderGap = 0.0065
public real boxCatBorderGap = 0.0055
public real boxUndoBorderGap = 0.0045
public real boxDefuseBorderGap = 0.0045
public real boxSellBorderGap = 0.0045
public real buttonListButtonGapCol = 0.001
public real buttonListButtonGapRow = 0.005
// material control
public boolean flexibleShop = false // (true) can sell items not added to the shop. This includes items reached over RefButtons and material for autocompletion. I don't know that item, but your description is enough. I craft it, no problem.
public boolean sharedItems = false // (false) can only fuse material owned by neutral passive (default) or oneself. The code handling that is in TasItemFusion.
public boolean canProviderGetItem = true // (true) when the mainShopper's inventory is full, try to give the other matieral provider the item
public boolean canUndo = true // (true) There is an Undo Button which allows to Revert BuyActions done in this shopping. A shopping ends when the UI is closed, changing current shop counts as closed.
public boolean canDefuse = true // (true) There is a Defuse Button which allows to defuse FusionItems hold.
public string DefuseButtonIcon = "ReplaceableTextures\\CommandButtons\\BTNdemolish"
public string DefuseButtonIconDisabled = "ReplaceableTextures\\CommandButtonsDisabled\\DISBTNdemolish"
public boolean canSellItems = true // (true)
public real SellFactor = 0.75
public boolean SellUsesCostModifier = true
public string SellButtonIcon = "ReplaceableTextures\\CommandButtons\\BTNReturnGoods"
public string SellButtonIconDisabled = "ReplaceableTextures\\CommandButtonsDisabled\\DISBTNReturnGoods"

public string MainUserTexture = "ui\\widgets\\console\\human\\commandbutton\\human-multipleselection-border"
public string MainItemTexture = "ui\\widgets\\console\\human\\commandbutton\\human-multipleselection-border"

public real shopRange = 900 // the max distance between shop and Shoper, this can be overwritten by shopObject.Range.
public real updateTime = 0.4 // how many seconds pass before a new update is applied. update: search new shopers, validat current shopers and update UI.
// Titel-text in the reference Boxes
public string textUpgrades = "COLON_UPGRADE" //tries to localize on creation
public string textMats = "SCORESCREEN_TAB3"
public string textInventory = "INVENTORY"
public string textUser = "USER"
public string textCanNotBuyPrefix = "Can not buy: "
public string textCanNotBuySufix = "OUTOFSTOCKTOOLTIP"
public string textNoValidShopper = "No valid Shoper"
public string textUndo = "Undo: "
public string textUnBuyable = "xxxxxxx"
public string textDefuse = "Defuse:"
public string textSell = "Sell:"
public string textQuickLink = "ShortCuts:"
public string categoryModeTextAnd = "ui\\widgets\\battlenet\\bnet-mainmenu-friends-disabled"
public string categoryModeTextOr = "Or"
public string categoryModeIconOr = "ui\\widgets\\battlenet\\bnet-mainmenu-friends-up"
public string categoryModeIconAnd = "And"


public oskeytype quickLinkKey = OSKEY_LSHIFT // null will prevent the user from changing shortcuts.

// how many refButtons, refButtons have pages, if needed.
// A feature is disabled with a counter smaller than 1.
public integer refButtonCountMats = 4 // materialRefs.
public integer refButtonCountUp = 4 // possible upgrades of the current Selected
public integer refButtonCountInv = 6 // inventory items, this system allows an unitgroup to provide items, if you don't use that feature only upto 6 makes sense.
public integer refButtonCountUser = 6 // References to the shopping Units/material provider.
public integer refButtonCountQuickLink = 4 // User SelectAble Shortcuts
public real refButtonSize = 0.02
public real refButtonGap = 0.003
public real refButtonPageSize = 0.012
public boolean refButtonPageRotate = true //(true) swap to first page when going above last page, and swap to last page when going down first Page
public string refButtonPageUp = "ReplaceableTextures\\CommandButtons\\BTNReplay-SpeedUp"
public string refButtonPageDown = "ReplaceableTextures\\CommandButtons\\BTNReplay-SpeedDown"
public real refButtonBoxSizeY = 0.047

// (true) right clicking an refInventoryButton in the UI will sell the item
// (false) right clicking it will buy it again.
public boolean inventoryRightClickSell = true
public boolean inventoryShowMainOnly = true // (false) show all items currently useable

public boolean userButtonOrder = true // (true) Create an UnitTargetOrder Event enables right clicking Units in the world to swap main shoppers.

public real doubleClickTimeOut = 2.0 // amount of seconds a doppleclick inside the Buttonlist counts as Buying

// model displayed when buy request was started.
//public string spriteModel = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl" // in 1.31 the coins are black only.
//public string spriteModel = "Abilities\\Weapons\\RockBoltMissile\\RockBoltMissile.mdl"
//public string spriteModel = "Abilities\\Weapons\\BansheeMissile\\BansheeMissile.mdl"
//public string spriteModel = "Abilities\\Spells\\Other\\GeneralAuraTarget\\GeneralAuraTarget.mdl"
public string spriteModel = "war3mapImported\\BansheeMissile.mdx" //by abfal, (no sound).
public real spriteScale = 0.0006 // The scale has to fit the used model. if you use non-UI models use a low scale, 0.001 or below.
public integer spriteAnimationIndex = 1 // 1 = death animation

public integer buttonListRows = 5
// buttonListCols has a strong impact on the xSize of this UI. make sure that refButtons of one type fit into this.
public integer buttonListCols = 3

// this will not change the size of the Buttons, nor the space the text can take
// true = Show
// false = hide
public boolean buttonListShowGold = true
public boolean buttonListShowLumber = true
public boolean buyButtonShowGold = true
public boolean buyButtonShowLumber = true

// which button is used inside the ButtonList? Enable one block and disable the other one

public string buttonListButtonName = "TasButtonSmall"
public real buttonListButtonSizeX = 0.1
public real buttonListButtonSizeY = 0.0325

// "TasButtonGrid" are smaller, they don't show the names in the list
//public string buttonListButtonName = "TasButtonGrid"
//public real buttonListButtonSizeX = 0.064
//public real buttonListButtonSizeY = 0.0265

public real categoryButtonSize = 0.019
// -------
// Config End
Config is one thing but TasItemShop has not gotten any Data yet. Feeding TasItemShop with data is suggested to be done in the script file TasItemShopUserInit. Unlike in the Lua version it is independent you can just disable/remove it.
The Idea for TasItemShopUserInit is that you tell TasItemShop here what data you want to use for it. Data cotains categories, shop UnitTypes, buyAble items, Item-Categories, Item-Fusions and Haggle-Skills.

Could look like this:
JASS:
library TasItemShopUserInit initializer TasItemShopUserInit requires TasItemShop
// This script  is meant to be used by vjass user to write init data for TasItemShop

    private function ShopCostFunction_ngme takes nothing returns nothing
    endfunction
     // This runs right before the actually UI is created.
    // this is a good place to add items, categories, fusions shops etc.
    function TasItemShopUserInit takes nothing returns nothing
        local integer shopObject
        // this can all be done in GUI aswell, enable the next Line or remove all Text of this function if you only want to use GUI
        //if true then return end

        // define Categories: Icon, Text
        // the Categories are displayed in the order added.
        // it is a good idea to save the returned Value in a local to make the category setup later much easier to understand.
        // you can only have 31 categories
        local integer catDmg = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNSteelMelee", "COLON_DAMAGE")
        local integer catArmor = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNHumanArmorUpOne", "COLON_ARMOR")
        local integer catStr = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNGauntletsOfOgrePower", "STRENGTH")
        local integer catAgi = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNSlippersOfAgility", "AGILITY")
        local integer catInt = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNMantleOfIntelligence", "INTELLECT")
        local integer catLife = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNPeriapt", "Life")
        local integer catLifeReg = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNRegenerate", "LifeRegeneration")
        local integer catMana = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNPendantOfMana", "Mana")
        local integer catManaReg = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNSobiMask", "ManaRegeneration")
        local integer catOrb = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNOrbOfDarkness", "Orb")
        local integer catAura = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNLionHorn", "Aura")
        local integer catActive = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNStaffOfSilence", "Active")
        local integer catPower = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNControlMagic", "SpellPower")
        local integer catCooldown = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNHumanMissileUpOne", "Cooldown")
        local integer catAtkSpeed = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNHumanMissileUpOne", "Attackspeed")
        local integer catMress = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNRunedBracers", "Magic-Resistence")
        local integer catConsum = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNPotionGreenSmall", "ConsumAble")
        local integer catMoveSpeed = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNBootsOfSpeed", "COLON_MOVE_SPEED")
        local integer catCrit = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNCriticalStrike", "Crit")
        local integer catLifeSteal = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNVampiricAura", "Lifesteal")
        local integer catEvade = TasItemShopAddCategory("ReplaceableTextures\\CommandButtons\\BTNEvasion", "Evasion")
 
        call TasItemShopAdd5('rst1', 'bgst', 'rin1', 'ciri', 'belv')
        call TasItemShopAdd('rag1', catAgi)
        call TasItemShopAdd5('rlif', 'ajen', 'clfm', 'ward', 'kpin')
        call TasItemShopAdd5('lgdh', 'rde4', 'pmna', 'rhth', 'ssil')
        call TasItemShopAdd5('spsh', 'lhst', 'afac', 'sbch', 'brac')
        call TasItemShopAdd5('rwiz', 'evtl', 'penr', 'prvt', 'rde3')
        call TasItemShopAdd5('hval', 'hcun', 'mcou', 'cnob', 'ckng')
        call TasItemShopAdd5('rat6', 'rat9', 'ratf', 'bspd', 'gcel')
        call TasItemShopAdd5('rde2', 'clsd', 'dsum', 'stel', 'desc')

        call TasItemShopAdd5('modt', 'ofro', 'thdm', 'hlst', 'mnst')
        call TasItemShopAdd5('pghe', 'pgma', 'pnvu', 'pres', 'ankh')
        call TasItemShopAdd5('shas', 'stwp', 'ofir', 'oli2', 'odef')
        call TasItemShopAdd5('oven', 'oslo', 'ocor', 'shtm', 'I001')

        // setup custom shops
        // custom Shops are optional.
        // They can have a White or Blacklist of items they can(n't) sell and have a fixed cost modifier for Gold, Lumber aswell as a function for more dynamic things for Gold and Lumber.
        set shopObject = 'n000'
        // 'n000' can only sell this items (this items don't have to be in the pool of items)
        call TasItemShopAddShop5(shopObject, 'hlst', 'mnst', 'pghe', 'pgma', 'pnvu')
        call TasItemShopAddShop5(shopObject, 'pres', 'ankh', 'stwp', 'shas', 0)
        // enable WhiteListMode
        call TasItemShopSetMode(shopObject, true)
 
        // 'n001' can't sell this items (from the default pool of items)
        set shopObject = 'n001'
        call TasItemShopAddShop5(shopObject, 'hlst', 'mnst', 'pghe', 'pgma', 'pnvu')
        call TasItemShopAddShop5(shopObject, 'pres', 'ankh', 'stwp', 'shas', 0)
        // enable BlackListMode
        call TasItemShopSetMode(shopObject, false)
 
        // create an shopObject for 'ngme', has to pay 20% more than normal, beaware that this can be overwritten by GUI Example
        call TasItemShopCreateShop('ngme', false, 1.2, 1.2, function ShopCostFunction_ngme)
        //'I002' crown +100 was never added to the database but this shop can craft/sell it.
        set shopObject = 'n002'
        call TasItemShopAddShop5(shopObject, 'ckng', 'I001', 'I002', 'arsh', 0)
        call TasItemShopSetMode(shopObject, true)
 

        // Define skills/Buffs that change the costs in the shop
        // cursed Units have to pay +25%
        call TasItemShopAddHaggleSkill('Bcrs', 1.25, 1.25, 0, 0)

        // define Fusions
        // result created by 'xxx', 'xx' , 'x'+.
        // item can only be crafted by one way
        // can add any amount of material in the Lua version
        call TasItemFusionAdd2('bgst', 'rst1', 'rst1')
        call TasItemFusionAdd2('ciri', 'rin1', 'rin1')
        call TasItemFusionAdd2('belv', 'rag1', 'rag1')
        call TasItemFusionAdd2('hval', 'rag1', 'rst1')
        call TasItemFusionAdd2('hcun', 'rag1', 'rin1')
        call TasItemFusionAdd2('mcou', 'rst1', 'rin1')
        call TasItemFusionAdd2('ckng', 'cnob', 'cnob')
        call TasItemFusionAdd2('rat9', 'rat6', 'rat6')
        call TasItemFusionAdd2('ratf', 'rat9', 'rat9')
        call TasItemFusionAdd('rde4', 'rde3')
        call TasItemFusionAdd('rde3', 'rde2')
        call TasItemFusionAdd('rhth', 'prvt')
        call TasItemFusionAdd('pmna', 'penr')
        call TasItemFusionAdd2('arsh', 'rde3', 'rde2')

        call TasItemFusionAdd('lhst', 'sfog')

        // crown of Kings + 50
        call TasItemFusionAdd4('I001', 'ckng', 'ckng', 'ckng', 'ckng')
        call TasItemFusionAdd4('I001', 'ckng', 'ckng', 'bgst', 'bgst')
        call TasItemFusionAdd6('I001', 'ciri', 'ciri', 'belv', 'belv', 'cnob', 'cnob')
        // crown of Kings + 100, this is a joke you can not craft it because it was not added to buyAble Items
        call TasItemFusionAdd2('I002', 'I001', 'I001')

        // define item Categories
        // uses the locals from earlier.
        // An item can have multiple categories just add them together like this: catStr + catAgi + catInt
 
        call TasItemSetCategory('rst1', catStr)
        call TasItemSetCategory('bgst', catStr)
        call TasItemSetCategory('rin1', catInt)
        call TasItemSetCategory('ciri', catInt)
        call TasItemSetCategory('rag1', catAgi)
        call TasItemSetCategory('belv', catAgi)

        call TasItemSetCategory('I001', catStr + catAgi + catInt)

        call TasItemSetCategory('ckng', catStr + catAgi + catInt)
        call TasItemSetCategory('mcou', catStr + catInt)
        call TasItemSetCategory('hval', catStr + catAgi)
        call TasItemSetCategory('hcun', catAgi + catInt)
        call TasItemSetCategory('cnob', catStr + catAgi + catInt)

        call TasItemSetCategory('rat9', catDmg)
        call TasItemSetCategory('rat6', catDmg)
        call TasItemSetCategory('ratf', catDmg)
 
        call TasItemSetCategory('rlif', catLifeReg)

        call TasItemSetCategory('ajen', catAura + catAtkSpeed + catMoveSpeed)
        call TasItemSetCategory('clfm', catAura + catDmg)
        call TasItemSetCategory('ward', catAura + catDmg)
        call TasItemSetCategory('kpin', catAura + catManaReg)
        call TasItemSetCategory('lgdh', catAura + catMoveSpeed + catLifeReg)
        call TasItemSetCategory('rde4', catArmor)
        call TasItemSetCategory('pmna', catMana)
        call TasItemSetCategory('rhth', catLife)
        call TasItemSetCategory('ssil', catActive)
        call TasItemSetCategory('lhst', catAura + catArmor)
        call TasItemSetCategory('afac', catAura + catDmg)
        call TasItemSetCategory('sbch', catAura + catDmg)
        call TasItemSetCategory('sbch', catAura + catLifeSteal)
        call TasItemSetCategory('brac', catMress)
        call TasItemSetCategory('spsh', catMress + catActive)
        call TasItemSetCategory('rwiz', catManaReg)
        call TasItemSetCategory('crys', catActive)
        call TasItemSetCategory('evtl', catEvade)
        call TasItemSetCategory('penr', catMana)
        call TasItemSetCategory('prvt', catLife)
        call TasItemSetCategory('rde3', catArmor)
        call TasItemSetCategory('bspd', catMoveSpeed)
        call TasItemSetCategory('gcel', catAtkSpeed)
        call TasItemSetCategory('rde2', catArmor)
        call TasItemSetCategory('clsd', catActive)
        call TasItemSetCategory('dsum', catActive + catMoveSpeed)
        call TasItemSetCategory('stel', catActive + catMoveSpeed)
        call TasItemSetCategory('desc', catActive + catMoveSpeed)
        call TasItemSetCategory('ofro', catDmg + catOrb)
        call TasItemSetCategory('modt', catLifeSteal + catOrb)
        call TasItemSetCategory('thdm', catActive)
        call TasItemSetCategory('hlst', catActive + catConsum + catLifeReg)
        call TasItemSetCategory('mnst', catActive + catConsum + catManaReg)
        call TasItemSetCategory('pghe', catActive + catConsum)
        call TasItemSetCategory('pgma', catActive + catConsum)
        call TasItemSetCategory('pnvu', catActive + catConsum)
        call TasItemSetCategory('pres', catActive + catConsum)
        call TasItemSetCategory('ankh', catConsum)
        call TasItemSetCategory('stwp', catActive + catConsum + catMoveSpeed)
        call TasItemSetCategory('shas', catActive + catConsum + catMoveSpeed)
        call TasItemSetCategory('ofir', catOrb + catDmg)
        call TasItemSetCategory('oli2', catOrb + catDmg)
        call TasItemSetCategory('odef', catOrb + catDmg)
        call TasItemSetCategory('oven', catOrb + catDmg)
        call TasItemSetCategory('oslo', catOrb + catDmg)
        call TasItemSetCategory('ocor', catOrb + catDmg)
        call TasItemSetCategory('shtm', catActive)
    endfunction
endlibrary



ChangeLog:

v4m (jass) v4g (Lua) Fixed a desync problem with ItemCodes aded to QuickLink/ShortCuts
v4g) (jass) Fixed a bug removing wrongly Items. Triggered by Sell -> Undo -> Buy.
v4f) fixed: undo was hidden, when any player closed the shopUI
v4e) (jass) Fixed The req-System TasItemCost did not clear the items created to measure costs
v4d) (jass) Fixed a bug that the wrong inventory item was selected.
V4c)
The ShortCutBox will glow, when the user holds the key to add/Remove ShortCut-Entries.​
(vjass) Fixed a bug with RefBox Placing.​
V4b) Fixed: After remoing the first ShortCut of Page 2, one got an empty Box without pages.

V4a)
(lua) fixed: when an item in inventory was clicked, it was not selected therefore no sell/Defuse was shown​
The selected Inventory Item has now a indicator (used for Sell/Defuse).​
fixed: when no refButton was used the BuyButton was inside the ButtonList​
fixed: Sell/Defuse beeing hidden by other players Actions.​
Doesn't create any OskeyEvents anymore, if no quickLinkKey is set.​
Can now Clear the QuickLink data for a player.​
Increased the distance between Text and Icon in the Buy button (new TasButtonList.fdf)​
QuickLink has now a higher priority than Inventory and User.​
Mats has now a higher priority than Upgrades.​
With Default setup Mat, Upgrades and QuickLink fit into the top row (ButtonList 3 Cols, RefBoxes have 4 Buttons).​
QuickLink can now be set by GUI.​
Fixed: TooltipsBoxed were sometimes not fitting the ToolTip Text when leaving the 4:3 Screen.​
More Buttons will not keep focus anymore.​
Defuse and Sell don't hide anymore, instead they become unclickable. Defuse also has now an own fixed Icon. (new TasItemShop.fdf)​
Defuse and Sell Tooltips are reposed to not leave the Screen.​
Can now Set the TooltipTextSizeX in the code config.​
Added TooltipTextSizeXBix which is used for Tooltips that have x chars or more​
V4)
Buttons will not keep focus anymore.​
The ButtonList can be scroll while any non interactive part of TasItemShop is Hovered.​
(vjass) fixed a bug with Upgrade Page, using wrongly offset of material for displaying.​
(vjass) fixed material provided (again)​
fixed an error when canSellItems or canDefuse were disabled​
Can now Tooggle between Or/And logic for multiple selected categories.​
Displaying Fusions costs is now less taxing.​
Added a Config to (dis)(en)able the TargetUnitEvent, to select MainShoppers with right click.​
Outsourced the parentselection for the UI Parent into a custom Function GetParent.​
Added an Highlighter for currently selected in the ButtonList.​
Added user Customizeable ShortCuts.​
V3c) (vjass) fixed a bug that did not mark mats provided in some cirumstances.
V3b)
(Lua) fixed a bug when not all ref Buttons had data.​
(vjass) fixed a bug with disabled canDefuse.​
V3a) Fixed the GUI Demo not evoking the Shop init.
V3)
Fixed a bug in the vjass version, it took away materials not needed for the bought item.​
(could produce desyncs and wierd results)​

Added a ESC-Event Trigger which closes the Shop.​
Splited GUI demo Triggers by functionality.​
Added another trigger which executes the GUI triggers in a sane order.​
Added config booleans to show/hide Gold/Lumber in the buyButton and for Buttons in the ButtonList​
Added a config boolean to let rightlicks onto a refInventoryButton sell it or Buy another one​

Added a config boolean to show only the items of the main Unit.​
Will still use material from other users.​

V2a (vjass only)
Reseted some counters fitting the Save&Load reset.​
V2
Improved Defuse​
Can now Sell Items to the shop​
Can now setup Gaps between Cols and Rows in the ButtonList​
Displays Current position when hovering the Slider​
Added a vjass version.​
Fixed a bug with Undo: Droped Items were not removed.​


Credits:

abfal (Custom Banshee Missile by)​
ScrewTheTrees(Fred) & Niklas (reposing on window change)​
Bribe​
BPower​
SpasMaster (feedback)​
chopinski (feedback)​
pick-a-chew (feedback)​


Previews
Contents

TasItemshopV4h (Map)

TasItemshopV4m jass (Map)

Level 2
Joined
Jun 19, 2021
Messages
6
First you have to make sure you are using the right version. If your map is in jass mode you copy the jass version. If your map is in Lua than you use the other one. Your can see the code mode of your map in Scenario - Map Options - bottom part of the PoPup Window.
The default code mode is jass.
If your map is in jass make sure that you enabled vjass: trigger editor - jasshelper - enable vjass. That requires to enable jasshelper.

The imports do not produce any compiler errors. Without the imported Files the Custom UI will not display and won't work in the game.
Export all and import all are fine when done in the current Version of Warcraft 3.
My man! Thanks
 
Level 12
Joined
May 16, 2020
Messages
660
Thanks for the update Tasyen. Isn't the above also a bug?

I took some more pics, to hopefully explain the problem better:

1. Here you can see the Shadow Hunter being just outside of the top-right shop's range (= no shop arrow):

View attachment 381818

2. However, if I move the hero to the center of the map, where NO shop is, he again gets the Shop arrow:

View attachment 381819

3. And here just to show that really no other shop is nearby from which the Hero can buy from:

View attachment 381820


I get the same behaviour in my (bigger) map. The heroes at the very center of the map always get the shop arrow, even though there is no shop for miles nearby.

Hi Tasyen, were you able to confirm the thing with the arrow?

Since it's happening in the middle of the map, which is usually when a "point" is not correctly recognized, I assume somewhere in the system a point is not correct.
 
Wierd, I encountered it now.
Now that I think about it, the reason could be the hidden Cost detector Shop, created in TasItemCost. The position seems fitting (180/-340) => mid of test map.
That hidden shop is required to automatically detect costs of items, might change its position or give it a special select hero version without arrow.
 
Fantastic UI System that definitely deserves a high rating, as expected of the custom UI master himself.

There isn't much for me to tackle on here, aside from the dependencies having to use module initialization for the
vJASS equivalent of these systems themselves.

In the vJASS version, the TasItemShopAddCategory function will always add more instances, even if the explicit
check for the maximum number of categories is made.

In the IsRightClick library, even if the optional dependency Frameloader is not required, the library will only compile
when said library exists. (There is an extra line that renders the optional tag effectively useless.)

Status:
Awaiting Update

 
Jass Updated to 4h)
IsRightClick compiles now without FrameLoader.
function TasItemShopAddCategory, placed the array writting into an else path only happening when the limit is not exceeded yet.

aside from the dependencies having to use module initialization for the
vJASS equivalent of these systems themselves.
Never used that. The vjass manual speaks about struct which my code does not contain.
 
aside from the dependencies having to use module initialization for the
vJASS equivalent of these systems themselves.
Never used that. The vjass manual speaks about struct which my code does not contain.

This was what I was referring to (module initialization):

JASS:
private module Init
    private static method onInit takes nothing returns nothing
        // Initialization process here..
    endmethod
endmodule
// Dummy struct that's only used for initialization purposes
private struct S extends array
    implement Init
endstruct

With module initialization, it is guaranteed that the initialization function within the library
will be processed first, by order of requirements. The initialization function cannot be
reliably processed first by any other type of initialization, including library initialization
(counterintuitive as it may sound).
 
Level 12
Joined
May 16, 2020
Messages
660
Wierd, I encountered it now.
Now that I think about it, the reason could be the hidden Cost detector Shop, created in TasItemCost. The position seems fitting (180/-340) => mid of test map.
That hidden shop is required to automatically detect costs of items, might change its position or give it a special select hero version without arrow.

Hey Tasyen, just writing in case this problem was forgotten: In the new version the arrow problem still appears. Cheers!
 
Sry, I might have worded that wrong. You have to change the position/select skill/unit inside your map in the Req TasItemCost.
on default it creates a hidden markplace ('nmrk') unit owned by neutral extra, If you don't use this unitType in your map I suggest to change the Select Hero ('Aneu') skill in side object Editor to Shared Shop allies ('Aall') for marktplace. That unit skill change would require 0 code change.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Worked - thank you!

I do use the Marketplace Unit Type as my default shop model. However, I changed the default ability "Select Hero" to "Shop Sharing, Allied Bldg.", and I don't see any negative impact (the "correct" shop in the corner of my map still provides an arrow and I can buy from this store as usual). Why did you write "if you don't use this unitType?
 
Recently I tried to add TasItemshop to some AoS map. Setting the categories were quite tiresome, so I though one could autoDetect some of the default categories TasItemshop uses.

it can auto detect Str/AGI/INT/Armor/Mana/Life/Regeneration/MoveSpeed/Aura/Active/Consumeable/MagicRess

It does this by running the game: creating many units in pairs one with an item and another without then comparing their values. This detection generates code when it runs which you then feed back into the map's code, after that you remove the detector from your map (should only be done in single player).
There is a vjass and Lua version.
Because of jass limits, the vjass version can not allways handle all registered Items at once (if there are many), therefore it can also only take a subset, generate that, take the part and repeat with a different subset until you got all.
When you don't want that STR/AGI/INT also count for Armor/Mana/Life/Regeneration/MoveSpeed you should set their effect in game play constants to 0 for the generation.

Like in FdfCreatorMap the generated text is written into an EditBox which content you copy paste.
Select the Editbox
Press Pos1
Press shift+ End
ctrl + c
Paste it into an editor, afterwards into your map.
The Lua version generates jass code, which can be converted into Lua with 2 search & ReplaceAll
call ->
// -> --

The map does not contain TasItemShop but requires a working version in the same Map to work.
Created with Warcraft 3 V1.31
 

Attachments

  • DetectItemEffect - TasShop - V3.w3x
    32.4 KB · Views: 25
Updated vjass version to v4k to fix a bug related to TasButtonList 10b (jass version). It's a small fix one only needs to change a function inside the req TasButtonList (TIS) (CC).
JASS:
function TasButtonListAddDataEx takes integer listIndex, integer data, integer playerIndex returns nothing
    local integer listHandle = GetHandleId(LoadLocationHandle(Hash, GetHandleId(TasButtonListDataList[listIndex]), playerIndex))
    local integer index = LoadInteger(Hash, listHandle, 0) + 1
    local integer dataFilteredCount
    call SaveInteger(Hash, listHandle, 0, index)
    call SaveInteger(Hash, listHandle, index, data)
    if GetLocalPlayer() == Player(playerIndex) then
        // add to current filtered for local player only
        set listHandle = GetHandleId(TasButtonListDataListFiltered[listIndex])
        set dataFilteredCount = LoadInteger(Hash, listHandle, 0) + 1
        call SaveInteger(Hash, listHandle, 0, dataFilteredCount)
        call SaveInteger(Hash, listHandle, dataFilteredCount, index)
        call BlzFrameSetMinMaxValue(TasButtonListSlider[listIndex], TasButtonListButtonCount[listIndex], dataFilteredCount)
    endif
endfunction
 
Level 13
Joined
Jul 15, 2007
Messages
763
I can't believe I've slept on this resource for so long, it's pretty incredible. Fairly easy to implement and easy to modify if you know a bit of JASS.

Whilst learning how to use it, i noticed that items that are on the shortcut list that aren't also added to any shop via "call TasItemShopAdd5" can cause desyncs. It may be obvious but if one ever removes all "TasItemShopAdd5" for an item, but accidentally leaves behind an "TasItemShopShortCuts", they might run into issues. Maybe a failsafe could exist for this?

Regardless, an exceptional resource!
 
I can't believe I've slept on this resource for so long, it's pretty incredible. Fairly easy to implement and easy to modify if you know a bit of JASS.

Whilst learning how to use it, i noticed that items that are on the shortcut list that aren't also added to any shop via "call TasItemShopAdd5" can cause desyncs. It may be obvious but if one ever removes all "TasItemShopAdd5" for an item, but accidentally leaves behind an "TasItemShopShortCuts", they might run into issues. Maybe a failsafe could exist for this?

Regardless, an exceptional resource!
Thanks, for your feedback&report.

Updated to 4m (jass) /4g (Lua)
Fixed a desync problem with ItemCodes added to QuickLink/ShortCuts which never were added to TasItemShop before.

To update the system in your map you only need to update the TasItemShop script.
The change done was not big, in case you want to keep it like it is. But want the fix you change 3 Lines in the Script TasItemShop:
Update Version at the top

Lua
search the function TasItemShopUI.SetQuickLink(player, itemCode)
Add the code in the box below, as the first Lines of the function
Lua:
-- request to calc the itemCode costs, this is done in case it was not added to the shop
TasItemCaclCost(itemCode)

jass
search the function public function SetQuickLink
Add the code in the box below, right below the line local integer loopA
JASS:
// request to calc the itemCode costs, this is done in case it was not added to the shop
call TasItemCaclCost(itemCode)
 
there are functions to add items to the list. They are mentioned in the description of the system on this Site. Or at the top of TasItemShop. I guess you use the vjass version.
JASS:
// TasItemShopAdd(itemCode, category)
        // adds itemCode to the common Buyable Item pool and sets the category
// TasItemShopAddShop(unitCode, itemCode)
        // adds itemcode for that specific shop
When you don't need during match changes just use the suggested UserInit or the GUI map init thing.


I did not include a feature to remove items. Theoretically it is possible. When you use a BlackList shop you could change the content of public integer array BUY_ABLE_ITEMS and the value of public integer BUY_ABLE_ITEMS_Count = 0 That would remove the item from all none WhiteList shops.

For WhiteList shops you need to understand Table by bribe.
This is how WhiteListe items are stored:
public HashTable ShopsItems stores the shop items for WhiteList shops its the only stuff one can buy.
ShopsItems[unitCode][0] is the total amount of itemCodes stored in that for that shop UnitCode
ShopsItems[unitCode][x] = itemCode are the itemCodes.
 
Top