diff --git a/Shopkeeper.lua b/Shopkeeper.lua
index d477a48..d379860 100644
--- a/Shopkeeper.lua
+++ b/Shopkeeper.lua
@@ -1,501 +1,9 @@
-- Shopkeeper Main Addon File
--- Last Updated August 8, 2014
+-- Last Updated August 10, 2014
-- Written July 2014 by Dan Stone (@khaibit) - dankitymao@gmail.com
-- Released under terms in license accompanying this file.
-- Distribution without license is prohibited!
--- Workaround because GetDisplayName() is broken
--- Maybe not needed anymore, will test
-function Shopkeeper.GetAccountName()
- local acctName = GetDisplayName()
- if acctName == nil or acctName == "" then
- -- Hopefully, they're in a guild and we can use GetPlayerGuildMemberIndex
- if GetNumGuilds() > 0 then
- acctName = GetGuildMemberInfo(GetGuildId(1), GetPlayerGuildMemberIndex(GetGuildId(1)))
- -- But if they're in no guilds, we have to use the AccountName CVar, which only works
- -- if they saved their account name on the login page. Best we can do with patch 1.2.3
- -- breaking GetDisplayName(), but if they aren't in any guilds, why are they using this
- -- addon anyway?
- else
- acctName = "@" .. GetCVar("AccountName")
- end
- end
- return acctName
-end
-
--- Translate from the i18n table
-function Shopkeeper.translate(stringName)
- local result = Shopkeeper.i18n.localized[stringName]
- assert(result, ("The id %q was not found in the current locale"):format(stringName))
- return result
-end
-
-function Shopkeeper.localizedNumber(numberValue)
- local stringPrice = numberValue
- -- Insert thousands separators for the price
- -- local stringPrice = numberValue
- local subString = "%1" .. Shopkeeper.translate("thousandsSep") .."%2"
- while true do
- stringPrice, k = string.gsub(stringPrice, "^(-?%d+)(%d%d%d)", subString)
- if (k == 0) then break end
- end
-
- return stringPrice
-end
-
--- Create a textual representation of a time interval
--- (X and Y) or Z in LUA is the equivalent of C-style
--- ternary syntax X ? Y : Z so long as Y is not false or nil
-function Shopkeeper.textTimeSince(theTime, useLowercase)
- local secsSince = GetTimeStamp() - theTime
- if secsSince < 60 then
- return ((useLowercase and zo_strformat(Shopkeeper.translate('timeSecondsAgoLC'), secsSince)) or
- zo_strformat(Shopkeeper.translate('timeSecondsAgo'), secsSince))
- elseif secsSince < 3600 then
- return ((useLowercase and zo_strformat(Shopkeeper.translate('timeMinutesAgoLC'), math.floor(secsSince / 60.0))) or
- zo_strformat(Shopkeeper.translate('timeMinutesAgo'), math.floor(secsSince / 60.0)))
- elseif secsSince < 86400 then
- return ((useLowercase and zo_strformat(Shopkeeper.translate('timeHoursAgoLC'), math.floor(secsSince / 3600.0))) or
- zo_strformat(Shopkeeper.translate('timeHoursAgo'), math.floor(secsSince / 3600.0)))
- else
- return ((useLowercase and zo_strformat(Shopkeeper.translate('timeDaysAgoLC'), math.floor(secsSince / 86400.0))) or
- zo_strformat(Shopkeeper.translate('timeDaysAgo'), math.floor(secsSince / 86400.0)))
- end
-end
-
--- A utility function to grab all the keys of the sound table
--- to populate the options dropdown
-function Shopkeeper.soundKeys()
- local keyList = {}
- local keyIndex = 0
- for i = 1, #Shopkeeper.alertSounds do
- keyIndex = keyIndex + 1
- keyList[keyIndex] = Shopkeeper.alertSounds[i].name
- end
-
- return keyList
-end
-
--- A utility function to find the key associated with a given value in
--- the sounds table. Best we can do is a linear search unfortunately,
--- but it's a small table.
-function Shopkeeper.searchSounds(sound)
- for i, theSound in ipairs(Shopkeeper.alertSounds) do
- if theSound.sound == sound then return theSound.name end
- end
-
- -- If we hit this point, we didn't find what we were looking for
- return nil
-end
-
-function Shopkeeper.searchSoundNames(name)
- for i,theSound in ipairs(Shopkeeper.alertSounds) do
- if theSound.name == name then return theSound.sound end
- end
-end
-
--- Handle the OnMoveStop event for the window
-function Shopkeeper.OnWindowMoveStop()
- Shopkeeper.savedVariables.winLeft = ShopkeeperWindow:GetLeft()
- Shopkeeper.savedVariables.winTop = ShopkeeperWindow:GetTop()
- Shopkeeper.savedVariables.miniWinLeft = ShopkeeperMiniWindow:GetLeft()
- Shopkeeper.savedVariables.miniWinTop = ShopkeeperMiniWindow:GetTop()
-end
-
-function Shopkeeper.OnStatsWindowMoveStop()
- Shopkeeper.savedVariables.statsWinLeft = ShopkeeperStatsWindow:GetLeft()
- Shopkeeper.savedVariables.statsWinTop = ShopkeeperStatsWindow:GetTop()
-end
-
--- Restore the window position from saved vars
-function Shopkeeper:RestoreWindowPosition()
- local left = self.savedVariables.winLeft
- local top = self.savedVariables.winTop
- local statsLeft = self.savedVariables.statsWinLeft
- local statsTop = self.savedVariables.statsWinTop
- local miniLeft = self.savedVariables.miniWinLeft
- local miniTop = self.savedVariables.miniWinTop
-
- ShopkeeperWindow:ClearAnchors()
- ShopkeeperStatsWindow:ClearAnchors()
- ShopkeeperMiniWindow:ClearAnchors()
- ShopkeeperWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
- ShopkeeperStatsWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, statsLeft, statsTop)
- ShopkeeperMiniWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, miniLeft, miniTop)
-end
-
--- Handle the changing of main window font settings
-function Shopkeeper:UpdateFonts()
- local LMP = LibStub("LibMediaProvider-1.0")
- if LMP then
- local font = LMP:Fetch('font', Shopkeeper.savedVariables.windowFont)
- local look = string.format('%s|16', font)
- local titleLook = string.format('%s|22', font)
- local headerLook = string.format('%s|20', font)
- local miniLook = string.format('%s|12', font)
- local miniTitleLook = string.format('%s|18', font)
- local miniHeaderLook = string.format('%s|16', font)
- ShopkeeperWindowSearchLabel:SetFont(look)
- ShopkeeperWindowSearchBox:SetFont(look)
- ShopkeeperWindowTitle:SetFont(titleLook)
- ShopkeeperWindowBuyer:SetFont(headerLook)
- ShopkeeperWindowGuild:SetFont(headerLook)
- ShopkeeperWindowItemName:SetFont(headerLook)
- ShopkeeperWindowSellTime:SetFont(headerLook)
- ShopkeeperWindowPrice:SetFont(headerLook)
- ShopkeeperSwitchViewButton:SetFont(look)
- ShopkeeperPriceSwitchButton:SetFont(look)
- ShopkeeperResetButton:SetFont(look)
- ShopkeeperRefreshButton:SetFont(look)
- ShopkeeperMiniWindowSearchLabel:SetFont(miniLook)
- ShopkeeperMiniWindowSearchBox:SetFont(miniLook)
- ShopkeeperMiniWindowTitle:SetFont(miniTitleLook)
- ShopkeeperMiniWindowGuild:SetFont(miniHeaderLook)
- ShopkeeperMiniWindowItemName:SetFont(miniHeaderLook)
- ShopkeeperMiniWindowSellTime:SetFont(miniHeaderLook)
- ShopkeeperMiniWindowPrice:SetFont(miniHeaderLook)
- ShopkeeperMiniSwitchViewButton:SetFont(miniLook)
- ShopkeeperMiniPriceSwitchButton:SetFont(miniLook)
- ShopkeeperMiniResetButton:SetFont(miniLook)
- ShopkeeperMiniRefreshButton:SetFont(miniLook)
-
- ShopkeeperStatsWindowTitle:SetFont(titleLook)
- ShopkeeperStatsWindowItemsSoldLabel:SetFont(look)
- ShopkeeperStatsWindowTotalGoldLabel:SetFont(look)
- ShopkeeperStatsWindowBiggestSaleLabel:SetFont(look)
- ShopkeeperStatsWindowSliderSettingLabel:SetFont(look)
- ShopkeeperStatsWindowSliderLabel:SetFont(look)
-
- for i = 1, #Shopkeeper.DataRows do
- local dataRow = Shopkeeper.DataRows[i]
- dataRow:GetNamedChild("Buyer"):SetFont(look)
- dataRow:GetNamedChild("Guild"):SetFont(look)
- dataRow:GetNamedChild("ItemName"):SetFont(look)
- dataRow:GetNamedChild("Quantity"):SetFont(look)
- dataRow:GetNamedChild("SellTime"):SetFont(look)
- dataRow:GetNamedChild("Price"):SetFont(look)
- if i <= #Shopkeeper.MiniDataRows then
- local miniDataRow = Shopkeeper.MiniDataRows[i]
- miniDataRow:GetNamedChild("Guild"):SetFont(miniLook)
- miniDataRow:GetNamedChild("ItemName"):SetFont(miniLook)
- miniDataRow:GetNamedChild("Quantity"):SetFont(miniLook)
- miniDataRow:GetNamedChild("SellTime"):SetFont(miniLook)
- miniDataRow:GetNamedChild("Price"):SetFont(miniLook)
- end
- end
- end
-end
-
--- Item tooltips
-function Shopkeeper:ShowToolTip(itemName, itemButton)
- InitializeTooltip(ItemTooltip, itemButton)
- ItemTooltip:SetLink(itemName)
-end
-
--- Clear a given row's data
-function Shopkeeper.ClearDataRow(index)
- if index < 1 or index > 15 then
- return
- end
-
- local dataRow = Shopkeeper.DataRows[index]
- dataRow:GetNamedChild("Buyer"):SetText("")
- dataRow:GetNamedChild("Buyer"):SetHandler("OnMouseDoubleClick", nil)
- dataRow:GetNamedChild("Guild"):SetText("")
- dataRow:GetNamedChild("ItemIcon"):SetTexture(nil)
- dataRow:GetNamedChild("ItemIcon"):SetHidden(true)
- local itemCell = dataRow:GetNamedChild("ItemName")
- itemCell:SetText("")
- itemCell:SetHandler("OnMouseDoubleClick", nil)
- itemCell:SetHandler("OnMouseEnter", nil)
- dataRow:GetNamedChild("Quantity"):SetText("")
- dataRow:GetNamedChild("SellTime"):SetText("")
- dataRow:GetNamedChild("Price"):SetText("")
-end
-
-function Shopkeeper.ClearMiniDataRow(index)
- if index < 1 or index > 8 then
- return
- end
-
- local dataRow = Shopkeeper.MiniDataRows[index]
- dataRow:GetNamedChild("Guild"):SetText("")
- dataRow:GetNamedChild("ItemIcon"):SetTexture(nil)
- dataRow:GetNamedChild("ItemIcon"):SetHidden(true)
- local itemCell = dataRow:GetNamedChild("ItemName")
- itemCell:SetText("")
- itemCell:SetHandler("OnMouseDoubleClick", nil)
- itemCell:SetHandler("OnMouseEnter", nil)
- dataRow:GetNamedChild("Quantity"):SetText("")
- dataRow:GetNamedChild("SellTime"):SetText("")
- dataRow:GetNamedChild("Price"):SetText("")
-end
-
--- Fill out a row with the given data
-function Shopkeeper.SetDataRow(index, buyer, guild, itemName, icon, quantity, sellTime, price, seller)
- if index < 1 or index > 15 then return end
-
- local dataRow = Shopkeeper.DataRows[index]
-
- -- Some extra stuff for the Buyer cell to handle double-click and color changes
- local buyerCell = dataRow:GetNamedChild("Buyer")
- buyerCell:SetText(buyer)
- -- If the seller is the player, color the buyer green. Otherwise, blue.
- local acctName = Shopkeeper.GetAccountName()
- if seller == acctName then
- buyerCell:SetNormalFontColor(0.18, 0.77, 0.05, 1)
- buyerCell:SetPressedFontColor(0.18, 0.77, 0.05, 1)
- buyerCell:SetMouseOverFontColor(0.32, 0.90, 0.18, 1)
- else
- buyerCell:SetNormalFontColor(0.21, 0.54, 0.94, 1)
- buyerCell:SetPressedFontColor(0.21, 0.54, 0.94, 1)
- buyerCell:SetMouseOverFontColor(0.34, 0.67, 1, 1)
- end
- buyerCell:SetHandler("OnMouseDoubleClick", function()
- if SCENE_MANAGER.currentScene.name == "mailSend" then
- ZO_MailSendToField:SetText("")
- ZO_MailSendToField:SetText(ZO_MailSendToField:GetText() .. buyer)
- else
- ZO_ChatWindowTextEntryEditBox:SetText("/w " .. buyer .. " " .. ZO_ChatWindowTextEntryEditBox:GetText())
- end
- end)
- local buyerCellLabel = buyerCell:GetLabelControl()
- buyerCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-
- -- Guild cell
- dataRow:GetNamedChild("Guild"):SetText(guild)
- local guildCellLabel = dataRow:GetNamedChild("Guild"):GetLabelControl()
- guildCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-
- -- Item Icon
- dataRow:GetNamedChild("ItemIcon"):SetHidden(false)
- dataRow:GetNamedChild("ItemIcon"):SetTexture(icon)
-
- -- Item name cell
- local itemCell = dataRow:GetNamedChild("ItemName")
- itemCell:SetText(zo_strformat("<<t:1>>", itemName))
- -- Insert the item link into the chat box, with a quick substitution so brackets show up
- itemCell:SetHandler("OnMouseDoubleClick", function()
- ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. string.gsub(itemName, "|H0", "|H1"))
- end)
- itemCell:SetHandler("OnMouseEnter", function() Shopkeeper:ShowToolTip(itemName, itemCell) end)
- itemCell:SetHandler("OnMouseExit", function() ClearTooltip(ItemTooltip) end)
- local itemCellLabel = itemCell:GetLabelControl()
- itemCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-
- -- Quantity cell
- dataRow:GetNamedChild("Quantity"):SetText("x" .. quantity)
-
- -- Sale time cell
- dataRow:GetNamedChild("SellTime"):SetText(sellTime)
-
- -- Handle the setting of whether or not to show pre-cut sale prices
- -- math.floor(number + 0.5) is a quick shorthand way to round for
- -- positive values.
- local dispPrice = price
- if Shopkeeper.savedVariables.showFullPrice then
- if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
- dispPrice = math.floor((dispPrice / quantity) + 0.5)
- end
- else
- local cutPrice = price * (1 - (GetTradingHouseCutPercentage() / 100))
- if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
- cutPrice = cutPrice / quantity
- end
- dispPrice = math.floor(cutPrice + 0.5)
- end
-
- -- Insert thousands separators for the price
- local stringPrice = Shopkeeper.localizedNumber(dispPrice)
-
- -- Finally, set the price
- dataRow:GetNamedChild("Price"):SetText(stringPrice .. " " .. string.format("|t16:16:%s|t","EsoUI/Art/currency/currency_gold.dds"))
-end
-
--- Fill out a row with the given data
-function Shopkeeper.SetMiniDataRow(index, guild, itemName, icon, quantity, sellTime, price, seller)
- if index < 1 or index > 8 then return end
-
- local dataRow = Shopkeeper.MiniDataRows[index]
-
- -- Guild cell
- dataRow:GetNamedChild("Guild"):SetText(guild)
- local guildCellLabel = dataRow:GetNamedChild("Guild"):GetLabelControl()
- guildCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-
- -- Item Icon
- dataRow:GetNamedChild("ItemIcon"):SetHidden(false)
- dataRow:GetNamedChild("ItemIcon"):SetTexture(icon)
-
- -- Item name cell
- local itemCell = dataRow:GetNamedChild("ItemName")
- itemCell:SetText(zo_strformat("<<t:1>>", itemName))
- -- Insert the item link into the chat box, with a quick substitution so brackets show up
- itemCell:SetHandler("OnMouseDoubleClick", function()
- ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. string.gsub(itemName, "|H0", "|H1"))
- end)
- itemCell:SetHandler("OnMouseEnter", function() Shopkeeper:ShowToolTip(itemName, itemCell) end)
- itemCell:SetHandler("OnMouseExit", function() ClearTooltip(ItemTooltip) end)
- local itemCellLabel = itemCell:GetLabelControl()
- itemCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
-
- -- Quantity cell
- dataRow:GetNamedChild("Quantity"):SetText("x" .. quantity)
-
- -- Sale time cell
- dataRow:GetNamedChild("SellTime"):SetText(sellTime)
-
- -- Handle the setting of whether or not to show pre-cut sale prices
- -- math.floor(number + 0.5) is a quick shorthand way to round for
- -- positive values.
- local dispPrice = price
- if Shopkeeper.savedVariables.showFullPrice then
- if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
- dispPrice = math.floor((dispPrice / quantity) + 0.5)
- end
- else
- local cutPrice = price * (1 - (GetTradingHouseCutPercentage() / 100))
- if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
- cutPrice = cutPrice / quantity
- end
- dispPrice = math.floor(cutPrice + 0.5)
- end
-
- -- Insert thousands separators for the price
- local stringPrice = Shopkeeper.localizedNumber(dispPrice)
-
- -- Finally, set the price
- dataRow:GetNamedChild("Price"):SetText(stringPrice .. " " .. string.format("|t16:16:%s|t","EsoUI/Art/currency/currency_gold.dds"))
-end
-
--- Build the data rows based on the position of the slider
-function Shopkeeper.DisplayRows()
- if Shopkeeper.savedVariables.viewSize == "full" then
- local startIndex = Shopkeeper.shopSlider:GetValue()
- if startIndex + #Shopkeeper.DataRows > #Shopkeeper.SearchTable then
- startIndex = #Shopkeeper.SearchTable - #Shopkeeper.DataRows
- end
-
- if startIndex < 1 then startIndex = 0 end
-
- -- Hide the slider if there's less than a full page of results
- Shopkeeper.shopSlider:SetHidden(#Shopkeeper.SearchTable < 16)
-
- for i = 1, #Shopkeeper.DataRows do
- local rowIndex = i + startIndex
- if rowIndex > #Shopkeeper.SearchTable then
- Shopkeeper.ClearDataRow(i)
- Shopkeeper.shopSlider:SetHidden(true)
- else
- local scanResult = Shopkeeper.SearchTable[rowIndex]
-
- Shopkeeper.SetDataRow(i, scanResult[1], scanResult[2], scanResult[3], scanResult[4], scanResult[5], Shopkeeper.textTimeSince(scanResult[6], false), scanResult[7], scanResult[8])
- end
- end
-
- -- Scale the slider's range to the number of items we have minus the number of rows
- local sliderMax = 0
- local tableToUse = Shopkeeper.ScanResults
- if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
- if #tableToUse > 15 then sliderMax = (#tableToUse - 15) end
- Shopkeeper.shopSlider:SetMinMax(0, sliderMax)
- else
- local startIndex = Shopkeeper.miniShopSlider:GetValue()
- if startIndex + #Shopkeeper.MiniDataRows > #Shopkeeper.SearchTable then
- startIndex = #Shopkeeper.SearchTable - #Shopkeeper.MiniDataRows
- end
-
- if startIndex < 1 then startIndex = 0 end
-
- -- Hide the slider if there's less than a full page of results
- Shopkeeper.miniShopSlider:SetHidden(#Shopkeeper.SearchTable < 9)
-
- for i = 1, #Shopkeeper.MiniDataRows do
- local rowIndex = i + startIndex
- if rowIndex > #Shopkeeper.SearchTable then
- Shopkeeper.ClearMiniDataRow(i)
- Shopkeeper.miniShopSlider:SetHidden(true)
- else
- local scanResult = Shopkeeper.SearchTable[rowIndex]
-
- Shopkeeper.SetMiniDataRow(i, scanResult[2], scanResult[3], scanResult[4], scanResult[5], Shopkeeper.textTimeSince(scanResult[6], false), scanResult[7], scanResult[8])
- end
- end
-
- -- Scale the slider's range to the number of items we have minus the number of rows
- local sliderMax = 0
- local tableToUse = Shopkeeper.ScanResults
- if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
- if #tableToUse > 8 then sliderMax = (#tableToUse - 8) end
- Shopkeeper.miniShopSlider:SetMinMax(0, sliderMax)
- end
-end
-
-function Shopkeeper.ToggleViewMode()
- if Shopkeeper.savedVariables.viewSize == "full" then
- Shopkeeper.savedVariables.viewSize = "half"
- ShopkeeperWindow:SetHidden(true)
- Shopkeeper.DisplayRows()
- ShopkeeperMiniWindow:SetHidden(false)
-
- if Shopkeeper.savedVariables.openWithMail then
- MAIL_INBOX_SCENE:RemoveFragment(Shopkeeper.uiFragment)
- MAIL_SEND_SCENE:RemoveFragment(Shopkeeper.uiFragment)
- MAIL_INBOX_SCENE:AddFragment(Shopkeeper.miniUiFragment)
- MAIL_SEND_SCENE:AddFragment(Shopkeeper.miniUiFragment)
- end
-
- if Shopkeeper.savedVariables.openWithStore then
- TRADING_HOUSE_SCENE:RemoveFragment(Shopkeeper.uiFragment)
- TRADING_HOUSE_SCENE:AddFragment(Shopkeeper.miniUiFragment)
- end
- else
- Shopkeeper.savedVariables.viewSize = "full"
- ShopkeeperMiniWindow:SetHidden(true)
- Shopkeeper.DisplayRows()
- ShopkeeperWindow:SetHidden(false)
-
- if Shopkeeper.savedVariables.openWithMail then
- MAIL_INBOX_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
- MAIL_SEND_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
- MAIL_INBOX_SCENE:AddFragment(Shopkeeper.uiFragment)
- MAIL_SEND_SCENE:AddFragment(Shopkeeper.uiFragment)
- end
-
- if Shopkeeper.savedVariables.openWithStore then
- TRADING_HOUSE_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
- TRADING_HOUSE_SCENE:AddFragment(Shopkeeper.uiFragment)
- end
- end
-end
-
--- Set the visibility status of the main window to the opposite of its current status
-function Shopkeeper.ToggleShopkeeperWindow()
- if Shopkeeper.savedVariables.viewSize == "full" then
- ShopkeeperMiniWindow:SetHidden(true)
- if ShopkeeperWindow:IsHidden() then
- Shopkeeper.DisplayRows()
- SetGameCameraUIMode(true)
- end
-
- ShopkeeperWindow:SetHidden(not ShopkeeperWindow:IsHidden())
- else
- ShopkeeperWindow:SetHidden(true)
- if ShopkeeperMiniWindow:IsHidden() then
- Shopkeeper.DisplayRows()
- SetGameCameraUIMode(true)
- end
-
- ShopkeeperMiniWindow:SetHidden(not ShopkeeperMiniWindow:IsHidden())
- end
-end
-
--- Set the visibility status of the stats window to the opposite of its current status
-function Shopkeeper.ToggleShopkeeperStatsWindow()
- if ShopkeeperStatsWindow:IsHidden() then Shopkeeper.UpdateStatsWindow() end
- ShopkeeperStatsWindow:SetHidden(not ShopkeeperStatsWindow:IsHidden())
-end
-
-- Sort the scan results by 'ordering' order (asc/desc).
-- We sort both the search result table and the master scan results table because either we do it
-- now or we sort at separate times and try to keep track of what state each is in. No thanks!
@@ -626,12 +134,15 @@ function Shopkeeper.TimeSort()
end
end
+-- Calculate some stats based on the player's sales
+-- And return them as a table.
function Shopkeeper.SalesStats(statsDays)
local itemsSold = 0
local goldMade = 0
local largestSingle = {0, nil}
local oldestTime = 0
local newestTime = 0
+ local kioskSales = 0
-- 86,400 seconds in a day; this will be the epoch time statsDays ago
local statsDaysEpoch = GetTimeStamp() - (86400 * statsDays)
@@ -641,6 +152,9 @@ function Shopkeeper.SalesStats(statsDays)
local theItem = Shopkeeper.SelfSales[i]
if statsDays == 0 or theItem[6] > statsDaysEpoch then
itemsSold = itemsSold + 1
+ if #theItem > 8 and theItem[9] then
+ kioskSales = kioskSales + 1
+ end
goldMade = goldMade + theItem[7]
if oldestTime == 0 or theItem[6] < oldestTime then oldestTime = theItem[6] end
if newestTime == 0 or theItem[6] > newestTime then newestTime = theItem[6] end
@@ -654,6 +168,10 @@ function Shopkeeper.SalesStats(statsDays)
local dayWindow = 1
if timeWindow > 86400 then dayWindow = math.floor(timeWindow / 86400) + 1 end
local goldPerDay = math.floor(goldMade / dayWindow)
+ local kioskPercentage = 0
+ if itemsSold > 0 then
+ kioskPercentage = math.floor((kioskSales / itemsSold) * 100)
+ end
-- If they have the option set to show prices post-cut, calculate that here
if not Shopkeeper.savedVariables.showFullPrice then
@@ -668,11 +186,13 @@ function Shopkeeper.SalesStats(statsDays)
numDays = dayWindow,
totalGold = goldMade,
avgGold = goldPerDay,
- biggestSale = largestSingle }
+ biggestSale = largestSingle,
+ kioskPercent = kioskPercentage, }
end
+-- Update all the fields of the stats window based on the response from SalesStats()
function Shopkeeper.UpdateStatsWindow()
- local sliderLevel = Shopkeeper.statsSlider:GetValue()
+ local sliderLevel = ShopkeeperStatsWindowSlider:GetValue()
if sliderLevel == 0 then
ShopkeeperStatsWindowSliderSettingLabel:SetText(Shopkeeper.translate('statsTimeAll'))
else
@@ -680,7 +200,7 @@ function Shopkeeper.UpdateStatsWindow()
end
local newStats = Shopkeeper.SalesStats(sliderLevel)
- ShopkeeperStatsWindowItemsSoldLabel:SetText(string.format(Shopkeeper.translate('statsItemsSold'), Shopkeeper.localizedNumber(newStats['numSold'])))
+ ShopkeeperStatsWindowItemsSoldLabel:SetText(string.format(Shopkeeper.translate('statsItemsSold'), Shopkeeper.localizedNumber(newStats['numSold']), newStats['kioskPercent']))
ShopkeeperStatsWindowTotalGoldLabel:SetText(string.format(Shopkeeper.translate('statsTotalGold'), Shopkeeper.localizedNumber(newStats['totalGold']), Shopkeeper.localizedNumber(newStats['avgGold'])))
ShopkeeperStatsWindowBiggestSaleLabel:SetText(string.format(Shopkeeper.translate('statsBiggest'), zo_strformat("<<t:1>>", newStats['biggestSale'][2]), Shopkeeper.localizedNumber(newStats['biggestSale'][1])))
end
@@ -796,7 +316,7 @@ function Shopkeeper:LibAddonInit()
Shopkeeper.savedVariables.scanFreq = value
EVENT_MANAGER:UnregisterForUpdate(Shopkeeper.name)
local scanInterval = value * 1000
- EVENT_MANAGER:RegisterForUpdate(Shopkeeper.name, scanInterval, function() Shopkeeper:ScanStores(false, false) end)
+ EVENT_MANAGER:RegisterForUpdate(Shopkeeper.name, scanInterval, function() Shopkeeper:ScanStores(false) end)
end,
},
[6] = {
@@ -825,34 +345,12 @@ function Shopkeeper:LibAddonInit()
end
end
--- Handle scrolling the main window
-function Shopkeeper.OnSliderMouseWheel(self, delta)
- if Shopkeeper.savedVariables.viewSize == "full" then
- local oldSliderLevel = Shopkeeper.shopSlider:GetValue()
- local newSliderLevel = oldSliderLevel - delta
- Shopkeeper.shopSlider:SetValue(newSliderLevel)
- else
- local oldSliderLevel = Shopkeeper.miniShopSlider:GetValue()
- local newSliderLevel = oldSliderLevel - delta
- Shopkeeper.miniShopSlider:SetValue(newSliderLevel)
- end
-end
-
--- Update the table if the slider moved
-function Shopkeeper.OnSliderMoved(self, sliderLevel, eventReason)
- Shopkeeper.DisplayRows()
-end
-
-function Shopkeeper.OnStatsSliderMoved(self, sliderLevel, eventReason)
- Shopkeeper.UpdateStatsWindow()
-end
-
-- Filters the ScanResults (or SelfSales) table into the SearchTable,
-- using the Shopkeeper.viewMode to determine which one to use.
function Shopkeeper.DoSearch(searchText)
Shopkeeper.SearchTable = {}
local searchTerm = string.lower(searchText)
- local acctName = Shopkeeper.GetAccountName()
+ local acctName = GetDisplayName()
local tableToUse = Shopkeeper.ScanResults
if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
@@ -935,7 +433,6 @@ end
-- and updates the displayed table, sending a message to chat if
-- the scan was initiated via the 'refresh' button.
function Shopkeeper:PostScan(doAlert)
- Shopkeeper.isScanning = false
if Shopkeeper.savedVariables.viewSize == "full" then
Shopkeeper.DoSearch(ShopkeeperWindowSearchBox:GetText())
else
@@ -946,10 +443,10 @@ function Shopkeeper:PostScan(doAlert)
local tableToUse = Shopkeeper.ScanResults
if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
if #tableToUse > 15 then sliderMax = (#tableToUse - 15) end
- Shopkeeper.shopSlider:SetMinMax(0, sliderMax)
+ ShopkeeperWindowSlider:SetMinMax(0, sliderMax)
sliderMax = 0
if #tableToUse > 8 then sliderMax = (#tableToUse - 8) end
- Shopkeeper.miniShopSlider:SetMinMax(0, sliderMax)
+ ShopkeeperMiniWindowSlider:SetMinMax(0, sliderMax)
if Shopkeeper.curSort[1] == "time" then
Shopkeeper.SortByTime(Shopkeeper.curSort[2])
@@ -971,6 +468,7 @@ function Shopkeeper:PostScan(doAlert)
local numSold = 0
local totalGold = 0
local numAlerts = #Shopkeeper.alertQueue
+ local lastEvent = {}
for i = 1, numAlerts do
local theEvent = table.remove(Shopkeeper.alertQueue, 1)
numSold = numSold + 1
@@ -996,25 +494,36 @@ function Shopkeeper:PostScan(doAlert)
-- false or nil.)
local alertSound = (i > 1) and SOUNDS.NONE or Shopkeeper.savedVariables.alertSoundName
- -- On-screen alert
+ -- On-screen alert - need to do something to avoid queueing identical messages in a row
if Shopkeeper.savedVariables.showAnnounceAlerts then
+
+ local textTime = Shopkeeper.textTimeSince(theEvent.saleTime, true)
+ local alertSuffix = ""
+ if lastEvent[1] ~= nil and theEvent.itemName == lastEvent[1].itemName and textTime == lastEvent[2] then
+ lastEvent[3] = lastEvent[3] + 1
+ alertSuffix = " (" .. lastEvent[3] .. ")"
+ else
+ lastEvent[1] = theEvent
+ lastEvent[2] = textTime
+ lastEvent[3] = 1
+ end
-- German word order differs so argument order also needs to be changed
-- Also due to plurality differences in German, need to differentiate
-- single item sold vs. multiple of an item sold.
if Shopkeeper.locale == "de" then
if theEvent.quant > 1 then
- CENTER_SCREEN_ANNOUNCE:AddMessage(EVENT_SKILL_RANK_UPDATE, CSA_EVENT_SMALL_TEXT, alertSound,
+ CENTER_SCREEN_ANNOUNCE:AddMessage("ShopkeeperAlert", CSA_EVENT_SMALL_TEXT, alertSound,
string.format(Shopkeeper.translate('salesAlertColor'), theEvent.quant, zo_strformat("<<t:1>>", theEvent.itemName),
- stringPrice, theEvent.guild, Shopkeeper.textTimeSince(theEvent.saleTime, true)))
+ stringPrice, theEvent.guild, textTime) .. alertSuffix)
else
- CENTER_SCREEN_ANNOUNCE:AddMessage(EVENT_SKILL_RANK_UPDATE, CSA_EVENT_SMALL_TEXT, alertSound,
- string.format(Shopkeeper.translate('salesAlertColorSingle'), zo_strformat("<<t:1>>", theEvent.itemName),
- stringPrice, theEvent.guild, Shopkeeper.textTimeSince(theEvent.saleTime, true)))
+ CENTER_SCREEN_ANNOUNCE:AddMessage("ShopkeeperAlert", CSA_EVENT_SMALL_TEXT, alertSound,
+ string.format(Shopkeeper.translate('salesAlertColorSingle'),zo_strformat("<<t:1>>", theEvent.itemName),
+ stringPrice, theEvent.guild, textTime) .. alertSuffix)
end
else
- CENTER_SCREEN_ANNOUNCE:AddMessage(EVENT_SKILL_RANK_UPDATE, CSA_EVENT_SMALL_TEXT, alertSound,
+ CENTER_SCREEN_ANNOUNCE:AddMessage("ShopkeeperAlert", CSA_EVENT_SMALL_TEXT, alertSound,
string.format(Shopkeeper.translate('salesAlertColor'), zo_strformat("<<t:1>>", theEvent.itemName),
- theEvent.quant, stringPrice, theEvent.guild, Shopkeeper.textTimeSince(theEvent.saleTime, true)))
+ theEvent.quant, stringPrice, theEvent.guild, textTime) .. alertSuffix)
end
end
@@ -1042,7 +551,7 @@ function Shopkeeper:PostScan(doAlert)
local stringPrice = Shopkeeper.localizedNumber(totalGold)
if Shopkeeper.savedVariables.showAnnounceAlerts then
- CENTER_SCREEN_ANNOUNCE:AddMessage(EVENT_SKILL_RANK_UPDATE, CSA_EVENT_SMALL_TEXT, Shopkeeper.savedVariables.alertSoundName,
+ CENTER_SCREEN_ANNOUNCE:AddMessage("ShopkeeperAlert", CSA_EVENT_SMALL_TEXT, Shopkeeper.savedVariables.alertSoundName,
string.format(Shopkeeper.translate('salesGroupAlertColor'), numSold, stringPrice))
else
CHAT_SYSTEM:AddMessage(string.format("[Shopkeeper] " .. Shopkeeper.translate('salesGroupAlert'),
@@ -1055,75 +564,102 @@ function Shopkeeper:PostScan(doAlert)
Shopkeeper.DisplayRows()
end
+-- Makes sure all the necessary data is there, and adds the passed-in event theEvent
+-- to the ScanResults and SelfSales table. If doAlert is true, also adds it to
+-- alertQueue, which means an alert may fire during PostScan.
+function Shopkeeper:InsertEvent(theEvent, doAlert)
+ local thePlayer = string.lower(GetDisplayName())
+
+ if theEvent.itemName ~= nil and theEvent.seller ~= nil and theEvent.buyer ~= nil and theEvent.salePrice ~= nil then
+ -- Grab the icon
+ local itemIcon, _, _, _ = GetItemLinkInfo(theEvent.itemName)
+
+ -- Insert the entry into the ScanResults table
+ table.insert(Shopkeeper.ScanResults, {theEvent.buyer, theEvent.guild, theEvent.itemName, itemIcon,
+ theEvent.quant, theEvent.saleTime, theEvent.salePrice,
+ theEvent.seller, theEvent.kioskSale})
+
+ -- And then, if it's the player's sale, insert into that table
+ if string.lower(theEvent.seller) == thePlayer then
+ table.insert(Shopkeeper.SelfSales, {theEvent.buyer, theEvent.guild, theEvent.itemName, itemIcon,
+ theEvent.quant, theEvent.saleTime, theEvent.salePrice,
+ theEvent.seller, theEvent.kioskSale})
+ if doAlert and (Shopkeeper.savedVariables.showChatAlerts or Shopkeeper.savedVariables.showAnnounceAlerts) then
+ table.insert(Shopkeeper.alertQueue, theEvent)
+ end
+ end
+ end
+end
+
-- Actually carries out of the scan of a specific guild store's sales history.
--- If checkOlder is true, will request older events first if there are any.
--- Inserts all events that occurred after guildID guild's last scan into the ScanResults table.
--- Inserts all events that occurred after guildID guild's last scan and were sold by the player
--- into the SelfSales table.
+-- Grabs all the members of the guild first to determine if a sale came from the
+-- guild's kiosk (guild trader) or not.
+-- Calls InsertEvent to actually insert the event into the ScanResults and SelfSales
+-- tables.
function Shopkeeper:DoScan(guildID, checkOlder, doAlert)
- local timeWindow = 10
- if Shopkeeper.missedLastScan[guildID] ~= nil and Shopkeeper.missedLastScan[guildID] == true then
- timeWindow = 25
- end
- local thePlayer = string.lower(Shopkeeper.GetAccountName())
local numEvents = GetNumGuildEvents(guildID, GUILD_HISTORY_SALES)
- for i = 1, numEvents do
- local theEvent = {}
- _, theEvent.secsSince, theEvent.seller, theEvent.buyer,
- theEvent.quant, theEvent.itemName, theEvent.salePrice, _ = GetGuildEventInfo(guildID, GUILD_HISTORY_SALES, i)
- theEvent.guild = GetGuildName(guildID)
- -- Only worry about items sold since our last scan
- if theEvent.secsSince ~= nil then
- theEvent.saleTime = Shopkeeper.requestTimestamp - theEvent.secsSince
-
- if Shopkeeper.acctSavedVariables.lastScan[guildID] == nil or GetDiffBetweenTimeStamps(theEvent.saleTime, (Shopkeeper.acctSavedVariables.lastScan[guildID] - timeWindow)) >= 0 then
- if theEvent.itemName ~= nil and theEvent.seller ~= nil and theEvent.buyer ~= nil and theEvent.salePrice ~= nil then
- -- Grab the icon
- local itemIcon, _, _, _ = GetItemLinkInfo(theEvent.itemName)
-
- -- If the seller is the player and this isn't a deep scan (and thus the first upon login or reset),
- -- queue up an alert
- if not checkOlder and (Shopkeeper.savedVariables.showChatAlerts or Shopkeeper.savedVariables.showAnnounceAlerts)
- and string.lower(theEvent.seller) == thePlayer then
- table.insert(Shopkeeper.alertQueue, theEvent)
- end
-
- -- Insert the entry into the ScanResults table
- table.insert(Shopkeeper.ScanResults, {theEvent.buyer, theEvent.guild, theEvent.itemName, itemIcon,
- theEvent.quant, theEvent.saleTime, theEvent.salePrice,
- theEvent.seller})
-
- -- And then, if it's the player's sale, insert into that table
- if string.lower(theEvent.seller) == thePlayer then
- table.insert(Shopkeeper.SelfSales, {theEvent.buyer, theEvent.guild, theEvent.itemName, itemIcon,
- theEvent.quant, theEvent.saleTime, theEvent.salePrice,
- theEvent.seller})
- end
+ local prevEvents = 0
+ if Shopkeeper.numEvents[guildID] ~= nil then prevEvents = Shopkeeper.numEvents[guildID] end
+
+ if numEvents > prevEvents then
+ local guildMemberInfo = {}
+ -- Index the table with the account names themselves as they're
+ -- (hopefully!) unique - search much faster
+ for i = 1, GetNumGuildMembers(guildID) do
+ local guildMemInfo, _, _, _, _ = GetGuildMemberInfo(guildID, i)
+ guildMemberInfo[string.lower(guildMemInfo)] = true
+ end
+
+ for i = (prevEvents + 1), numEvents do
+ local theEvent = {}
+ _, theEvent.secsSince, theEvent.seller, theEvent.buyer,
+ theEvent.quant, theEvent.itemName, theEvent.salePrice, _ = GetGuildEventInfo(guildID, GUILD_HISTORY_SALES, i)
+ theEvent.guild = GetGuildName(guildID)
+ theEvent.saleTime = GetTimeStamp() - theEvent.secsSince
+
+ -- If we didn't add an entry to guildMemberInfo earlier setting the
+ -- buyer's name index to true, then this was either bought at a kiosk
+ -- or the buyer left the guild after buying but before we scanned.
+ -- Close enough!
+ theEvent.kioskSale = (guildMemberInfo[string.lower(theEvent.buyer)] == nil)
+
+ -- If we're doing a deep scan, revert to timestamp checking
+ -- For reasons I cannot determine, I am getting items not previously
+ -- seen up to 13 seconds BEFORE the last call to RequestGuildHistoryCategoryNewest.
+ -- Bizarre, but adding this fudge factor hasn't resulted in dupes...yet.
+ if checkOlder then
+ if Shopkeeper.acctSavedVariables.lastScan[guildID] == nil or GetDiffBetweenTimeStamps(theEvent.saleTime, (Shopkeeper.acctSavedVariables.lastScan[guildID] - 13)) >= 0 then
+ Shopkeeper:InsertEvent(theEvent, false)
end
+
+ -- Otherwise, all new events are assumed good
+ -- Inspiration for event number-based handling from sirinsidiator
+ else
+ Shopkeeper:InsertEvent(theEvent, true)
end
end
end
+ -- We got through any new (to us) events, so update the timestamp and number of events
Shopkeeper.acctSavedVariables.lastScan[guildID] = Shopkeeper.requestTimestamp
+ Shopkeeper.numEvents[guildID] = numEvents
+
+ -- If we have another guild to scan, see if we need to check older and scan it
if guildID < GetNumGuilds() then
local nextGuild = guildID + 1
- local didScan = RequestGuildHistoryCategoryNewest(nextGuild, GUILD_HISTORY_SALES)
- if Shopkeeper.missedScan[nextGuild] ~= nil then Shopkeeper.missedLastScan[nextGuild] = Shopkeeper.missedScan[nextGuild]
- else Shopkeeper.missedLastScan[nextGuild] = false end
-
- if not didScan then
- Shopkeeper.missedScan[nextGuild] = true
- else
- Shopkeeper.missedScan[nextGuild] = false
- end
+ local nextCheckOlder = false
+ if Shopkeeper.numEvents[nextGuild] == nil or Shopkeeper.numEvents[nextGuild] == 0 then nextCheckOlder = true end
+ RequestGuildHistoryCategoryNewest(nextGuild, GUILD_HISTORY_SALES)
Shopkeeper.requestTimestamp = GetTimeStamp()
- if checkOlder then
- zo_callLater(function() Shopkeeper:ScanOlder(nextGuild, doAlert) end, 1250)
+ if nextCheckOlder then
+ zo_callLater(function() Shopkeeper:ScanOlder(nextGuild, doAlert) end, 1500)
else
- zo_callLater(function() Shopkeeper:DoScan(nextGuild , false, doAlert) end, 1250)
+ zo_callLater(function() Shopkeeper:DoScan(nextGuild, false, doAlert) end, 1500)
end
+ -- Otherwise, start the postscan routines
else
- zo_callLater(function() Shopkeeper:PostScan(doAlert) end, 1250)
+ Shopkeeper.isScanning = false
+ Shopkeeper:PostScan(doAlert)
end
end
@@ -1132,63 +668,46 @@ end
function Shopkeeper:ScanOlder(guildNum, doAlert)
local numEvents = GetNumGuildEvents(guildNum, GUILD_HISTORY_SALES)
local _, secsSince, _, _, _, _, _, _ = GetGuildEventInfo(guildNum, GUILD_HISTORY_SALES, numEvents)
- local lastScan = 0
- if Shopkeeper.acctSavedVariables.lastScan[guildNum] ~= nil then lastScan = Shopkeeper.acctSavedVariables.lastScan[guildNum] end
- if not DoesGuildHistoryCategoryHaveMoreEvents(guildNum, GUILD_HISTORY_SALES) or
- not RequestGuildHistoryCategoryOlder(guildNum, GUILD_HISTORY_SALES) or
- GetDiffBetweenTimeStamps(lastScan, GetTimeStamp() - secsSince) > 0 then
- zo_callLater(function() Shopkeeper:DoScan(guildNum, true, doAlert) end, 1250)
+ local secsSinceScan = nil
+ if Shopkeeper.acctSavedVariables.lastScan[guildNum] ~= nil then
+ secsSinceScan = GetTimeStamp() - Shopkeeper.acctSavedVariables.lastScan[guildNum]
+ end
+
+ if DoesGuildHistoryCategoryHaveMoreEvents(guildNum, GUILD_HISTORY_SALES) and
+ (secsSinceScan == nil or secsSinceScan > secsSince) then
+ RequestGuildHistoryCategoryOlder(guildNum, GUILD_HISTORY_SALES)
+ zo_callLater(function() Shopkeeper:ScanOlder(guildNum, doAlert) end, 1500)
else
- zo_callLater(function() Shopkeeper:ScanOlder(guildNum, doAlert) end, 1250)
+ zo_callLater(function() Shopkeeper:DoScan(guildNum, true, doAlert) end, 1500)
end
end
-- Scans all stores a player has access to with delays between them.
-function Shopkeeper:ScanStores(checkOlder, doAlert)
+function Shopkeeper:ScanStores(doAlert)
-- If it's been less than a minute since we last scanned the store,
-- don't do it again so we don't hammer the server either accidentally
-- or on purpose
- local timeLimit = GetTimeStamp() - 59
+ local timeLimit = GetTimeStamp() - 60
local guildNum = GetNumGuilds()
-- Nothing to scan!
if guildNum == 0 then return end
- if not Shopkeeper.isScanning and (Shopkeeper.acctSavedVariables.lastScan[1] == nil or timeLimit > Shopkeeper.acctSavedVariables.lastScan[1]) then
+
+ if not Shopkeeper.isScanning and ((Shopkeeper.acctSavedVariables.lastScan[1] == nil) or (timeLimit > Shopkeeper.acctSavedVariables.lastScan[1])) then
Shopkeeper.isScanning = true
+ local checkOlder = false
- -- We'll track if we get a true back here or not, because if it's false,
- -- someone checked this history manually recently and times may be off
- -- by up to 10-15 seconds because of that, and the next scan may get items
- -- that should have been caught by this one
- local didScan = RequestGuildHistoryCategoryNewest(1, GUILD_HISTORY_SALES)
-
- if Shopkeeper.missedScan[1] ~= nil then
- Shopkeeper.missedLastScan[1] = Shopkeeper.missedScan[1]
- else
- Shopkeeper.missedLastScan[1] = false
- end
-
- if not didScan then
- Shopkeeper.missedScan[1] = true
- else
- Shopkeeper.missedScan[1] = false
- end
+ if Shopkeeper.numEvents[1] == nil or Shopkeeper.numEvents[1] == 0 then checkOlder = true end
+ RequestGuildHistoryCategoryNewest(1, GUILD_HISTORY_SALES)
Shopkeeper.requestTimestamp = GetTimeStamp()
- if checkOlder then
- zo_callLater(function() Shopkeeper:ScanOlder(1, doAlert) end, 1250)
- else
- zo_callLater(function() Shopkeeper:DoScan(1, checkOlder, doAlert) end, 1250)
+ if checkOlder then
+ zo_callLater(function() Shopkeeper:ScanOlder(1, doAlert) end, 1500)
+ else
+ zo_callLater(function() Shopkeeper:DoScan(1, checkOlder, doAlert) end, 1500)
end
end
end
--- It's silly, but I have to re-set the fonts each time the UI reloads because I define defaults
--- in the .xml (at least as far as I can figure.) The PlayerActive event fires after each of these,
--- so it's a nice place to hook in for that.
-function Shopkeeper.PlayerActive()
- Shopkeeper:UpdateFonts()
-end
-
-- Handle the refresh button - do a scan if it's been more than a minute
-- since the last successful one.
function Shopkeeper.DoRefresh()
@@ -1199,12 +718,14 @@ function Shopkeeper.DoRefresh()
-- or on purpose
local timeLimit = timeStamp - 59
local guildNum = GetNumGuilds()
- if Shopkeeper.acctSavedVariables.lastScan[1] == nil or timeLimit > Shopkeeper.acctSavedVariables.lastScan[1] then
- CHAT_SYSTEM:AddMessage("[Shopkeeper] " .. Shopkeeper.translate('refreshStart'))
- Shopkeeper:ScanStores(false, true)
+ if guildNum > 0 then
+ if Shopkeeper.acctSavedVariables.lastScan[1] == nil or timeLimit > Shopkeeper.acctSavedVariables.lastScan[1] then
+ CHAT_SYSTEM:AddMessage("[Shopkeeper] " .. Shopkeeper.translate('refreshStart'))
+ Shopkeeper:ScanStores(true)
- else
- CHAT_SYSTEM:AddMessage("[Shopkeeper] " .. Shopkeeper.translate('refreshWait'))
+ else
+ CHAT_SYSTEM:AddMessage("[Shopkeeper] " .. Shopkeeper.translate('refreshWait'))
+ end
end
end
@@ -1218,11 +739,15 @@ function Shopkeeper.DoReset()
Shopkeeper.acctSavedVariables.scanHistory = {}
Shopkeeper.acctSavedVariables.lastScan = {}
Shopkeeper.DisplayRows()
- Shopkeeper:ScanStores(true, false)
+ Shopkeeper.isScanning = false
+ Shopkeeper.numEvents = {}
CHAT_SYSTEM:AddMessage("[Shopkeeper] " .. Shopkeeper.translate('resetDone'))
+ CHAT_SYSTEM:AddMessage("[Shopkeeper] " .. Shopkeeper.translate('refreshStart'))
+ Shopkeeper:ScanStores(true)
end
--- Set up the main window and the additional button added to the guild store interface
+-- Set up the labels and tooltips from translation files and do a couple other UI
+-- setup routines
function Shopkeeper:SetupShopkeeperWindow()
-- Shopkeeper button in guild store screen
local reopenShopkeeper = CreateControlFromVirtual("ShopkeeperReopenButton", ZO_TradingHouseLeftPane, "ZO_DefaultButton")
@@ -1265,236 +790,97 @@ function Shopkeeper:SetupShopkeeperWindow()
ShopkeeperStatsWindowTitle:SetText("Shopkeeper " .. Shopkeeper.translate('statsTitle'))
ShopkeeperStatsWindowSliderLabel:SetText(Shopkeeper.translate('statsDays'))
- -- Set up some helpful tooltips for the Buyer and Item column headers
+ -- Set up some helpful tooltips for the Buyer, Item, Time, and Price column headers
ShopkeeperWindowBuyer:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('buyerTooltip'))
- end)
-
- ShopkeeperWindowBuyer:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('buyerTooltip')) end)
ShopkeeperWindowItemName:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('itemTooltip'))
- end)
-
- ShopkeeperWindowItemName:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('itemTooltip')) end)
ShopkeeperMiniWindowItemName:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('itemTooltip'))
- end)
-
- ShopkeeperMiniWindowItemName:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('itemTooltip')) end)
ShopkeeperWindowSellTime:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortTimeTip'))
- end)
-
- ShopkeeperWindowSellTime:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortTimeTip')) end)
ShopkeeperMiniWindowSellTime:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortTimeTip'))
- end)
-
- ShopkeeperMiniWindowSellTime:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortTimeTip')) end)
ShopkeeperWindowPrice:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortPriceTip'))
- end)
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortPriceTip')) end)
- ShopkeeperWindowPrice:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
-
ShopkeeperMiniWindowPrice:SetHandler("OnMouseEnter", function(self)
- ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortPriceTip'))
- end)
-
- ShopkeeperMiniWindowPrice:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
-
+ ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sortPriceTip')) end)
-- View switch button
- local switchViews = CreateControlFromVirtual("ShopkeeperSwitchViewButton", ShopkeeperWindow, "ZO_DefaultButton")
- switchViews:SetAnchor(BOTTOMLEFT, ShopkeeperWindow, BOTTOMLEFT, 20, -5)
- switchViews:SetWidth(175)
- switchViews:SetText(Shopkeeper.translate('viewModeAllName'))
- switchViews:SetHandler("OnClicked", Shopkeeper.SwitchViewMode)
-
- local miniSwitchViews = CreateControlFromVirtual("ShopkeeperMiniSwitchViewButton", ShopkeeperMiniWindow, "ZO_DefaultButton")
- miniSwitchViews:SetAnchor(BOTTOMLEFT, ShopkeeperMiniWindow, BOTTOMLEFT, 2, -5)
- miniSwitchViews:SetWidth(175)
- miniSwitchViews:SetText(Shopkeeper.translate('viewModeAllName'))
- miniSwitchViews:SetHandler("OnClicked", Shopkeeper.SwitchViewMode)
+ ShopkeeperSwitchViewButton:SetText(Shopkeeper.translate('viewModeAllName'))
+ ShopkeeperMiniSwitchViewButton:SetText(Shopkeeper.translate('viewModeAllName'))
-- Total / unit price switch button
- local unitPrice = CreateControlFromVirtual("ShopkeeperPriceSwitchButton", ShopkeeperWindow, "ZO_DefaultButton")
- unitPrice:SetAnchor(LEFT, switchViews, RIGHT, 0, 0)
- unitPrice:SetWidth(175)
if Shopkeeper.savedVariables.showUnitPrice then
- unitPrice:SetText(Shopkeeper.translate('showTotalPrice'))
+ ShopkeeperPriceSwitchButton:SetText(Shopkeeper.translate('showTotalPrice'))
else
- unitPrice:SetText(Shopkeeper.translate('showUnitPrice'))
+ ShopkeeperPriceSwitchButton:SetText(Shopkeeper.translate('showUnitPrice'))
end
- unitPrice:SetHandler("OnClicked", Shopkeeper.SwitchPriceMode)
- local miniUnitPrice = CreateControlFromVirtual("ShopkeeperMiniPriceSwitchButton", ShopkeeperMiniWindow, "ZO_DefaultButton")
- miniUnitPrice:SetAnchor(LEFT, miniSwitchViews, RIGHT, 0, 0)
- miniUnitPrice:SetWidth(175)
if Shopkeeper.savedVariables.showUnitPrice then
- miniUnitPrice:SetText(Shopkeeper.translate('showTotalPrice'))
+ ShopkeeperMiniPriceSwitchButton:SetText(Shopkeeper.translate('showTotalPrice'))
else
- miniUnitPrice:SetText(Shopkeeper.translate('showUnitPrice'))
+ ShopkeeperMiniPriceSwitchButton:SetText(Shopkeeper.translate('showUnitPrice'))
end
- miniUnitPrice:SetHandler("OnClicked", Shopkeeper.SwitchPriceMode)
-- Refresh button
- local refreshButton = CreateControlFromVirtual("ShopkeeperRefreshButton", ShopkeeperWindow, "ZO_DefaultButton")
- refreshButton:SetAnchor(BOTTOMRIGHT, ShopkeeperWindow, BOTTOMRIGHT, -20, -5)
- refreshButton:SetWidth(150)
- refreshButton:SetText(Shopkeeper.translate('refreshLabel'))
- refreshButton:SetHandler("OnClicked", Shopkeeper.DoRefresh)
- local miniRefreshButton = CreateControlFromVirtual("ShopkeeperMiniRefreshButton", ShopkeeperMiniWindow, "ZO_DefaultButton")
- miniRefreshButton:SetAnchor(BOTTOMRIGHT, ShopkeeperMiniWindow, BOTTOMRIGHT, -2, -5)
- miniRefreshButton:SetWidth(150)
- miniRefreshButton:SetText(Shopkeeper.translate('refreshLabel'))
- miniRefreshButton:SetHandler("OnClicked", Shopkeeper.DoRefresh)
+ ShopkeeperRefreshButton:SetText(Shopkeeper.translate('refreshLabel'))
+ ShopkeeperMiniRefreshButton:SetText(Shopkeeper.translate('refreshLabel'))
-- Reset button
- local resetButton = CreateControlFromVirtual("ShopkeeperResetButton", ShopkeeperWindow, "ZO_DefaultButton")
- resetButton:SetAnchor(BOTTOMRIGHT, ShopkeeperWindow, BOTTOMRIGHT, -170, -5)
- resetButton:SetWidth(150)
- resetButton:SetText(Shopkeeper.translate('resetLabel'))
- resetButton:SetHandler("OnClicked", Shopkeeper.DoReset)
- local miniResetButton = CreateControlFromVirtual("ShopkeeperMiniResetButton", ShopkeeperMiniWindow, "ZO_DefaultButton")
- miniResetButton:SetAnchor(BOTTOMRIGHT, ShopkeeperMiniWindow, BOTTOMRIGHT, -152, -5)
- miniResetButton:SetWidth(150)
- miniResetButton:SetText(Shopkeeper.translate('resetLabel'))
- miniResetButton:SetHandler("OnClicked", Shopkeeper.DoReset)
+ ShopkeeperResetButton:SetText(Shopkeeper.translate('resetLabel'))
+ ShopkeeperMiniResetButton:SetText(Shopkeeper.translate('resetLabel'))
-- Make the 15 rows that comprise the visible table
if #Shopkeeper.DataRows == 0 then
local dataRowOffsetX = 25
local dataRowOffsetY = 74
- for i = 1,15 do
+ for i = 1, 15 do
local dRow = CreateControlFromVirtual("ShopkeeperDataRow", ShopkeeperWindow, "ShopkeeperDataRow", i)
dRow:SetSimpleAnchorParent(dataRowOffsetX, dataRowOffsetY+((dRow:GetHeight()+2)*(i-1)))
Shopkeeper.DataRows[i] = dRow
end
end
- -- And for the mini window
+ -- And 8 for the mini window
if #Shopkeeper.MiniDataRows == 0 then
local dataRowOffsetX = 10
local dataRowOffsetY = 74
- for i = 1,8 do
+ for i = 1, 8 do
local dRow = CreateControlFromVirtual("ShopkeeperMiniDataRow", ShopkeeperMiniWindow, "ShopkeeperMiniDataRow", i)
dRow:SetSimpleAnchorParent(dataRowOffsetX, dataRowOffsetY+((dRow:GetHeight()+2)*(i-1)))
Shopkeeper.MiniDataRows[i] = dRow
end
end
-
- -- Close buttons
- ShopkeeperWindowCloseButton:SetNormalTexture("/esoui/art/hud/radialicon_cancel_up.dds")
- ShopkeeperWindowCloseButton:SetMouseOverTexture("/esoui/art/hud/radialicon_cancel_over.dds")
- ShopkeeperWindowCloseButton:SetHandler("OnClicked", function() ShopkeeperWindow:SetHidden(true) end)
- ShopkeeperMiniWindowCloseButton:SetNormalTexture("/esoui/art/hud/radialicon_cancel_up.dds")
- ShopkeeperMiniWindowCloseButton:SetMouseOverTexture("/esoui/art/hud/radialicon_cancel_over.dds")
- ShopkeeperMiniWindowCloseButton:SetHandler("OnClicked", function() ShopkeeperMiniWindow:SetHidden(true) end)
- ShopkeeperStatsWindowCloseButton:SetNormalTexture("/esoui/art/hud/radialicon_cancel_up.dds")
- ShopkeeperStatsWindowCloseButton:SetMouseOverTexture("/esoui/art/hud/radialicon_cancel_over.dds")
- ShopkeeperStatsWindowCloseButton:SetHandler("OnClicked", function() ShopkeeperStatsWindow:SetHidden(true) end)
-- Stats buttons
- ShopkeeperWindowStatsButton:SetNormalTexture("/esoui/art/tradinghouse/tradinghouse_listings_tabicon_up.dds")
- ShopkeeperWindowStatsButton:SetMouseOverTexture("/esoui/art/tradinghouse/tradinghouse_listings_tabicon_over.dds")
- ShopkeeperWindowStatsButton:SetHandler("OnClicked", Shopkeeper.ToggleShopkeeperStatsWindow)
ShopkeeperWindowStatsButton:SetHandler("OnMouseEnter", function(self)
ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('statsTooltip'))
end)
- ShopkeeperWindowStatsButton:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
- ShopkeeperMiniWindowStatsButton:SetNormalTexture("/esoui/art/tradinghouse/tradinghouse_listings_tabicon_up.dds")
- ShopkeeperMiniWindowStatsButton:SetMouseOverTexture("/esoui/art/tradinghouse/tradinghouse_listings_tabicon_over.dds")
- ShopkeeperMiniWindowStatsButton:SetHandler("OnClicked", Shopkeeper.ToggleShopkeeperStatsWindow)
ShopkeeperMiniWindowStatsButton:SetHandler("OnMouseEnter", function(self)
ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('statsTooltip'))
end)
- ShopkeeperMiniWindowStatsButton:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
-- View size change buttons
- ShopkeeperWindowViewSizeButton:SetNormalTexture("/esoui/art/inventory/inventory_tabicon_quest_up.dds")
- ShopkeeperWindowViewSizeButton:SetMouseOverTexture("/esoui/art/inventory/inventory_tabicon_quest_over.dds")
- ShopkeeperWindowViewSizeButton:SetHandler("OnClicked", Shopkeeper.ToggleViewMode)
ShopkeeperWindowViewSizeButton:SetHandler("OnMouseEnter", function(self)
ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sizeTooltip'))
end)
- ShopkeeperWindowViewSizeButton:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
- ShopkeeperMiniWindowViewSizeButton:SetNormalTexture("/esoui/art/inventory/inventory_tabicon_quest_up.dds")
- ShopkeeperMiniWindowViewSizeButton:SetMouseOverTexture("/esoui/art/inventory/inventory_tabicon_quest_over.dds")
- ShopkeeperMiniWindowViewSizeButton:SetHandler("OnClicked", Shopkeeper.ToggleViewMode)
ShopkeeperMiniWindowViewSizeButton:SetHandler("OnMouseEnter", function(self)
ZO_Tooltips_ShowTextTooltip(self, TOP, Shopkeeper.translate('sizeTooltip'))
end)
- ShopkeeperMiniWindowViewSizeButton:SetHandler("OnMouseExit", function(self) ZO_Tooltips_HideTextTooltip() end)
-
-- Slider setup
ShopkeeperWindow:SetHandler("OnMouseWheel", Shopkeeper.OnSliderMouseWheel)
- Shopkeeper.shopSlider = CreateControl(ShopkeeperWindowSlider, ShopkeeperWindow, CT_SLIDER)
- Shopkeeper.shopSlider.texture = "/esoui/art/miscellaneous/scrollbox_elevator.dds"
- Shopkeeper.shopSlider.offset = 0
- local tex = Shopkeeper.shopSlider.texture
- Shopkeeper.shopSlider:SetDimensions(20,561)
- Shopkeeper.shopSlider:SetMouseEnabled(true)
- Shopkeeper.shopSlider:SetThumbTexture(tex,tex,tex,20,50,0,0,1,1)
- Shopkeeper.shopSlider:SetMinMax(0, 100)
- Shopkeeper.shopSlider:SetValue(0)
- Shopkeeper.shopSlider:SetValueStep(1)
- Shopkeeper.shopSlider:SetAnchor(LEFT, ShopkeeperWindow, RIGHT, -20, 17)
- Shopkeeper.shopSlider:SetHandler("OnValueChanged", Shopkeeper.OnSliderMoved)
- Shopkeeper.sliderBG = CreateControl(nil, Shopkeeper.shopSlider, CT_BACKDROP)
- Shopkeeper.sliderBG:SetCenterColor(0, 0, 0)
- Shopkeeper.sliderBG:SetAnchor(TOPLEFT, Shopkeeper.shopSlider, TOPLEFT, 0, -4)
- Shopkeeper.sliderBG:SetAnchor(BOTTOMRIGHT, Shopkeeper.shopSlider, BOTTOMRIGHT, 0, 4)
- Shopkeeper.sliderBG:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4)
-
+ ShopkeeperWindowSlider:SetValue(0)
ShopkeeperMiniWindow:SetHandler("OnMouseWheel", Shopkeeper.OnSliderMouseWheel)
- Shopkeeper.miniShopSlider = CreateControl(ShopkeeperMiniWindowSlider, ShopkeeperMiniWindow, CT_SLIDER)
- Shopkeeper.miniShopSlider.texture = "/esoui/art/miscellaneous/scrollbox_elevator.dds"
- Shopkeeper.miniShopSlider.offset = 0
- Shopkeeper.miniShopSlider:SetDimensions(20,300)
- Shopkeeper.miniShopSlider:SetMouseEnabled(true)
- Shopkeeper.miniShopSlider:SetThumbTexture(tex,tex,tex,20,50,0,0,1,1)
- Shopkeeper.miniShopSlider:SetMinMax(0, 100)
- Shopkeeper.miniShopSlider:SetValue(0)
- Shopkeeper.miniShopSlider:SetValueStep(1)
- Shopkeeper.miniShopSlider:SetAnchor(LEFT, ShopkeeperMiniWindow, RIGHT, -20, 17)
- Shopkeeper.miniShopSlider:SetHandler("OnValueChanged", Shopkeeper.OnSliderMoved)
- Shopkeeper.miniSliderBG = CreateControl(nil, Shopkeeper.miniShopSlider, CT_BACKDROP)
- Shopkeeper.miniSliderBG:SetCenterColor(0, 0, 0)
- Shopkeeper.miniSliderBG:SetAnchor(TOPLEFT, Shopkeeper.miniShopSlider, TOPLEFT, 0, -4)
- Shopkeeper.miniSliderBG:SetAnchor(BOTTOMRIGHT, Shopkeeper.miniShopSlider, BOTTOMRIGHT, 0, 4)
- Shopkeeper.miniSliderBG:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4)
-
- Shopkeeper.statsSlider = CreateControl(ShopkeeperStatsWindowSlider, ShopkeeperStatsWindow, CT_SLIDER)
- Shopkeeper.statsSlider.texture = "/esoui/art/miscellaneous/scrollbox_elevator.dds"
- Shopkeeper.statsSlider.offset = 0
- Shopkeeper.statsSlider:SetDimensions(375,14)
- Shopkeeper.statsSlider:SetMouseEnabled(true)
- Shopkeeper.statsSlider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16)
- Shopkeeper.statsSlider:SetMinMax(0, 30)
- Shopkeeper.statsSlider:SetValue(0)
- Shopkeeper.statsSlider:SetValueStep(1)
- Shopkeeper.statsSlider:SetOrientation(ORIENTATION_HORIZONTAL)
- Shopkeeper.statsSlider:SetAnchor(BOTTOM, ShopkeeperStatsWindow, BOTTOM, 25, -15)
- Shopkeeper.statsSlider:SetHandler("OnValueChanged", Shopkeeper.OnStatsSliderMoved)
- Shopkeeper.statsSliderBG = CreateControl(nil, Shopkeeper.statsSlider, CT_BACKDROP)
- Shopkeeper.statsSliderBG:SetCenterColor(0, 0, 0)
- Shopkeeper.statsSliderBG:SetAnchor(TOPLEFT, Shopkeeper.statsSlider, TOPLEFT, 0, 4)
- Shopkeeper.statsSliderBG:SetAnchor(BOTTOMRIGHT, Shopkeeper.statsSlider, BOTTOMRIGHT, 0, -4)
- Shopkeeper.statsSliderBG:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4)
-
-
- -- Sorting handlers
- ShopkeeperWindowPrice:SetHandler("OnMouseUp", Shopkeeper.PriceSort)
- ShopkeeperWindowSellTime:SetHandler("OnMouseUp", Shopkeeper.TimeSort)
- ShopkeeperMiniWindowPrice:SetHandler("OnMouseUp", Shopkeeper.PriceSort)
- ShopkeeperMiniWindowSellTime:SetHandler("OnMouseUp", Shopkeeper.TimeSort)
+ ShopkeeperMiniWindowSlider:SetValue(0)
+ ShopkeeperStatsWindowSlider:SetValue(0)
-- Search handler
ZO_PreHookHandler(ShopkeeperWindowSearchBox, "OnTextChanged", function(self) Shopkeeper.DoSearch(ShopkeeperWindowSearchBox:GetText()) end)
@@ -1534,8 +920,8 @@ function Shopkeeper:Initialize()
["scanHistory"] = {},
}
- self.savedVariables = ZO_SavedVars:New("ShopkeeperSavedVars", 1, Shopkeeper.GetAccountName(), Defaults)
- self.acctSavedVariables = ZO_SavedVars:NewAccountWide("ShopkeeperSavedVars", 1, Shopkeeper.GetAccountName(), acctDefaults)
+ self.savedVariables = ZO_SavedVars:New("ShopkeeperSavedVars", 1, GetDisplayName(), Defaults)
+ self.acctSavedVariables = ZO_SavedVars:NewAccountWide("ShopkeeperSavedVars", 1, GetDisplayName(), acctDefaults)
self.ScanResults = Shopkeeper.acctSavedVariables.scanHistory
-- Update the lastScan value, as it was previously a number
@@ -1571,7 +957,7 @@ function Shopkeeper:Initialize()
end
-- Now that we've truncated, populate the SelfSales table
- local loggedInAccount = string.lower(Shopkeeper.GetAccountName())
+ local loggedInAccount = string.lower(GetDisplayName())
for i = 1, #self.ScanResults do
if string.lower(self.ScanResults[i][8]) == loggedInAccount then table.insert(self.SelfSales, self.ScanResults[i]) end
end
@@ -1644,18 +1030,15 @@ function Shopkeeper:Initialize()
ShopkeeperMiniWindow:SetHidden(true)
end)
- -- Update fonts after each UI load
- EVENT_MANAGER:RegisterForEvent(Shopkeeper.name, EVENT_PLAYER_ACTIVATED, Shopkeeper.PlayerActive)
-
-- RegisterForUpdate lets us scan at a given interval (in ms), so we'll use that to
-- keep the sales history updated
local scanInterval = self.savedVariables.scanFreq * 1000
- EVENT_MANAGER:RegisterForUpdate(Shopkeeper.name, scanInterval, function() Shopkeeper:ScanStores(false, false) end)
+ EVENT_MANAGER:RegisterForUpdate(Shopkeeper.name, scanInterval, function() Shopkeeper:ScanStores(false) end)
-- Right, we're all set up, so give the client a few seconds to catch up on everything
-- and then do an initial (deep) scan in case it's been a while since the player
-- logged on.
- zo_callLater(function() Shopkeeper:ScanStores(true, false) end, 5000)
+ zo_callLater(function() Shopkeeper:ScanStores(false) end, 5000)
end
diff --git a/Shopkeeper.txt b/Shopkeeper.txt
index 1bb232d..c65a36c 100644
--- a/Shopkeeper.txt
+++ b/Shopkeeper.txt
@@ -2,9 +2,9 @@
## APIVersion: 100008
## Description: Notifies you when you've sold something in a guild store and presents guild sales info in a convenient table.
## Author: Dan Stone (@khaibit) - dankitymao@gmail.com
-## Version: 0.9a
+## Version: 0.9b
## License: See license - distribution without license is prohibited!
-## LastUpdated: August 8, 2014
+## LastUpdated: August 10, 2014
## SavedVariables: ShopkeeperSavedVars
## OptionalDependsOn: LibAddonMenu-2.0 LibMediaProvider-1.0 LibStub
@@ -25,6 +25,8 @@ Libs\LibAddonMenu-2.0\controls\slider.lua
Libs\LibAddonMenu-2.0\controls\texture.lua
Shopkeeper.xml
Shopkeeper_Namespace_Init.lua
+Shopkeeper_Util.lua
+Shopkeeper_UI.lua
i18n\$(language).lua
Shopkeeper.lua
bindings.xml
\ No newline at end of file
diff --git a/Shopkeeper.xml b/Shopkeeper.xml
index e1d8b7f..7acd0db 100644
--- a/Shopkeeper.xml
+++ b/Shopkeeper.xml
@@ -1,6 +1,6 @@
<!--
Shopkeeper UI Layout File
- Last Updated August 8, 2014
+ Last Updated August 10, 2014
Written July 2014 by Dan Stone (@khaibit) - dankitymao@gmail.com
Released under terms in license accompanying this file.
Distribution without license is prohibited!
@@ -14,41 +14,62 @@
</OnMoveStop>
<Controls>
<Backdrop name="$(parent)BG" inherits="ZO_DefaultBackdrop" />
- <Label name="$(parent)Title" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="CENTER" text="Shopkeeper Sales Statistics">
+ <Label name="$(parent)Title" height="25" width="95" inheritAlpha="true" color="D5B526" verticalAlignment="CENTER" horizontalAlignment="CENTER" text="Shopkeeper Sales Statistics">
<Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="0" offsetY="5" />
</Label>
- <Button name="$(parent)CloseButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)CloseButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="CENTER" relativeTo="$(parent)" relativePoint="TOPRIGHT" offsetX="-20" offsetY="20" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/hud/radialicon_cancel_up.dds" mouseOver="/esoui/art/hud/radialicon_cancel_over.dds" />
+ <OnClicked>
+ ShopkeeperStatsWindow:SetHidden(true)
+ </OnClicked>
</Button>
- <Label name="$(parent)ItemsSoldLabel" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Items sold: 0">
- <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="15" offsetY="55" />
+ <Label name="$(parent)ItemsSoldLabel" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Items sold: 0">
+ <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="0" offsetY="45" />
</Label>
- <Label name="$(parent)TotalGoldLabel" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Total gold: 0 (0 per day)">
- <Anchor point="TOPRIGHT" relativeTo="$(parent)" relativePoint="TOPRIGHT" offsetX="-15" offsetY="55" />
+ <Label name="$(parent)TotalGoldLabel" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Total gold: 0 (0 per day)">
+ <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="0" offsetY="70" />
</Label>
- <Label name="$(parent)BiggestSaleLabel" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="CENTER" text="Biggest sale: (0)">
- <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="0" offsetY="90" />
+ <Label name="$(parent)BiggestSaleLabel" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="CENTER" text="Biggest sale: (0)">
+ <Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="0" offsetY="95" />
</Label>
- <Label name="$(parent)SliderSettingLabel" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="CENTER" text="Using all data">
+ <Label name="$(parent)SliderSettingLabel" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="CENTER" text="Using all data">
<Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="0" offsetY="125" />
</Label>
- <Label name="$(parent)SliderLabel" font="ZoFontGame" height="25" width="50" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Days: ">
+ <Label name="$(parent)SliderLabel" height="25" width="50" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Days: ">
<Anchor point="BOTTOMLEFT" relativeTo="$(parent)" relativePoint="BOTTOMLEFT" offsetX="10" offsetY="-14" />
</Label>
+ <Slider name="$(parent)Slider" mouseEnabled="true" step="1" orientation="horizontal">
+ <Anchor point="BOTTOM" relativeTo="$(parent)" relativePoint="BOTTOM" offsetX="25" offsetY="-15" />
+ <ThumbTexture textureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" disabledTextureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" highlightedTextureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" thumbWidth="8" thumbHeight="16" left="0" top="0" bottom="1" right="1" />
+ <Dimensions x="375" y="14" />
+ <Limits min="0" max="30" />
+ <OnValueChanged>
+ Shopkeeper.OnStatsSliderMoved()
+ </OnValueChanged>
+ <Controls>
+ <Backdrop name="$(parent)Backdrop" centerColor="000000">
+ <Edge file="/EsoUI/Art/Tooltips/UI-SliderBackdrop.dds" edgeFileWidth="32" edgeFileHeight="4" />
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="0" offsetY="4" />
+ <Anchor point="BOTTOMRIGHT" relativeTo="$(parent)" relativePoint="BOTTOMRIGHT" offsetX="0" offsetY="-4" />
+ </Backdrop>
+ </Controls>
+ </Slider>
</Controls>
</TopLevelControl>
+
<TopLevelControl movable="true" mouseEnabled="true" name="ShopkeeperWindow" hidden="true">
- <Dimensions x="907" y="685" />
+ <Dimensions x="925" y="685" />
<OnMoveStop>
Shopkeeper.OnWindowMoveStop()
</OnMoveStop>
<Controls>
<Backdrop name="$(parent)BG" inherits="ZO_DefaultBackdrop" />
- <Label name="$(parent)SearchLabel" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Search: ">
+ <Label name="$(parent)SearchLabel" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Search: ">
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="15" offsetY="10" />
</Label>
- <EditBox name="$(parent)SearchBox" mouseEnabled="true" editEnabled="true" font="ZoFontGame" textType="TEXT_TYPE_ALL" multiLine="false" newLineEnabled="false">
+ <EditBox name="$(parent)SearchBox" mouseEnabled="true" editEnabled="true" textType="TEXT_TYPE_ALL" multiLine="false" newLineEnabled="false">
<Anchor point="LEFT" relativeTo="$(parent)SearchLabel" relativePoint="RIGHT" offsetX="5" offsetY="0" />
<Dimensions x="175" y="25" />
<Controls>
@@ -67,54 +88,135 @@
self:LoseFocus()
</OnEscape>
</EditBox>
- <Button name="$(parent)CloseButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)CloseButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="CENTER" relativeTo="$(parent)" relativePoint="TOPRIGHT" offsetX="-20" offsetY="20" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/hud/radialicon_cancel_up.dds" mouseOver="/esoui/art/hud/radialicon_cancel_over.dds" />
+ <OnClicked>
+ ShopkeeperWindow:SetHidden(true)
+ </OnClicked>
</Button>
- <Label name="$(parent)Title" font="ZoFontGame" height="25" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Shopkeeper - Your Sales">
+ <Label name="$(parent)Title" height="25" inheritAlpha="true" color="D5B526" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Shopkeeper - Your Sales">
<Anchor point="TOP" relativeTo="$(parent)" relativePoint="TOP" offsetX="-10" offsetY="5" />
</Label>
- <Button name="$(parent)StatsButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)StatsButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="LEFT" relativeTo="$(parent)Title" relativePoint="RIGHT" offsetX="15" offsetY="0" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/tradinghouse/tradinghouse_listings_tabicon_up.dds" mouseOver="/esoui/art/tradinghouse/tradinghouse_listings_tabicon_over.dds" />
+ <OnClicked>
+ Shopkeeper.ToggleShopkeeperStatsWindow()
+ </OnClicked>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Button name="$(parent)ViewSizeButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)ViewSizeButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="LEFT" relativeTo="$(parent)StatsButton" relativePoint="RIGHT" offsetX="0" offsetY="0" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/inventory/inventory_tabicon_quest_up.dds" mouseOver="/esoui/art/inventory/inventory_tabicon_quest_over.dds" />
+ <OnClicked>
+ Shopkeeper.ToggleViewMode()
+ </OnClicked>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Button name="$(parent)Buyer" font="ZoFontGame" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Buyer">
+ <Button name="$(parent)Buyer" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Buyer">
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="30" offsetY="44" />
- <Dimensions x="60" y="25" />
+ <Dimensions x="78" y="25" />
<FontColors normalColor="3689EF" mouseOverColor="3689EF" pressedColor="3689EF"/>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Label name="$(parent)Guild" font="ZoFontGame" width="140" height="25" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Guild">
- <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="143" offsetY="44" />
+ <Label name="$(parent)Guild" width="140" height="25" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Guild">
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="161" offsetY="44" />
</Label>
- <Button name="$(parent)ItemName" font="ZoFontGame" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Item">
+ <Button name="$(parent)ItemName" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Item">
<Dimensions x="200" y="25" />
- <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="352" offsetY="44" />
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="370" offsetY="44" />
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Button name="$(parent)SellTime" font="ZoFontGame" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Sale Time">
- <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="649" offsetY="44" />
+ <Button name="$(parent)SellTime" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Sale Time">
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="667" offsetY="44" />
<Dimensions x="95" y="25" />
+ <OnMouseUp>
+ Shopkeeper.TimeSort()
+ </OnMouseUp>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
<Texture name="$(parent)SortTime" textureFile="/esoui/art/miscellaneous/list_sortheader_icon_sortdown.dds" alpha="1">
<Dimensions x="40" y="40" />
- <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="731" offsetY="54" />
+ <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="749" offsetY="54" />
<TextureCoords left="0" right="1" top="0" bottom="1" />
</Texture>
- <Button name="$(parent)Price" font="ZoFontGame" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Price">
- <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="775" offsetY="44" />
+ <Button name="$(parent)Price" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Price">
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="793" offsetY="44" />
<Dimensions x="85" y="25" />
<FontColors normalColor="D5B526" mouseOverColor="D5B526" pressedColor="D5B526" />
+ <OnMouseUp>
+ Shopkeeper.PriceSort()
+ </OnMouseUp>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
<Texture name="$(parent)SortPrice" textureFile="/esoui/art/miscellaneous/list_sortheader_icon_neutral.dds" alpha="1">
<Dimensions x="40" y="40" />
- <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="850" offsetY="54" />
+ <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="868" offsetY="54" />
<TextureCoords left="0" right="1" top="0" bottom="1" />
- </Texture>
+ </Texture>
+ <Button name="ShopkeeperSwitchViewButton" inherits="ZO_DefaultButton">
+ <Anchor point="BOTTOMLEFT" relativeTo="$(parent)" relativePoint="BOTTOMLEFT" offsetX="20" offsetY="-5" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.SwitchViewMode()
+ </OnClicked>
+ </Button>
+ <Button name="ShopkeeperPriceSwitchButton" inherits="ZO_DefaultButton">
+ <Anchor point="LEFT" relativeTo="ShopkeeperSwitchViewButton" relativePoint="RIGHT" offsetX="0" offsetY="0" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.SwitchPriceMode()
+ </OnClicked>
+ </Button>
+ <Button name="ShopkeeperRefreshButton" inherits="ZO_DefaultButton">
+ <Anchor point="BOTTOMRIGHT" relativeTo="$(parent)" relativePoint="BOTTOMRIGHT" offsetX="-20" offsetY="-5" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.DoRefresh()
+ </OnClicked>
+ </Button>
+ <Button name="ShopkeeperResetButton" inherits="ZO_DefaultButton">
+ <Anchor point="RIGHT" relativeTo="ShopkeeperRefreshButton" relativePoint="LEFT" offsetX="0" offsetY="0" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.DoReset()
+ </OnClicked>
+ </Button>
+ <Slider name="$(parent)Slider" mouseEnabled="true" step="1">
+ <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="RIGHT" offsetX="-20" offsetY="17" />
+ <ThumbTexture textureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" disabledTextureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" highlightedTextureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" thumbWidth="20" thumbHeight="50" left="0" top="0" bottom="1" right="1" />
+ <Dimensions x="20" y="561" />
+ <Limits min="0" max="100" />
+ <OnValueChanged>
+ Shopkeeper.OnSliderMoved()
+ </OnValueChanged>
+ <Controls>
+ <Backdrop name="$(parent)Backdrop" centerColor="000000">
+ <Edge file="/EsoUI/Art/Tooltips/UI-SliderBackdrop.dds" edgeFileWidth="32" edgeFileHeight="4" />
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="0" offsetY="-4" />
+ <Anchor point="BOTTOMRIGHT" relativeTo="$(parent)" relativePoint="BOTTOMRIGHT" offsetX="0" offsetY="4" />
+ </Backdrop>
+ </Controls>
+ </Slider>
</Controls>
</TopLevelControl>
+
<TopLevelControl movable="true" mouseEnabled="true" name="ShopkeeperMiniWindow" hidden="true">
<Dimensions x="650" y="416" />
<OnMoveStop>
@@ -122,10 +224,10 @@
</OnMoveStop>
<Controls>
<Backdrop name="$(parent)BG" inherits="ZO_DefaultBackdrop" />
- <Label name="$(parent)SearchLabel" font="ZoFontGame" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Search: ">
+ <Label name="$(parent)SearchLabel" height="25" width="95" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Search: ">
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="15" offsetY="10" />
</Label>
- <EditBox name="$(parent)SearchBox" mouseEnabled="true" editEnabled="true" font="ZoFontGame" textType="TEXT_TYPE_ALL" multiLine="false" newLineEnabled="false">
+ <EditBox name="$(parent)SearchBox" mouseEnabled="true" editEnabled="true" textType="TEXT_TYPE_ALL" multiLine="false" newLineEnabled="false">
<Anchor point="LEFT" relativeTo="$(parent)SearchLabel" relativePoint="RIGHT" offsetX="5" offsetY="0" />
<Dimensions x="175" y="25" />
<Controls>
@@ -144,91 +246,170 @@
self:LoseFocus()
</OnEscape>
</EditBox>
- <Button name="$(parent)CloseButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)CloseButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="CENTER" relativeTo="$(parent)" relativePoint="TOPRIGHT" offsetX="-20" offsetY="20" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/hud/radialicon_cancel_up.dds" mouseOver="/esoui/art/hud/radialicon_cancel_over.dds" />
+ <OnClicked>
+ ShopkeeperMiniWindow:SetHidden(true)
+ </OnClicked>
</Button>
- <Label name="$(parent)Title" font="ZoFontGame" height="25" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Shopkeeper - Your Sales">
+ <Label name="$(parent)Title" height="25" inheritAlpha="true" color="D5B526" verticalAlignment="TOP" horizontalAlignment="CENTER" text="Shopkeeper - Your Sales">
<Anchor point="LEFT" relativeTo="$(parent)SearchBox" relativePoint="RIGHT" offsetX="40" offsetY="0" />
</Label>
- <Button name="$(parent)StatsButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)StatsButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="LEFT" relativeTo="$(parent)Title" relativePoint="RIGHT" offsetX="15" offsetY="0" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/tradinghouse/tradinghouse_listings_tabicon_up.dds" mouseOver="/esoui/art/tradinghouse/tradinghouse_listings_tabicon_over.dds" />
+ <OnClicked>
+ Shopkeeper.ToggleShopkeeperStatsWindow()
+ </OnClicked>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Button name="$(parent)ViewSizeButton" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
+ <Button name="$(parent)ViewSizeButton" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="CENTER">
<Anchor point="LEFT" relativeTo="$(parent)StatsButton" relativePoint="RIGHT" offsetX="0" offsetY="0" />
<Dimensions x="48" y="48" />
+ <Textures normal="/esoui/art/inventory/inventory_tabicon_quest_up.dds" mouseOver="/esoui/art/inventory/inventory_tabicon_quest_over.dds" />
+ <OnClicked>
+ Shopkeeper.ToggleViewMode()
+ </OnClicked>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Label name="$(parent)Guild" font="ZoFontGame" width="120" height="25" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Guild">
+ <Label name="$(parent)Guild" width="120" height="25" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Guild">
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="15" offsetY="44" />
</Label>
- <Button name="$(parent)ItemName" font="ZoFontGame" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Item">
+ <Button name="$(parent)ItemName" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Item">
<Dimensions x="200" y="25" />
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="140" offsetY="44" />
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
- <Button name="$(parent)SellTime" font="ZoFontGame" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Sale Time">
+ <Button name="$(parent)SellTime" inheritAlpha="true" color="FFFFFF" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Sale Time">
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="420" offsetY="44" />
<Dimensions x="95" y="25" />
+ <OnMouseUp>
+ Shopkeeper.TimeSort()
+ </OnMouseUp>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
<Texture name="$(parent)SortTime" textureFile="/esoui/art/miscellaneous/list_sortheader_icon_sortdown.dds" alpha="1">
<Dimensions x="40" y="40" />
<Anchor point="LEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="495" offsetY="54" />
<TextureCoords left="0" right="1" top="0" bottom="1" />
</Texture>
- <Button name="$(parent)Price" font="ZoFontGame" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Price">
+ <Button name="$(parent)Price" inheritAlpha="true" verticalAlignment="TOP" horizontalAlignment="LEFT" text="Price">
<Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="540" offsetY="44" />
<Dimensions x="85" y="25" />
<FontColors normalColor="D5B526" mouseOverColor="D5B526" pressedColor="D5B526" />
+ <OnMouseUp>
+ Shopkeeper.PriceSort()
+ </OnMouseUp>
+ <OnMouseExit>
+ ZO_Tooltips_HideTextTooltip()
+ </OnMouseExit>
</Button>
<Texture name="$(parent)SortPrice" textureFile="/esoui/art/miscellaneous/list_sortheader_icon_neutral.dds" alpha="1">
<Dimensions x="40" y="40" />
<Anchor point="LEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="600" offsetY="54" />
<TextureCoords left="0" right="1" top="0" bottom="1" />
- </Texture>
+ </Texture>
+ <Button name="ShopkeeperMiniSwitchViewButton" inherits="ZO_DefaultButton">
+ <Anchor point="BOTTOMLEFT" relativeTo="$(parent)" relativePoint="BOTTOMLEFT" offsetX="2" offsetY="-5" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.SwitchViewMode()
+ </OnClicked>
+ </Button>
+ <Button name="ShopkeeperMiniPriceSwitchButton" inherits="ZO_DefaultButton">
+ <Anchor point="LEFT" relativeTo="ShopkeeperMiniSwitchViewButton" relativePoint="RIGHT" offsetX="0" offsetY="0" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.SwitchPriceMode()
+ </OnClicked>
+ </Button>
+ <Button name="ShopkeeperMiniRefreshButton" inherits="ZO_DefaultButton">
+ <Anchor point="BOTTOMRIGHT" relativeTo="$(parent)" relativePoint="BOTTOMRIGHT" offsetX="-2" offsetY="-5" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.DoRefresh()
+ </OnClicked>
+ </Button>
+ <Button name="ShopkeeperMiniResetButton" inherits="ZO_DefaultButton">
+ <Anchor point="RIGHT" relativeTo="ShopkeeperMiniRefreshButton" relativePoint="LEFT" offsetX="0" offsetY="0" />
+ <Dimensions x="160" />
+ <OnClicked>
+ Shopkeeper.DoReset()
+ </OnClicked>
+ </Button>
+ <Slider name="$(parent)Slider" mouseEnabled="true" step="1">
+ <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="RIGHT" offsetX="-20" offsetY="17" />
+ <ThumbTexture textureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" disabledTextureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" highlightedTextureFile="/esoui/art/miscellaneous/scrollbox_elevator.dds" thumbWidth="20" thumbHeight="50" left="0" top="0" bottom="1" right="1" />
+ <Dimensions x="20" y="300" />
+ <Limits min="0" max="100" />
+ <OnValueChanged>
+ Shopkeeper.OnSliderMoved()
+ </OnValueChanged>
+ <Controls>
+ <Backdrop name="$(parent)Backdrop" centerColor="000000">
+ <Edge file="/EsoUI/Art/Tooltips/UI-SliderBackdrop.dds" edgeFileWidth="32" edgeFileHeight="4" />
+ <Anchor point="TOPLEFT" relativeTo="$(parent)" relativePoint="TOPLEFT" offsetX="0" offsetY="-4" />
+ <Anchor point="BOTTOMRIGHT" relativeTo="$(parent)" relativePoint="BOTTOMRIGHT" offsetX="0" offsetY="4" />
+ </Backdrop>
+ </Controls>
+ </Slider>
</Controls>
</TopLevelControl>
- <Control name="ShopkeeperDataRow" horizontalAlignment="LEFT" verticalAlignment="CENTER" color="CFDCBD" font="ZoFontGame" virtual="true">
- <Dimensions x="857" y="36" />
+
+ <Control name="ShopkeeperDataRow" horizontalAlignment="LEFT" verticalAlignment="CENTER" color="CFDCBD" virtual="true">
+ <Dimensions x="875" y="36" />
<Anchor point="TOPLEFT" offsetX="25" offsetY="25" />
<Controls>
<Backdrop name="$(parent)BG" inherits="ZO_ThinBackdrop" />
- <Button name="$(parent)Buyer" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Buyer">
+ <Button name="$(parent)Buyer" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Buyer">
<Anchor point="TOPLEFT" offsetX="5" offsetY="5" />
- <Dimensions x="113" y="26" />
+ <Dimensions x="131" y="26" />
<FontColors normalColor="3689EF" mouseOverColor="69EFFF" pressedColor="3689EF" />
</Button>
- <Button name="$(parent)Guild" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Guild">
- <Anchor point="TOPLEFT" offsetX="120" offsetY="5" />
+ <Button name="$(parent)Guild" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Guild">
+ <Anchor point="TOPLEFT" offsetX="138" offsetY="5" />
<Dimensions x="160" y="26" />
<FontColors normalColor="FFFFFF" mouseOverColor="FFFFFF" pressedColor="FFFFFF" />
</Button>
<Texture name="$(parent)ItemIcon" alpha="1">
<Dimensions x="32" y="32" />
- <Anchor point="TOPLEFT" offsetX="288" offsetY="3" />
+ <Anchor point="TOPLEFT" offsetX="306" offsetY="3" />
<TextureCoords left="0" right="1" top="0" bottom="1" />
</Texture>
- <Button name="$(parent)ItemName" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Item Name">
- <Anchor point="TOPLEFT" offsetX="328" offsetY="5" />
+ <Button name="$(parent)ItemName" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Item Name">
+ <Anchor point="TOPLEFT" offsetX="346" offsetY="5" />
<Dimensions x="242" y="26" />
<FontColors normalColor="0000FF" mouseOverColor="0000FF" pressedColor="0000FF" />
</Button>
- <Label name="$(parent)Quantity" font="ZoFontGame" width="30" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="x1">
- <Anchor point="TOPLEFT" offsetX="575" offsetY="7" />
+ <Label name="$(parent)Quantity" width="30" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="x1">
+ <Anchor point="TOPLEFT" offsetX="593" offsetY="7" />
</Label>
- <Label name="$(parent)SellTime" font="ZoFontGame" width="115" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Time">
- <Anchor point="TOPLEFT" offsetX="625" offsetY="7" />
+ <Label name="$(parent)SellTime" width="115" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Time">
+ <Anchor point="TOPLEFT" offsetX="643" offsetY="7" />
</Label>
- <Label name="$(parent)Price" font="ZoFontGame" width="115" height="26" inheritAlpha="true" color="D5B526" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Price">
- <Anchor point="TOPLEFT" offsetX="751" offsetY="7" />
+ <Label name="$(parent)Price" width="115" height="26" inheritAlpha="true" color="D5B526" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Price">
+ <Anchor point="TOPLEFT" offsetX="769" offsetY="7" />
</Label>
</Controls>
</Control>
- <Control name="ShopkeeperMiniDataRow" horizontalAlignment="LEFT" verticalAlignment="CENTER" color="CFDCBD" font="ZoFontGame" virtual="true">
+
+ <Control name="ShopkeeperMiniDataRow" horizontalAlignment="LEFT" verticalAlignment="CENTER" color="CFDCBD" virtual="true">
<Dimensions x="615" y="36" />
<Anchor point="TOPLEFT" offsetX="10" offsetY="25" />
<Controls>
<Backdrop name="$(parent)BG" inherits="ZO_ThinBackdrop" />
- <Button name="$(parent)Guild" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Guild">
+ <Button name="$(parent)Guild" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Guild">
<Anchor point="TOPLEFT" offsetX="5" offsetY="5" />
<Dimensions x="120" y="26" />
<FontColors normalColor="FFFFFF" mouseOverColor="FFFFFF" pressedColor="FFFFFF" />
@@ -238,18 +419,18 @@
<Anchor point="TOPLEFT" offsetX="125" offsetY="3" />
<TextureCoords left="0" right="1" top="0" bottom="1" />
</Texture>
- <Button name="$(parent)ItemName" font="ZoFontGame" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Item Name">
+ <Button name="$(parent)ItemName" inheritAlpha="true" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Item Name">
<Anchor point="TOPLEFT" offsetX="160" offsetY="5" />
<Dimensions x="215" y="26" />
<FontColors normalColor="0000FF" mouseOverColor="0000FF" pressedColor="0000FF" />
</Button>
- <Label name="$(parent)Quantity" font="ZoFontGame" width="30" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="x1">
+ <Label name="$(parent)Quantity" width="30" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="x1">
<Anchor point="TOPLEFT" offsetX="380" offsetY="7" />
</Label>
- <Label name="$(parent)SellTime" font="ZoFontGame" width="115" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Time">
+ <Label name="$(parent)SellTime" width="115" height="26" inheritAlpha="true" color="FFFFFF" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Time">
<Anchor point="TOPLEFT" offsetX="410" offsetY="7" />
</Label>
- <Label name="$(parent)Price" font="ZoFontGame" width="115" height="26" inheritAlpha="true" color="D5B526" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Price">
+ <Label name="$(parent)Price" width="115" height="26" inheritAlpha="true" color="D5B526" verticalAlignment="CENTER" horizontalAlignment="LEFT" text="Price">
<Anchor point="TOPLEFT" offsetX="530" offsetY="7" />
</Label>
</Controls>
diff --git a/Shopkeeper_Namespace_Init.lua b/Shopkeeper_Namespace_Init.lua
index a9fe120..7540e56 100644
--- a/Shopkeeper_Namespace_Init.lua
+++ b/Shopkeeper_Namespace_Init.lua
@@ -1,12 +1,12 @@
-- Shopkeeper Namespace Setup
--- Last Updated August 8, 2014
+-- Last Updated August 10, 2014
-- Written July 2014 by Dan Stone (@khaibit) - dankitymao@gmail.com
-- Released under terms in license accompanying this file.
-- Distribution without license is prohibited!
Shopkeeper = {}
Shopkeeper.name = "Shopkeeper"
-Shopkeeper.version = "0.9a"
+Shopkeeper.version = "0.9b"
Shopkeeper.locale = "en"
Shopkeeper.viewMode = "self"
Shopkeeper.isScanning = false
@@ -16,13 +16,12 @@ Shopkeeper.MiniDataRows = {}
-- ScanResults, SelfSales and SearchTable have the following fields:
-- 1: Buyer 2: Guild 3: Item Name 4: Item Icon
-- 5: Quantity 6: UNIX Time 7: Price 8: Seller
+ -- 9: Was a kiosk sale (true/false, maybe nil for older data)
Shopkeeper.ScanResults = {}
Shopkeeper.SelfSales = {}
Shopkeeper.SearchTable = {}
-Shopkeeper.missedScan = {}
-Shopkeeper.missedLastScan = {}
+Shopkeeper.numEvents = {}
Shopkeeper.alertQueue = {}
-Shopkeeper.shopSlider = {}
Shopkeeper.curSort = {"time", "desc"}
Shopkeeper.uiFragment = {}
diff --git a/Shopkeeper_UI.lua b/Shopkeeper_UI.lua
new file mode 100644
index 0000000..3afbc07
--- /dev/null
+++ b/Shopkeeper_UI.lua
@@ -0,0 +1,430 @@
+-- Shopkeeper UI Functions File
+-- Last Updated August 10, 2014
+-- Written August 2014 by Dan Stone (@khaibit) - dankitymao@gmail.com
+-- Released under terms in license accompanying this file.
+-- Distribution without license is prohibited!
+
+-- Handle the OnMoveStop event for the windows
+function Shopkeeper.OnWindowMoveStop()
+ Shopkeeper.savedVariables.winLeft = ShopkeeperWindow:GetLeft()
+ Shopkeeper.savedVariables.winTop = ShopkeeperWindow:GetTop()
+ Shopkeeper.savedVariables.miniWinLeft = ShopkeeperMiniWindow:GetLeft()
+ Shopkeeper.savedVariables.miniWinTop = ShopkeeperMiniWindow:GetTop()
+end
+
+function Shopkeeper.OnStatsWindowMoveStop()
+ Shopkeeper.savedVariables.statsWinLeft = ShopkeeperStatsWindow:GetLeft()
+ Shopkeeper.savedVariables.statsWinTop = ShopkeeperStatsWindow:GetTop()
+end
+
+-- Restore the window positions from saved vars
+function Shopkeeper:RestoreWindowPosition()
+ local left = self.savedVariables.winLeft
+ local top = self.savedVariables.winTop
+ local statsLeft = self.savedVariables.statsWinLeft
+ local statsTop = self.savedVariables.statsWinTop
+ local miniLeft = self.savedVariables.miniWinLeft
+ local miniTop = self.savedVariables.miniWinTop
+
+ ShopkeeperWindow:ClearAnchors()
+ ShopkeeperStatsWindow:ClearAnchors()
+ ShopkeeperMiniWindow:ClearAnchors()
+ ShopkeeperWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, left, top)
+ ShopkeeperStatsWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, statsLeft, statsTop)
+ ShopkeeperMiniWindow:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, miniLeft, miniTop)
+end
+
+-- Handle the changing of window font settings
+function Shopkeeper:UpdateFonts()
+ local LMP = LibStub("LibMediaProvider-1.0")
+ if LMP then
+ local font = LMP:Fetch('font', Shopkeeper.savedVariables.windowFont)
+ local fontString = font .. "|%d"
+ ShopkeeperWindowSearchLabel:SetFont(string.format(fontString, 16))
+ ShopkeeperWindowSearchBox:SetFont(string.format(fontString, 16))
+ ShopkeeperWindowTitle:SetFont(string.format(fontString, 26))
+ ShopkeeperWindowBuyer:SetFont(string.format(fontString, 20))
+ ShopkeeperWindowGuild:SetFont(string.format(fontString, 20))
+ ShopkeeperWindowItemName:SetFont(string.format(fontString, 20))
+ ShopkeeperWindowSellTime:SetFont(string.format(fontString, 20))
+ ShopkeeperWindowPrice:SetFont(string.format(fontString, 20))
+ ShopkeeperSwitchViewButton:SetFont(string.format(fontString, 16))
+ ShopkeeperPriceSwitchButton:SetFont(string.format(fontString, 16))
+ ShopkeeperResetButton:SetFont(string.format(fontString, 16))
+ ShopkeeperRefreshButton:SetFont(string.format(fontString, 16))
+ ShopkeeperMiniWindowSearchLabel:SetFont(string.format(fontString, 12))
+ ShopkeeperMiniWindowSearchBox:SetFont(string.format(fontString, 12))
+ ShopkeeperMiniWindowTitle:SetFont(string.format(fontString, 20))
+ ShopkeeperMiniWindowGuild:SetFont(string.format(fontString, 16))
+ ShopkeeperMiniWindowItemName:SetFont(string.format(fontString, 16))
+ ShopkeeperMiniWindowSellTime:SetFont(string.format(fontString, 16))
+ ShopkeeperMiniWindowPrice:SetFont(string.format(fontString, 16))
+ ShopkeeperMiniSwitchViewButton:SetFont(string.format(fontString, 12))
+ ShopkeeperMiniPriceSwitchButton:SetFont(string.format(fontString, 12))
+ ShopkeeperMiniResetButton:SetFont(string.format(fontString, 12))
+ ShopkeeperMiniRefreshButton:SetFont(string.format(fontString, 12))
+
+ ShopkeeperStatsWindowTitle:SetFont(string.format(fontString, 26))
+ ShopkeeperStatsWindowItemsSoldLabel:SetFont(string.format(fontString, 18))
+ ShopkeeperStatsWindowTotalGoldLabel:SetFont(string.format(fontString, 18))
+ ShopkeeperStatsWindowBiggestSaleLabel:SetFont(string.format(fontString, 18))
+ ShopkeeperStatsWindowSliderSettingLabel:SetFont(string.format(fontString, 18))
+ ShopkeeperStatsWindowSliderLabel:SetFont(string.format(fontString, 16))
+
+ for i = 1, #Shopkeeper.DataRows do
+ local dataRow = Shopkeeper.DataRows[i]
+ dataRow:GetNamedChild("Buyer"):SetFont(string.format(fontString, 16))
+ dataRow:GetNamedChild("Guild"):SetFont(string.format(fontString, 16))
+ dataRow:GetNamedChild("ItemName"):SetFont(string.format(fontString, 16))
+ dataRow:GetNamedChild("Quantity"):SetFont(string.format(fontString, 16))
+ dataRow:GetNamedChild("SellTime"):SetFont(string.format(fontString, 16))
+ dataRow:GetNamedChild("Price"):SetFont(string.format(fontString, 16))
+ if i <= #Shopkeeper.MiniDataRows then
+ local miniDataRow = Shopkeeper.MiniDataRows[i]
+ miniDataRow:GetNamedChild("Guild"):SetFont(string.format(fontString, 12))
+ miniDataRow:GetNamedChild("ItemName"):SetFont(string.format(fontString, 12))
+ miniDataRow:GetNamedChild("Quantity"):SetFont(string.format(fontString, 12))
+ miniDataRow:GetNamedChild("SellTime"):SetFont(string.format(fontString, 12))
+ miniDataRow:GetNamedChild("Price"):SetFont(string.format(fontString, 12))
+ end
+ end
+ end
+end
+
+-- Item tooltips
+function Shopkeeper:ShowToolTip(itemName, itemButton)
+ InitializeTooltip(ItemTooltip, itemButton)
+ ItemTooltip:SetLink(itemName)
+end
+
+-- Clear a given row's data
+function Shopkeeper.ClearDataRow(index)
+ if index < 1 or index > 15 then
+ return
+ end
+
+ local dataRow = Shopkeeper.DataRows[index]
+ dataRow:GetNamedChild("Buyer"):SetText("")
+ dataRow:GetNamedChild("Buyer"):SetHandler("OnMouseDoubleClick", nil)
+ dataRow:GetNamedChild("Guild"):SetText("")
+ dataRow:GetNamedChild("ItemIcon"):SetTexture(nil)
+ dataRow:GetNamedChild("ItemIcon"):SetHidden(true)
+ local itemCell = dataRow:GetNamedChild("ItemName")
+ itemCell:SetText("")
+ itemCell:SetHandler("OnMouseDoubleClick", nil)
+ itemCell:SetHandler("OnMouseEnter", nil)
+ dataRow:GetNamedChild("Quantity"):SetText("")
+ dataRow:GetNamedChild("SellTime"):SetText("")
+ dataRow:GetNamedChild("Price"):SetText("")
+end
+
+function Shopkeeper.ClearMiniDataRow(index)
+ if index < 1 or index > 8 then
+ return
+ end
+
+ local dataRow = Shopkeeper.MiniDataRows[index]
+ dataRow:GetNamedChild("Guild"):SetText("")
+ dataRow:GetNamedChild("ItemIcon"):SetTexture(nil)
+ dataRow:GetNamedChild("ItemIcon"):SetHidden(true)
+ local itemCell = dataRow:GetNamedChild("ItemName")
+ itemCell:SetText("")
+ itemCell:SetHandler("OnMouseDoubleClick", nil)
+ itemCell:SetHandler("OnMouseEnter", nil)
+ dataRow:GetNamedChild("Quantity"):SetText("")
+ dataRow:GetNamedChild("SellTime"):SetText("")
+ dataRow:GetNamedChild("Price"):SetText("")
+end
+
+-- Fill out a row with the given data
+function Shopkeeper.SetDataRow(index, buyer, guild, itemName, icon, quantity, sellTime, price, seller, kioskSale)
+ if index < 1 or index > 15 then return end
+
+ local dataRow = Shopkeeper.DataRows[index]
+
+ -- Some extra stuff for the Buyer cell to handle double-click and color changes
+ -- Plus add a marker if buyer is not in-guild (kiosk sale)
+ local buyerCell = dataRow:GetNamedChild("Buyer")
+ local buyerString = buyer
+ if kioskSale ~= nil and kioskSale == true then
+ buyerString = "|t16:16:/EsoUI/Art/icons/item_generic_coinbag.dds|t" .. buyerString
+ end
+ buyerCell:SetText(buyerString)
+ -- If the seller is the player, color the buyer green. Otherwise, blue.
+ local acctName = GetDisplayName()
+ if seller == acctName then
+ buyerCell:SetNormalFontColor(0.18, 0.77, 0.05, 1)
+ buyerCell:SetPressedFontColor(0.18, 0.77, 0.05, 1)
+ buyerCell:SetMouseOverFontColor(0.32, 0.90, 0.18, 1)
+ else
+ buyerCell:SetNormalFontColor(0.21, 0.54, 0.94, 1)
+ buyerCell:SetPressedFontColor(0.21, 0.54, 0.94, 1)
+ buyerCell:SetMouseOverFontColor(0.34, 0.67, 1, 1)
+ end
+ buyerCell:SetHandler("OnMouseDoubleClick", function()
+ if SCENE_MANAGER.currentScene.name == "mailSend" then
+ ZO_MailSendToField:SetText("")
+ ZO_MailSendToField:SetText(ZO_MailSendToField:GetText() .. buyer)
+ else
+ ZO_ChatWindowTextEntryEditBox:SetText("/w " .. buyer .. " " .. ZO_ChatWindowTextEntryEditBox:GetText())
+ end
+ end)
+ local buyerCellLabel = buyerCell:GetLabelControl()
+ buyerCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+
+ -- Guild cell
+ dataRow:GetNamedChild("Guild"):SetText(guild)
+ local guildCellLabel = dataRow:GetNamedChild("Guild"):GetLabelControl()
+ guildCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+
+ -- Item Icon
+ dataRow:GetNamedChild("ItemIcon"):SetHidden(false)
+ dataRow:GetNamedChild("ItemIcon"):SetTexture(icon)
+
+ -- Item name cell
+ local itemCell = dataRow:GetNamedChild("ItemName")
+ itemCell:SetText(zo_strformat("<<t:1>>", itemName))
+ -- Insert the item link into the chat box, with a quick substitution so brackets show up
+ itemCell:SetHandler("OnMouseDoubleClick", function()
+ ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. string.gsub(itemName, "|H0", "|H1"))
+ end)
+ itemCell:SetHandler("OnMouseEnter", function() Shopkeeper:ShowToolTip(itemName, itemCell) end)
+ itemCell:SetHandler("OnMouseExit", function() ClearTooltip(ItemTooltip) end)
+ local itemCellLabel = itemCell:GetLabelControl()
+ itemCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+
+ -- Quantity cell
+ dataRow:GetNamedChild("Quantity"):SetText("x" .. quantity)
+
+ -- Sale time cell
+ dataRow:GetNamedChild("SellTime"):SetText(sellTime)
+
+ -- Handle the setting of whether or not to show pre-cut sale prices
+ -- math.floor(number + 0.5) is a quick shorthand way to round for
+ -- positive values.
+ local dispPrice = price
+ if Shopkeeper.savedVariables.showFullPrice then
+ if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
+ dispPrice = math.floor((dispPrice / quantity) + 0.5)
+ end
+ else
+ local cutPrice = price * (1 - (GetTradingHouseCutPercentage() / 100))
+ if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
+ cutPrice = cutPrice / quantity
+ end
+ dispPrice = math.floor(cutPrice + 0.5)
+ end
+
+ -- Insert thousands separators for the price
+ local stringPrice = Shopkeeper.localizedNumber(dispPrice)
+
+ -- Finally, set the price
+ dataRow:GetNamedChild("Price"):SetText(stringPrice .. " " .. string.format("|t16:16:%s|t","EsoUI/Art/currency/currency_gold.dds"))
+end
+
+-- Fill out a row with the given data
+function Shopkeeper.SetMiniDataRow(index, guild, itemName, icon, quantity, sellTime, price, seller)
+ if index < 1 or index > 8 then return end
+
+ local dataRow = Shopkeeper.MiniDataRows[index]
+
+ -- Guild cell
+ dataRow:GetNamedChild("Guild"):SetText(guild)
+ local guildCellLabel = dataRow:GetNamedChild("Guild"):GetLabelControl()
+ guildCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+
+ -- Item Icon
+ dataRow:GetNamedChild("ItemIcon"):SetHidden(false)
+ dataRow:GetNamedChild("ItemIcon"):SetTexture(icon)
+
+ -- Item name cell
+ local itemCell = dataRow:GetNamedChild("ItemName")
+ itemCell:SetText(zo_strformat("<<t:1>>", itemName))
+ -- Insert the item link into the chat box, with a quick substitution so brackets show up
+ itemCell:SetHandler("OnMouseDoubleClick", function()
+ ZO_ChatWindowTextEntryEditBox:SetText(ZO_ChatWindowTextEntryEditBox:GetText() .. string.gsub(itemName, "|H0", "|H1"))
+ end)
+ itemCell:SetHandler("OnMouseEnter", function() Shopkeeper:ShowToolTip(itemName, itemCell) end)
+ itemCell:SetHandler("OnMouseExit", function() ClearTooltip(ItemTooltip) end)
+ local itemCellLabel = itemCell:GetLabelControl()
+ itemCellLabel:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+
+ -- Quantity cell
+ dataRow:GetNamedChild("Quantity"):SetText("x" .. quantity)
+
+ -- Sale time cell
+ dataRow:GetNamedChild("SellTime"):SetText(sellTime)
+
+ -- Handle the setting of whether or not to show pre-cut sale prices
+ -- math.floor(number + 0.5) is a quick shorthand way to round for
+ -- positive values.
+ local dispPrice = price
+ if Shopkeeper.savedVariables.showFullPrice then
+ if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
+ dispPrice = math.floor((dispPrice / quantity) + 0.5)
+ end
+ else
+ local cutPrice = price * (1 - (GetTradingHouseCutPercentage() / 100))
+ if Shopkeeper.savedVariables.showUnitPrice and quantity > 0 then
+ cutPrice = cutPrice / quantity
+ end
+ dispPrice = math.floor(cutPrice + 0.5)
+ end
+
+ -- Insert thousands separators for the price
+ local stringPrice = Shopkeeper.localizedNumber(dispPrice)
+
+ -- Finally, set the price
+ dataRow:GetNamedChild("Price"):SetText(stringPrice .. " " .. string.format("|t16:16:%s|t","EsoUI/Art/currency/currency_gold.dds"))
+end
+
+-- Build the data rows based on the position of the slider
+function Shopkeeper.DisplayRows()
+ if Shopkeeper.savedVariables.viewSize == "full" then
+ local startIndex = ShopkeeperWindowSlider:GetValue()
+ if startIndex + #Shopkeeper.DataRows > #Shopkeeper.SearchTable then
+ startIndex = #Shopkeeper.SearchTable - #Shopkeeper.DataRows
+ end
+
+ if startIndex < 1 then startIndex = 0 end
+
+ -- Hide the slider if there's less than a full page of results
+ ShopkeeperWindowSlider:SetHidden(#Shopkeeper.SearchTable < 16)
+
+ for i = 1, #Shopkeeper.DataRows do
+ local rowIndex = i + startIndex
+ if rowIndex > #Shopkeeper.SearchTable then
+ Shopkeeper.ClearDataRow(i)
+ ShopkeeperWindowSlider:SetHidden(true)
+ else
+ local scanResult = Shopkeeper.SearchTable[rowIndex]
+ -- Older data won't have kiosk info
+ local kioskSale = nil
+ if #scanResult > 8 then kioskSale = scanResult[9] end
+ Shopkeeper.SetDataRow(i, scanResult[1], scanResult[2], scanResult[3], scanResult[4], scanResult[5], Shopkeeper.textTimeSince(scanResult[6], false), scanResult[7], scanResult[8], kioskSale)
+ end
+ end
+
+ -- Scale the slider's range to the number of items we have minus the number of rows
+ local sliderMax = 0
+ local tableToUse = Shopkeeper.ScanResults
+ if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
+ if #tableToUse > 15 then sliderMax = (#tableToUse - 15) end
+ ShopkeeperWindowSlider:SetMinMax(0, sliderMax)
+ else
+ local startIndex = ShopkeeperMiniWindowSlider:GetValue()
+ if startIndex + #Shopkeeper.MiniDataRows > #Shopkeeper.SearchTable then
+ startIndex = #Shopkeeper.SearchTable - #Shopkeeper.MiniDataRows
+ end
+
+ if startIndex < 1 then startIndex = 0 end
+
+ -- Hide the slider if there's less than a full page of results
+ ShopkeeperMiniWindowSlider:SetHidden(#Shopkeeper.SearchTable < 9)
+
+ for i = 1, #Shopkeeper.MiniDataRows do
+ local rowIndex = i + startIndex
+ if rowIndex > #Shopkeeper.SearchTable then
+ Shopkeeper.ClearMiniDataRow(i)
+ ShopkeeperMiniWindowSlider:SetHidden(true)
+ else
+ local scanResult = Shopkeeper.SearchTable[rowIndex]
+ Shopkeeper.SetMiniDataRow(i, scanResult[2], scanResult[3], scanResult[4], scanResult[5], Shopkeeper.textTimeSince(scanResult[6], false), scanResult[7], scanResult[8])
+ end
+ end
+
+ -- Scale the slider's range to the number of items we have minus the number of rows
+ local sliderMax = 0
+ local tableToUse = Shopkeeper.ScanResults
+ if Shopkeeper.viewMode == "self" then tableToUse = Shopkeeper.SelfSales end
+ if #tableToUse > 8 then sliderMax = (#tableToUse - 8) end
+ ShopkeeperMiniWindowSlider:SetMinMax(0, sliderMax)
+ end
+end
+
+function Shopkeeper.ToggleViewMode()
+ if Shopkeeper.savedVariables.viewSize == "full" then
+ Shopkeeper.savedVariables.viewSize = "half"
+ ShopkeeperWindow:SetHidden(true)
+ Shopkeeper.DisplayRows()
+ ShopkeeperMiniWindow:SetHidden(false)
+
+ if Shopkeeper.savedVariables.openWithMail then
+ MAIL_INBOX_SCENE:RemoveFragment(Shopkeeper.uiFragment)
+ MAIL_SEND_SCENE:RemoveFragment(Shopkeeper.uiFragment)
+ MAIL_INBOX_SCENE:AddFragment(Shopkeeper.miniUiFragment)
+ MAIL_SEND_SCENE:AddFragment(Shopkeeper.miniUiFragment)
+ end
+
+ if Shopkeeper.savedVariables.openWithStore then
+ TRADING_HOUSE_SCENE:RemoveFragment(Shopkeeper.uiFragment)
+ TRADING_HOUSE_SCENE:AddFragment(Shopkeeper.miniUiFragment)
+ end
+ else
+ Shopkeeper.savedVariables.viewSize = "full"
+ ShopkeeperMiniWindow:SetHidden(true)
+ Shopkeeper.DisplayRows()
+ ShopkeeperWindow:SetHidden(false)
+
+ if Shopkeeper.savedVariables.openWithMail then
+ MAIL_INBOX_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
+ MAIL_SEND_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
+ MAIL_INBOX_SCENE:AddFragment(Shopkeeper.uiFragment)
+ MAIL_SEND_SCENE:AddFragment(Shopkeeper.uiFragment)
+ end
+
+ if Shopkeeper.savedVariables.openWithStore then
+ TRADING_HOUSE_SCENE:RemoveFragment(Shopkeeper.miniUiFragment)
+ TRADING_HOUSE_SCENE:AddFragment(Shopkeeper.uiFragment)
+ end
+ end
+end
+
+-- Set the visibility status of the main window to the opposite of its current status
+function Shopkeeper.ToggleShopkeeperWindow()
+ if Shopkeeper.savedVariables.viewSize == "full" then
+ ShopkeeperMiniWindow:SetHidden(true)
+ if ShopkeeperWindow:IsHidden() then
+ Shopkeeper.DisplayRows()
+ SetGameCameraUIMode(true)
+ end
+
+ ShopkeeperWindow:SetHidden(not ShopkeeperWindow:IsHidden())
+ else
+ ShopkeeperWindow:SetHidden(true)
+ if ShopkeeperMiniWindow:IsHidden() then
+ Shopkeeper.DisplayRows()
+ SetGameCameraUIMode(true)
+ end
+
+ ShopkeeperMiniWindow:SetHidden(not ShopkeeperMiniWindow:IsHidden())
+ end
+end
+
+-- Set the visibility status of the stats window to the opposite of its current status
+function Shopkeeper.ToggleShopkeeperStatsWindow()
+ if ShopkeeperStatsWindow:IsHidden() then Shopkeeper.UpdateStatsWindow() end
+ ShopkeeperStatsWindow:SetHidden(not ShopkeeperStatsWindow:IsHidden())
+end
+
+-- Handle scrolling the main window
+function Shopkeeper.OnSliderMouseWheel(self, delta)
+ if Shopkeeper.savedVariables.viewSize == "full" then
+ local oldSliderLevel = ShopkeeperWindowSlider:GetValue()
+ local newSliderLevel = oldSliderLevel - delta
+ ShopkeeperWindowSlider:SetValue(newSliderLevel)
+ else
+ local oldSliderLevel = ShopkeeperMiniWindowSlider:GetValue()
+ local newSliderLevel = oldSliderLevel - delta
+ ShopkeeperMiniWindowSlider:SetValue(newSliderLevel)
+ end
+end
+
+-- Update the table if the slider moved
+function Shopkeeper.OnSliderMoved(self, sliderLevel, eventReason)
+ Shopkeeper.DisplayRows()
+end
+
+function Shopkeeper.OnStatsSliderMoved(self, sliderLevel, eventReason)
+ Shopkeeper.UpdateStatsWindow()
+end
\ No newline at end of file
diff --git a/Shopkeeper_Util.lua b/Shopkeeper_Util.lua
new file mode 100644
index 0000000..cbb2d9f
--- /dev/null
+++ b/Shopkeeper_Util.lua
@@ -0,0 +1,71 @@
+-- Shopkeeper Utility Functions File
+-- Last Updated August 10, 2014
+-- Written August 2014 by Dan Stone (@khaibit) - dankitymao@gmail.com
+-- Released under terms in license accompanying this file.
+-- Distribution without license is prohibited!
+
+-- Translate from the i18n table
+function Shopkeeper.translate(stringName)
+ local result = Shopkeeper.i18n.localized[stringName]
+ assert(result, ("The id %q was not found in the current locale"):format(stringName))
+ return result
+end
+
+function Shopkeeper.localizedNumber(numberValue)
+ local stringPrice = numberValue
+ -- Insert thousands separators for the price
+ -- local stringPrice = numberValue
+ local subString = "%1" .. Shopkeeper.translate("thousandsSep") .."%2"
+ while true do
+ stringPrice, k = string.gsub(stringPrice, "^(-?%d+)(%d%d%d)", subString)
+ if (k == 0) then break end
+ end
+
+ return stringPrice
+end
+
+-- Create a textual representation of a time interval
+-- (X and Y) or Z in LUA is the equivalent of C-style
+-- ternary syntax X ? Y : Z so long as Y is not false or nil
+function Shopkeeper.textTimeSince(theTime, useLowercase)
+ local secsSince = GetTimeStamp() - theTime
+ if secsSince < 90 then
+ return ((useLowercase and zo_strformat(Shopkeeper.translate('timeSecondsAgoLC'), secsSince)) or
+ zo_strformat(Shopkeeper.translate('timeSecondsAgo'), secsSince))
+ elseif secsSince < 5400 then
+ return ((useLowercase and zo_strformat(Shopkeeper.translate('timeMinutesAgoLC'), math.floor(secsSince / 60.0))) or
+ zo_strformat(Shopkeeper.translate('timeMinutesAgo'), math.floor(secsSince / 60.0)))
+ elseif secsSince < 86400 then
+ return ((useLowercase and zo_strformat(Shopkeeper.translate('timeHoursAgoLC'), math.floor(secsSince / 3600.0))) or
+ zo_strformat(Shopkeeper.translate('timeHoursAgo'), math.floor(secsSince / 3600.0)))
+ else
+ return ((useLowercase and zo_strformat(Shopkeeper.translate('timeDaysAgoLC'), math.floor(secsSince / 86400.0))) or
+ zo_strformat(Shopkeeper.translate('timeDaysAgo'), math.floor(secsSince / 86400.0)))
+ end
+end
+
+-- A utility function to grab all the keys of the sound table
+-- to populate the options dropdown
+function Shopkeeper.soundKeys()
+ local keyList = {}
+ for i = 1, #Shopkeeper.alertSounds do table.insert(keyList, Shopkeeper.alertSounds[i].name) end
+ return keyList
+end
+
+-- A utility function to find the key associated with a given value in
+-- the sounds table. Best we can do is a linear search unfortunately,
+-- but it's a small table.
+function Shopkeeper.searchSounds(sound)
+ for i, theSound in ipairs(Shopkeeper.alertSounds) do
+ if theSound.sound == sound then return theSound.name end
+ end
+
+ -- If we hit this point, we didn't find what we were looking for
+ return nil
+end
+
+function Shopkeeper.searchSoundNames(name)
+ for i,theSound in ipairs(Shopkeeper.alertSounds) do
+ if theSound.name == name then return theSound.sound end
+ end
+end
\ No newline at end of file
diff --git a/i18n/DE.lua b/i18n/DE.lua
index aa273d7..563ecd9 100644
--- a/i18n/DE.lua
+++ b/i18n/DE.lua
@@ -71,7 +71,7 @@ Shopkeeper.i18n.localized = {
statsTitle = "Sales Statistics",
statsTimeAll = "Using all data",
statsTimeSome = "Going back %d days",
- statsItemsSold = "Items sold: %d",
+ statsItemsSold = "Items sold: %d (%d%% from guild trader)",
statsTotalGold = "Total gold: %s |t16:16:EsoUI/Art/currency/currency_gold.dds|t (%s |t16:16:EsoUI/Art/currency/currency_gold.dds|t per day)",
statsBiggest = "Gr\195\182\195\159ter Verkaufs: %s (%s |t16:16:EsoUI/Art/currency/currency_gold.dds|t)",
statsDays = "Tagen: ",
diff --git a/i18n/EN.lua b/i18n/EN.lua
index ac29047..0ff0a68 100644
--- a/i18n/EN.lua
+++ b/i18n/EN.lua
@@ -70,7 +70,7 @@ Shopkeeper.i18n.localized = {
statsTitle = "Sales Statistics",
statsTimeAll = "Using all data",
statsTimeSome = "Going back %d days",
- statsItemsSold = "Items sold: %d",
+ statsItemsSold = "Items sold: %d (%d%% from guild trader)",
statsTotalGold = "Total gold: %s |t16:16:EsoUI/Art/currency/currency_gold.dds|t (%s |t16:16:EsoUI/Art/currency/currency_gold.dds|t per day)",
statsBiggest = "Biggest sale: %s (%s |t16:16:EsoUI/Art/currency/currency_gold.dds|t)",
statsDays = "Days: ",
diff --git a/i18n/FR.lua b/i18n/FR.lua
index 8ac2301..e1daf86 100644
--- a/i18n/FR.lua
+++ b/i18n/FR.lua
@@ -70,7 +70,7 @@ Shopkeeper.i18n.localized = {
statsTitle = "Sales Statistics",
statsTimeAll = "Using all data",
statsTimeSome = "Going back %d days",
- statsItemsSold = "Items sold: %d",
+ statsItemsSold = "Items sold: %d (%d%% from guild trader)",
statsTotalGold = "Total gold: %s |t16:16:EsoUI/Art/currency/currency_gold.dds|t (%s |t16:16:EsoUI/Art/currency/currency_gold.dds|t per day)",
statsBiggest = "Biggest sale: %s (%s |t16:16:EsoUI/Art/currency/currency_gold.dds|t)",
statsDays = "Days: ",
diff --git a/readme b/readme
index 6b715aa..e61da27 100644
--- a/readme
+++ b/readme
@@ -3,6 +3,13 @@ Inc. or its affiliates. The Elder Scrolls
trademarks or trademarks of ZeniMax Media Inc. in the United States and/or
other countries. All rights reserved.
+Changelog for 0.9b
+ Further rewrite of part of the scanning routines to be more accurate
+ Some small tweaks to the time display routines (will go up to 90 seconds before saying 1 minute, 90 minutes before 1 hour, etc.)
+ Fixes to on-screen alerts to avoid 'missing' multiple identical alerts
+ GUILD TRADER SUPPORT! Buyer names now have a gold bag icon next to them if they are not in the guild (i.e. bought at your guild's trader kiosk)
+ Stats Window now also shows you percentage of sales made at the guild trader
+ Other minor tweaks and optimizations as we push towards a fully-translated, fully-functional 1.0 release!
Changelog for 0.9a
Rewrite of part of the scanning routines to be more accurate