Name | Type | is_array | initial_value |
Skill | abilcode | No | |
Unit | unit | No |
--[[ 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
--[[ TasHeroLearnEx V2e by Tasyen
A custom UI System to allow an Unit to have many skills to learn from.
TasHeroLearnEx.UpdateHeroData()
use this when you changed the HeroData from the outside or after InitBlizzard happened
function TasHeroLearnEx.CustomUnitLearnAbility(unit, abiCode)
Make Unit learn/improve abiCode and evoke a Learn Event
considers level requirments
overwrites TriggerRegisterAnyUnitEventBJ, DestroyTrigger (they still do what they should do)
and for a short time GetTriggerUnit, GetTriggerEventId, GetLearningUnit, GetLearnedSkill, GetLearnedSkillLevel, GetTriggerPlayer
only overwrites with hookEvent = true
Can use Hook version 7.0.1 by Bribe When provided
]]
do
local hookEvent = true --[[ Hook into Learn Event Triggers and Throw them? Only read at init
when you don't use hookEvent then you need to fill TasHeroLearnEx.Action with actionFunctions(unit, abiCode, abilityLevel, owner, unitCode)
TasHeroLearnEx.Action[FourCC('AHbz')] = function(unit, abiCode, abilityLevel, owner, unitCode) end
TasHeroLearnEx.Action[0] allways runs (hookEvent = false)
--]]
local AutoRun = true --(true) will create Itself at 0s, (false) you need to TasHeroLearnEx.Init()
local testSkill = FourCC'Agyb' -- should not in the command card
local action
if CreateFourCCTable then action = CreateFourCCTable() else action = {} end
-- the none hookEvent approach runs for any skill learned by TasHeroLearnEx
action[0] = function(unit, abiCode, abilityLevel, owner, unitCode)
print("Action 0", GetUnitName(unit), GetAbilityName(abiCode))
end
TasHeroLearnEx = {
-- Where is the TOCFile in your map?
TocPath = "war3mapImported\\TasHeroLearnEx.toc"
,HookEvent = hookEvent
,Action = action
-- Data for each UnitCode
,HeroData = {
-- supported Keys unit, unitCode, Player, 0; unit > unitCode > Player > 0
-- [0] is used by everyone, if not one of the others is used currently.
-- [bj_lastCreatedUnit] = "AHfs,AHbn,AHdr,AHpx,AHhb,AHds,AHre,AHad"
-- [FourCC('Hblm')] = "AHfs,AHbn,AHdr,AHpx,AHhb,AHds,AHre,AHad"
-- [Player(0)] = "AHfs,AHbn,AHdr,AHpx,AHhb,AHds,AHre,AHad"
-- [0] = "AEmb,AEim,AEev,AEme,AEer,AEfn,AEah,AEtq"
-- you can set a field from outside of this system, But if you do you should use TasHeroLearnEx.UpdateHeroData() after setting your wanted data.
-- TasHeroLearnEx.HeroData[FourCC('Hblm')] = "AHfs,AHbn,AHdr,AHpx,AHhb,AHds,AHre,AHad"
[FourCC('Hblm')] = "AHfs,AHbn,AHdr,AHpx,AHhb,AHds,AHre,AHad,AHbz,AHab,AHwe,AHmt,AHtc,AHtb,AHbh,AHav,AOwk,AOcr,AOmi,AOww,AOfs,AOsf,AOcl,AOeq"
,[Player(1)] = "AUim,AUts,AUcb,AUls,AUfn,AUfu,AUdr,AUdd,AUav,AUsl,AUcs,AUin,AUdc,AUdp,AUau,AUan"
}
,HeroAbilityLevelSkip = 2 -- should match the map gameplay constant
,Filter = function(unit) -- used for HeroData[0]
if IsUnitIllusion(unit) then return false end
-- if not IsUnitType(unit, UNIT_TYPE_HERO) then return false end
--return true if this unit is allowed to use HeroData[0] HeroData[player]
return true
end
,Cols = 8 --amout of buttons in one Row
,Rows = 1 -- amount of Rows
,ShowEnemy = true -- can look into enemy builts false/true?
,HideMaxLevelSlot = false -- true shows empty slots for max Leveld skills.
,UserControl = false -- Show the Buttons to toggle ShowEnemy & HideMaxLevelSlot
,HideWithoutUser = true -- hide TasHeroLearnEx UI when currently nothing would be displayed.
,UseUIScale = true
--ToolTip
,ToolTipSizeX = 0.2
,ToolTipPosX = 0.79
,ToolTipPosY = 0.165
,ToolTipPos = FRAMEPOINT_BOTTOMRIGHT
-- Box
--Happens once at creation, decides how TasHeroLearnEx is posed
,PosBox = function(frame)
--BlzFrameSetAbsPoint(frame, FRAMEPOINT_BOTTOMLEFT, 0.195, 0.135)
BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMLEFT, BlzGetFrameByName("SimpleInfoPanelUnitDetail", 0), FRAMEPOINT_TOPLEFT, -0.1, 0.02)
end
-- ShowButton
,OpenButtonTexture = "ReplaceableTextures\\CommandButtons\\BTNSkillz.blp"
--Happens once at creation, decides where Open Button is posed
,PosOpen = function(frame)
--BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOPRIGHT, 0.6, 0.15)
--BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, BlzGetFrameByName("SimpleInfoPanelUnitDetail", 0), FRAMEPOINT_TOPRIGHT, 0.1, 0.015)
BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, BlzGetFrameByName("SimpleInfoPanelUnitDetail", 0), FRAMEPOINT_TOPLEFT, 0.0, -0.01)
end
-- ParentFunc who you want as parent, this runs at InitBlizzard, if you need more control you need to modify the part that calls local function Init()
,ParentFunc = function() return BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0) end
-- how many LearnPoints an unit has to spent
,GetLearnPoints = function(unit)
return GetHeroSkillPoints(unit)
--return GetPlayerState(GetOwningPlayer(unit), PLAYER_STATE_RESOURCE_GOLD)//100
end
-- pay costs function is called inside TasHeroLearnEx.CustomUnitLearnAbility
,Costs = function(unit, abiCode)
-- can't pay return false
if TasHeroLearnEx.GetLearnPoints(unit) <= 0 then return false end
--SetPlayerState(GetOwningPlayer(unit), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetOwningPlayer(unit), PLAYER_STATE_RESOURCE_GOLD) - 100)
UnitModifySkillPoints(unit, -1)
return true
end
-- System stuff below
,Selected = {} -- current Selected Unit for [player]
,ViewOffset = __jarray(0) -- currentPage
,UpdateHeroData = function()
for key, value in pairs(TasHeroLearnEx.HeroData) do
if type(value) == "string" then
TasHeroLearnEx.HeroData[key] = this.IdString2IdArray(value)
end
end
end
-- supported DataMods
,SelectData = function(unit)
if TasHeroLearnEx.HeroData[unit] then return TasHeroLearnEx.HeroData[unit]
elseif TasHeroLearnEx.HeroData[GetUnitTypeId(unit)] then return TasHeroLearnEx.HeroData[GetUnitTypeId(unit)]
elseif TasHeroLearnEx.HeroData[GetOwningPlayer(unit)] and this.Filter(unit) then return TasHeroLearnEx.HeroData[GetOwningPlayer(unit)]
elseif TasHeroLearnEx.HeroData[0] and this.Filter(unit) then return TasHeroLearnEx.HeroData[0]
else return nil
end
end
,AbilityCache = {} -- makes performance better in V1.31 cause it lacks ParseTags and needs to do tooltip nonsense which with a cachce needs to be done only once.
,StringCache = {}
}
this = TasHeroLearnEx
this.UpdateButton = function(index, abiCode, level, levelMax)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButton", index), true)
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnButtonBackdrop", index), BlzGetAbilityIcon(abiCode), 0, false)
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnButtonBackdropDisabled", index), TasHeroLearnEx.getDisabledIcon(BlzGetAbilityIcon(abiCode)), 0, false)
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnButtonBackdropPushed", index), BlzGetAbilityIcon(abiCode), 0, false)
if level >= levelMax then
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonChargeBoxChecked", index), true)
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnButtonChargeText", index), "")
else
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonChargeBoxChecked", index), false)
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnButtonChargeText", index), level + 1)
end
end
this.EnforceUpdateOnce = true
local UpdateUILastData, UpdateUILastOffset, UpdateUILastUnit, UpdateUILastLevel, UpdateUILastPoints = 0,0,0,0, 0 -- buttons
local LastAbiCode, LastAbiLevel = 0,0 -- tooltip
this.UpdateUI = function()
--async
local foundTooltip = false
local unit = this.Selected[GetLocalPlayer()]
if this.HideWithoutUser then BlzFrameSetVisible(this.SuperParent, unit ~= nil) if not unit then return end end
local data = this.SelectData(unit)
if not data and this.HideWithoutUser then BlzFrameSetVisible(this.SuperParent, false) unit = nil return else BlzFrameSetVisible(this.SuperParent, true) end
local heroLevel = GetUnitLevel(unit)
local showCurrent = this.ShowEnemy or IsUnitAlly(unit, GetLocalPlayer())
local hasControl = IsUnitOwnedByPlayer(unit, GetLocalPlayer()) or GetPlayerAlliance(GetOwningPlayer(unit), GetLocalPlayer(), ALLIANCE_SHARED_CONTROL)
local learnPoints = this.GetLearnPoints(unit)
if (IsUnitAlly(unit, GetLocalPlayer()) or this.ShowEnemy) and data and learnPoints > 0 then
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnButtonChargeText", 0), learnPoints)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonChargeBox", 0), true)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonSprite", 0), true)
else
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonChargeBox", 0), false)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonSprite", 0), false)
end
local scale = BlzFrameGetWidth(BlzGetFrameByName("ConsoleUIBackdrop", 0))
if this.UseUIScale and scale > 0.1 then
scale = scale/0.8
BlzFrameSetScale(this.Parent, scale)
BlzFrameSetScale(this.Open, scale)
end
if BlzFrameIsVisible(this.Parent) then
-- skip visual updating the buttons when unneeded!!
local skipUpdate = UpdateUILastData == data
and UpdateUILastOffset == this.ViewOffset[GetLocalPlayer()]
and UpdateUILastUnit == GetHandleId(unit) -- compare GetHandleId to not keep a ref
and UpdateUILastLevel == heroLevel
and UpdateUILastPoints == learnPoints
if this.EnforceUpdateOnce then
this.EnforceUpdateOnce = false
skipUpdate = false
end
UpdateUILastData = data
UpdateUILastOffset = this.ViewOffset[GetLocalPlayer()]
UpdateUILastUnit = GetHandleId(unit)
UpdateUILastPoints = learnPoints
UpdateUILastLevel = heroLevel
for i = 1, this.Cols*this.Rows do
local skillIndex = i + this.ViewOffset[GetLocalPlayer()]
if data and data[skillIndex] then
local abiCode = data[skillIndex]
local level = GetUnitAbilityLevel(unit, abiCode)
local levelReq, levelSkipReq, levelMax
if level == 0 then
levelReq = this.GetAbilityData(abiCode, "reqLevel", S2I)
levelSkipReq = 0 -- does not matter much when one has currently level 0
levelMax = 1 -- Assume it can be learned atleast once
else
levelReq = this.GetAbilityData(abiCode, "reqLevel", S2I)
levelSkipReq = this.GetAbilityData(abiCode, "levelSkip", S2I)
levelMax = this.GetAbilityData(abiCode, "levels", S2I)
end
if levelSkipReq == 0 then levelSkipReq = this.HeroAbilityLevelSkip end
levelReq = levelSkipReq*level + levelReq
--print(heroLevel, levelReq, heroLevel >= levelReq)
--print(level)
-- tooltip
if BlzFrameIsVisible(BlzGetFrameByName("TasHeroLearnButtonTooltip", i)) then
foundTooltip = true
-- only update Tooltip when needed
if abiCode ~= LastAbiCode or level ~= LastAbiLevel then
LastAbiCode = abiCode
LastAbiLevel = level
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnTooltipIcon", 0), BlzGetAbilityIcon(abiCode), 0, false)
if hasControl then
if heroLevel >= levelReq and level < levelMax then
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipText", 0), BlzGetAbilityResearchExtendedTooltip(abiCode, 0))
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipName", 0), BlzGetAbilityTooltip(abiCode, level))
elseif level >= levelMax then
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipName", 0), BlzGetAbilityTooltip(abiCode, level - 1))
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipText", 0), "|Cffffff00 - "..GetLocalizedString("QUESTCOMPLETED").."|r\n\n".. BlzGetAbilityResearchExtendedTooltip(abiCode, 0))
elseif heroLevel < levelReq then
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipName", 0), BlzGetAbilityTooltip(abiCode, level))
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipText", 0), GetLocalizedString("REQUIRESTOOLTIP") .."\n - "..GetLocalizedString("REQUIREDLEVELTOOLTIP").." ".. R2I(levelReq).."|r\n\n".. BlzGetAbilityResearchExtendedTooltip(abiCode, 0))
end
elseif showCurrent then
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipName", 0), BlzGetAbilityTooltip(abiCode, level - 1))
BlzFrameSetText(BlzGetFrameByName("TasHeroLearnTooltipText", 0), BlzGetAbilityExtendedTooltip(abiCode, level - 1))
end
end
end
-- button
if abiCode and hasControl then
if not this.HideMaxLevelSlot or level < levelMax then
if not skipUpdate then this.UpdateButton(i, abiCode, level, levelMax) end
BlzFrameSetEnable(BlzGetFrameByName("TasHeroLearnButton", i), heroLevel >= levelReq and level < levelMax)
else
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButton", i), false)
end
elseif abiCode and showCurrent and level >= 1 then
BlzFrameSetEnable(BlzGetFrameByName("TasHeroLearnButton", i), false)
if not skipUpdate then this.UpdateButton(i, abiCode, level-1, levelMax) end
else
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButton", i), false)
end
else
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButton", i), false)
end
end
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnTooltipBoxFrame", 0), foundTooltip)
end
unit = nil
end
local AbilityCache = this.AbilityCache
function this.GetAbilityData(abiCode, tag, convertFunc)
-- was this ability already parsed?
if not AbilityCache[abiCode] then
AbilityCache[abiCode] = {}
AbilityCache[abiCode].String = string.pack(">I4", abiCode) -- store the result
end
if not AbilityCache[abiCode][tag] then
-- calc it and store it
-- have ParseTags native?
if ParseTags then
this.AbilityCache[abiCode][tag] = ParseTags("<"..AbilityCache[abiCode].String..","..tag..">")
else
BlzSetAbilityExtendedTooltip(testSkill, "<"..AbilityCache[abiCode].String..","..tag..">", 0)
this.AbilityCache[abiCode][tag] = BlzGetAbilityExtendedTooltip(testSkill, 0)
end
if convertFunc then this.AbilityCache[abiCode][tag] = convertFunc(this.AbilityCache[abiCode][tag]) end
end
return this.AbilityCache[abiCode][tag]
end
function TasHeroLearnEx.getDisabledIcon(icon)
--ReplaceableTextures\CommandButtons\BTNHeroPaladin.tga -> ReplaceableTextures\CommandButtonsDisabled\DISBTNHeroPaladin.tga
if not this.StringCache[icon] and string.sub(icon,35,35) ~= "\\" then return icon end --this string has not enough chars return it
if not this.StringCache[icon] then
local old = icon
-- make it lower to reduce the amount of cases and for warcraft 3 FilePath case does not matter
icon = string.lower(icon)
if string.find(icon, "commandbuttons\\btn") then this.StringCache[old] = string.gsub(icon, "commandbuttons\\btn", "commandbuttonsdisabled\\disbtn" )
-- default wacraft 3 style
elseif string.find(icon, "passivebuttons\\pasbtn") then this.StringCache[old] = string.gsub(icon, "passivebuttons\\pasbtn", "commandbuttonsdisabled\\dispasbtn" )
--recommented by hiveworkshop
elseif string.find(icon, "passivebuttons\\pas") then this.StringCache[old] = string.gsub(icon, "passivebuttons\\pas", "commandbuttonsdisabled\\dispas" )
elseif string.find(icon, "commandbuttons\\atc") then this.StringCache[old] = string.gsub(icon, "commandbuttons\\atc", "commandbuttonsdisabled\\disbtn" ) end
icon = old
end
return this.StringCache[icon]
end
--[[ EvokeUnitEvent Skill by Tasyen
This system tries to let a custom system creator to start an unit event to give a simpler api.
]]
do
if TasHeroLearnEx.HookEvent then
local list = {}
-- hook into TriggerRegisterAnyUnitEventBJ to find triggers having the wanted event
local realAnyUnit = TriggerRegisterAnyUnitEventBJ
function TriggerRegisterAnyUnitEventBJ(whichTrigger, whichPlayerUnitEvent)
if GetHandleId(whichPlayerUnitEvent) == GetHandleId(EVENT_PLAYER_HERO_SKILL) then
table.insert(list, whichTrigger)
list[whichTrigger] = true
end
realAnyUnit(whichTrigger, whichPlayerUnitEvent)
end
-- remove triggers that are going to be destroyed
local realDestroyTrigger = DestroyTrigger
function DestroyTrigger(trig)
if list[trig] then
list[trig] = nil
for i = #list, 1, -1 do
if list[i] == trig then table.remove(list, i) break end
end
end
realDestroyTrigger(trig)
end
-- data used to replace default getters
local hero, skill, level, owner
local FuncGetTriggerUnit, FuncGetTriggerEventId, FuncGetLearningUnit, FuncGetLearnedSkill, FuncGetLearnedSkillLevel, FuncGetTriggerPlayer = GetTriggerUnit, GetTriggerEventId, GetLearningUnit, GetLearnedSkill, GetLearnedSkillLevel, GetTriggerPlayer
-- a learn trigger could evoke non learn triggers they still need to use the real getters
local function OGetTriggerUnit() if list[GetTriggeringTrigger()] then return hero else return FuncGetTriggerUnit() end end
local function OGetTriggerEventId() if list[GetTriggeringTrigger()] then return GetHandleId(EVENT_PLAYER_HERO_SKILL) else return FuncGetTriggerEventId() end end
local function OGetLearningUnit() if list[GetTriggeringTrigger()] then return hero else return FuncGetLearningUnit() end end
local function OGetLearnedSkill() if list[GetTriggeringTrigger()] then return skill else return FuncGetLearnedSkill() end end
local function OGetLearnedSkillLevel() if list[GetTriggeringTrigger()] then return level else return FuncGetLearnedSkillLevel() end end
local function OGetTriggerPlayer() if list[GetTriggeringTrigger()] then return owner else return FuncGetTriggerPlayer() end end
local hooks = {}
-- evoke custom Event
function this.EvokeUnitLevelEvent(unit, abiCode)
-- print("EvokeUnitLevelEvent", #list)
-- store data that replaces the getters
hero = unit
skill = abiCode
level = GetUnitAbilityLevel(unit, abiCode)
owner = GetOwningPlayer(unit)
if AddHook then
_ ,hooks[1] = AddHook("GetTriggerUnit", OGetTriggerUnit, 0)
_ ,hooks[2] = AddHook("GetTriggerEventId", OGetTriggerEventId, 0)
_ ,hooks[3] = AddHook("GetLearningUnit", OGetLearningUnit, 0)
_ ,hooks[4] = AddHook("GetLearnedSkill", OGetLearnedSkill, 0)
_ ,hooks[5] = AddHook("GetLearnedSkillLevel", OGetLearnedSkillLevel, 0)
_ ,hooks[6] = AddHook("GetTriggerPlayer", OGetTriggerPlayer, 0)
else
GetTriggerUnit = OGetTriggerUnit
GetTriggerEventId = OGetTriggerEventId
GetLearningUnit = OGetLearningUnit
GetLearnedSkill = OGetLearnedSkill
GetLearnedSkillLevel = OGetLearnedSkillLevel
GetTriggerPlayer = OGetTriggerPlayer
end
for _, trigger in ipairs(list) do
ConditionalTriggerExecute(trigger)
end
--restore the getters
if AddHook then
for i,v in ipairs(hooks) do
v()
end
while table.remove(hooks) do end
else
GetTriggerUnit = FuncGetTriggerUnit
GetTriggerEventId = FuncGetTriggerEventId
GetLearningUnit = FuncGetLearningUnit
GetLearnedSkill = FuncGetLearnedSkill
GetLearnedSkillLevel = FuncGetLearnedSkillLevel
GetTriggerPlayer = FuncGetTriggerPlayer
end
-- print("EvokeUnitLevelEvent Done")
end
else
function this.EvokeUnitLevelEvent(unit, abiCode)
if this.Action[0] then
this.Action[0](unit, abiCode, GetUnitAbilityLevel(unit, abiCode), GetOwningPlayer(unit), GetUnitTypeId(unit))
end
if this.Action[abiCode] then
this.Action[abiCode](unit, abiCode, GetUnitAbilityLevel(unit, abiCode), GetOwningPlayer(unit), GetUnitTypeId(unit))
end
end
end
end
-- Make Unit learn abiCode and evoke a Learn Event
function this.CustomUnitLearnAbility(unit, abiCode)
if not abiCode or abiCode <= 0 or not unit then return end
if GetUnitAbilityLevel(unit, abiCode) == 0 then
if this.GetAbilityData(abiCode, "reqLevel", S2I) > GetUnitLevel(unit) then return end
if not this.Costs(unit, abiCode) then return end
UnitAddAbility(unit, abiCode)
UnitMakeAbilityPermanent(unit, true, abiCode)
elseif GetUnitAbilityLevel(unit, abiCode) < BlzGetAbilityIntegerField(BlzGetUnitAbility(unit, abiCode), ABILITY_IF_LEVELS) then
local levelReq = this.GetAbilityData(abiCode, "reqLevel", S2I)
--levelSkipReq = BlzGetAbilityIntegerField(abi, ABILITY_IF_LEVEL_SKIP_REQUIREMENT)
local levelSkipReq = this.GetAbilityData(abiCode, "levelSkip", S2I)
if levelSkipReq == 0 then levelSkipReq = this.HeroAbilityLevelSkip end
levelReq = levelSkipReq*GetUnitAbilityLevel(unit, abiCode) + levelReq
if levelReq > GetUnitLevel(unit) then return end
if not this.Costs(unit, abiCode) then return end
IncUnitAbilityLevel(unit, abiCode)
UnitMakeAbilityPermanent(unit, true, abiCode)
else
--print("CustomUnitLearnEvent max Level", GetUnitName(unit), GetAbilityName(abiCode))
return
end
this.EvokeUnitLevelEvent(unit, abiCode)
end
-- "ACfb,AInv,A070" -> {FourCC('ACfb'),FourCC('AInv'),FourCC('A070')}
function this.IdString2IdArray(string)
local result = {}
local startIndex = 1
while startIndex + 3 <= string.len(string) do
local skillCode = string.sub(string, startIndex, startIndex + 3)
startIndex = startIndex + 5
skillCode = FourCC(skillCode)
table.insert(result, skillCode)
end
return result
end
do
local function InitFrames()
BlzGetFrameByName("ConsoleUIBackdrop", 0)
BlzLoadTOCFile(TasHeroLearnEx.TocPath)
TasHeroLearnEx.SuperParent = BlzCreateFrame("TasHeroLearnParentFrame", TasHeroLearnEx.ParentFunc(), 0, 0)
TasHeroLearnEx.Parent = BlzGetFrameByName("TasHeroLearnFrame", 0)
TasButtonAction(TasHeroLearnEx.Parent, function(frame, player) end) -- use the clear focus feature from TasButtonAction
TasHeroLearnEx.PosBox(TasHeroLearnEx.Parent)
BlzFrameSetSize(TasHeroLearnEx.Parent, 0.04, 0.04)
local frame = BlzCreateFrameByType("SLIDER", "TasHeroLearnSlider", TasHeroLearnEx.Parent, "QuestMainListScrollBar", 0)
BlzFrameClearAllPoints(frame)
BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, TasHeroLearnEx.Parent, FRAMEPOINT_BOTTOMRIGHT, -0.004, 0.008)
BlzFrameSetStepSize(frame, 1)
TasSliderAction(frame, function(frame, player, value)
this.ViewOffset[player] = R2I(value*this.Cols)
end)
TasSliderAction(TasHeroLearnEx.Parent, nil, 1, BlzGetFrameByName("TasHeroLearnSlider", 0))
frame = BlzCreateFrameByType("GLUETEXTBUTTON", "TasHeroLearnToggleA", TasHeroLearnEx.Parent, "ScriptDialogButton", 0)
BlzFrameSetSize(frame, 0.03, 0.03)
BlzFrameSetText(frame, "A")
BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, TasHeroLearnEx.Parent, FRAMEPOINT_TOPRIGHT, -0.004, 0.003)
TasButtonAction(frame, function(frame, player)
if GetLocalPlayer() == player then
this.HideMaxLevelSlot = not this.HideMaxLevelSlot
end
end)
BlzFrameSetVisible(frame, this.UserControl)
frame = BlzCreateFrameByType("GLUETEXTBUTTON", "TasHeroLearnToggleB", TasHeroLearnEx.Parent, "ScriptDialogButton", 0)
BlzFrameSetSize(frame, 0.03, 0.03)
BlzFrameSetText(frame, "B")
BlzFrameSetPoint(frame, FRAMEPOINT_RIGHT, BlzGetFrameByName("TasHeroLearnToggleA", 0), FRAMEPOINT_LEFT, -0.004, 0)
TasButtonAction(frame, function(frame, player)
if GetLocalPlayer() == player then
this.ShowEnemy = not this.ShowEnemy
end
end)
BlzFrameSetVisible(frame, this.UserControl)
if GetHandleId(TasHeroLearnEx.SuperParent) == 0 then print("Error - TasHeroLearnEx Create TasHeroLearnParentFrame") end
TasHeroLearnEx.Open = BlzCreateFrame("TasHeroLearnButton", TasHeroLearnEx.SuperParent, 0, 0)
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnButtonBackdrop", 0), this.OpenButtonTexture, 0, false)
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnButtonBackdropDisabled", 0), TasHeroLearnEx.getDisabledIcon(this.OpenButtonTexture), 0, false)
BlzFrameSetTexture(BlzGetFrameByName("TasHeroLearnButtonBackdropPushed", 0), this.OpenButtonTexture, 0, false)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonChargeBox", 0), false)
BlzGetFrameByName("TasHeroLearnButtonChargeText", 0)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonChargeBoxChecked", 0), false)
TasHeroLearnEx.PosOpen(TasHeroLearnEx.Open)
TasButtonAction(TasHeroLearnEx.Open, function(frame, player)
if GetLocalPlayer() == player then
BlzFrameSetVisible(TasHeroLearnEx.Parent, not BlzFrameIsVisible(TasHeroLearnEx.Parent))
end
end)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonSprite", 0), false)
local count = 0
for i = 1, this.Rows*this.Cols do
frame = BlzCreateFrame("TasHeroLearnButton", TasHeroLearnEx.Parent, 0, i)
TasHeroLearnEx[frame] = i
-- reserve HandleIds to allow async access later
BlzGetFrameByName("TasHeroLearnButtonBackdrop", i)
BlzGetFrameByName("TasHeroLearnButtonBackdropDisabled", i)
BlzGetFrameByName("TasHeroLearnButtonBackdropPushed", i)
BlzGetFrameByName("TasHeroLearnButtonTooltip", i)
BlzGetFrameByName("TasHeroLearnButtonChargeBox", i)
BlzGetFrameByName("TasHeroLearnButtonChargeText", i)
BlzGetFrameByName("TasHeroLearnButtonChargeBoxChecked", i)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnButtonSprite", i), false)
count = count + 1
if count > this.Cols then
BlzFrameSetPoint(frame, FRAMEPOINT_TOPLEFT, BlzGetFrameByName("TasHeroLearnButton", i - this.Cols), FRAMEPOINT_BOTTOMLEFT, 0, -0.002)
count = 1
elseif i > 1 then
BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasHeroLearnButton", i - 1), FRAMEPOINT_RIGHT, 0.002, 0)
end
TasButtonAction(frame, function(frame, player)
local unit = TasHeroLearnEx.Selected[player]
if IsUnitType(unit, UNIT_TYPE_DEAD) or IsUnitPaused(unit) or IsUnitIllusion(unit) then return end
if IsUnitOwnedByPlayer(unit, player) or GetPlayerAlliance(GetOwningPlayer(unit), player, ALLIANCE_SHARED_CONTROL) then
local i = TasHeroLearnEx[frame]
local skillIndex = i + this.ViewOffset[player]
--print(i, skillIndex)
this.CustomUnitLearnAbility(TasHeroLearnEx.Selected[player], this.SelectData(TasHeroLearnEx.Selected[player])[skillIndex])
else
DisplayTextToPlayer(player, 0, 0, "Can't Learn - You have no control over this unit")
end
end)
TasSliderAction(frame, nil, 1, BlzGetFrameByName("TasHeroLearnSlider", 0))
end
BlzFrameSetPoint(BlzGetFrameByName("TasHeroLearnButton", 1), FRAMEPOINT_TOPLEFT, TasHeroLearnEx.Parent, FRAMEPOINT_TOPLEFT, 0.006, -0.006)
frame = BlzGetFrameByName("TasHeroLearnButton", 1)
BlzFrameSetSize(TasHeroLearnEx.Parent, BlzFrameGetWidth(frame)*this.Cols + (this.Cols - 1)*0.002 + 0.023, BlzFrameGetHeight(frame)*this.Rows + (this.Rows - 1)*0.002 + 0.012)
BlzFrameSetSize(BlzGetFrameByName("TasHeroLearnSlider", 0), BlzFrameGetWidth(BlzGetFrameByName("TasHeroLearnSlider", 0)), BlzFrameGetHeight(TasHeroLearnEx.Parent) - 0.02)
-- create one ToolTip which shows data for current hovered inside a timer.
-- also reserve handleIds to allow async usage
BlzCreateFrame("TasHeroLearnTooltipBoxFrame", TasHeroLearnEx.SuperParent, 0, 0)
BlzGetFrameByName("TasHeroLearnTooltipBox", 0)
BlzGetFrameByName("TasHeroLearnTooltipIcon", 0)
BlzGetFrameByName("TasHeroLearnTooltipName", 0)
BlzGetFrameByName("TasHeroLearnTooltipSeperator", 0)
BlzGetFrameByName("TasHeroLearnTooltipText", 0)
BlzFrameSetSize(BlzGetFrameByName("TasHeroLearnTooltipText", 0), this.ToolTipSizeX, 0)
BlzFrameSetAbsPoint(BlzGetFrameByName("TasHeroLearnTooltipText", 0), this.ToolTipPos, this.ToolTipPosX, this.ToolTipPosY)
BlzFrameSetPoint(BlzGetFrameByName("TasHeroLearnTooltipBox", 0), FRAMEPOINT_TOPLEFT, BlzGetFrameByName("TasHeroLearnTooltipIcon", 0), FRAMEPOINT_TOPLEFT, -0.005, 0.005)
BlzFrameSetPoint(BlzGetFrameByName("TasHeroLearnTooltipBox", 0), FRAMEPOINT_BOTTOMRIGHT, BlzGetFrameByName("TasHeroLearnTooltipText", 0), FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
BlzFrameSetVisible(BlzGetFrameByName("TasHeroLearnTooltipBoxFrame", 0), false)
BlzFrameSetVisible(this.Parent, false)
--BlzFrameSetVisible(TasHeroLearnEx.SuperParent, false)
end
function this.Init()
local trigger
this.UpdateHeroData()
trigger = CreateTrigger()
TriggerAddAction(trigger, function()
if GetLocalPlayer() == GetTriggerPlayer() then BlzFrameSetVisible(TasHeroLearnEx.Parent, false) end
end)
for i = 0, bj_MAX_PLAYERS - 1 do
TriggerRegisterPlayerEventEndCinematic(trigger, Player(i))
end
-- selection
trigger = CreateTrigger()
TriggerAddAction(trigger, function()
TasHeroLearnEx.Selected[GetTriggerPlayer()] = GetTriggerUnit()
local data = this.SelectData(GetTriggerUnit())
if data then
local skillCount = #data
--local max = R2I(math.max(0, (skillCount - 1)/(this.Cols)))
local max = R2I(math.max(0, (skillCount +this.Cols - this.Cols*this.Rows)/this.Cols) )
BlzFrameSetValue(BlzGetFrameByName("TasHeroLearnSlider", 0), math.min(max, BlzFrameGetValue(BlzGetFrameByName("TasHeroLearnSlider", 0))))
BlzFrameSetMinMaxValue(BlzGetFrameByName("TasHeroLearnSlider", 0), 0, max)
else
BlzFrameSetValue(BlzGetFrameByName("TasHeroLearnSlider", 0), 0)
BlzFrameSetMinMaxValue(BlzGetFrameByName("TasHeroLearnSlider", 0), 0, 0)
end
this.EnforceUpdateOnce = true
this.UpdateUI()
end)
TriggerRegisterAnyUnitEventBJ(trigger, EVENT_PLAYER_UNIT_SELECTED)
-- TooltipUpdate
TimerStart(CreateTimer(), 0.2, true, this.UpdateUI)
InitFrames()
if FrameLoaderAdd then FrameLoaderAdd(InitFrames) end
end
if AutoRun then
if OnInit then -- Total Initialization v5.2.0.1 by Bribe
OnInit.trig(this.Init)
else -- without
local real = InitBlizzard
function InitBlizzard()
real()
this.Init()
end
end
end
end
end