Name | Type | is_array | initial_value |
SpecialShop | unit | No | |
TasItemShop_Item | itemcode | No | |
TasItemShop_Unit | unitcode | No | |
TasItemShop_UnitExact | unit | No |
do
local old = TriggerAddAction
function TriggerAddAction(whichTrigger, actionFunc)
old(whichTrigger, function() xpcall(actionFunc, print) end)
end
end
-- After Loading in 1.31 FourCC stops working. Hence one overwrittes it with a function I got the function from Zed (Hive Discord)
local isReforged = (BlzFrameGetChild ~= nil)
if not isReforged then
function FourCC(id)
return 0x1000000 * string.byte(id:sub(1,1)) +
0x10000 * string.byte(id:sub(2,2)) +
0x100 * string.byte(id:sub(3,3)) +
string.byte(id:sub(4,4))
end
end
-- After Loading string.pack & string.unpack stop working. Hence one nils them for the save.
do
local real = InitBlizzard
function InitBlizzard()
real()
-- enable the next line as soon blizzard fixed the bug in current version
--if GetLocalizedString("REFORGED") ~= "REFORGED" then return end
local tim = CreateTimer()
local trig = CreateTrigger()
TriggerRegisterGameEvent(trig, EVENT_GAME_SAVE)
TriggerAddAction(trig, function()
local backup = string.pack
local backup2 = string.unpack
string.pack = nil
string.unpack = nil
-- print("saved")
TimerStart(tim, 0, false, function()
string.pack = backup
string.unpack = backup2
-- print("backup")
end)
end)
local trig2 = CreateTrigger()
TriggerRegisterGameEvent(trig2, EVENT_GAME_LOADED)
TriggerAddAction(trig2, function()
-- prevent restoring the backups when the game is loaded
PauseTimer(tim)
-- print("Loaded")
end)
end
end
-- in 1.31 and upto 1.32.9 PTR (when I wrote this). Frames are not correctly saved and loaded, breaking the game.
-- This runs all functions added to it with a 0s delay after the game was loaded.
FrameLoader = {
OnLoadTimer = function ()
for _,v in ipairs(FrameLoader) do v() end
end
,OnLoadAction = function()
TimerStart(FrameLoader.Timer, 0, false, FrameLoader.OnLoadTimer)
end
}
function FrameLoaderAdd(func)
if not FrameLoader.Timer then
FrameLoader.Trigger = CreateTrigger()
FrameLoader.Timer = CreateTimer()
TriggerRegisterGameEvent(FrameLoader.Trigger, EVENT_GAME_LOADED)
TriggerAddAction(FrameLoader.Trigger, FrameLoader.OnLoadAction)
end
table.insert(FrameLoader, func)
end
--Global Initialization 'Lite' by Bribe, with special thanks to Tasyen and Eikonium
--Last updated 11 Nov 2022
do
local addInit
function OnGlobalInit(initFunc) addInit("InitGlobals", initFunc) end -- Runs once all GUI variables are instantiated.
function OnTrigInit (initFunc) addInit("InitCustomTriggers", initFunc) end -- Runs once all InitTrig_ are called.
function OnMapInit (initFunc) addInit("RunInitializationTriggers", initFunc) end -- Runs once all Map Initialization triggers are run.
function OnGameStart (initFunc) addInit("MarkGameStarted", initFunc) end -- Runs once the game has actually started.
do
local initializers = {}
addInit=function(initName, initFunc)
initializers[initName] = initializers[initName] or {}
table.insert(initializers[initName], initFunc)
end
local function init(initName, continue)
if initializers[initName] then
for _,initFunc in ipairs(initializers[initName]) do pcall(initFunc) end
end
if continue then continue() end
end
local function hook(name, continue)
local _name=rawget(_G, name)
if _name then
rawset(_G, name, function()
_name()
init(name, continue) --run the initializer after the hooked handler function has been called.
end)
else
init(name, continue) --run initializer immediately
end
end
hook("InitGlobals",function()
hook("InitCustomTriggers",function() --InitCustomTriggers and RunInitializationTriggers are declared after the users' code,
hook "RunInitializationTriggers" --hence users need to wait until they have been declared.
end)
end)
hook "MarkGameStarted"
end
end
--[[ TasFrameAction V1.3 by Tasyen
TasFrameAction is an Lua system to not have to care about Trigger and FrameEvents for FrameAction. All FrameEvents are binded to one trigger that trigger than calls the action for
handles frame Events in one trigger, care only about the actionFunction itself.
calls give Actions inside xpcall.
Supports only one Action per Event+Frame
Example
TasSliderAction(sliderFrame, function(frame, player, value)
print(BlzFrameGetName(frame), GetPlayerId(player), value)
end)
TasButtonAction(frame, function(frame, player))
wrapper for TasFrameAction meant for BUTTON just ControlClick
Removes focus & StopCamera
takes FRAMEEVENT_CONTROL_CLICK from TasFrameAction for this frame
TasSliderAction(frame, function(frame, player, value)[, StepSize, scrollTarget, allowPoll])
action happens when a Value is set
TasSliderAction.AvoidPoll (true) skip actions with the same value in a row by 1 player
set scrollTarget from the outside TasSliderAction.Target[frame] = scrollTarget
scrollTarget most likely removes the action from happen for frame.
takes FRAMEEVENT_MOUSE_WHEEL and FRAMEEVENT_SLIDER_VALUE_CHANGED from TasFrameAction for this frame
TasEditBoxAction(frame[, actionEnter, actionEdit])
skip an action to not have one for that event
function(frame, player, text)
TasDialogAction(frame, function(frame, player, accept))
TasCheckBoxAction(frame, function(frame, player, checked))
TasFrameMouseMoveAction(frame, actionEnter(frame, player), actionLeave(frame, player), actionWheel(frame, player, upwards))
TasFrameMouseUpAction(frame, function(frame, player, rightClick)
Happens when the mouse click is released over frame
rightClick does not work probably during Paused Games
takes FRAMEEVENT_MOUSE_UP
TasMenuAction(frame, function(frame, player, value))
for POPUPMENU
functions above use an entry in TasFrameAction
TasFrameAction(frame, action, frameEvent)
action = function(frame, player, value, text)
]]
TasFrameAction = setmetatable({
EVENTNAME= {
"CONTROL_CLICK", "MOUSE_ENTER", "MOUSE_LEAVE", "MOUSE_UP"
, "MOUSE_DOWN", "MOUSE_WHEEL", "CHECKBOX_CHECKED", "CHECKBOX_UNCHECKED"
, "EDITBOX_TEXT_CHANGED", "POPUPMENU_ITEM_CHANGED", "MOUSE_DOUBLECLICK", "SPRITE_ANIM_UPDATE"
, "SLIDER_VALUE_CHANGED", "DIALOG_CANCEL", "DIALOG_ACCEPT", "EDITBOX_ENTER"
}
,ERROR = function(x)
print("TasFrameAction - ERROR")
print("FrameName", BlzFrameGetName(BlzGetTriggerFrame()), TasFrameAction.EVENTNAME[GetHandleId(BlzGetTriggerFrameEvent())]
, "PlayerId:", GetPlayerId(GetTriggerPlayer())
-- , BlzGetTriggerFrameValue(), BlzGetTriggerFrameText()
)
print(x)
return x
end
}
,{
__call = function(table, frame, action, frameEvent)
-- first call?
if not TasFrameAction.Trigger then
-- FrameEventData
for i = 1, 16 do
TasFrameAction[ConvertFrameEventType(i)] = {}
end
-- yes, Create the Trigger and the click handler.
TasFrameAction.Trigger = CreateTrigger()
TriggerAddAction(TasFrameAction.Trigger, function()
local frame = BlzGetTriggerFrame()
local event = BlzGetTriggerFrameEvent()
-- call the action set for that frame&Event
if TasFrameAction[event][frame] then
xpcall(TasFrameAction[event][frame], TasFrameAction.ERROR, frame, GetTriggerPlayer(), BlzGetTriggerFrameValue(), BlzGetTriggerFrameText())
--TasFrameAction[event][frame](frame, GetTriggerPlayer(), BlzGetTriggerFrameValue(), BlzGetTriggerFrameText())
end
frame = nil
event = nil
end)
end
-- create the click event only when it does not exist yet.
if not TasFrameAction[frameEvent][frame] then
BlzTriggerRegisterFrameEvent(TasFrameAction.Trigger, frame, frameEvent)
end
-- Using [frameEvent][frame] brings a fixed amout of Tables.
TasFrameAction[frameEvent][frame] = action
end
})
TasSliderAction = setmetatable({
AvoidPoll = __jarray(true) -- default value (true) do not trigger the same value multiple times in a row
,StepSize = {}
,Target = { } -- some other Frame get scrolled?
,WHEEL = function(frame, player, value, text)
if GetLocalPlayer() == player then
local target = TasSliderAction.Target[frame]
if not target then target = frame end
if value > 0 then
BlzFrameSetValue(target, BlzFrameGetValue(target) + TasSliderAction.StepSize[frame])
else
BlzFrameSetValue(target, BlzFrameGetValue(target) - TasSliderAction.StepSize[frame])
end
end
end
,VALUE = function(frame, player, value, text)
if not TasSliderAction[frame] then return end
-- avoid Polling
if not TasSliderAction.AvoidPoll[frame] or TasSliderAction.AvoidPollData[player][frame] ~= value then
TasSliderAction.AvoidPollData[player][frame] = value
TasSliderAction[frame](frame, player, value)
end
end
}
,{__call = function(table, frame, action, stepSize, scrollTarget, allowPoll)
-- first call?
if not TasSliderAction.AvoidPollData then
TasSliderAction.AvoidPollData = {}
for i=0, bj_MAX_PLAYER_SLOTS - 1 do TasSliderAction.AvoidPollData[Player(i)] = __jarray(0.0) end
end
if allowPoll ~= nil then TasSliderAction.AvoidPoll[frame] = not allowPoll end
TasFrameAction(frame, TasSliderAction.WHEEL, FRAMEEVENT_MOUSE_WHEEL)
TasFrameAction(frame, TasSliderAction.VALUE, FRAMEEVENT_SLIDER_VALUE_CHANGED)
if type(action) =="function" then
TasSliderAction[frame] = action
end
TasSliderAction.StepSize[frame] = stepSize or 1
TasSliderAction.Target[frame] = scrollTarget
end
})
TasSliderAction.Set = TasSliderAction
TasButtonAction = setmetatable({
ACTION = function(frame, player, value, text)
-- remove Focus for the local clicking player
if player == GetLocalPlayer() then
BlzFrameSetEnable(frame, false)
BlzFrameSetEnable(frame, true)
StopCamera()
end
-- call the action set for that frame
if TasButtonAction[frame] then TasButtonAction[frame](frame, player) end
end
},{
__call = function(table, frame, action)
TasFrameAction(frame, TasButtonAction.ACTION, FRAMEEVENT_CONTROL_CLICK)
TasButtonAction[frame] = action
end
})
TasButtonAction.Set = TasButtonAction
TasEditBoxAction = setmetatable({
A = {}
,B = {}
,ENTER = function(frame, player, value, text)
if TasEditBoxAction.A[frame] then TasEditBoxAction.A[frame](frame, player, text) end
end
,EDIT = function(frame, player, value, text)
if TasEditBoxAction.B[frame] then TasEditBoxAction.B[frame](frame, player, text) end
end
},{
__call = function(table, frame, actionEnter, actionEdit)
if actionEnter then TasFrameAction(frame, TasEditBoxAction.ENTER, FRAMEEVENT_EDITBOX_ENTER) end
if actionEdit then TasFrameAction(frame, TasEditBoxAction.EDIT, FRAMEEVENT_EDITBOX_TEXT_CHANGED) end
TasEditBoxAction.A[frame] = actionEnter
TasEditBoxAction.B[frame] = actionEdit
end
})
TasEditBoxAction.Set = TasEditBoxAction
TasDialogAction = setmetatable({
ACTION = function(frame, player)
if TasDialogAction[frame] then TasDialogAction[frame](frame, player, BlzGetTriggerFrameEvent() == FRAMEEVENT_DIALOG_ACCEPT) end
end
},{
__call = function(table, frame, action)
TasFrameAction(frame, TasDialogAction.ACTION, FRAMEEVENT_DIALOG_ACCEPT)
TasFrameAction(frame, TasDialogAction.ACTION, FRAMEEVENT_DIALOG_CANCEL)
TasDialogAction[frame] = action
end
})
TasDialogAction.Set = TasDialogAction
TasCheckBoxAction = setmetatable({
ACTION = function(frame, player)
if TasCheckBoxAction[frame] then TasCheckBoxAction[frame](frame, player, BlzGetTriggerFrameEvent() == FRAMEEVENT_CHECKBOX_CHECKED) end
end
},{
__call = function(table, frame, action)
TasFrameAction(frame, TasCheckBoxAction.ACTION, FRAMEEVENT_CHECKBOX_CHECKED)
TasFrameAction(frame, TasCheckBoxAction.ACTION, FRAMEEVENT_CHECKBOX_UNCHECKED)
TasCheckBoxAction[frame] = action
end
})
TasCheckBoxAction.Set = TasCheckBoxAction
TasFrameMouseMoveAction = setmetatable({
A = {}
,B = {}
,C = {}
,ENTER = function(frame, player)
if TasFrameMouseMoveAction.A[frame] then TasFrameMouseMoveAction.A[frame](frame, player) end
end
,LEAVE = function(frame, player)
if TasFrameMouseMoveAction.B[frame] then TasFrameMouseMoveAction.B[frame](frame, player) end
end
,WHEEL = function(frame, player, value)
if TasFrameMouseMoveAction.C[frame] then TasFrameMouseMoveAction.C[frame](frame, player, value > 0) end
end
},{
__call = function(table, frame, actionEnter, actionLeave, actionWheel)
if actionEnter then TasFrameAction(frame, TasFrameMouseMoveAction.ENTER, FRAMEEVENT_MOUSE_ENTER) end
if actionLeave then TasFrameAction(frame, TasFrameMouseMoveAction.LEAVE, FRAMEEVENT_MOUSE_LEAVE) end
if actionWheel then TasFrameAction(frame, TasFrameMouseMoveAction.WHEEL, FRAMEEVENT_MOUSE_WHEEL) end
TasFrameMouseMoveAction.A[frame] = actionEnter
TasFrameMouseMoveAction.B[frame] = actionLeave
TasFrameMouseMoveAction.C[frame] = actionWheel
end
})
TasFrameMouseMoveAction.Set = TasFrameMouseMoveAction
TasFrameMouseUpAction = setmetatable({
TriggerCount = 0
,ACTION = function(frame, player)
-- during Pause EVENT_PLAYER_MOUSE_UP does not work, -> when The counter didn't increase since last Time do not allow this count as right click
local clickWorked = GetTriggerExecCount(TasFrameMouseUpAction.MouseTrigger) > TasFrameMouseUpAction.TriggerCount
if TasFrameMouseUpAction[frame] then TasFrameMouseUpAction[frame](frame, player, TasFrameMouseUpAction.RightClick[player] and clickWorked) end
TasFrameMouseUpAction.TriggerCount = GetTriggerExecCount(TasFrameMouseUpAction.MouseTrigger)
end
},{
__call = function(table, frame, action)
if not TasFrameMouseUpAction.MouseTrigger then
TasFrameMouseUpAction.RightClick = __jarray(false)
TasFrameMouseUpAction.MouseTrigger = CreateTrigger()
for i = 0, bj_MAX_PLAYERS - 1 do
TriggerRegisterPlayerEvent(TasFrameMouseUpAction.MouseTrigger, Player(i), EVENT_PLAYER_MOUSE_UP)
end
TriggerAddAction(TasFrameMouseUpAction.MouseTrigger, function()
TasFrameMouseUpAction.RightClick[GetTriggerPlayer()] = GetHandleId(BlzGetTriggerPlayerMouseButton()) == GetHandleId(MOUSE_BUTTON_TYPE_RIGHT)
end)
end
TasFrameAction(frame, TasFrameMouseUpAction.ACTION, FRAMEEVENT_MOUSE_UP)
TasFrameMouseUpAction[frame] = action
end
})
TasFrameMouseUpAction.Set = TasFrameMouseUpAction
TasMenuAction = setmetatable({
ACTION = function(frame, player, value)
if TasMenuAction[frame] then TasMenuAction[frame](frame, player, value) end
end
},{
__call = function(table, frame, action)
TasFrameAction(frame, TasMenuAction.ACTION, FRAMEEVENT_POPUPMENU_ITEM_CHANGED)
TasMenuAction[frame] = action
end
})
TasMenuAction.Set = TasMenuAction
function CreateSimpleTooltip(frame, text)
-- this FRAME is important when the Box is outside of 4:3 it can be limited to 4:3.
local toolTipParent = BlzCreateFrameByType("FRAME", "", frame, "", 0)
local toolTipBox = BlzCreateFrame("EscMenuControlBackdropTemplate", toolTipParent, 0, 0)
local toolTip = BlzCreateFrame("TasButtonTextTemplate", toolTipBox, 0, 0)
BlzFrameSetPoint(toolTip, FRAMEPOINT_BOTTOM, frame, FRAMEPOINT_TOP, 0, 0.008)
BlzFrameSetPoint(toolTipBox, FRAMEPOINT_TOPLEFT, toolTip, FRAMEPOINT_TOPLEFT, -0.008, 0.008)
BlzFrameSetPoint(toolTipBox, FRAMEPOINT_BOTTOMRIGHT, toolTip, FRAMEPOINT_BOTTOMRIGHT, 0.008, -0.008)
BlzFrameSetText(toolTip, text)
BlzFrameSetTooltip(frame, toolTipParent)
return toolTip
end
-- function TasItemCaclCost(...)
-- calculates the gold and lumbercost of given itemCodes, also accpets strings and a bunch of strings.
-- this will created the items, trigger buy item events + no target order events
-- function TasItemGetCost(itemCode)
-- returns the gold and lumber cost of that item
-- gold, lumber = TasItemGetCost(itemCode)
-- function TasItemCalcDestroy()
do
if OnInit then -- Total Initialization v5.2.0.1 by Bribe
OnInit(TasItemInit)
else -- without
local real = InitBlizzard
function InitBlizzard()
real()
TasItemInit()
end
end
function TasItemInit()
local shopOwner = Player(bj_PLAYER_NEUTRAL_EXTRA)
local shop = CreateUnit(shopOwner, FourCC('nmrk'), 700, -2000, 0)
local shopRect = Rect(0 , 0, 1000, 1000)
--print(GetHandleId(shop))
MoveRectTo(shopRect, GetUnitX(shop), GetUnitY(shop))
UnitAddAbility(shop, FourCC('AInv'))
ShowUnit(shop, false)
IssueNeutralTargetOrder(shopOwner, shop, "smart", shop)
local TasItemData = {
--Counter = 0,
Test = {Counter = 0}
}
function TasItemCalcDestroy()
EnumItemsInRect(shopRect, nil, function()
RemoveItem(GetEnumItem())
end)
ShowUnit(shop, true)
RemoveUnit(shop)
RemoveRect(shopRect)
TasItemData.Test = nil
end
local function Start()
--print("Start", GetObjectName(TasItemData.Test[1]))
local itemCode = TasItemData.Test[1]
AddItemToStock(shop, itemCode, 1, 1)
SetPlayerState(shopOwner, PLAYER_STATE_RESOURCE_GOLD, 99999999)
SetPlayerState(shopOwner, PLAYER_STATE_RESOURCE_LUMBER, 99999999)
local gold = GetPlayerState(shopOwner, PLAYER_STATE_RESOURCE_GOLD)
local lumber = GetPlayerState(shopOwner, PLAYER_STATE_RESOURCE_LUMBER)
IssueNeutralImmediateOrderById(shopOwner, shop, itemCode)
local item = CreateItem(itemCode, 0, 0)
TasItemData[itemCode] = {
Gold = gold - GetPlayerState(shopOwner, PLAYER_STATE_RESOURCE_GOLD),
Lumber = lumber - GetPlayerState(shopOwner, PLAYER_STATE_RESOURCE_LUMBER),
Charge = GetItemCharges(item)
}
RemoveItem(item)
item = nil
RemoveItemFromStock(shop, itemCode)
-- testing order does not matter much, simple reindex
TasItemData.Test[1] = TasItemData.Test[TasItemData.Test.Counter]
TasItemData.Test.Counter = TasItemData.Test.Counter - 1
if TasItemData.Test.Counter > 0 then
Start()
end
EnumItemsInRect(shopRect, nil, function()
RemoveItem(GetEnumItem())
end)
end
function TasItemCaclCost(...)
local item
for index, itemCode in ipairs({...}) do
if type(itemCode) == "string" then itemCode = FourCC(itemCode) end
-- if there is already data for that itemcode, skip it
if not TasItemData[itemCode] then
-- is this a valid itemCode? Create it, if that fails skip testing it
item = CreateItem(itemCode, 0, 0)
if GetHandleId(item) > 0 then
RemoveItem(item)
TasItemData.Test.Counter = TasItemData.Test.Counter + 1
TasItemData.Test[TasItemData.Test.Counter] = itemCode
end
end
end
if TasItemData.Test.Counter > 0 then Start() end
item = nil
end
function TasItemGetCost(itemCode)
if type(itemCode) == "string" then itemCode = FourCC(itemCode) end
if not TasItemData[itemCode] then TasItemCaclCost(itemCode) end
if TasItemData[itemCode] then
return TasItemData[itemCode].Gold, TasItemData[itemCode].Lumber, TasItemData[itemCode].Charge
else
return 0, 0, 0
end
end
end
end
--[[
TasButtonList15 by Tasyen
TasButtonList is a higher Level UI-Component to search, filter and select data using a fixed amount of buttons.
The UI-API part one has to do (as mapper using this system) is quite small.
Provides a built in Tooltip-Box
There can be many TasButtonList at the same Time.
Each player can have a different dataPool inside a TasButtonList.
Can differ between right click & left click (optional)
Supports differnt Buttons (they have to be defined in fdf)
ObjectEditor lists are handled with the default Actions, only need to define buttonAction in such a case.
TasButtonList.TooltipCreator = function CreateTasButtonTooltip(frameObject, parent[, button]) -- is used to create the tooltip
Structure
object.Data = {}, --an array each slot is the user data buttonListObject.Data[player][dataIndex] Count
object.Data[player].Count
object.DataFiltered = {Count = 0}, -- indexes of Data fitting the current search (async)
object.ViewPoint = 0,
object.Parent
object.Head -- hidden Frames the buttons are relative to the Head's bottom.
object.TotalFrame -- hidden Frames to manage positions better, covers the whole space of a TasButtonList
object.InputFrame -- search input
object.Slider
object.SliderText
object.SliderStep
object.Frames.GapCol -- has only a effect on new Rows
object.Frames.GapRow
object.Frames.Cols
object.Frames.Rows
object.Frames.ButtonName -- used to create buttons can be a name or function
object.Frames.CreateAction
object.Frames.Count -- total frameObject Count right now
object.Frames[1 to object.Frames.Count] = frameObject -- the frameObject each button is a frameobject
frameObject default this depends on the button created
frameObject.Button
frameObject.ToolTipFrame
frameObject.ToolTipFrameIcon
frameObject.ToolTipFrameName
frameObject.ToolTipFrameSeperator
frameObject.ToolTipFrameText
frameObject.Icon
frameObject.Text
frameObject.IconGold
frameObject.TextGold
frameObject.IconLumber
frameObject.TextLumber
TasButtonList actions
object.ButtonAction = function(data, buttonListObject, dataIndex, player) end
object.RightClickAction = function(data, buttonListObject, dataIndex, player) end
object.UpdateAction = function(frameObject, data) end
object.SearchAction = function(data, searchedText, buttonListObject) return true end
object.FilterAction = function(data, buttonListObject, isTextSearching) return true end
object.AsyncButtonAction = function(buttonListObject, data, frame) end
object.AsyncRightClickAction = function(buttonListObject, data, frame) end
function CreateTasButtonListEx2(buttonName, cols, rows[, colGap, rowGap, parent, createAction])
buttonName can be a string or a function, called for every button you wana create should return the interactive button
string -> fdf frameplueprint
function(buttonFrameObject, parent, index))
createAction function(frameObject, int, buttonCreated) use this to fill frameObject with the subFrames mostly for fdf also runs after the tooltips were created
returns the TasButtonList
function TasButtonListAddRow(buttonListObject[, buttonName, createAction])
add one more row to buttonListObject, reuses name & createAction used in CreateTasButtonList when not provided.
you should use TasButtonListSearch(buttonListObject) afterwards.
function CreateTasButtonListEx(buttonName, cols, rows, parent, buttonAction[, rightClickAction, updateAction, searchAction, filterAction, asyncButtonAction, asyncRightClickAction, colGap, rowGap])
create a new List
parent is the container of this Frame it will attach itself to its TOP.
buttonAction is the function that executes when an option is clicked. args: (clickedData, buttonListObject, dataIndex)
rightClickAction is the function that executes when an option is rightClicked. args: (clickedData, buttonListObject, dataIndex)
when your data are object Editor object-RawCodes (but not buffs) then updateAction & searchAction use a default one handling them.
updateAction runs for each Button and is used to set the diplayed content. args:(frameObject, data)
frameObject.Button
frameObject.ToolTipFrame
frameObject.ToolTipFrameIcon
frameObject.ToolTipFrameName
frameObject.ToolTipFrameSeperator
frameObject.ToolTipFrameText
frameObject.Icon
frameObject.Text
frameObject.IconGold
frameObject.TextGold
frameObject.IconLumber
frameObject.TextLumber
TasButtonList[frameObject] => buttonListObject
data is one entry of the TasButtonLists Data-Array.
searchAction is a function that returns true if the current data matches the searchText. Args: (data, searchedText, buttonListObject)
filterAction is meant to be used when one wants an addtional non text based filtering, with returning true allowing data or false rejecting it. Args: (data, buttonListObject, isTextSearching)
searchAction , udateAction & filterAction are async this functions should not do anything that alters the game state/flow.
function CreateTasButtonList(buttonCount, parent, buttonAction[, updateAction, searchAction, filterAction])
wrapper for CreateTasButtonListEx, 1 col, buttonCount rows.
function CreateTasButtonListV2(rowCount, parent, buttonAction[, updateAction, searchAction, filterAction])
wrapper for CreateTasButtonListEx, 2 Buttons each Row, takes more Height then the other Versions
function CreateTasButtonListV3(rowCount, parent, buttonAction[, updateAction, searchAction, filterAction])
wrapper for CreateTasButtonListEx, 3 Buttons each Row, only Icon, and Costs
Wrapper Creator for Lists having only Text in a Box
Default update & search: exepect data to be either a number (object Editor rawCode), a string or a table(title, text, icon)
function CreateTasButtonBoxedTextList(rowCount, colCount, parent, buttonAction[, updateAction, searchAction, filterAction])
function CreateTasButtonBoxedTextListBig(rowCount, colCount, parent, buttonAction[, updateAction, searchAction, filterAction])
Wrapper Creator for Lists having only Text
Default update & search: exepect data to be either a number (object Editor rawCode), a string or a table(title, text, icon)
function CreateTasButtonTextList(rowCount, colCount, parent, buttonAction[, updateAction, searchAction, filterAction])
function CreateTasButtonTextListBig(rowCount, colCount, parent, buttonAction[, updateAction, searchAction, filterAction])
function TasButtonListClearData(buttonListObject[, player])
remove all data
function TasButtonListRemoveData(buttonListObject, data[, player])
search for data and remove it
function TasButtonListAddData(buttonListObject, data[, player])
add data for one Button
function TasButtonListAddDataBatch(buttonListObject, player, ...)
calls TasButtonListAddData for each given arg after player
nil for player will add it for all players
you should not use FourCC in this, TasButtonList will do that for your
function TasButtonListAddDataBatchEx(buttonListObject, ...)
TasButtonListAddDataBatch with player nil (all players)
function TasButtonListCopyData(writeObject, readObject[, player])
writeObject uses the same data as readObject and calls UpdateButtonList.
The copier writeObject still has an own filtering and searching.
function UpdateTasButtonList(buttonListObject)
update the displayed Content should be done after Data was added or removed was used.
TasButtonListSearch(buttonListObject[, text])
The buttonList will search it's data for the given text, if nil is given as text it will search for what the user currently has in its box.
This will also update the buttonList
--]]
TasButtonList = {
Interpret4DigitString = true -- TasButtonListAddData will FourCC given 4 digit strings?
,DefaultOwnerFunc = function() return BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0) end -- when you dont give an parent the new parent is created for this
,TocPath ="war3mapimported\\TasButtonList.toc" -- where is the TasButtonList toc in your map
}
function TasButtonList.FirstInit()
BlzLoadTOCFile(TasButtonList.TocPath)
-- fix a save&Load bug in 1.31.1 and upto 1.32.10 (currently) which does not save&load frame-API actions
if FrameLoaderAdd then FrameLoaderAdd(function() BlzLoadTOCFile(TasButtonList.TocPath) end) end
TasButtonList.RightClickSound = CreateSound("Sound\\Interface\\MouseClick1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(TasButtonList.RightClickSound, "InterfaceClick")
SetSoundDuration(TasButtonList.RightClickSound, 239)
TasButtonList.FirstInit = nil -- this only runes once
end
TasButtonList.SyncTriggerAction = function(frame, player, value)
local buttonListObject = TasButtonList[frame]
local dataIndex = R2I(value)
if buttonListObject.ButtonAction then
-- call the wanted action, 1 the current Data
buttonListObject.ButtonAction(buttonListObject.Data[player][dataIndex], buttonListObject, dataIndex, player)
end
UpdateTasButtonList(buttonListObject)
end
TasButtonList.SyncTriggerRightClickAction = function(frame, player, value)
local buttonListObject = TasButtonList[frame]
local dataIndex = R2I(value)
if buttonListObject.RightClickAction then
-- call the wanted action, 1 the current Data
buttonListObject.RightClickAction(buttonListObject.Data[player][dataIndex], buttonListObject, dataIndex, player)
end
UpdateTasButtonList(buttonListObject)
end
-- handles the clicking
TasButtonList.ButtonTriggerAction = function(frame, player)
local buttonIndex = TasButtonList[frame].Index
local buttonListObject = TasButtonList[TasButtonList[frame]]
local dataIndex = buttonListObject.DataFiltered[buttonListObject.ViewPoint + buttonIndex]
if GetLocalPlayer() == player then
if buttonListObject.AsyncButtonAction then
buttonListObject.AsyncButtonAction(buttonListObject, buttonListObject.Data[GetLocalPlayer()][R2I(dataIndex)], frame)
end
BlzFrameSetValue(buttonListObject.SyncFrame, dataIndex)
end
end
TasButtonList.ButtonTriggerRightClickAction = function(frame, player, rightClick)
local buttonListObject = TasButtonList[TasButtonList[frame]]
-- if there is no RightClick Action for this Buttonlist skip other actions
if not buttonListObject.RightClickAction and not buttonListObject.AsyncRightClickAction then return end
local buttonIndex = TasButtonList[frame].Index
local dataIndex = buttonListObject.DataFiltered[buttonListObject.ViewPoint + buttonIndex]
if rightClick and GetLocalPlayer() == player then
if buttonListObject.AsyncRightClickAction then
buttonListObject.AsyncRightClickAction(buttonListObject, buttonListObject.Data[GetLocalPlayer()][R2I(dataIndex)], frame)
end
StartSound(TasButtonList.RightClickSound)
BlzFrameSetValue(buttonListObject.SyncFrameRightClick, dataIndex)
end
end
TasButtonList.SearchTriggerAction = function(frame, player, text)
TasButtonListSearch(TasButtonList[frame], BlzFrameGetText(frame))
end
TasButtonList.SliderTriggerAction = function(frame, player, value)
local buttonListObject = TasButtonList[frame]
if GetLocalPlayer() == player then
-- when there is enough data use viewPoint. the Viewpoint is reduced from the data to make top being top.
if buttonListObject.DataFiltered.Count > buttonListObject.Frames.Count then
buttonListObject.ViewPoint = buttonListObject.DataFiltered.Count - R2I(value)
else
buttonListObject.ViewPoint = 0
end
UpdateTasButtonList(buttonListObject)
if buttonListObject.SliderText then
local min = math.tointeger(buttonListObject.DataFiltered.Count - BlzFrameGetValue(frame))
local max = math.tointeger(buttonListObject.DataFiltered.Count - buttonListObject.Frames.Count)
BlzFrameSetText(buttonListObject.SliderText, min .. "/" .. max )
end
end
end
--runs once for each button shown
function UpdateTasButtonListDefaultObject(frameObject, data)
BlzFrameSetTexture(frameObject.Icon, BlzGetAbilityIcon(data), 0, false)
BlzFrameSetText(frameObject.Text, GetObjectName(data))
BlzFrameSetTexture(frameObject.ToolTipFrameIcon, BlzGetAbilityIcon(data), 0, false)
BlzFrameSetText(frameObject.ToolTipFrameName, GetObjectName(data))
-- frameObject.ToolTipFrameSeperator
BlzFrameSetText(frameObject.ToolTipFrameText, BlzGetAbilityExtendedTooltip(data, 0))
if not IsUnitIdType(data, UNIT_TYPE_HERO) then
local lumber = GetUnitWoodCost(data)
local gold = GetUnitGoldCost(data)
if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD) >= gold then
BlzFrameSetText(frameObject.TextGold, GetUnitGoldCost(data))
else
BlzFrameSetText(frameObject.TextGold, "|cffff2010"..GetUnitGoldCost(data))
end
if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_LUMBER) >= lumber then
BlzFrameSetText(frameObject.TextLumber, GetUnitWoodCost(data))
else
BlzFrameSetText(frameObject.TextLumber, "|cffff2010"..GetUnitWoodCost(data))
end
else
BlzFrameSetText(frameObject.TextLumber, 0)
BlzFrameSetText(frameObject.TextGold, 0)
end
end
--runs once for each button shown
function UpdateTasButtonListDefaultText(frameObject, data)
if type(data) == "string" then
BlzFrameSetTexture(frameObject.ToolTipFrameIcon, "UI/Widgets/EscMenu/Human/blank-background", 0, true)
BlzFrameSetText(frameObject.Text, GetLocalizedString(data))
BlzFrameSetText(frameObject.ToolTipFrameName, GetLocalizedString(data))
-- frameObject.ToolTipFrameSeperator
BlzFrameSetText(frameObject.ToolTipFrameText, GetLocalizedString(data))
elseif type(data) == "number" then
UpdateTasButtonListDefaultObject(frameObject, data)
elseif type(data) == "table" then
BlzFrameSetText(frameObject.Text, data[1])
BlzFrameSetText(frameObject.ToolTipFrameName, GetLocalizedString(data[1]))
-- frameObject.ToolTipFrameSeperator
BlzFrameSetText(frameObject.ToolTipFrameText, GetLocalizedString(data[2]))
-- have icon data?
if data[3] then
BlzFrameSetTexture(frameObject.ToolTipFrameIcon, data[3], 0, true)
else
BlzFrameSetTexture(frameObject.ToolTipFrameIcon, "UI/Widgets/EscMenu/Human/blank-background", 0, true)
end
end
end
function SearchTasButtonListDefaultObject(data, searchedText, buttonListObject)
--return BlzGetAbilityTooltip(data, 0)
--return GetObjectName(data, 0)
--return string.find(GetObjectName(data), searchedText)
return string.find(string.lower(GetObjectName(data)), string.lower(searchedText))
end
function SearchTasButtonListDefaultText(data, searchedText, buttonListObject)
if type(data) == "number" then
return string.find(string.lower(GetObjectName(data)), string.lower(searchedText))
elseif type(data) == "string" then
return string.find(string.lower(GetLocalizedString(data)), string.lower(searchedText))
elseif type(data) == "table" then
return string.find(string.lower(GetLocalizedString(data[1])), string.lower(searchedText)) or string.find(string.lower(GetLocalizedString(data[2])), string.lower(searchedText))
else
return true
end
end
-- update the shown content
function UpdateTasButtonList(buttonListObject)
xpcall(function()
local data = buttonListObject.Data[GetLocalPlayer()]
BlzFrameSetVisible(buttonListObject.Slider, buttonListObject.DataFiltered.Count > buttonListObject.Frames.Count)
for int = 1, buttonListObject.Frames.Count do
local frameObject = buttonListObject.Frames[int]
if buttonListObject.DataFiltered.Count >= int then
buttonListObject.UpdateAction(frameObject, data[buttonListObject.DataFiltered[int + buttonListObject.ViewPoint]])
BlzFrameSetVisible(frameObject.Button, true)
else
BlzFrameSetVisible(frameObject.Button, false)
end
end
end, print)
end
-- for backwards compatibility rightClickAction is the last argument
function InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction, rightClickAction, asyncButtonAction, asyncRightClickAction)
if TasButtonList.FirstInit then TasButtonList.FirstInit() end
local object = {
Data = {}, --an array each slot is the user data
DataFiltered = {Count = 0}, -- indexes of Data fitting the current search
ViewPoint = 0,
Frames = {},
Parent = parent
}
for index = 0, bj_MAX_PLAYER_SLOTS - 1 do
object.Data[Player(index)] = {Count = 0}
end
object.Head = BlzCreateFrameByType("FRAME", "TasButtonListHead", parent, "", 0)
BlzFrameSetSize(object.Head, 0.1, 0.005)
BlzFrameSetPoint(object.Head, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPRIGHT, 0, 0)
BlzFrameSetVisible(object.Head, false)
object.TotalFrame = BlzCreateFrameByType("FRAME", "TasButtonListTotalFrame", parent, "", 0)
BlzFrameSetVisible(object.TotalFrame, false)
BlzFrameSetPoint(object.TotalFrame, FRAMEPOINT_TOPLEFT, object.Head, FRAMEPOINT_TOPLEFT, 0, 0)
object.ButtonAction = buttonAction --call this inside the SyncAction after a button is clicked
object.RightClickAction = rightClickAction -- this inside a SyncAction when the button is right clicked.
object.UpdateAction = updateAction --function defining how to display stuff (async)
object.SearchAction = searchAction --function to return the searched Text (async)
object.FilterAction = filterAction --
object.AsyncButtonAction = asyncButtonAction -- happens in the clicking event inside a LocalPlayer Block
object.AsyncRightClickAction = asyncRightClickAction -- happens in the clicking event inside a LocalPlayer Block
if not updateAction then object.UpdateAction = UpdateTasButtonListDefaultObject end
if not searchAction then object.SearchAction = SearchTasButtonListDefaultObject end
table.insert(TasButtonList, object) --index to TasButtonList
TasButtonList[object] = #TasButtonList -- TasButtonList to Index
object.SyncFrame = BlzCreateFrameByType("SLIDER", "", parent, "", 0)
BlzFrameSetMinMaxValue(object.SyncFrame, 0, 9999999)
BlzFrameSetStepSize(object.SyncFrame, 1.0)
TasSliderAction(object.SyncFrame, TasButtonList.SyncTriggerAction)
TasSliderAction.AvoidPoll[object.SyncFrame] = false
BlzFrameSetVisible(object.SyncFrame, false)
TasButtonList[object.SyncFrame] = object
-- do this only if the function IsRightClick exists
object.SyncFrameRightClick = BlzCreateFrameByType("SLIDER", "", parent, "", 0)
BlzFrameSetMinMaxValue(object.SyncFrameRightClick, 0, 9999999)
BlzFrameSetStepSize(object.SyncFrameRightClick, 1.0)
TasSliderAction(object.SyncFrameRightClick, TasButtonList.SyncTriggerRightClickAction)
TasSliderAction.AvoidPoll[object.SyncFrameRightClick] = false
BlzFrameSetVisible(object.SyncFrameRightClick, false)
TasButtonList[object.SyncFrameRightClick] = object
object.InputFrame = BlzCreateFrame("TasEditBox", parent, 0, 0)
TasEditBoxAction(object.InputFrame, nil, TasButtonList.SearchTriggerAction)
BlzFrameSetPoint(object.InputFrame, FRAMEPOINT_TOPRIGHT, object.Head, FRAMEPOINT_TOPRIGHT, 0, 0)
TasButtonList[object.InputFrame] = object
BlzFrameSetSize(object.Head, 0.1, BlzFrameGetHeight(object.InputFrame) +0.005)
return object
end
function InitTasButtonListSlider(object, stepSize, rowCount, colGap, rowGap)
if not colGap then colGap = 0 end
if not rowGap then rowGap = 0 end
object.Slider = BlzCreateFrameByType("SLIDER", "FrameListSlider", object.Parent, "QuestMainListScrollBar", 0)
TasButtonList[object.Slider] = object -- the slider nows the TasButtonListobject
object.SliderStep = stepSize
BlzFrameSetStepSize(object.Slider, stepSize)
BlzFrameClearAllPoints(object.Slider)
BlzFrameSetVisible(object.Slider, true)
BlzFrameSetMinMaxValue(object.Slider, 0, 0)
--BlzFrameSetPoint(object.Slider, FRAMEPOINT_TOPLEFT, object.Frames[stepSize].Button, FRAMEPOINT_TOPRIGHT, 0, 0)
BlzFrameSetPoint(object.Slider, FRAMEPOINT_TOPLEFT, object.Head, FRAMEPOINT_BOTTOMRIGHT, 0, 0)
TasSliderAction(object.Slider, TasButtonList.SliderTriggerAction, StepSize)
-- if the function CreateSimpleTooltip exists, create a Text displaying current Position in the list
if CreateSimpleTooltip then
object.SliderText = CreateSimpleTooltip(object.Slider, "1000/1000")
BlzFrameClearAllPoints(object.SliderText)
BlzFrameSetPoint(object.SliderText, FRAMEPOINT_BOTTOMRIGHT, object.Slider, FRAMEPOINT_TOPLEFT, 0, 0)
end
end
function TasButtonListAddDataEx(buttonListObject, data, player)
local oData = buttonListObject.Data[player]
local oDataFil = buttonListObject.DataFiltered
-- convert 'Hpal' into the number
-- print(TasButtonList.Interpret4DigitString) print( data) print(type(data)) print(string.len(data))
if TasButtonList.Interpret4DigitString and type(data) == "string" and string.len(data) == 4 then data = FourCC(data) end
oData.Count = oData.Count + 1
oData[oData.Count] = data
if GetLocalPlayer() == player then
-- filterData is a local thing
oDataFil.Count = oDataFil.Count + 1
oDataFil[oDataFil.Count] = oData.Count
BlzFrameSetMinMaxValue(buttonListObject.Slider, buttonListObject.Frames.Count, oDataFil.Count)
end
end
function TasButtonListAddData(buttonListObject, data, player)
-- only add for one player?
if player and type(player) == "userdata" then
TasButtonListAddDataEx(buttonListObject, data, player)
else
-- no player -> add for all Players
for i = 0, bj_MAX_PLAYER_SLOTS - 1 do
TasButtonListAddDataEx(buttonListObject, data, Player(i))
end
end
end
function TasButtonListAddDataBatch(buttonListObject, player, ...)
for _, k in ipairs({...}) do
print(k)
TasButtonListAddData(buttonListObject, k, player)
end
end
function TasButtonListAddDataBatchEx(buttonListObject, ...)
TasButtonListAddDataBatch(buttonListObject, nil, ...)
end
function TasButtonListRemoveDataEx(buttonListObject, data, player)
local oData = buttonListObject.Data[player]
for index = 1, oData.Count do
value = oData[index]
if value == data then
oData[index] = oData[oData.Count]
oData.Count = oData.Count - 1
break
end
end
if GetLocalPlayer() == player then
BlzFrameSetMinMaxValue(buttonListObject.Slider, buttonListObject.Frames.Count, oData.Count)
end
end
function TasButtonListRemoveData(buttonListObject, data, player)
if player and type(player) == "userdata" then
TasButtonListRemoveDataEx(buttonListObject, data, player)
else
for i = 0, bj_MAX_PLAYER_SLOTS - 1 do
TasButtonListRemoveDataEx(buttonListObject, data, Player(i))
end
end
end
function TasButtonListClearDataEx(buttonListObject, player)
buttonListObject.Data[player].Count = 0
if GetLocalPlayer() == player then
buttonListObject.DataFiltered.Count = 0
BlzFrameSetMinMaxValue(buttonListObject.Slider, 0, 0)
end
end
function TasButtonListClearData(buttonListObject, player)
if player and type(player) == "userdata" then
TasButtonListClearDataEx(buttonListObject, player)
else
for i = 0, bj_MAX_PLAYER_SLOTS - 1 do
TasButtonListClearDataEx(buttonListObject, Player(i))
end
end
end
function TasButtonListCopyDataEx(writeObject, readObject, player)
writeObject.Data[player] = readObject.Data[player]
for index = 1, readObject.DataFiltered.Count do writeObject.DataFiltered[index] = readObject.DataFiltered[index] end
writeObject.DataFiltered.Count = readObject.DataFiltered.Count
if GetLocalPlayer() == player then
BlzFrameSetMinMaxValue(writeObject.Slider, writeObject.Frames.Count, writeObject.Data[player].Count)
BlzFrameSetValue(writeObject.Slider,999999)
end
end
function TasButtonListCopyData(writeObject, readObject, player)
if player and type(player) == "userdata" then
TasButtonListCopyDataEx(writeObject, readObject, player)
else
for i = 0, bj_MAX_PLAYER_SLOTS - 1 do
TasButtonListCopyDataEx(writeObject, readObject, Player(i))
end
end
end
function TasButtonListSearch(buttonListObject, text)
if not text then text = BlzFrameGetText(buttonListObject.InputFrame) end
local filteredData = buttonListObject.DataFiltered
local oData = buttonListObject.Data[GetLocalPlayer()]
local value
if GetLocalPlayer() == GetTriggerPlayer() then
filteredData.Count = 0
if text ~= "" then
for index = 1, oData.Count do
value = oData[index]
if buttonListObject.SearchAction(value, text, buttonListObject) and (not buttonListObject.FilterAction or buttonListObject.FilterAction(value, buttonListObject, true)) then
filteredData.Count = filteredData.Count + 1
filteredData[filteredData.Count] = index
end
end
else
for index = 1, oData.Count do
value = oData[index]
if not buttonListObject.FilterAction or buttonListObject.FilterAction(value, buttonListObject, false) then
filteredData.Count = filteredData.Count + 1
filteredData[filteredData.Count] = index
end
end
end
--table.sort(filteredData, function(a, b) return GetObjectName(buttonListObject.Data[a]) < GetObjectName(buttonListObject.Data[b]) end )
--update Slider, with that also update
BlzFrameSetMinMaxValue(buttonListObject.Slider, buttonListObject.Frames.Count, math.max(filteredData.Count,0))
BlzFrameSetValue(buttonListObject.Slider, 999999)
end
end
-- demo Creators
function CreateTasButtonTooltip(frameObject, parent, button)
if not button then button = frameObject.Button end
-- create an empty FRAME parent for the box BACKDROP, otherwise it can happen that it gets limited to the 4:3 Screen.
frameObject.ToolTipFrameFrame = BlzCreateFrame("TasButtonListTooltipBoxFrame", button, 0, 0)
if GetHandleId(frameObject.ToolTipFrameFrame) == 0 then print("Error function CreateTasButtonTooltip Creating TasButtonListTooltipBoxFrame") end
frameObject.ToolTipFrame = BlzGetFrameByName("TasButtonListTooltipBox", 0)
frameObject.ToolTipFrameIcon = BlzGetFrameByName("TasButtonListTooltipIcon", 0)
frameObject.ToolTipFrameName = BlzGetFrameByName("TasButtonListTooltipName", 0)
frameObject.ToolTipFrameSeperator = BlzGetFrameByName("TasButtonListTooltipSeperator", 0)
frameObject.ToolTipFrameText = BlzGetFrameByName("TasButtonListTooltipText", 0)
BlzFrameSetPoint(frameObject.ToolTipFrameText, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, -0.052)
BlzFrameSetPoint(frameObject.ToolTipFrame, FRAMEPOINT_TOPLEFT, frameObject.ToolTipFrameIcon, FRAMEPOINT_TOPLEFT, -0.005, 0.005)
BlzFrameSetPoint(frameObject.ToolTipFrame, FRAMEPOINT_BOTTOMRIGHT, frameObject.ToolTipFrameText, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
BlzFrameSetTooltip(button, frameObject.ToolTipFrameFrame)
end
TasButtonList.TooltipCreator = CreateTasButtonTooltip
function TasButtonListAddRow(buttonListObject, buttonName, createAction)
local object = buttonListObject
if not buttonName then buttonName = object.Frames.ButtonName end
if not createAction then createAction = object.Frames.CreateAction end
if not buttonName then print("TasButtonListAddRow - Error - no Name/function") return object end
local newCount = object.Frames.Count + object.Frames.Cols
local first = true
local colGap = object.Frames.GapCol
local rowGap = object.Frames.GapRow
local parent = object.Parent
local cols = object.Frames.Cols
local rows = object.Frames.Rows + 1
object.Frames.Rows = rows
for int = object.Frames.Count + 1, newCount do
local frameObject = {}
frameObject.Index = int
if type(buttonName) == "string" then
frameObject.Button = BlzCreateFrame(buttonName, parent, 0, 0)
if GetHandleId(frameObject.Button) == 0 then print("TasButtonList - Error - can't create:", buttonName) end
elseif type(buttonName) == "function" then
frameObject.Button = buttonName(frameObject, parent, int)
end
TasButtonList.TooltipCreator(frameObject, object.Parent, frameObject.Button)
if createAction then createAction(frameObject, int, frameObject.Button)
elseif type(buttonName) == "string" then --default TasButtonList behaviour
frameObject.Icon = BlzGetFrameByName("TasButtonIcon", 0)
frameObject.Text = BlzGetFrameByName("TasButtonText", 0)
frameObject.IconGold = BlzGetFrameByName("TasButtonIconGold", 0)
frameObject.TextGold = BlzGetFrameByName("TasButtonTextGold", 0)
frameObject.IconLumber = BlzGetFrameByName("TasButtonIconLumber", 0)
frameObject.TextLumber = BlzGetFrameByName("TasButtonTextLumber", 0)
end
TasButtonList[frameObject.Button] = frameObject
TasButtonList[frameObject] = object
object.Frames[int] = frameObject
TasButtonAction(frameObject.Button, TasButtonList.ButtonTriggerAction)
TasFrameMouseUpAction(frameObject.Button, TasButtonList.ButtonTriggerRightClickAction)
TasSliderAction(frameObject.Button, nil, cols, object.Slider)
if int > 1 then
if first then
BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOP, object.Frames[int - cols].Button, FRAMEPOINT_BOTTOM, 0, -rowGap)
first = false
else
BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_LEFT, object.Frames[int - 1].Button, FRAMEPOINT_RIGHT, colGap, 0)
end
else
--print(-BlzFrameGetWidth(frameObject.Button)*cols - colGap*(cols-1))
first = false
BlzFrameSetSize(object.Head, BlzFrameGetWidth(frameObject.Button)*cols + colGap*(cols-1), BlzFrameGetHeight(object.Head))
--print(BlzFrameGetWidth(object.Head), BlzFrameGetHeight(object.Head))
if cols > 1 then
BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOPLEFT, object.Head, FRAMEPOINT_BOTTOMLEFT, 0, 0)
else
BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOPRIGHT, object.Head, FRAMEPOINT_BOTTOMRIGHT, 0, 0)
end
end
end
BlzFrameSetPoint(object.TotalFrame, FRAMEPOINT_BOTTOMRIGHT, object.Frames[newCount].Button, FRAMEPOINT_BOTTOMRIGHT, 0, 0)
object.Frames.Count = newCount
BlzFrameSetSize(object.Slider, 0.012, BlzFrameGetHeight(object.Frames[1].Button) * rows + rowGap * (rows - 1))
end
function CreateTasButtonListEx2(buttonName, cols, rows, colGap, rowGap, parent, createAction)
if not rowGap then rowGap = 0.0 end
if not colGap then colGap = 0.0 end
if not parent then parent = BlzCreateFrameByType("SLIDER", "TasButtonListParent", TasButtonList.DefaultOwnerFunc(), "", 0) end
local buttonCount = rows*cols
local object = InitTasButtonListObject(parent)
object.Frames.Count = 0
object.Frames.ButtonName = buttonName
object.Frames.CreateAction = createAction
object.Frames.Cols = cols
object.Frames.Rows = 0
object.Frames.GapCol = colGap
object.Frames.GapRow = rowGap
InitTasButtonListSlider(object, cols, rows, colGap, rowGap)
TasSliderAction(parent, nil, cols, object.Slider)
TasSliderAction.AvoidPoll[object.Slider] = false
for int = 1, rows do TasButtonListAddRow(object) end
BlzFrameSetSize(object.Slider, 0.012, BlzFrameGetHeight(object.Frames[1].Button) * rows + rowGap * (rows - 1))
return object
end
function CreateTasButtonListEx(buttonName, cols, rows, parent, buttonAction, rightClickAction, updateAction, searchAction, filterAction, asyncButtonAction, asyncRightClickAction, colGap, rowGap)
local object = CreateTasButtonListEx2(buttonName, cols, rows, colGap, rowGap, parent, createAction)
object.ButtonAction = buttonAction --call this inside the SyncAction after a button is clicked
object.RightClickAction = rightClickAction -- this inside a SyncAction when the button is right clicked.
object.UpdateAction = updateAction --function defining how to display stuff (async)
object.SearchAction = searchAction --function to return the searched Text (async)
object.FilterAction = filterAction --
object.AsyncButtonAction = asyncButtonAction -- happens in the clicking event inside a LocalPlayer Block
object.AsyncRightClickAction = asyncRightClickAction -- happens in the clicking event inside a LocalPlayer Block
if not updateAction then object.UpdateAction = UpdateTasButtonListDefaultObject end
if not searchAction then object.SearchAction = SearchTasButtonListDefaultObject end
return object
end
-- wrapper creators, they dont have async stuff
function CreateTasButtonList(buttonCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasButton", 1, buttonCount, parent, buttonAction, nil, updateAction, searchAction, filterAction)
end
function CreateTasButtonListV2(rowCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasButtonSmall", 2, rowCount, parent, buttonAction, nil, updateAction, searchAction, filterAction)
end
function CreateTasButtonListV3(rowCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasButtonGrid", 3, rowCount, parent, buttonAction, nil, updateAction, searchAction, filterAction)
end
function CreateTasButtonBoxedTextList(rowCount, colCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasBoxedTextButtonSmall", colCount, rowCount, parent, buttonAction, nil, updateAction or UpdateTasButtonListDefaultText, searchAction or SearchTasButtonListDefaultText, filterAction)
end
function CreateTasButtonBoxedTextListBig(rowCount, colCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasBoxedTextButton", colCount, rowCount, parent, buttonAction, nil, updateAction or UpdateTasButtonListDefaultText, searchAction or SearchTasButtonListDefaultText, filterAction)
end
function CreateTasButtonTextList(rowCount, colCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasTextButtonSmall", colCount, rowCount, parent, buttonAction, nil, updateAction or UpdateTasButtonListDefaultText, searchAction or SearchTasButtonListDefaultText, filterAction)
end
function CreateTasButtonTextListBig(rowCount, colCount, parent, buttonAction, updateAction, searchAction, filterAction)
return CreateTasButtonListEx("TasTextButton", colCount, rowCount, parent, buttonAction, nil, updateAction or UpdateTasButtonListDefaultText, searchAction or SearchTasButtonListDefaultText, filterAction)
end
--[[ TasItemShopLite by Tasyen
An custom ui to buy items from a big pool and with a search bar, selecting a shop shows the ui.
requires:
TasItemCost
TasFrameAction
TasButtonList
optional
Global Initialization
CreateSimpleTooltip
FrameLoader
TasItemShopLite.Add(who, itemCode)
who = shop
who is either an unit, a unitCode, or a string like 'n000'
the shop needs the ability 'Asid'
itemcode can be a number, a table or a string like 'I000'
--]]
do
local this = {}
TasItemShopLite = this
this.AutoRun = true --(true) will create Itself at 0s, (false) you need to InitSpellView()
this.TocPath = "war3mapImported\\Templates.toc"
this.ParentFunc = function() -- who is the parent of this UI
return BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
end
this.Pos = function(frame)
-- position of the whole Shop UI
BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOPRIGHT, 0.79, 0.55)
end
this.TooltipPos = function(tooltip, button)
-- position of the tooltips
BlzFrameClearAllPoints(tooltip)
--BlzFrameSetPoint(tooltip, FRAMEPOINT_TOPRIGHT, button, FRAMEPOINT_BOTTOMRIGHT, 0, -0.052)
BlzFrameSetPoint(tooltip, FRAMEPOINT_TOPRIGHT, this.FrameBox, FRAMEPOINT_TOPLEFT, 0, -0.052)
--BlzFrameSetAbsPoint(tooltip, FRAMEPOINT_TOPRIGHT, 0, -0.052)
end
local buttonListRows = 5
local buttonListCols = 3
local buttonListButtonGapCol = 0.001
local buttonListButtonGapRow = 0.005
-- which button is used inside the ButtonList? Enable one block and disable the other one
--local buttonListButtonName = "TasButtonSmall"
--local buttonListButtonSizeX = 0.1
--local buttonListButtonSizeY = 0.0325
-- "TasButtonGrid" are smaller, they don't show the names in the list
local buttonListButtonName = "TasButtonGrid"
local buttonListButtonSizeX = 0.064
local buttonListButtonSizeY = 0.0265
--local buttonListButtonName = "TasButton"
--local buttonListButtonSizeX = 0.2
--local buttonListButtonSizeY = 0.0265
this.SoundConfig = function()
local SoundNoLumber = {}
local SoundNoGold = {}
this.SoundNoLumber = SoundNoLumber
this.SoundNoGold = SoundNoGold
SoundNoGold[RACE_HUMAN] = CreateSound("Sound\\Interface\\Warning\\Human\\KnightNoGold1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoGold[RACE_HUMAN], "NoGoldHuman")
SetSoundDuration(SoundNoGold[RACE_HUMAN], 1618)
SoundNoLumber[RACE_HUMAN] = CreateSound("Sound\\Interface\\Warning\\Human\\KnightNoLumber1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoLumber[RACE_HUMAN], "NoLumberHuman")
SetSoundDuration(SoundNoLumber[RACE_HUMAN], 1903)
local raceNaga = ConvertRace(11)
SoundNoGold[raceNaga] = CreateSound("Sound\\Interface\\Warning\\Naga\\NagaNoGold1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoGold[raceNaga], "NoGoldNaga")
SetSoundDuration(SoundNoGold[raceNaga], 2690)
SoundNoLumber[raceNaga] = CreateSound("Sound\\Interface\\Warning\\Naga\\NagaNoLumber1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoLumber[raceNaga], "NoLumberNaga")
SetSoundDuration(SoundNoLumber[raceNaga], 2011)
SoundNoGold[RACE_ORC] = CreateSound("Sound\\Interface\\Warning\\Orc\\GruntNoGold1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoGold[RACE_ORC], "NoGoldOrc")
SetSoundDuration(SoundNoGold[RACE_ORC], 1450)
SoundNoLumber[RACE_ORC] = CreateSound("Sound\\Interface\\Warning\\Orc\\GruntNoLumber1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoLumber[RACE_ORC], "NoLumberOrc")
SetSoundDuration(SoundNoLumber[RACE_ORC], 1219)
SoundNoGold[RACE_NIGHTELF] = CreateSound("Sound\\Interface\\Warning\\NightElf\\SentinelNoGold1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoGold[RACE_NIGHTELF], "NoGoldNightElf")
SetSoundDuration(SoundNoGold[RACE_NIGHTELF], 1229)
SoundNoLumber[RACE_NIGHTELF] = CreateSound("Sound\\Interface\\Warning\\NightElf\\SentinelNoLumber1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoLumber[RACE_NIGHTELF], "NoLumberNightElf")
SetSoundDuration(SoundNoLumber[RACE_NIGHTELF], 1454)
SoundNoGold[RACE_UNDEAD] = CreateSound("Sound\\Interface\\Warning\\Undead\\NecromancerNoGold1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoGold[RACE_UNDEAD], "NoGoldUndead")
SetSoundDuration(SoundNoGold[RACE_UNDEAD], 2005)
SoundNoLumber[RACE_UNDEAD] = CreateSound("Sound\\Interface\\Warning\\Undead\\NecromancerNoLumber1.wav", false, false, false, 10, 10, "")
SetSoundParamsFromLabel(SoundNoLumber[RACE_UNDEAD], "NoLumberUndead")
SetSoundDuration(SoundNoLumber[RACE_UNDEAD], 2005)
end
-- config ende
this.Items = {} -- what can be bought [unit] = {itemCode1, ItemCode2, ...} > [unitCode] = {itemCode1, ItemCode2, ...}
this.Add = function(who, itemCode)
if type(itemCode) == "string" then itemCode = FourCC(itemCode) end
if type(who) == "string" then who = FourCC(who) end
if type(itemCode) == "table" then for i, v in ipairs(itemCode) do this.Add(who, v) end return end
if not this.Items[who] then this.Items[who] = {} end
table.insert(this.Items[who], itemCode)
TasItemCaclCost(itemCode)
end
function TasItemShopAddShop(unitCode, ...) for i, v in ipairs({...}) do this.Add(unitCode, v) end end
this.CurrentShop = {}
local formatNoDigit = "\x25.0f"
local function updateItemFrame(frameObject, data)
BlzFrameSetTexture(frameObject.Icon, BlzGetAbilityIcon(data), 0, false)
BlzFrameSetText(frameObject.Text, GetObjectName(data))
BlzFrameSetTexture(frameObject.ToolTipFrameIcon, BlzGetAbilityIcon(data), 0, false)
BlzFrameSetText(frameObject.ToolTipFrameName, GetObjectName(data))
-- frameObject.ToolTipFrameSeperator
BlzFrameSetText(frameObject.ToolTipFrameText, BlzGetAbilityExtendedTooltip(data, 0))
local gold, lumber = TasItemGetCost(data)
if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD) >= gold then
BlzFrameSetText(frameObject.TextGold, string.format(formatNoDigit, gold))
else
BlzFrameSetText(frameObject.TextGold, "|cffff2010"..string.format( formatNoDigit, gold))
end
if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_LUMBER) >= lumber then
BlzFrameSetText(frameObject.TextLumber, string.format(formatNoDigit, lumber))
else
BlzFrameSetText(frameObject.TextLumber, "|cffff2010"..string.format( formatNoDigit, lumber))
end
end
function this.BuyItem(player, itemCode)
local gold, lumber = TasItemGetCost(itemCode)
if GetPlayerState(player, PLAYER_STATE_RESOURCE_GOLD) >= gold then
if GetPlayerState(player, PLAYER_STATE_RESOURCE_LUMBER) >= lumber then
AddItemToStock(this.CurrentShop[player], itemCode, 1, 1)
IssueNeutralImmediateOrderById(player, this.CurrentShop[player], itemCode)
RemoveItemFromStock(this.CurrentShop[player], itemCode)
this.Show(player, this.CurrentShop[player])
elseif not GetSoundIsPlaying(this.SoundNoLumber[GetPlayerRace(player)]) then
StartSoundForPlayerBJ(player, this.SoundNoLumber[GetPlayerRace(player)])
end
elseif not GetSoundIsPlaying(this.SoundNoGold[GetPlayerRace(player)]) then
StartSoundForPlayerBJ(player, this.SoundNoGold[GetPlayerRace(player)])
end
end
local function searchAction(data, searchedText, buttonListObject)
local text = string.lower(searchedText)
if string.find(string.lower(BlzGetAbilityTooltip(data, 0)), text, 1, true) then return true end
if string.find(string.lower(BlzGetAbilityExtendedTooltip(data, 0)), text, 1, true) then return true end
return string.find(string.lower(GetObjectName(data)), string.lower(text))
end
function this.InitFrames()
BlzLoadTOCFile(this.TocPath)
local frames, parent, object, frame
parent = this.ParentFunc()
-- super
this.FrameParentSuper = BlzCreateFrameByType("FRAME", "TasItemShopUI", parent, "", 0)
this.FrameBox = BlzCreateFrameByType("BACKDROP", "TasItemShopUIBox", this.FrameParentSuper, "EscMenuControlBackdropTemplate", 0)
parent = BlzCreateFrameByType("FRAME", "TasItemShopUI", this.FrameParentSuper, "", 0)
BlzFrameSetSize(parent, 0.01, 0.01)
this.Pos(parent)
this.FrameParentList = parent
this.FrameMouseListener = BlzCreateFrameByType("SLIDER", "TasItemShopUI", this.FrameParentList, "", 0)
-- ButtonList
object = CreateTasButtonListEx2(buttonListButtonName, buttonListCols, buttonListRows, buttonListButtonGapCol, buttonListButtonGapRow, this.FrameParentList)
object.ButtonAction = function(data, buttonListObject, dataIndex, player)
this.BuyItem(player, data)
end
object.UpdateAction = updateItemFrame
object.SearchAction = searchAction
this.ButtonList = object
for i, v in ipairs(this.ButtonList.Frames) do this.TooltipPos(v.ToolTipFrameText, v.Button) end
frame = BlzCreateFrame("TasButtonTextTemplate", this.FrameParentList, 0, 0)
BlzFrameSetPoint(frame, FRAMEPOINT_TOPRIGHT, this.ButtonList.InputFrame, FRAMEPOINT_BOTTOMRIGHT, -0.002, 0)
BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)
BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMLEFT, this.ButtonList.Head, FRAMEPOINT_BOTTOMLEFT, 0, 0)
BlzFrameSetText(frame, "Name")
this.FrameTitelText = frame
BlzFrameSetSize(this.ButtonList.Head, BlzFrameGetWidth(this.ButtonList.Head), BlzFrameGetHeight(this.ButtonList.Head) + 0.01)
BlzFrameSetAllPoints(this.FrameMouseListener, this.ButtonList.TotalFrame)
TasSliderAction(this.FrameMouseListener, nil, cols, this.ButtonList.Slider)
BlzFrameSetPoint(this.FrameBox, FRAMEPOINT_BOTTOMRIGHT, this.ButtonList.TotalFrame, FRAMEPOINT_BOTTOMRIGHT, 0.003, -0.003)
BlzFrameSetPoint(this.FrameBox, FRAMEPOINT_TOPLEFT, this.ButtonList.TotalFrame, FRAMEPOINT_TOPLEFT, -0.003, 0.003)
BlzFrameSetVisible(this.FrameParentSuper, false)
end
function this.Show(player, shop)
local flag = (shop ~=nil)
local shopCode = GetUnitTypeId(shop)
if flag and not this.Items[shopCode] and not this.Items[shop] then flag = false end
if player == GetLocalPlayer() then
BlzFrameSetVisible(this.FrameParentSuper, flag)
end
if flag then
local oldShop = this.CurrentShop[player]
local isNewShop = oldShop ~= shop
this.CurrentShop[player] = shop
local buttonList = this.ButtonList
if isNewShop then
TasButtonListClearData(buttonList, player)
local data = this.Items[shop]
if data then for i, v in ipairs(data) do TasButtonListAddData(buttonList, v, player) end
else
local data = this.Items[shopCode]
if data then for i, v in ipairs(data) do TasButtonListAddData(buttonList, v, player) end end
end
end
if GetLocalPlayer() == player then
BlzFrameSetText(this.FrameTitelText, GetUnitName(shop))
if isNewShop then
TasButtonListSearch(buttonList)
end
end
UpdateTasButtonList(buttonList)
else
this.CurrentShop[player] = nil
end
end
local function CreateTriggerEx(action)
local trigger = CreateTrigger()
TriggerAddAction(trigger, action)
return trigger
end
function this.Init()
this.InitFrames()
this.SoundConfig()
if FrameLoaderAdd then FrameLoaderAdd(this.InitFrames) end
this.TriggerSelect = CreateTriggerEx(function()
this.Show(GetTriggerPlayer(), GetTriggerUnit())
end)
TriggerRegisterAnyUnitEventBJ(this.TriggerSelect, EVENT_PLAYER_UNIT_SELECTED)
this.TriggerESC = CreateTriggerEx(function()
this.Show(GetTriggerPlayer())
end)
for i = 0, bj_MAX_PLAYER_SLOTS - 1 do
player = Player(i)
TriggerRegisterPlayerEventEndCinematic(this.TriggerESC, player)
end
end
if this.AutoRun then
if OnInit then -- Total Initialization v5.2.0.1 by Bribe
OnInit.final(this.Init)
else -- without
local real = MarkGameStarted
function MarkGameStarted()
real()
this.Init()
end
end
end
end
-- "ACfb,AInv,A070,0,A00X" -> {FourCC('ACfb'),FourCC('AInv'),FourCC('A070'),0,FourCC('A00X')}
function IdString2IdArray(string)
local result = {}
local startIndex = 1
while startIndex + 3 <= string.len(string) do
local skillCode = string.sub(string, startIndex, startIndex + 3)
if string.sub(skillCode, 1, 2) == "0," then
startIndex = startIndex + 2
skillCode = 0
else
startIndex = startIndex + 5
skillCode = FourCC(skillCode)
end
table.insert(result, skillCode)
end
return result
end
function InitShopUserData()
-- shops with the unitCode 'n000' sell this items
TasItemShopLite.Add('n000', IdString2IdArray("pdiv,pres,pghe,pgma,pnvu,rej3,pnvl,pomn,rej4,rej2,rej1,pspd,dust,pinv,phea,pman,pams,pgin,pclr,plcl"))
-- shops with the unitCode 'n001' sell this items
TasItemShopLite.Add('n001', IdString2IdArray("ckng,modt,tkno,ratf,ofro,desc,fgdg,infs,shar,sand,wild,srrc,odef,rde4,pmna,rhth,ssil,spsh,sres,pdiv,pres,totw,fgfh,fgrd,fgrg,hcun,hval,mcou,ajen,clfm,ratc,war2,kpin,lgdh,ankh,whwd,fgsk,wcyc,hlst,mnst,belv,bgst,ciri,lhst,afac,sbch,brac,rwiz,pghe,pgma,pnvu,sror,woms,crys,evtl,penr,prvt,rat9,rde3,rlif,bspd,rej3,will,wlsd,wswd,cnob,gcel,rat6,rde2"))
-- this unit sells other items then his normal type would
TasItemShopLite.Add(udg_SpecialShop, IdString2IdArray("ckng,tkno,rde4,tdx2,tin2,tpow"))
end