Thread Tools Display Modes
08/14/14, 10:31 AM   #1
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Destroying an item - Event questions

Hi,

as an item is selected to be destroyed the event EVENT_MOUSE_REQUEST_DESTROY_ITEM will fire.
The parameters are:
eventCode, bagId, slotIndex, itemCount, name, needsConfirm

I registered a callback function for the event which is executing fine.
I'm able to check the item which should be destroyed.
If the item should not be destroyed you'll have to manually press "Abort" at the popup on screen.

I'd like to do this automatically:
Assuming I accidently try to destroy an item I want to keep, and I got some marker for this item to check, if the item should be kept.

Questions:
-Is there a possibility to disable the destruction popup asking me if I want to destroy the item?
(Tried to play around with the parameter needsConfirm but it does not work as I thought)

-Is there a way to keep the item, even if I press/choose "Yes" in the destruction popup?

Did anyone play around with this already and got some ideas?

Thanks for your help.

Regards
Baertram
  Reply With Quote
08/14/14, 11:03 AM   #2
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Try changing dialog button's callback:
Lua Code:
  1. ESO_Dialogs["DESTROY_ITEM_PROMPT"].buttons[1].callback = function(dialog)
  2.     RespondToDestroyRequest(g_allowDestroyItem)
  3. end

I couldn't find a way to get mainTextParams passed to the dialog. So I was thinking you could do your test in EVENT_MOUSE_REQUEST_DESTROY_ITEM and set a global g_allowDestroyItem flag, and use that to override what the OK button does.

edit: if needsConfirm is true, it will fire a different dialog that requires you to type a word. Like when you want to delete a character, but I've never seen that with an item.

edit2: perhaps it woud be best to suppress the "Destroy" option in context menu in the first place

Last edited by merlight : 08/14/14 at 11:12 AM.
  Reply With Quote
08/14/14, 11:31 AM   #3
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Thx for the input.
I think the function RespondToDestroyRequest is not working as it is private. But I'll test it.
Edit: As I assumed it will raise an error because the function is private.

Oh well, It seems I interpreted the needsConfirm parameter wrong then

Disabling the destroy right-click menu pint is the next step. But you could easily drag&drop the item out of your inventory to destroy it too. So I'm currently focusing on this way.

Last edited by Baertram : 08/14/14 at 11:55 AM.
  Reply With Quote
08/14/14, 03:21 PM   #4
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Baertram View Post
Thx for the input.
I think the function RespondToDestroyRequest is not working as it is private. But I'll test it.
Edit: As I assumed it will raise an error because the function is private.
I just took it from their callback. Not sure what "private" means here. Perhaps it can only be called from certain places, like dialog button callback.

Anyway, here's how you can hide "Destroy" action, should you want it. Change allowDestroyItem() to something useful, this one forbids destroying stacks of 2 items for illustration:
Lua Code:
  1. local function allowDestroyItem(inventorySlot)
  2.     local stackSize = GetSlotStackSize(ZO_Inventory_GetBagAndIndex(inventorySlot))
  3.     return stackSize ~= 2
  4. end
  5. local function preAddSlotAction(self, actionStringId, ...)
  6.     if actionStringId == SI_ITEM_ACTION_DESTROY then
  7.         return not allowDestroyItem(self.m_inventorySlot)
  8.     end
  9. end
  10. ZO_PreHook(ZO_InventorySlotActions, "AddSlotAction", preAddSlotAction)

Edit 2: deleted malfunctioning code from my first attempt, this is much simpler and at least doesn't break putting items in bank

Last edited by merlight : 08/14/14 at 04:34 PM.
  Reply With Quote
08/14/14, 03:33 PM   #5
Fyrakin
 
Fyrakin's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 129
Originally Posted by merlight View Post
I just took it from their callback. Not sure what "private" means here. Perhaps it can only be called from certain places, like dialog button callback.
Private means local function declaration used in main esoui modules. You can't call it outside module if its local.
  Reply With Quote
08/14/14, 03:42 PM   #6
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Fyrakin View Post
Private means local function declaration used in main esoui modules. You can't call it outside module if its local.
Don't confuse it with local. RespondToDestroyRequest is a global function, present in _G, but is marked as private - error message says inaccessible from insecure code. I wonder how they know which lua code is secure
  Reply With Quote
08/14/14, 04:04 PM   #7
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 648
Private means that the function is accessible from ESO code only. Not third party addons.

Protected means that you can only use a function in certain circumstances (like out of combat, for example, or in response to a hardware event).
  Reply With Quote
08/15/14, 07:59 AM   #8
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
So I've come with two possible solutions, both of them a bit hacky.
This one replaces the "Yes" button with "Not really" button. I was not sure when exactly my EVENT_MOUSE_REQUEST_DESTROY_ITEM handler would be called (before or after the dialog is shown), so I override the button there and also in dialog's OnShow handler.

Lua Code:
  1. local DestroyItemDialog = ESO_Dialogs["DESTROY_ITEM_PROMPT"]
  2. local g_allowDestroyItem = false
  3.  
  4. local function overrideDialogYesButton(dialog)
  5.     if dialog.info == DestroyItemDialog then
  6.         local button1 = dialog:GetNamedChild("Button1")
  7.         if g_allowDestroyItem then
  8.             button1:SetText(GetString(SI_YES))
  9.             button1:SetClickSound(SOUNDS.DIALOG_ACCEPT)
  10.             button1.m_callback = DestroyItemDialog.buttons[1].callback
  11.         else
  12.             button1:SetText("Not really")
  13.             button1:SetClickSound(SOUNDS.DIALOG_DECLINE)
  14.             button1.m_callback = DestroyItemDialog.noChoiceCallback
  15.         end
  16.     end
  17. end
  18.  
  19. local function onRequestDestroyItem(eventCode, bagId, slotIndex, itemCount, name, needsConfirm)
  20.     if not needsConfirm then
  21.         g_allowDestroyItem = (math.random(2) == 1)
  22.         overrideDialogYesButton(ZO_Dialog1)
  23.     end
  24. end
  25.  
  26. EVENT_MANAGER:RegisterForEvent("ItemProtector", EVENT_MOUSE_REQUEST_DESTROY_ITEM, onRequestDestroyItem)
  27. ZO_PreHookHandler(ZO_Dialog1, "OnShow", overrideDialogYesButton)

This one replaces the default EVENT_MOUSE_REQUEST_DESTROY_ITEM handler with one that shows a custom dialog on protected items:
Lua Code:
  1. local DestroyItemDialog = ESO_Dialogs["DESTROY_ITEM_PROMPT"]
  2. local PreventDestroyItemDialog = {
  3.     title = {text = "Protected item"},
  4.     mainText = {text = "<<2[// $d]>> <<X:1>> cannot be destroyed"},
  5.     noChoiceCallback = DestroyItemDialog.noChoiceCallback,
  6.     buttons = {
  7.         [1] = {text = SI_DIALOG_EXIT, keybind = "DIALOG_NEGATIVE", callback = DestroyItemDialog.noChoiceCallback}
  8.     }  
  9. }  
  10. ZO_Dialogs_RegisterCustomDialog("CUSTOM_PREVENT_DESTROY_ITEM", PreventDestroyItemDialog)
  11.  
  12. local function onRequestDestroyItem(eventCode, bagId, slotIndex, itemCount, name, needsConfirm)
  13.     local _, actualItemCount = GetItemInfo(bagId, slotIndex)
  14.     local itemLink = GetItemLink(bagId, slotIndex)
  15.  
  16.     if itemCount == 0 and actualItemCount > 1 then
  17.         itemCount = actualItemCount
  18.     end
  19.  
  20.     if(needsConfirm) then
  21.         ZO_Dialogs_ShowDialog("CONFIRM_DESTROY_ITEM_PROMPT", nil, {mainTextParams = {itemLink, itemCount, GetString(SI_DESTROY_ITEM_CONFIRMATION)}})
  22.     elseif math.random(2) == 1 then
  23.         ZO_Dialogs_ShowDialog("DESTROY_ITEM_PROMPT", nil, {mainTextParams = {itemLink, itemCount}})
  24.     else
  25.         ZO_Dialogs_ShowDialog("CUSTOM_PREVENT_DESTROY_ITEM", nil, {mainTextParams = {itemLink, itemCount}})
  26.     end
  27. end
  28.  
  29. ZO_PlayerInventory:UnregisterForEvent(EVENT_MOUSE_REQUEST_DESTROY_ITEM)
  30. ZO_PlayerInventory:RegisterForEvent(EVENT_MOUSE_REQUEST_DESTROY_ITEM, onRequestDestroyItem)

Last edited by merlight : 08/15/14 at 09:17 AM.
  Reply With Quote
08/15/14, 08:30 AM   #9
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Thx for the code merlight.
But both versions of your dialogs just change the buttons or dialog itsself. You wil lstill be able to press the primary and secondary keys of your keybindings to raise the Click event on button1 or button2, right?

Yesterday I changed the destroy dialog so the "Yes" button is totally hidden for some items.
But you were able to press the primary key so the OnClick() was executed.

I changed the callback method of this Yes button then, returning nil or false. The items won't be destroyed anymore now :-)
If you
But the items remain in the "locked" state inside your inventory, because they were locked upon destroying.
I can unlock them again by trying to destroy them and say no this time.

Any1 got an idea how to unlock a locked item inside the inventory again?
The event is EVENT_INVENTORY_ITEM_SLOT_UNLOCKED which will be normally called. Can I manually call it somehow in my dialog's callback function?
  Reply With Quote
08/15/14, 09:13 AM   #10
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
The first variant replaces button text AND callback. Just tried that with a lockpick. If you see "/E/ Not really" and press /E/, nothing happens because the callback is replaced with the /Esc/ one.

The second variant shows a custom dialog, there is only one button and that does the /Esc/ action of the original destroy dialog, i.e. cancel destruction. It will probably make more sense if the button shows "/Alt/ Exit" instead of "/E/ OK" ... edited the above code to make it so.

Last edited by merlight : 08/15/14 at 09:19 AM.
  Reply With Quote
08/15/14, 11:36 AM   #11
Fyrakin
 
Fyrakin's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 129
Originally Posted by merlight View Post
The first variant replaces button text AND callback. Just tried that with a lockpick. If you see "/E/ Not really" and press /E/, nothing happens because the callback is replaced with the /Esc/ one.

The second variant shows a custom dialog, there is only one button and that does the /Esc/ action of the original destroy dialog, i.e. cancel destruction. It will probably make more sense if the button shows "/Alt/ Exit" instead of "/E/ OK" ... edited the above code to make it so.
So, if you change callback for the confirm button to something like
Code:
            text =       SI_CHAT_DIALOG_CONFIRM_ITEM_DESTRUCTION,
            callback =  function(dialog)
                            RespondToDestroyRequest(false)
                        end,
You still get the locked item?
  Reply With Quote
08/15/14, 11:55 AM   #12
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
As Baertram wrote you cannot set (well you can but it will cause error)
Lua Code:
  1. callback = function(dialog) RespondToDestroyRequest(false) end
... because that's a new anonymous function, ESO somehow knows it comes from and addon and doesn't allow it to call RespondToDestroyRequest. The funny thing is you can set
Lua Code:
  1. callback = ESO_Dialogs["DESTROY_ITEM_PROMPT"].buttons[1].callback
  2. -- if you want RespondToDestroyRequest(true)
  3.  
  4. callback = ESO_Dialogs["DESTROY_ITEM_PROMPT"].buttons[2].callback
  5. -- if you want RespondToDestroyRequest(false)
... these are their original callbacks, which are allowed and do call RespondToDestroyRequest (button 1 passes true, button 2 passes false)
  Reply With Quote
08/15/14, 12:28 PM   #13
Fyrakin
 
Fyrakin's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 129
Originally Posted by merlight View Post
As Baertram wrote you cannot set (well you can but it will cause error)
Lua Code:
  1. callback = function(dialog) RespondToDestroyRequest(false) end
... because that's a new anonymous function, ESO somehow knows it comes from and addon and doesn't allow it to call RespondToDestroyRequest. The funny thing is you can set
Lua Code:
  1. callback = ESO_Dialogs["DESTROY_ITEM_PROMPT"].buttons[1].callback
  2. -- if you want RespondToDestroyRequest(true)
  3.  
  4. callback = ESO_Dialogs["DESTROY_ITEM_PROMPT"].buttons[2].callback
  5. -- if you want RespondToDestroyRequest(false)
... these are their original callbacks, which are allowed and do call RespondToDestroyRequest (button 1 passes true, button 2 passes false)
I see, this is the original array of this button:
Code:
    buttons =
    {
        [1] =
        {
            text =      SI_YES,
            callback =  function(dialog)
                            RespondToDestroyRequest(true)
                        end,
        },
        [2] =
        {
            text =      SI_NO,
            callback =  function(dialog)
                            RespondToDestroyRequest(false)
                        end,
        }
  Reply With Quote
08/17/14, 09:36 AM   #14
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Alright merlight, thanks again.
Never thought of just replacing the callback of the "Yes" button with the callback of the "No" button :-)
  Reply With Quote

ESOUI » AddOns » AddOn Help/Support » Destroying an item - Event questions


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off