• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Item Shop System

This bundle is marked as high quality. It exceeds standards and is highly desirable.
shop-system-png.429914


shop-gif.429915

intro-png.429911

Hello Hivers, this is my version of an Item Shop System. Its customizable and intuitive. It requires at least version 1.32 of the game. Big thanks to @Tasyen for helping me with a few problems during the development and for providing the FDF creation tips. I highly recommend checking his version of a Shop system as well. This system is multiplayer safe and quite efficient. If you find any bugs, please report them here in this thread.

importing-png.429909

Importing Shop System is very simple, just copy the Shop and Components scripts over to you map and import the Assets as follows:

imports-png.429910


functionalities-png.429908
detailing-png.429902

This Shop System is capable of detailing the build path of an item with up to 5 components. It can show what other items the current selected item is used in as well.

filtering-png.429907

You can filter item view by category (up to 13) or by name. It is also possible to switch the filtering logic between AND & OR.

tagging-png.429917

You can tag item as favorites by holding the TAB key (configurable) and clicking an item (up to 13). To untag an item just hold TAB and click in the item inside the Favorites list.

buy-sell-png.429898

Youi can Double/Right click an item in the list, detail or favorites view to buy it (Obs: Right click is currently not working because blizzard broke the MOUSE_UP event). To sell an item just Double/Right click an item in your invetory.

inventory-png.429913

Unit inventory is displayer under the unit portrait.

dismantle-undo-png.429904

You can dismantle an item and undo a transaction. The undo will only work as long as the shop is no closed and dismantle will only work as long as the unit has enough inventory space to hold the component items.


api-png.429919


vJASS:
function CreateShop takes integer id, real aoe, real returnRate returns nothing
    id => Unit id raw code
    aoe => The shop interaction range
    returnRate => The tax imposed on selling items

function ShopAddCategory takes integer id, string icon, string description returns integer
    id => Unit id raw code
    icon => The new category icon
    description => The new category description
    returns the value of the new category for this shop

function ShopAddItem takes integer id, integer itemId, integer categories returns nothing
    id => Unit id raw code
    itemId => The item id raw code
    categories => The categories at which the item belongs in this shop

function ItemAddComponents takes integer whichItem, integer a, integer b, integer c, integer d, integer e returns nothing
    whichItem => The main item id raw code
    a => First component raw code (use 0 for none)
    b => Second component raw code (use 0 for none)
    c => Third component raw code (use 0 for none)
    d => Fourth component raw code (use 0 for none)
    e => Fifth component raw code (use 0 for none)

function UnitHasItemOfType takes unit u, integer id returns boolean
    u => The unit
    id => The item id raw code to be checked
    returns true if the unit has an item of the type id

function UnitCountItemOfType takes unit u, integer id returns integer
    u => The unit
    id => The item id raw code to be checked
    returns the amount of items of the type id a unit has

function ShopFilter takes unit u, player owner, unit shop returns boolean
    u => The unit
    owner => The owning player
    shop => the shop unit
    returns true if the unit fits the filter for shop enumaration

example-png.429905

vJASS:
scope Example
    struct Items
        static constant integer BOOTS_OF_SPEED      = 'I00A'
        static constant integer LIFE_CRYSTAL        = 'I00B'
        static constant integer HOMECOMING_STONE    = 'I00D'
        static constant integer GLOVES_OF_HASTE     = 'I00C'
        static constant integer BOOTS_OF_THE_BRAVES = 'I009'

        private static method configure takes nothing returns nothing
            call ItemAddComponents(BOOTS_OF_THE_BRAVES, BOOTS_OF_SPEED, HOMECOMING_STONE, GLOVES_OF_HASTE, LIFE_CRYSTAL, 0)
        endmethod

        static method create takes integer shop, real aoe, real tax returns thistype
            local integer damage
            local integer armor
            local integer strength
            local integer agility
            local integer intelligence
            local integer health
            local integer mana
            local integer attackSpeed
            local integer movement
            local integer spellPower
            local integer cooldown
            local integer regeneration
            local integer consumable

            call CreateShop(shop, aoe, tax)

            set damage = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNSteelMelee", "Damage")
            set armor = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNHumanArmorUpOne", "Armor")
            set strength = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNGauntletsOfOgrePower", "Strength")
            set agility = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNSlippersOfAgility", "Agility")
            set intelligence = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNMantleOfIntelligence", "Intelligence")
            set health = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNFireCrystalElement", "Health")
            set mana = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNItem_Gem_Aquamarine.blp", "Mana")
            set attackSpeed = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNGlove.blp", "Attack Speed")
            set movement = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNBootsOfSpeed", "Movement")
            set spellPower = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNControlMagic", "Spell Power")
            set cooldown = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNSpin.blp", "Cooldown")
            set regeneration = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNTowerRegen.blp", "Regeneration")
            set consumable = ShopAddCategory(shop, "ReplaceableTextures\\CommandButtons\\BTNPotionGreenSmall", "Consumable")

            call ShopAddItem(shop, BOOTS_OF_SPEED, movement)
            call ShopAddItem(shop, LIFE_CRYSTAL, health)
            call ShopAddItem(shop, HOMECOMING_STONE, movement)
            call ShopAddItem(shop, GLOVES_OF_HASTE, attackSpeed)
            call ShopAddItem(shop, BOOTS_OF_THE_BRAVES, movement + health + attackSpeed + cooldown)

            return 0
        endmethod

        private static method onInit takes nothing returns nothing
            call configure()
            call create('ngme', 600, 0.5)
        endmethod
    endstruct
endscope

credits-png.429900

  • Tasyen
  • Bribe
  • Magtheridon
  • Hate

04/07/2023
  • Release
  • LUA version in the making
Contents

Shop (Map)

Reviews
Wrda
You can set a all points of a frame to another frame's points by using BlzFrameSetAllPoints, it looks like you're trying to do this in the play method of the components trigger, and in other places. Create method of Item struct has a potential...
Level 8
Joined
May 19, 2016
Messages
146
Wow incredibly useful and the amout of Items you made for the System for showcase. awesome.
The handling is well done and i like the Big Shop Window.

You should add the ''stack count'' in the Hero's inventory though if the Shop Window is opened.
I clicked the Healthpotions and didnt knew how many i got until you close the Shop to look and reopen it to buy more.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
That's awesome, good job! I've seen some pretty amazing item systems using custom UI but they've always lacked in aesthetic appeal, which this appears to have a lot of.

One minor thing that jumped out to me though was the Tooltip background is too transparent and makes it difficult to read the text when highlighting an Item. I'm basing this off of the above gif, so apologies if this is no longer the case.
 

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,870
You can set a all points of a frame to another frame's points by using BlzFrameSetAllPoints, it looks like you're trying to do this in the play method of the components trigger, and in other places.

Create method of Item struct has a potential reference item leak when returning 0.
To be honest, I think you should swap "clear favourites" button with the "close" one, looks more intuitive.

There's room for minor optimizations, such as in show method of Inventory struct, specifically GetLocalPlayer and GetOwningPlayer.

Seems a bit tricky to interact with the first inventory slot of the unit (to sell the item) if it's at the far left position, collides with a minimap button.

Overall, this is a great system that expands completely the concept of shops in Warcraft 3. Perhaps you would like the icons of shift left and right to be in accordance to their direction? Up and down looks a bit confusing.
Brilliant.

Approved
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
I always get a crash to desktop (CTD) when saving and loading this save. I know I need save and load function. I read this tutorial of Tasyen: UI: Save&Load Frames but this Shop system too hard for me to modifier.
Don't you generate the entire shop using a single function call - and if not, couldn't you just wrap it all into one function? Because if I understand correctly, all you need to do is create your shop after a 0s delay when the game is loaded, as per the instructions in that tutorial you linked.

I simplified the tutorial code to make it even easier for you:
vJASS:
library FrameLoader initializer init_function
    private function timerAction takes nothing returns nothing
        // THIS IS THE ONLY THING YOU NEED TO EDIT:
        call CreateMyShop()
        call DestroyTimer(GetExpiredTimer())
    endfunction

    private function eventAction takes nothing returns nothing
        local timer t = CreateTimer()
        call TimerStart(t, 0, false, function timerAction) // This acts as a 1 frame delay
        set t = null
    endfunction

    private function init_function takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterGameEvent(t, EVENT_GAME_LOADED)
        call TriggerAddAction(t, function eventAction)
        set t = null
    endfunction
endlibrary
You would replace call CreateMyShop() with a function you've created that contains ALL of your Shop creation code.
 
Last edited:
Level 2
Joined
Dec 30, 2021
Messages
6
Don't you generate the entire shop using a single function call - and if not, couldn't you just wrap it all into one function? Because if I understand correctly, all you need to do is create your shop after a 0s delay when the game is loaded, as per the instructions in that tutorial you linked.

I simplified the tutorial code to make it even easier for you:
vJASS:
library FrameLoader initializer init_function
    private function timerAction takes nothing returns nothing
        // THIS IS THE ONLY THING YOU NEED TO EDIT:
        call CreateMyShop()
        call DestroyTimer(GetExpiredTimer())
    endfunction

    private function eventAction takes nothing returns nothing
        local timer t = CreateTimer()
        call TimerStart(t, 0, false, function timerAction) // This acts as a 1 frame delay
        set t = null
    endfunction

    private function init_function takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterGameEvent(t, EVENT_GAME_LOADED)
        call TriggerAddAction(t, function eventAction)
        set t = null
    endfunction
endlibrary
You would replace call CreateMyShop() with a function you've created that contains ALL of your Shop creation code.
Thanks you so much.
 
Top