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

About natives AddItemToStock/AddItemToAllStock/AddUnitToStock/AddUnitToAllStock

Status
Not open for further replies.
Level 5
Joined
Oct 27, 2007
Messages
158
I came across this thread on bugged natives. Both natives in the Jass snippets below are not bugged. In fact all the natives used to add items to marketplaces work fine. You just need to undo Blizzard's forced shop behavior. I couldn't find any posts that explained what's going on in greater detail and offering solutions, so here goes...

JASS:
AddItemToAllStock
AddUnitToAllStock //No matter how much stock you pass as a parameter, it only counts as 1

JASS:
native AddItemToAllStock            takes integer itemId, integer currentStock, integer stockMax returns nothing
native AddItemToAllStock            takes integer itemId, integer currentStock, integer stockMax returns nothing
// After adding an item to a neutral building through either of these functions,
// it will cause any units that purchase the item to receive only one of it 
// before it is completely removed from the stock. Regardless of the stock 
// amount, the item will only remain available in the building for one purchase.

The behavior you're seeing is because of Blizzard.j function InitNeutralBuildings. This function is called at map initialization in the function main from InitBlizzard(). It configures all marketplaces to offer items of the same type and level that are dropped by mobs, but only if an item table is setup in the WE for those mobs. If setup through the WE then it calls UnitDropItem automatically, which creates and drops the item and makes sure items of the same type and level are available in future marketplace stock updates.

Only the shops for PLAYER_NEUTRAL_PASSIVE are setup to only have one of each item in stock. There's a trigger for PLAYER_NEUTRAL_PASSIVE that instantly removes the purchased item from the stock after being sold. Hence the item is removed when purchased regardless of the maximum stock available.

A solution to this is to disable the trigger that forces the item to be removed from stock and disable the stock update timer.

  • Disable Marketplace updates
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Pausing the timer will make sure no more Marketplace stock updates will occur. --------
      • Custom script: call PauseTimer(bj_stockUpdateTimer)
      • -------- Destroying the timer is optional, but can be done if you want to free a handle index. --------
      • Custom script: call DestroyTimer(bj_stockUpdateTimer)
      • Custom script: set bj_stockUpdateTimer = null
      • -------- Disable the trigger that removes the sold item from the marketplace stock. --------
      • -------- Destroying the trigger will free the memory used for the trigger object but will leak the handle ID and triggeraction object. --------
      • -------- Therefore destroying the trigger is not recommended since you can't free the associated triggeraction. --------
      • Custom script: call DisableTrigger(bj_stockItemPurchased)
      • -------- From here on you can do whatever you like to implement your own marketplace behavior. --------
Another solution for Jass coders is to edit war3map.j and remove
JASS:
call InitBlizzard()
in the main function and copy & paste the contents of the function in main and replace the
JASS:
call InitNeutralBuildings()
with your own shop initialization function. For GUI users this last solution will not work since there's no way to change the contents of the main function from within the GUI, other than changing the contents of the map initialization trigger. GUI users could use another player for shops to circumvent this "forced remove sold item" behavior from neutral passive shops. Keep in mind that this only stops the removal of items after a purchase. Marketplaces are still updated with items with item type and level of previously dropped items. Therefore if you're a GUI user you're better of disabling the timer and trigger involved in marketplace stock updating, if you want to have full control over your shop.

I've attached a demo map to try this out. Try the map with and without disabling trigger/timer. You'll see the difference in behavior of the marketplace.
 

Attachments

  • Marketplace.w3x
    19.6 KB · Views: 124
Level 5
Joined
Oct 27, 2007
Messages
158
Triggers and scripts is for asking help related to fixing triggers / scripts.

Is this thing a question as I do not see one in there ?

If you mean for this to be a tutorial on how to fix then it belongs in Tutorial section.

Forum rules

Talk regarding custom created spells and systems takes place in here as well as anything else trigger related (JASS or GUI). Get help creating a spell, implementing a system, have your GUI problems solved or fix your JASS syntax errors, etc.

Again pretty bold with the statements aren't we? Where exactly does it say it's only for help relating to fixing triggers/scripts?

This is not a tutorial. It shows a workaround for both Jass and GUI users to get shops to work and at the same time debunks the myth that those natives are bugged.

What is your problem?
 
Awesome!

I was the one who reported those as bugged. *guiltily weeps* But I never even thought it had to do with InitBlizzard. I edited the bug-list thread and provided a link to this. It is good to know that there is indeed a workaround!

EDIT: Just to clarify, this issue doesn't happen with AddUnitToAllStock, right? Because on this page, I noted that it doesn't. I just want to be sure.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
Forum rules

Again pretty bold with the statements aren't we? Where exactly does it say it's only for help relating to fixing triggers/scripts?

This is not a tutorial. It shows a workaround for both Jass and GUI users to get shops to work and at the same time debunks the myth that those natives are bugged.

What is your problem?

I have no problem. I simply thought that this should be a tutorial on the tutorial page. I think it would be better served as a short tutorial on how to fix the bugs mentioned above.
 
Level 5
Joined
Oct 27, 2007
Messages
158
Awesome!

I was the one who reported those as bugged. *guiltily weeps* But I never even thought it had to do with InitBlizzard. I edited the bug-list thread and provided a link to this. It is good to know that there is indeed a workaround!

EDIT: Just to clarify, this issue doesn't happen with AddUnitToAllStock, right? Because on this page, I noted that it doesn't. I just want to be sure.

It doesn't happen with the add unit stock natives, even with the default Blizzard shop behavior. That's because only an item sold event is registered in Blizzard.j The item being removed from the shop only happens when the shop is owned by the neutral passive player. The stock updates are only for marketplaces but the item being removed from a shop after a purchase is for all shops owned by the neutral passive player that have the sell items ability. No check is done that the selling unit is actually a marketplace. Only Blizzard knows why this would be a good idea. The natives AddItemToAllStock and AddUnitToAllStock both work for any shop that has the item/unit sell ability and select unit/hero ability. Considering that I don't understand Blizzard's implementation of updating all marketplaces stock for all players, but removing a purchased item from any shop that sold it with the item sell ability, that is owned by the neutral passive player. I consider it an oversight on their part.

Even if you only use units, items could get added to the shop if you use item drop tables made in the WE. The bloated WE code generation for each custom unit drop always generates a call to UnitDropItem. That will make the item it self and items of the same type and level obtainable through a shop. This is of course undesired when they're intended to be a rare drop only. Therefore it's better to just disable the default shop behavior. Why this wasn't made optional in the first place is beyond me.

JASS:
function RemovePurchasedItem takes nothing returns nothing
    call RemoveItemFromStock(GetSellingUnit(), GetItemTypeId(GetSoldItem()))
endfunction

    // Set up a trigger to fire whenever an item is sold.
    set bj_stockItemPurchased = CreateTrigger()
    call TriggerRegisterPlayerUnitEvent(bj_stockItemPurchased, Player(PLAYER_NEUTRAL_PASSIVE), EVENT_PLAYER_UNIT_SELL_ITEM, null)
    call TriggerAddAction(bj_stockItemPurchased, function RemovePurchasedItem)
 
Last edited:
Status
Not open for further replies.
Top