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

[Solved] Bag System & A unit acquires an item event

Level 2
Joined
Mar 4, 2012
Messages
8
Hi guys,
I'm using this system Bag System and Advanced Item Handling System in my map to have multiple bags and inventory slots for my heroes, it's great and works like a charm but I ran into a problem. When switching from one bag to another, it seems that the system re-acquires all the items the bag contains, which isn't a problem for me in the first place, but when using a trigger with the event "A unit acquires an item", it can easily be abused.

Here is a trigger I have for one of my quests, the player needs to collect 5 venom samples from spiders:
  • Dangerous Venom quest update
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Triggering unit) Equal to Player
      • (Item-type of (Item being manipulated)) Equal to Venom Sample
    • Actions
      • Set VariableSet VenomSampleCount = (VenomSampleCount + 1)
      • Game - Display to Player Group - Player 1 (Red) for 2.00 seconds the text: (|cffffcc00SIDE QUEST PROGRESS:|r + (Venom Sample collected: + ((String(VenomSampleCount)) + /5)))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • VenomSampleCount Equal to 5
        • Then - Actions
          • Quest - Mark Quest_DangerousVenom as Completed
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • Do nothing
Assuming the player has collected only one sample, when the player switches bags, it adds another sample to the integer (because the system re-acquires the same sample previously looted), so the player can abuse the system by switching bags repeatedly to get the necessary quest item count. How can I prevent this?

Thanks for the help!
 
Last edited:
Level 20
Joined
Aug 29, 2012
Messages
827
Maybe you can fiddle with those functions?

  • Test
    • Events
    • Conditions
      • (Owner of (Item being manipulated)) Not equal to Player 1 (Red)
    • Actions
      • Item - Change ownership of (Item being manipulated) to Player 1 (Red) and Retain color
In this case you could use "item owner" as a way to say "this item has been picked by the player"
 
Level 2
Joined
Mar 4, 2012
Messages
8
Maybe you can fiddle with those functions?

  • Test
    • Events
    • Conditions
      • (Owner of (Item being manipulated)) Not equal to Player 1 (Red)
    • Actions
      • Item - Change ownership of (Item being manipulated) to Player 1 (Red) and Retain color
In this case you could use "item owner" as a way to say "this item has been picked by the player"

I tried but no luck, I also tried working with custom values but didn't work either.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,550
Hi guys,
I'm using this system Bag System and Advanced Item Handling System in my map to have multiple bags and inventory slots for my heroes, it's great and works like a charm but I ran into a problem. When switching from one bag to another, it seems that the system re-acquires all the items the bag contains, which isn't a problem for me in the first place, but when using a trigger with the event "A unit acquires an item", it can easily be abused.

Here is a trigger I have for one of my quests, the player needs to collect 5 venom samples from spiders:
  • Dangerous Venom quest update
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • (Triggering unit) Equal to Player
      • (Item-type of (Item being manipulated)) Equal to Venom Sample
    • Actions
      • Set VariableSet VenomSampleCount = (VenomSampleCount + 1)
      • Game - Display to Player Group - Player 1 (Red) for 2.00 seconds the text: (|cffffcc00SIDE QUEST PROGRESS:|r + (Venom Sample collected: + ((String(VenomSampleCount)) + /5)))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • VenomSampleCount Equal to 5
        • Then - Actions
          • Quest - Mark Quest_DangerousVenom as Completed
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • Do nothing
Assuming the player has collected only one sample, when the player switches bags, it adds another sample to the integer (because the system re-acquires the same sample previously looted), so the player can abuse the system by switching bags repeatedly to get the necessary quest item count. How can I prevent this?

Thanks for the help!
And what's currently stopping the user from just dropping and picking up the Venom Sample again? It sounds like your issue is the design of your item-acquiring triggers and unrelated to the system.

There's an Event for detecting when you Lose an item - allowing you to undo quest progress. There's always methods for making Item's undroppable, marking them in some way to "filter them out" of future pick-ups, etc...
 
Level 17
Joined
Apr 13, 2008
Messages
1,597
That looks like some outdated, no longer supported stuff.

This should exit a prototype phase eventually, hopefully in November:

 
Level 2
Joined
Mar 4, 2012
Messages
8
And what's currently stopping the user from just dropping and picking up the Venom Sample again? It sounds like your issue is the design of your item-acquiring triggers and unrelated to the system.

There's an Event for detecting when you Lose an item - allowing you to undo quest progress. There's always methods for making Item's undroppable, marking them in some way to "filter them out" of future pick-ups, etc...
The item is flagged as undroppable in the Object Editor, so users can't drop it or even move it in the inventory.
I suppose this is not the issue. I mean it can't do some conflicts or anything, right?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,550
The item is flagged as undroppable in the Object Editor, so users can't drop it or even move it in the inventory.
I suppose this is not the issue. I mean it can't do some conflicts or anything, right?
I was under the impression that the trigger for dropping the item would fail if it was Undroppable - But that sounds like it's not the case. Edit: The system is removing/creating new Items which is why Undroppable is irrelevant, so you'll have to modify the system or see if it offers it's own solution.

Alternatively, you can use a system that is more modern and likely better:
Note: TasInventoryEx destroys & recreates Items to drop/move them. Hence many trigger item changes are gone when using TasInventoryEx. HOWEVER, it retains the Custom Value of the Item so you could rely on that - assuming that your Item Indexer doesn't recycle the Custom Value.


Edit #2:
I attached a map with a rather basic implementation of that Bag system which takes advantage of some more modern features like automated item stacking and custom ui frames. It works for a single Hero per Player and requires that you enable this Gameplay Constant for stacking Item Charges automatically:
1699986207317.png

If you want to hide the custom UI for the Page buttons and Page text then you can call either of these functions for a Player:
vJASS:
function SIM_Hide_UI takes player p returns nothing
function SIM_Show_UI takes player p returns nothing
It's easy to do in the standard Trigger Editor as well:
  • Set Variable TempPlayer = (Some player)
  • Custom script: call SIM_Hide_UI(udg_TempPlayer)
  • Custom script: call SIM_Show_UI(udg_TempPlayer)
You can define the maximum number of pages at the very top of the code:
vJASS:
    globals
        // DEFINE THE MAX NUMBER OF PAGES
        private integer MAX_PAGES = 5
It also implements an extremely niche Item Indexer which indexes each item that has been acquired by a Hero. If this acquisition Event hasn't happened yet then the item's Custom Value will remain at 0. The system also NEVER destroys an Item, which was the main appeal of making this, and should make your life a lot easier and allow you to take advantage of item Custom Value to track item-specific data throughout the game. Just remember that an item hasn't been indexed until a Hero has picked it up! (I could probably change this, I was being lazy and this made the system work easily).

Edit #3: I forgot to attach the map... (whoops)
 

Attachments

  • Simple Item Manager 1.w3m
    26.7 KB · Views: 5
Last edited:
Level 2
Joined
Mar 4, 2012
Messages
8
I was under the impression that the trigger for dropping the item would fail if it was Undroppable - But that sounds like it's not the case. Edit: The system is removing/creating new Items which is why Undroppable is irrelevant, so you'll have to modify the system or see if it offers it's own solution.

Alternatively, you can use a system that is more modern and likely better:
Note: TasInventoryEx destroys & recreates Items to drop/move them. Hence many trigger item changes are gone when using TasInventoryEx. HOWEVER, it retains the Custom Value of the Item so you could rely on that - assuming that your Item Indexer doesn't recycle the Custom Value.


Edit #2:
I attached a map with a rather basic implementation of that Bag system which takes advantage of some more modern features like automated item stacking and custom ui frames. It works for a single Hero per Player and requires that you enable this Gameplay Constant for stacking Item Charges automatically:
View attachment 453889
If you want to hide the custom UI for the Page buttons and Page text then you can call either of these functions for a Player:
vJASS:
function SIM_Hide_UI takes player p returns nothing
function SIM_Show_UI takes player p returns nothing
It's easy to do in the standard Trigger Editor as well:
  • Set Variable TempPlayer = (Some player)
  • Custom script: call SIM_Hide_UI(udg_TempPlayer)
  • Custom script: call SIM_Show_UI(udg_TempPlayer)
You can define the maximum number of pages at the very top of the code:
vJASS:
    globals
        // DEFINE THE MAX NUMBER OF PAGES
        private integer MAX_PAGES = 5
It also implements an extremely niche Item Indexer which indexes each item that has been acquired by a Hero. If this acquisition Event hasn't happened yet then the item's Custom Value will remain at 0. The system also NEVER destroys an Item, which was the main appeal of making this, which should make your life a lot easier and allow you to take advantage of item Custom Value to track item-specific data throughout the game. Just remember that an item hasn't been indexed until a Hero has picked it up! (I could probably change this, I was being lazy and this made the system work easily).

Edit #3: I forgot to attach the map... (whoops)
Thanks a lot for your system, it's great and simple, exactly what I wanted in the first place. I've added a small trigger to hide the UI when the player selects a unit other than his hero, because it's a bit weird to see the UI on a unit that isn't his or even have any inventory but everything else is perfect for my use.

Thanks again Uncle, much appreciated.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,550
Thanks a lot for your system, it's great and simple, exactly what I wanted in the first place. I've added a small trigger to hide the UI when the player selects a unit other than his hero, because it's a bit weird to see the UI on a unit that isn't his or even have any inventory but everything else is perfect for my use.

Thanks again Uncle, much appreciated.
No problem, glad it works for you. I added two more functions that could come in handy:
vJASS:
    // You can call this function to assign a custom value to the given Item
    function SIM_Index_Item takes item itm returns nothing
        if itm != null and GetItemUserData(itm) == 0 then
            set INDEX = INDEX + 1
            // This isn't guaranteed to be safe!
            // Max Size is 32,768 at the time of creating this
            if INDEX >= JASS_MAX_ARRAY_SIZE then
                set INDEX = 1
            endif
            call SetItemUserData(itm, INDEX)
            set udg_SIM_Index = INDEX
            set udg_SIM_Item = itm
            set udg_SIM_ItemEvent = 1.00
            set udg_SIM_ItemEvent = 0.00
        endif
    endfunction

    // You can call this function to make the given Hero use this system (one Hero per Player)
    function SIM_Set_Hero takes unit u returns nothing
        local integer pn = GetPlayerId(GetOwningPlayer(u))
        call SaveUnitHandle(HASH, pn, KEY_HERO, u)
        if LoadInteger(HASH, pn, KEY_CURRENT_PAGE) == 0 then
            call SaveInteger(HASH, pn, KEY_LAST_PAGE, 1)
            call SaveInteger(HASH, pn, KEY_CURRENT_PAGE, 1)
            // Modify page text
            if GetLocalPlayer() == Player(pn) then
                call BlzFrameSetText(PAGE_TEXT, "Page |cffffcc00" + I2S(1) + "/" + I2S(MAX_PAGES))
            endif
        endif
    endfunction

SIM_Index_Item lets you index an item whenever you want, which is useful if you want to use an item's custom value right away instead of needing it to be picked up by a Hero first.

SIM_Index_Hero lets you set a Hero (or technically any kind of Unit) as the primary user of the system. A Player can only have one of these units set at a time.

These new functions are called like SIM_Show_UI but take an Item/Unit as their (parameter):
  • Custom script: call SIM_Index_Item(some item)
  • Custom script: call SIM_Set_Hero(some unit)
To update to this new version, simply copy the code in the new map (the green custom script file called SimpleItemManager) and replace your old code with it. There's no need to copy or change the other triggers/variables/folders.
 

Attachments

  • Simple Item Manager 2.w3m
    27.8 KB · Views: 4
Last edited:
Level 2
Joined
Mar 4, 2012
Messages
8
No problem, glad it works for you. I added two more functions that could come in handy:
vJASS:
    // You can call this function to assign a custom value to the given Item
    function SIM_Index_Item takes item itm returns nothing
        if itm != null and GetItemUserData(itm) == 0 then
            set INDEX = INDEX + 1
            // This isn't guaranteed to be safe!
            // Max Size is 32,768 at the time of creating this
            if INDEX >= JASS_MAX_ARRAY_SIZE then
                set INDEX = 1
            endif
            call SetItemUserData(itm, INDEX)
            set udg_SIM_Index = INDEX
            set udg_SIM_Item = itm
            set udg_SIM_ItemEvent = 1.00
            set udg_SIM_ItemEvent = 0.00
        endif
    endfunction

    // You can call this function to make the given Hero use this system (one Hero per Player)
    function SIM_Set_Hero takes unit u returns nothing
        local integer pn = GetPlayerId(GetOwningPlayer(u))
        call SaveUnitHandle(HASH, pn, KEY_HERO, u)
        if LoadInteger(HASH, pn, KEY_CURRENT_PAGE) == 0 then
            call SaveInteger(HASH, pn, KEY_LAST_PAGE, 1)
            call SaveInteger(HASH, pn, KEY_CURRENT_PAGE, 1)
            // Modify page text
            if GetLocalPlayer() == Player(pn) then
                call BlzFrameSetText(PAGE_TEXT, "Page |cffffcc00" + I2S(1) + "/" + I2S(MAX_PAGES))
            endif
        endif
    endfunction

SIM_Index_Item lets you index an item whenever you want, which is useful if you want to use an item's custom value right away instead of needing it to be picked up by a Hero first.

SIM_Index_Hero lets you set a Hero (or technically any kind of Unit) as the primary user of the system. A Player can only have one of these units set at a time.

These new functions are called like SIM_Show_UI but take an Item/Unit as their (parameter):
  • Custom script: call SIM_Index_Item(some item)
  • Custom script: call SIM_Set_Hero(some unit)
To update to this new version, simply copy the code in the new map (the green custom script file called SimpleItemManager) and replace your old code with it. There's no need to copy or change the other triggers/variables/folders.
This gonna be useful, thanks.

After a few tests, I've found a bug. When I switch inventory pages, I can't move the camera with the arrow keys anymore (using Classic keybindings preset) mouse control works fine. It's fixed when I hide and show the UI again. Do you have any idea what's behind this?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,550
This gonna be useful, thanks.

After a few tests, I've found a bug. When I switch inventory pages, I can't move the camera with the arrow keys anymore (using Classic keybindings preset) mouse control works fine. It's fixed when I hide and show the UI again. Do you have any idea what's behind this?
Yeah, unfortunately the custom UI frames have a few bugs that need to be fixed by Blizzard.

Edit: It should be fixed in this version. It's not perfect but it'll be like that until we get a proper patch fix.
 

Attachments

  • Simple Item Manager 3.w3m
    27.9 KB · Views: 8
Last edited:
Level 2
Joined
Mar 4, 2012
Messages
8
Yeah, unfortunately the custom UI frames have a few bugs that need to be fixed by Blizzard.

Edit: It should be fixed in this version. It's not perfect but it'll be like that until we get a proper patch fix.
It's fixed, wonderful.
Can I PM you if I have questions or suggestions about your system ? Right now I don't have any but maybe in the future.
 
Level 39
Joined
Feb 27, 2007
Messages
5,016
Uncle sees basically every thread in every relevant forum. Post publicly and he'll find it, or you can @ him in a post to send a special notification. Sometimes others may have input or an alternative solution to what he would suggest.
 
Top