• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Marketplace Issues

Status
Not open for further replies.
Level 4
Joined
Aug 5, 2007
Messages
49
So I was using the goblin merchant for all my items in my game but decided I wanted to add a specific item ban system, it seems the only way I can remove an item from a shop via triggers is if it's a marketplace. All seems to be good, cept no matter how much stock I give the item when I add it, it gets removed on sale, or removes another random item in the shop. at no point in my game do I use the "remove item from marketplace" command so I can only assume this is some kind of weird built in thing.

any ideas how to get it to work as intended? (as a goblin merchant I can add / remove items from)
 
Level 39
Joined
Feb 27, 2007
Messages
5,033
LOL

There is no way what he suggested is the best solution here. If the item removed seems to be somewhat random (or at least occasionally not the same item that was bought) there is definitely a bug you've encountered, as that is not expected marketplace behavior. To get item removal to work I believe you just have to first add the items to the shop(s) via triggers if you want to later be able to remove them. Try that and see if it still wigs out.
 
Level 8
Joined
Mar 19, 2017
Messages
248
This is not a bug but rather an Initialization Trigger (and as such, it is registered for any map) so you must undo some functions.
Simply do the following (ie. on a map initialization trigger), especially the disable trigger one (this will automatically remove an item once is sold, no matter how much items are actually on stock):

JASS:
call PauseTimer(bj_stockUpdateTimer)
call DisableTrigger(bj_stockItemPurchased)
 
Level 12
Joined
Nov 3, 2013
Messages
989
So I was using the goblin merchant for all my items in my game but decided I wanted to add a specific item ban system, it seems the only way I can remove an item from a shop via triggers is if it's a marketplace.
You can remove items from any shop with triggers, if said items were also added to the the shop triggers.

So basically, remove the sold items from the shop in the object editor, then add the items to the shop at gamestart/map init with triggers - now you can remove them, add to stock, etc. with triggers at any time.

Same deal with sold units.
 
Level 39
Joined
Feb 27, 2007
Messages
5,033
You can remove items from any shop with triggers, if said items were also added to the the shop triggers.
-___-
To get item removal to work I believe you just have to first add the items to the shop(s) via triggers if you want to later be able to remove them. Try that and see if it still wigs out.

@disruptive_ I read through the Blizzard.j functions that use those objects (and the functions that use those functions) and I'm curious about the connection you saw here? As I understand those are the things that keep shop stocks refreshing/generating new items.
 
Level 8
Joined
Mar 19, 2017
Messages
248
All seems to be good, cept no matter how much stock I give the item when I add it, it gets removed on sale, or removes another random item in the shop.

@disruptive_ I read through the Blizzard.j functions that use those objects (and the functions that use those functions) and I'm curious about the connection you saw here? As I understand those are the things that keep shop stocks refreshing/generating new items.

The bj_stockItemPurchased trigger does exactly that, if the selling unit is of Neutral Player, then it removes the item sold with the RemoveItemFromStock function (that only affects units with Sell Item ability, the only one beign the Marketplace, but if the user somehow adds this ability to another neutral unit, then it will also perform the action). The function (action of the bj_stockItemPurchased) trigger is called RemoveItemPurchased (that comes from InitNeutralBuildings, the last coming from InitBlizzard).

This relates to the problem of the OP. The timer is the one that refreshes the marketplace.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,033
I think my brain shut off and didn't process what I read and I thought you were suggesting that doing one of those things would be to blame for the OP's situation. Sorry. Regardless, it's good to know that this happens internally via triggers and timers; I would have assumed it to be simply a part of the game code.
 
Level 13
Joined
Jul 15, 2007
Messages
763
I have a multiple shops based on Marketplaces and i have the opposite problem to you; i have to use triggers to remove items when they reach 0 stock they will just replenish. I think the shop abilities may determine if a marketplace item is removed or not when it is bought.
 
Level 8
Joined
Mar 19, 2017
Messages
248
Stock replenishment is part of the item (object editor wise).
The RemovePurchasedItem function only makes sense if the stock is 1, otherwise it will look rather strange to see how the item is removed while having a stock of ie. 5.
Your problem, given the object editor limitations (all items have stock amount and stock replenishment time) can only be solved by saving the stock data of each item with a (hash)Table. Don't know if messing with negative values could work.
You should update that data whenever an item is sold or bought (the events that have special relation here), and since these events exist this is completely the doable. Should the data becomes 0 then you can use the RemoveItemFromStock function. Then a system to restock is the next logical step.

Since i'm on procrastinante mode, i actually made a system out of the idea of a custom automatic liquidate->restock->liquidate, about...an hour ago (don't be hard on the efficiency department), maybe is useful (since WE 1.30 features JassHelper there is no reason to not learn vJass, except...the awful current interface):


JASS:
//modified a bit to show only the relevant aspects
//uses Table;TimerUtils;Alloc (Alloc is not essential)
struct fair extends array 
 static constant integer MAXIMUM_STOCK = 10
 static constant real PHASE_TIME = 60
 static Table FT 
 unit u 
 Table List
 Table Stocked
 integer id
 integer itemCount //items currently on the list
 integer itemStocked //items already stocked, stocked is mutually exclusive with listed.
 integer phase
 timer t
 implement Alloc

 method destroy takes nothing returns nothing 
  call this.List.flush()
  call this.Stocked.flush() 
  call FT.remove(GetHandleId(this.u))
  call this.deallocate() 
 endmethod 

 method registerToList takes integer id, integer stock returns nothing 
  set this.itemCount = this.itemCount + 1 
  set this.List[this.itemCount] = id 
  if stock > 0 then 
   set this.List[id] = stock 
  endif 
 endmethod

 method registerMarket takes nothing returns nothing 
  call this.registerToList(ITEM_TO_ADD,STOCK_CLASS) //1 = 1, 2 = 2-5, could be changed tho
  ......
 endmethod 

 method registerCaravan takes nothing returns nothing 
  call this.registerToList(ITEM_TO_ADD,STOCK_CLASS)
  .......  
 endmethod 

  method rollItem takes nothing returns nothing //gives an item from the list, the listed item will be now stocked and delisted.
    local integer count 
    local integer ran 
    local integer stock = 0 
   
    if this.itemStocked <= MAXIMUM_STOCK then 
     set count = this.itemCount
     set ran = GetRandomInt(1, this.itemCount) 
     if this.List[this.List[ran]] == 1 then 
      set stock = 1 
     elseif this.List[this.List[ran]] >= 2 then 
      set stock = GetRandomInt(2, 5) 
     endif 
     call AddItemToStock(u, this.List[ran], stock, stock)
     set this.itemStocked = this.itemStocked + 1 
     set this.Stocked[this.itemStocked] = this.List[ran] 
     set this.itemCount = this.itemCount - 1
      if ran != count then
       set this.List[ran] = this.List[count] 
     else 
       call this.List.remove(count)
     endif 
    endif 
 endmethod 

 static method periodic takes nothing returns nothing 
    local thistype this = GetTimerData(GetExpiredTimer())
    local integer i = 1
   
    if this.phase == 2 then  //phase 2 is restock
     set this.phase = 0 //why no loop? don't know
     call this.rollItem()
     call this.rollItem()
     call this.rollItem()
     call this.rollItem()
     call this.rollItem()
     call this.rollItem()
     call this.rollItem()
     call this.rollItem() 
     call this.rollItem()
     call this.rollItem() 
    elseif this.phase == 1 then  //phase 1 is liquidation of all items
      loop 
        exitwhen this.itemStocked == 0
         call RemoveItemFromStock(this.u, this.Stocked[i]) 
         call AddResourceAmount(this.u, GetRandomInt(1,20 + GetRandomInt(3,10))) // just to give some UI info as i used the gold mine ability for markets
         call this.registerToList(this.Stocked[i],-1)
        set this.itemStocked = this.itemStocked - 1  
      endloop   
      call PingMinimap(GetUnitX(this.u), GetUnitY(this.u), 5.) 
      set this.phase = 2
    elseif this.phase <= 0 then 
     set this.phase = 1 
    endif 
 endmethod 

 static method create takes unit u returns thistype
  local thistype this = fair.allocate()
  local integer n = GetRandomInt(1,10)
 
  set total = total + 1
  set this.u = u 
  set this.List = Table.create()
  set this.Stocked = Table.create()
  set this.itemCount = 0 
  set this.itemStocked = 0 
  set this.id = total
  set this.phase = 2

   if GetUnitTypeId(u) == 'MRKT' then       
     set this.t = NewTimerEx(this) 
     call this.registerFair()
     call TimerStart(this.t, PHASE_TIME, true, function thistype.periodic)   
   else 
     call this.registerCaravan()
   endif 

  set FT[GetHandleId(u)] = this 
  return this   
 endmethod 
endstruct

static method onInit takes nothing returns nothing 
 set FT = Table.create()
endmethod
 
Status
Not open for further replies.
Top