ESOUI SVN ItemLock

[/] [trunk/] [ItemLock.lua] - Rev 3

Compare with Previous | Blame | View Log

--[[
***********************************************************************************
Copyright (c) 2014, saykoaddon
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

[1] Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

[2] Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.
 
[3] Neither the name of the copyright holder nor the names of its contributors
    may be used to endorse or promote products derived from this software without
    specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***********************************************************************************
]]

------- ItemLock Class ----------------------
ItemLock = ZO_Object:Subclass()
local DECONSTRUCTION_BAG = ZO_SmithingTopLevelDeconstructionPanelInventoryBackpackContents

-- Creates variables
function ItemLock:New()
        ItemLock.name = "ItemLock"
        ItemLock.version = 2
        ItemLock.eventHandlers = {}
        ItemLock.list = ZO_SavedVars:New(ItemLock.name .. "_SavedVariables", 1, "list", {}, nil)
        ItemLock.settings = ZO_SavedVars:New(ItemLock.name .. "_SavedVariables", 1, "settings", { isActive = true }, nil)
        
        ItemLock.settings.isActive = true -- <= REMOVE THIS LINE TO KEEP SETTINGS BETWEEN SESSIONS
end

-- Initializes event handlers and chat commands
function ItemLock:Init()
        EVENT_MANAGER:RegisterForEvent( ItemLock.name .. "_OnInventorySlotLocked", EVENT_INVENTORY_SLOT_LOCKED, ItemLock_OnInventorySlotLocked )
        ZO_CreateStringId("SI_BINDING_NAME_ITEM_LOCK_TOGGLE_ENABLE", "Enable/Disable")
        ZO_CreateStringId("SI_BINDING_NAME_ITEM_LOCK_TOGGLE_LOCK", "Lock/Unlock")
        SLASH_COMMANDS["/itemlock"] = ItemLock.ToggleEnable
        
        -- override event handlers of DECONSTRUCTION_BAG, it is used to update item controls' event handlers
        ItemLock:PreHookHandler( "OnEffectivelyShown", DECONSTRUCTION_BAG, ItemLock_DECONSTRUCTION_BAG_OnEffectivelyShown )
        ItemLock:PreHookHandler( "OnMouseWheel", DECONSTRUCTION_BAG, ItemLock_DECONSTRUCTION_BAG_OnMouseWheel )
end

-- activates item protection
function ItemLock:Activate()
        ItemLock.settings.isActive = true
        CHAT_SYSTEM:AddMessage( ItemLock.name .. " is on")
end

-- deactivates item protection
function ItemLock:Deactivate()
        ItemLock.settings.isActive = false
        CHAT_SYSTEM:AddMessage( ItemLock.name .. " is off")
end

-- returns protection status
function ItemLock:IsActive()
        return ItemLock.settings.isActive
end

-- toggles item protection
function ItemLock:ToggleEnable()
        if (ItemLock:IsActive()) then
                ItemLock:Deactivate()
        else
                ItemLock:Activate()
        end
end

-- checks if item is in protection list
function ItemLock:IsItemLocked(itemId)
        return itemId and ItemLock.list[itemId]
end

-- adds item to protection list
function ItemLock:LockItem(itemId)
        if( not itemId ) then return end
        ItemLock.list[itemId] = 1
end

-- removes item from protection list
function ItemLock:UnlockItem(itemId)
        if( not itemId ) then return end
        ItemLock.list[itemId] = nil
end

-- toggles item's protection status by manipulating protection list
function ItemLock:ToggleLock()
        local control = WINDOW_MANAGER:GetMouseOverControl()
        
        -- make sure control contains an item
        if( not control or not control.dataEntry or not control.dataEntry.data ) then return nil end
        
        local bag = control.dataEntry.data.bagId
        local slot = control.dataEntry.data.slotIndex
        
        -- make sure control contains an item
        if( not bag or not slot ) then return nil end
        
        -- get instance id of the item, this value is persistant across all game and sessions
        local id = GetItemInstanceId(bag, slot)
        
        if( not id ) then return nil end
        
        -- convert to string to prevent negative number error of saved vars
        local idStr = tostring(id)
        
        -- check if item is in the protection list
        if( ItemLock:IsItemLocked(idStr) ) then
                ItemLock:UnlockItem(idStr)
                CHAT_SYSTEM:AddMessage( GetItemLink(bag, slot, LINK_STYLE_BRACKETS) .. " has been unlocked") 
        else
                ItemLock:LockItem(idStr)
                CHAT_SYSTEM:AddMessage( GetItemLink(bag, slot, LINK_STYLE_BRACKETS) .. " has been locked") 
        end
        
end

-- warns user with a chat message
function ItemLock:WarnUser(bag, slot)
        CHAT_SYSTEM:AddMessage( "WARNING!!!!" )
        CHAT_SYSTEM:AddMessage( "You are trying to deconstruct a locked item" )
        CHAT_SYSTEM:AddMessage( "Item: " .. GetItemLink(bag, slot, LINK_STYLE_BRACKETS) ) 
end

-- fired when user selects an item to deconstruct
-- warns user if the item is in protection list
function ItemLock:DeconstructionSelectionHandler(bag, slot)

        -- make sure user is on deconstruction panel
        if( not DECONSTRUCTION_BAG or DECONSTRUCTION_BAG:IsHidden() ) then return nil end

        -- if not active then abort checking
        if( not ItemLock:IsActive() ) then return nil end
        
        -- get instance id of the item, this value is persistant across all game
        local id = GetItemInstanceId(bag, slot)
        
        -- convert to string to prevent negative number error of saved vars
        local idStr = tostring(id)
        
        -- if item is in protection list, warn user
        if( ItemLock:IsItemLocked(idStr) ) then
                ItemLock:WarnUser(bag, slot)
                return true
        end
        
        return false
end

-- gets handler from the event handler list
function ItemLock:GetEventHandler(eventName, objName)
        if( not ItemLock.eventHandlers or not ItemLock.eventHandlers[eventName] ) then return nil end
        return ItemLock.eventHandlers[eventName][objName]
end

-- adds handler to the event handler list
function ItemLock:SetEventHandler(eventName, objName, handler)
        if ( not ItemLock.eventHandlers[eventName] ) then ItemLock.eventHandlers[eventName] = {} end
        ItemLock.eventHandlers[eventName][objName] = handler
end

-- puts given handler in front of the event handler of given object
function ItemLock:PreHookHandler(eventName, control, handler)
        ItemLock:SetEventHandler(eventName, control:GetName(), control:GetHandler(eventName) )
        control:SetHandler(eventName, handler)
end

-----------------------------------------

-- EVENT HANDLER FUNCTIONS -----

-- handler function for inventory item controls' OnMouseDoubleClick event
function ItemLock_InventoryItem_OnMouseDoubleClick(self, ...)
        
        -- make sure control contains an item
        if( self and self.dataEntry and self.dataEntry.data ) then      
                local bag = self.dataEntry.data.bagId
                local slot = self.dataEntry.data.slotIndex
                
                if( bag and slot ) then
                        -- check if deconstruction is forbidden
                        -- if so, return false to prevent selection of the item
                        if( ItemLock:DeconstructionSelectionHandler(bag, slot) ) then return false end
                end
        end
        
        -- call the original handler function
        local func = ItemLock:GetEventHandler("OnMouseDoubleClick", self:GetName())
        if ( not func ) then return false end
        
        return func(self, ...)
end

-- handler function for EVENT_INVENTORY_SLOT_LOCKED global event
function ItemLock_OnInventorySlotLocked(self, bag, slot)
        -- check if deconstruction is forbidden
        -- if so, clear item hold by cursor
        if( ItemLock:DeconstructionSelectionHandler(bag, slot) ) then ClearCursor() end
end

-- handler function for decontruction bag's OnEffectivelyShown event
function ItemLock_DECONSTRUCTION_BAG_OnEffectivelyShown(self, ...)
        
        if ( not self ) then return false end
        
        for i = 1, self:GetNumChildren() do
                -- override OnMouseDoubleClick event of inventory item controls
                if( self:GetChild(i):GetHandler("OnMouseDoubleClick") ~= ItemLock_InventoryItem_OnMouseDoubleClick ) then
                        ItemLock:PreHookHandler( "OnMouseDoubleClick", self:GetChild(i), ItemLock_InventoryItem_OnMouseDoubleClick )
                end
        end
        
        -- call the original handler function
        local func = ItemLock:GetEventHandler("OnEffectivelyShown", self:GetName())
        if ( not func ) then return false end
        
        return func(self, ...)
end

-- handler function for decontruction bag's OnMouseWheel event
function ItemLock_DECONSTRUCTION_BAG_OnMouseWheel(self, ...)
        
        if ( not self ) then return false end
        
        for i = 1, self:GetNumChildren() do
                -- override OnMouseDoubleClick event of inventory item controls
                if( self:GetChild(i):GetHandler("OnMouseDoubleClick") ~= ItemLock_InventoryItem_OnMouseDoubleClick ) then
                        ItemLock:PreHookHandler( "OnMouseDoubleClick", self:GetChild(i), ItemLock_InventoryItem_OnMouseDoubleClick )
                end
        end
        
        -- call the original handler function
        local func = ItemLock:GetEventHandler("OnMouseWheel", self:GetName())
        if ( not func ) then return false end
        
        return func(self, ...)
end
-----------------------------------------

------- Entry Point ----------------
local function OnAddOnLoaded(eventCode, addOnName)
        if (addOnName ~= "ItemLock") then
                return
        end
        
        -- create and initialize variables
        ItemLock:New()
        ItemLock:Init()
end

------- Entry Point Register --------
EVENT_MANAGER:RegisterForEvent("Event_ItemLock_Loaded", EVENT_ADD_ON_LOADED, OnAddOnLoaded)

Compare with Previous | Blame