| 12-28-2007, 09:59 PM | #1 |
I have set up a system for item stocking. Basically, there is no automatic restock. When an item is bought the stock decreases by one, when it is sold it increases by one at the shop where it was sold. I prevent buying from allied shops and use a two dimensional array to keep track of 45 items of 6 different players. This almost works perfectly. When selling, half the time it will predictably remove a seeminly random item from stock, and only update the pawned item's stock to one less than it should be. This is odd behavior, similar to what you might see if you take out either annoted waits. (The waits are mentioned on other posts on this forum also)The last strange thing is that on the pawn items trigger I needed to remove the item before adding it again with a differnet stock, or it would glitch every time. With the sell items this was completely unnecessary. So with that data, I have three questions: Whats going on, how can i fix it, and can I replace the waits wtih anything else to make it more rugged? Here are the two triggers, and thanks! The perfectly working buy item trig: JASS:function Trig_item_bought_Actions takes nothing returns nothing local integer playerNum = GetPlayerId(GetOwningPlayer(GetSellingUnit())) //most of these vars for 2d array local integer itemId = GetItemTypeId(GetSoldItem()) local integer arraySpot = get_item_spot(itemId)+ playerNum *45 if (Player(playerNum) == GetOwningPlayer(GetBuyingUnit())) then //no buying from allied shops call DisplayTextToForce(GetPlayersAll(), I2S(udg_itemStock[arraySpot])) set udg_itemStock[arraySpot] = udg_itemStock[arraySpot] -1 if (udg_itemStock[arraySpot] > 0) then call DisplayTextToForce(GetPlayersAll(), I2S(udg_itemStock[arraySpot])) call TriggerSleepAction(0.27) //this is necessary for some reason if (udg_itemStock[arraySpot] > 0) then //check again in case user bought another item call DisplayTextToForce(GetPlayersAll(), I2S(udg_itemStock[arraySpot])) call AddItemToStock(GetSellingUnit(), itemId, udg_itemStock[arraySpot], udg_itemStock[arraySpot]) //for some reason, stock can be manipulated here with no RemoveItemFromStock. That is required when selling an item. else //remove if 0, prevent restock call RemoveItemFromStock(GetSellingUnit(), itemId) endif else //remove if 0, prevent restock call RemoveItemFromStock(GetSellingUnit(), itemId) endif call DisplayTextToForce(GetPlayersAll(), I2S(udg_itemStock[arraySpot])) else //illegal buy call RemoveItem( GetSoldItem() ) call DisplayTextToForce(GetPlayersAll(), "|cffFFFF00You cannot buy from allied shops. Have your ally buy it for you|r") call PlayLocalSound(gg_snd_error, playerNum) call TriggerSleepAction(0.27) if (udg_itemStock[arraySpot] > 0) then call AddItemToStock(GetSellingUnit(), itemId, udg_itemStock[arraySpot], udg_itemStock[arraySpot]) endif endif endfunction //=========================================================================== function InitTrig_item_bought takes nothing returns nothing set gg_trg_item_bought = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_item_bought, EVENT_PLAYER_UNIT_SELL_ITEM ) call TriggerAddAction( gg_trg_item_bought, function Trig_item_bought_Actions ) endfunction And the unusably glitchy sell trigger (oh and how do I better the conditions?): JASS:function is_Filter_hvlt takes nothing returns boolean return ( GetUnitTypeId(GetFilterUnit()) == 'hvlt' ) endfunction function is_Filter_ovln takes nothing returns boolean return ( GetUnitTypeId(GetFilterUnit()) == 'ovln' ) endfunction function is_Filter_utom takes nothing returns boolean return ( GetUnitTypeId(GetFilterUnit()) == 'utom' ) endfunction function is_Filter_eden takes nothing returns boolean return ( GetUnitTypeId(GetFilterUnit()) == 'eden' ) endfunction function is_Filter_ngme takes nothing returns boolean return ( GetUnitTypeId(GetFilterUnit()) == 'ngme' ) endfunction function Trig_item_returned_Actions takes nothing returns nothing local integer itemId = GetItemTypeId(GetSoldItem()) //most of these vars are for 2d array local integer shopNum = get_item_spot(itemId) local integer playerNum = GetPlayerId(GetOwningPlayer(GetSellingUnit())) local integer arraySpot = shopNum + playerNum *45 local unit shop call DisplayTextToForce(GetPlayersAll(), I2S(udg_itemStock[arraySpot])) set udg_itemStock[arraySpot] = udg_itemStock[arraySpot] +1 //array works fine set bj_wantDestroyGroup = true call DisplayTextToForce(GetPlayersAll(), "shopnum: " + I2S(shopNum)) if (shopNum < 9) then //figure out which shop the item came from set shop = GroupPickRandomUnit(GetUnitsOfPlayerMatching(Player(playerNum), Condition(function is_Filter_hvlt))) elseif (shopNum < 17) then set shop = GroupPickRandomUnit(GetUnitsOfPlayerMatching(Player(playerNum), Condition(function is_Filter_ovln))) elseif (shopNum < 25) then set shop = GroupPickRandomUnit(GetUnitsOfPlayerMatching(Player(playerNum), Condition(function is_Filter_utom))) elseif (shopNum < 34) then set shop = GroupPickRandomUnit(GetUnitsOfPlayerMatching(Player(playerNum), Condition(function is_Filter_eden))) else set shop = GroupPickRandomUnit(GetUnitsOfPlayerMatching(Player(playerNum), Condition(function is_Filter_ngme))) endif call DisplayTextToForce(GetPlayersAll(), I2S(udg_itemStock[arraySpot])) call RemoveItemFromStock(shop, itemId) //this is necessary or the stock will not change. call TriggerSleepAction(0.27) //I dont know why, but this is necessary or odd things happen call AddItemToStock(shop, itemId, udg_itemStock[arraySpot], udg_itemStock[arraySpot]) endfunction //=========================================================================== function InitTrig_item_returned takes nothing returns nothing set gg_trg_item_returned = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_item_returned, EVENT_PLAYER_UNIT_PAWN_ITEM ) call TriggerAddAction( gg_trg_item_returned, function Trig_item_returned_Actions ) endfunction JASS:function get_item_spot takes integer ID returns integer if (ID == 'sreg') then return 0 elseif (ID == 'plcl') then return 1 //this repeats 43 more times endif return 0 //prevent crash endfunction |
| 12-30-2007, 10:40 PM | #2 |
Ok, so I figured it out. At least I know exactly whats going on and a suitable workaround. The neutral building add item triggers are more complex than at first seems. The AddItemToStock seems to, unintuitively, change the current stock and then the max stock. This means that it behaves as one would assume when lowering the stock of an item below the last set maximum. When you raise the stock and the stock max both to above the old max, however, the stock will be at the old maximum until the item replenishes more. The best workaround I know for this is to simply call the function twice with the same parameters when you know the new stock will be above the old stock max. However, I did not discover this right away (due in inexperience in bugtesting) and found another workaround, which is, however, flawed. (Blizzards fault!) You can call RemoveItemFromStock before adding your item again, and it will be at the correct stock. However, this will cause the first item which the shop is selling to be removed, I assume because its AddITemFromStock is trying to remove the item first, but its not there. It works like this: JASS:call RemoveItemFromStock(shop, itemId) //comment this line and all is normal call TriggerSleepAction(1) //added this line to see which func was removing the incorrect item. call AddItemToStock(shop, itemId, 3, 3) //without the RemoveItem commented, //this will remove the first item for sale in a shop. Because I was working on two or three things at the same time for this system, this bug cause me lots of trouble. Perhaps this info should be added to some giant stickied thread of "Weird things about the editor that don't work quite exactly as one might assume"? Adios ![]() PS: A "0" second wait ir required between buying the item and manipulating the stock. Why? Of course this comes out to 0.27 seconds, is there a way to speed this up? |
| 12-30-2007, 11:05 PM | #3 |
Use a 0 second timer. The events actually fire right before the transaction takes place (in-case you want to prevent it all together). To do so, use an attach method to attach your locals to a timer, start it for 0 seconds and make it execute a function which does the remainder of the actions. I know it seems stupid to have to do so much, but thats what I have used in the past. (I think you could get away with globals instead of attaching, but attaching is fool-proof and I've never done any serious testing with globals). |
| 12-30-2007, 11:51 PM | #4 |
That sounds good, like it would be instant. I've never used handle vars before, how would that work? *burys head in tutorials* Edit: Would I use something large like HSAS? It says it is the fastest way to attach thins to timers. Edit2: HSAS or ABC? Maybe ABC because its smaller, and speed is not a huge concern here? |
| 12-31-2007, 12:39 AM | #5 |
Yes, you can use that, CSCache or even SmartTimers Each has a different approach, so you would have to learn how. If you are using vJass, I recommend making a struct to save all your locals to and then saving the struct to the timer. |
