TasSpellView

This bundle is marked as pending. It has not been reviewed by a staff member yet.

Introduction


TasSpellView is a custom UI system for Warcraft 3 V1.31 or higher.
It allows to see the abilities of units one can not command.

Details


Creates a set of custom buttons over the default command card while one selects an unit of which the player has no control.
The custom buttons display icon, tooltips, current cooldown & current Level. Does not display requirments nor disable state.
The tooltip contain manacosts, cooldown, range and aoe.
For (Warcraft V1.31.1) cooldown, Level & correct tooltip-Level are only displayed when the abilityCodes are provided on an unitCode ('Hpal') base or when you enable the Autodetection of IdData and they were casted or learned. Does not matter if your map only has 1 level skills. Or when the system runs in a Warcraft 3 version with BlzGetAbilityId (with that it can calc it during the match). Reforged has it.

Works for Observers.

The whole Lua system you could copy paste it and it works.
Lua:
--[[ TasSpellView 1.2 by Tasyen
displays with custom UI the abilites of not controled units in the command card

TasSpellView.AddTechReq(skillCode, techCode[, techAmount])
    skillCode requires TechCode of level techAmount techamount is 1 when not provided
    each adds 1 more requirment
    TasSpellView.AddTechReq('Ahwd','Rowd',2)
TasSpellView.AddUnitSkill(unitCode, skillCode)
    units of unitCode have skillCode, you can this multiple times for one unitCode with different skillCodes or once with many skillCodes in one string
    adding skills disables autodetect for units of that unitcode, autodetect works better in Reforged than in Warcraft 3 V1.31.1
    TasSpellView.AddUnitSkill('unec', 'Acri,Arai,Auhf,Aiun')
    TasSpellView.AddUnitSkill('unec', 'Acri')

    can use Total Initialization by Bribe
]]
do
    TasSpellView = {
        AutoRun = true --(true) will create Itself at 0s, (false) you need to InitSpellView() or InitTasSpellView()
        ,TocPath = "war3mapImported/TasSpellView.toc" -- when this fails or nil or "" create by code. TasSpellView.CodeOnly = true enforces code creation
        ,ParentFuncSimple = function()
            if GetHandleId(BlzGetFrameByName("CommandBarFrame", 0)) > 0 then return BlzGetFrameByName("CommandBarFrame",  0) end
            return BlzGetFrameByName("ConsoleUI", 0)
        end
        ,ParentFunc = function()
         --   if GetHandleId(BlzGetFrameByName("ConsoleUIBackdrop", 0)) > 0 then return BlzGetFrameByName("ConsoleUIBackdrop",  0) end
            return BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
        end
        ,TextFormat0 = "\x25.0f"
        ,TextFormat1 = "\x25.1f"
        ,TextReplace = "\x25\x25d"
        ,TextDisallowed = "X" -- display this when not allowed by tech data in chargebox
        ,UpdateTime = 0.1 -- lower number is faster
        -- allowed Unit can be further custimzed in function this.ShowAllowed
        ,ShowHero = true 
        ,ShowAlly = true -- can see skills of friends
        ,ShowEnemy = true -- can see skills of enemies, includes hostile creeps
        ,ShowNeutral = true -- can see skills of Neutral Players, includes hostile creeps
        ,UseCommandCardPos = true -- display skills as object editor setup says, taking a slot twice will not show some skils. for Non heroes
        ,UseCommandCardPosHero = true --^^ for hero & hero-illusion
        ,ShowCooldown = true -- can be async, needs BlzGetAbilityId for ability by index 
        ,ShowCooldownText = true -- show remaining cooldown text overlay requires BlzGetAbilityId or setup in UnitSkills
        ,ShortBigNumber = true -- Display values greater than 9999, in thousands like 10k or 100k for Range,Mana,Area
        ,ToolTipSizeX = 0.26
        ,ToolTipPosX = 0.79
        ,ToolTipPosY = 0.165
        ,ToolTipPos = FRAMEPOINT_BOTTOMRIGHT
        ,Data = {} -- temp display data
        ,UnitSkills = { 
            -- you can store the abilities shown for that unitCode
            --, otherwise the system will show the abilites found by index which pass the filter
            -- TasSpellView.AddUnitSkill fills this
            -- [FourCC'Ulic'] = {[1]= FourCC'AUfn',[2]= FourCC'AUfu',[3]= FourCC'AUdr',[4]= FourCC'AUdd'}
        }
        ,IdData = { -- stores Ability to FourCC in Warcraft 3 V1.31.1, does nothing when BlzGetAbilityId is found
            Enabled = 2
            -- 0 -> disable this feature
            -- 1 -> create Learn_Skill Trigger
            -- 2 -> create SPELL_EFFECT Trigger ^^
            -- 3 -> hook UnitAddAbility ^^
        } 
        ,TechReq = {} -- TasSpellView[FourCC'AHhb'] = {FourCC'hfoo', 1, FourCC'hsor', 2}
        ,Frame = {Tooltip = {}} -- [0 to 11] = {Button=y,Icon=y,...}        
    }
    local this = TasSpellView
    local thisTooltip = this.Frame.Tooltip
    function this.ShowAllowed(unit, localPlayer)
            local controlType = GetHandleId(GetPlayerController(GetOwningPlayer(unit))) -- user = 0 computer = 1, treat all above as Neutral
            if this.ShowNeutral and controlType >= 2 then return true end

            if not this.ShowAlly and IsUnitAlly(unit, localPlayer) then return false end
            if not this.ShowEnemy and IsUnitEnemy(unit, localPlayer) then return false end
            if not this.ShowHero and IsHeroUnitId(GetUnitTypeId(unit)) then return false end

            return true
        end
    function this.IdString2IdArray(x)
        local result = {}
        local startIndex = 1
        while startIndex + 3 <= string.len(x)  do
            local skillCode = string.sub(x, startIndex, startIndex + 3)
            startIndex = startIndex + 5
            skillCode = FourCC(skillCode)
            table.insert(result, skillCode)
        end
        return result
    end
    this.AddTechReq = function(skillCode, techCode, techAmount)
        if  type(skillCode) == "string" then skillCode = FourCC(skillCode) end
        if not this.TechReq[skillCode] then this.TechReq[skillCode] = {} end
        if  type(techCode) == "string" then techCode = FourCC(techCode) end
        table.insert(this.TechReq[skillCode], techCode)
        table.insert(this.TechReq[skillCode], techAmount or 1)
    end
    this.AddUnitSkill = function(unitCode, skillCode)
        if type(unitCode) == "string" then unitCode = FourCC(unitCode) end
        if not this.UnitSkills[unitCode] then this.UnitSkills[unitCode] = {} end
        if type(skillCode) == "string" then
            if string.len( skillCode ) >4 then
                for i, v in ipairs(this.IdString2IdArray(skillCode)) do table.insert(this.UnitSkills[unitCode], v) end
            else
                if  type(skillCode) == "string" then skillCode = FourCC(skillCode) end
                table.insert(this.UnitSkills[unitCode], skillCode)
            end
        else
            table.insert(this.UnitSkills[unitCode], skillCode)
        end
    end
    if TasAbilityData then
        this.GetField = TasAbilityData.GetField
    else -- dont have lib, recreate the needed feature
        local AbilityCache = {}
        local testSkill = FourCC'AHre' -- should not be used in the map
        function this.GetField(abiCode, tag, convertFunc, formatTag)
            if not formatTag then formatTag = "" end
            -- 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
                    AbilityCache[abiCode][tag] = ParseTags("<"..AbilityCache[abiCode].String..","..tag..formatTag..">")
                else
                    --local backup = BlzGetAbilityExtendedTooltip(abiCode, 0)
                    BlzSetAbilityExtendedTooltip(testSkill, "<"..AbilityCache[abiCode].String..","..tag..formatTag..">", 0)
                    AbilityCache[abiCode][tag] = BlzGetAbilityExtendedTooltip(testSkill, 0)
                    --BlzSetAbilityExtendedTooltip(abiCode, backup, 0)
                end
                if convertFunc then AbilityCache[abiCode][tag] = convertFunc(AbilityCache[abiCode][tag]) end
            end
            return AbilityCache[abiCode][tag]
        end
    end    

    function this.AbiFilter(abi, text)
        if BlzGetAbilityBooleanField(abi, ABILITY_BF_ITEM_ABILITY) then return false end

        local posY = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)
        if posY == -11 then return false end

        local pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + posY*4
        if pos < 0 or pos > 11 then return false end

        if text == "Tool tip missing!" or text == "" or text == " " then return false end

        return true
    end
    this.GetUnitDataAddSkill = function(unit, index, skill)
        local i = index
        if not this.Data[i] then this.Data[i] = {} end
        local data = this.Data[i]
        if not skill then skill = data.FourCC
        else data.FourCC = skill end
        local abi = BlzGetUnitAbility(unit, skill)
        local level = GetUnitAbilityLevel(unit, skill)
        data.Used = true
        data.Icon = BlzGetAbilityIcon(skill)
        BlzFrameSetTexture(this.Frame[i].Icon, data.Icon, 0, false)
        if level > 0 then
            data.Mana = BlzGetUnitAbilityManaCost(unit, skill, level - 1)
            data.Cool = BlzGetUnitAbilityCooldown(unit, skill, level - 1)
            data.Range = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, level - 1))
            data.Area = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, level - 1))
            data.Name = BlzGetAbilityTooltip(skill, level - 1)
            data.Text = BlzGetAbilityExtendedTooltip(skill, level - 1)
        else
            data.Name =  BlzGetAbilityResearchTooltip(skill, 0)
            data.Text = BlzGetAbilityResearchExtendedTooltip(skill, 0)
            data.Mana = BlzGetAbilityManaCost(skill, 0)
            data.Cool = BlzGetAbilityCooldown(skill, 0)
            data.Range = R2I(this.GetField(skill, "Rng1"))
            data.Area = R2I(this.GetField(skill, "Area1"))
        end
        if this.ShortBigNumber then
            if data.Mana > 9999 then
                data.Mana = string.format(this.TextFormat0, data.Mana/1000).."k"
            end
            if data.Range > 9999 then
                data.Range = string.format(this.TextFormat0, data.Range/1000).."k"
            end
            if data.Area > 9999 then
                data.Area = string.format(this.TextFormat0, data.Area/1000).."k"
            end
        end
        abi = nil
    end
    this.GetUnitData = function(unit)
        local unitCode = GetUnitTypeId(unit)
        local isHero = IsHeroUnitId(unitCode)
        local commandCardPos = (not isHero and this.UseCommandCardPos) or (isHero and this.UseCommandCardPosHero)
        for i= 0, 11 do this.Data[i].FourCC = 0 this.Data[i].Used = false end
        if not unit or unitCode == 0 then return end

        -- have presaved Data
        if this.UnitSkills[unitCode] then
            if commandCardPos then
                for i, v in ipairs(this.UnitSkills[unitCode]) do 
                    local pos = BlzGetAbilityPosX(v) + BlzGetAbilityPosY(v)*4
                    if pos >= 0 and pos <= 11 then this.Data[pos].FourCC = v end
                end
                -- only these are displayed, only add upto 11 skills and only get text/icons/data once for each slot
                for i= 0, 11 do
                    if this.Data[i].FourCC > 0 then
                        this.GetUnitDataAddSkill(unit, i)
                    end
                end
            else
                for i= 0, 11 do
                    local skill = this.UnitSkills[unitCode][i + 1]
                    if skill then this.GetUnitDataAddSkill(unit, i, skill) end
                end
            end
        else
            local i = 0
            local addCount = 0
            local abi
            for i = 0, 9999 do
                if addCount > 11 then break end -- only 12 fit into the commandcard starts addcount is increased afterwards therefore bigger then 11
                abi = BlzGetUnitAbilityByIndex(unit, i)
                if not abi then break end
                if this.AbiFilter(abi, BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL, 0)) then
                    if BlzGetAbilityId or this.IdData[abi] then
                        -- treat it like MOD_ABI_CODE
                        if this.IdData[abi] then abi = this.IdData[abi]
                        elseif BlzGetAbilityId then abi = BlzGetAbilityId(abi)
                        end

                        if commandCardPos then
                            local pos = BlzGetAbilityPosX(abi) + BlzGetAbilityPosY(abi)*4
                            if pos >= 0 and pos <= 11 then this.Data[pos].FourCC = abi end
                            for i= 0, 11 do
                                if this.Data[i].FourCC > 0 then
                                    this.GetUnitDataAddSkill(unit, i)
                                end
                            end
                        else
                            this.GetUnitDataAddSkill(unit, addCount, abi)
                        end
                    else
                        local insertPos = addCount
                        if commandCardPos then
                            local pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)*4
                            if pos >= 0 and pos <= 11 then insertPos = pos end
                        end
                        -- store the data
                        local data = this.Data[insertPos]
                        data.Used = true
                        data.Icon = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_ICON_NORMAL, 0)
                        BlzFrameSetTexture(this.Frame[insertPos].Icon, data.Icon, 0, false)
                        data.Name = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL, 0)
                        data.Text = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL_EXTENDED, 0)
                        data.Mana = BlzGetAbilityIntegerLevelField(abi, ABILITY_ILF_MANA_COST, 0)
                        data.Cool = BlzGetAbilityRealLevelField(abi, ABILITY_RLF_COOLDOWN, 0)
                        data.Range = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, 0))
                        data.Area = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, 0))
                        if this.ShortBigNumber then
                            if data.Mana > 9999 then
                                data.Mana = string.format(this.TextFormat0, data.Mana/1000).."k"
                            end
                            if data.Range > 9999 then
                                data.Range = string.format(this.TextFormat0, data.Range/1000).."k"
                            end
                            if data.Area > 9999 then
                                data.Area = string.format(this.TextFormat0, data.Area/1000).."k"
                            end
                        end
                    end
                    addCount = addCount + 1
                end
            end
            abi = nil
        end
    end

    local LastHoveredIndex, LastUnit, LastUnitCode
    function this.TechFullFilled(player, skill)
        local data = this.TechReq[skill]
        if not data then return true end
        local lastIndex = #data
        for i=1,lastIndex,2 do
            if GetPlayerTechCount(player, data[i], true) < data[i + 1] then return false end
        end
    end
    
    function this.Update()
        -- check for visible buttons, if any is visible then do not show TasSpellView
        for i= 0, 11 do
            if BlzFrameIsVisible(BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, i)) then
                BlzFrameSetVisible(this.ParentSimple, false)
                BlzFrameSetVisible(this.Parent, false)
                LastUnit = nil
                return
            end
        end

        local foundTooltip = false
        local unit
        local localPlayer = GetLocalPlayer()
        local unitCode
        if not UnitInfoGetUnit then
            GroupEnumUnitsSelected(this.Group, localPlayer, nil)
            unit = FirstOfGroup(this.Group)
            GroupClear(this.Group)
        else
            unit = UnitInfoPanelUnit
        end
        -- from this point you need to clear unit = nil !!!
        unitCode = GetUnitTypeId(unit)
        if unit ~= LastUnit or LastUnitCode ~= unitCode then
            -- happen only when a new unit is selected or the unit morphed
            LastUnit = unit
            LastUnitCode = unitCode
            this.GetUnitData(unit)
            LastHoveredIndex = -1
            for i = 0, 11 do
                local dataI = this.Data[i]
                local obj = this.Frame[i]
                BlzFrameSetVisible(obj.Button, dataI.Used)
                
                if dataI.FourCC <= 0 then
                    BlzFrameSetVisible(obj.Cooldown, false)
                    BlzFrameSetVisible(obj.OverLayFrame, false)
                else
                    BlzFrameSetVisible(obj.Cooldown, true)
                    BlzFrameSetVisible(obj.OverLayFrame, true)
                end
            end
        end
        local showSpellView
        if unitCode > 0 then
            local hasControl = IsUnitOwnedByPlayer(unit, localPlayer) or GetPlayerAlliance(GetOwningPlayer(unit), localPlayer, ALLIANCE_SHARED_CONTROL)
            showSpellView = not hasControl
            if showSpellView then showSpellView = this.ShowAllowed(unit, localPlayer) end
        else
            showSpellView = false
        end
        BlzFrameSetVisible(this.ParentSimple, showSpellView)
        BlzFrameSetVisible(this.Parent, showSpellView)
        if showSpellView then
            local stillShowLastTooltip = LastHoveredIndex >= 0 and BlzFrameIsVisible(this.Frame[LastHoveredIndex].SimpleTooltip)
            --print("stillShowLastTooltip",stillShowLastTooltip)
            local data = this.Data
            for i = 0, 11 do
                local dataI = data[i]
                local obj = this.Frame[i]
                if dataI.Used then
                    if dataI.FourCC > 0 then
                        local skill = dataI.FourCC
                        local level = GetUnitAbilityLevel(unit, skill)
                        if this.ShowCooldown then
                            local cdRemain = BlzGetUnitAbilityCooldownRemaining(unit, skill)
                            if cdRemain > 0 then
                                if this.ShowCooldownText then
                                    BlzFrameSetVisible(obj.TextCool, true)
                                    if cdRemain > 5 then
                                        BlzFrameSetText(obj.TextCool, string.format(this.TextFormat0, cdRemain))
                                    else
                                        BlzFrameSetText(obj.TextCool, string.format( this.TextFormat1, cdRemain))
                                    end
                                else
                                    BlzFrameSetVisible(obj.TextCool, false)
                                end
                                -- this be inaccurate when the map has systems to change cooldowns only during the casting.
                                local cdTotal = BlzGetUnitAbilityCooldown(unit, skill, level - 1)
                                --print(GetObjectName(skill),cdRemain,cdTotal, cdRemain/cdTotal)
                                BlzFrameSetVisible(obj.Cooldown, true)
                                BlzFrameSetValue(obj.Cooldown, 100-(cdRemain/cdTotal)*100)
                                --print(BlzFrameIsVisible(obj.Cooldown), BlzFrameGetValue(obj.Cooldown))
                            else
                                BlzFrameSetVisible(obj.TextCool, false)
                                BlzFrameSetVisible(obj.Cooldown, false)
                            end
                        else
                            BlzFrameSetVisible(obj.Cooldown, false)
                        end
                        
                        BlzFrameSetVisible(obj.OverLayFrame, true)
                        if not this.TechFullFilled(GetOwningPlayer(unit), skill) then BlzFrameSetText(obj.ChargeBoxText, this.TextDisallowed)
                        else BlzFrameSetText(obj.ChargeBoxText, level) end
                    end

                    -- hovered?
                    if not stillShowLastTooltip and not foundTooltip and BlzFrameIsVisible(obj.SimpleTooltip) then
                        foundTooltip = true
                        -- only update Tooltip when needed
                        if i ~= LastHoveredIndex then
                            LastHoveredIndex = i
                            BlzFrameSetTexture(thisTooltip.Icon, dataI.Icon, 0, false)
                            BlzFrameSetText(thisTooltip.Name, dataI.Name)
                            BlzFrameSetText(thisTooltip.Text, dataI.Text)
                            BlzFrameSetText(thisTooltip.TextMana, dataI.Mana)
                            BlzFrameSetText(thisTooltip.TextCool, dataI.Cool)
                            BlzFrameSetText(thisTooltip.TextRange, dataI.Range)
                            BlzFrameSetText(thisTooltip.TextArea, dataI.Area)
                        end
                    end
                end
            end
            BlzFrameSetVisible(thisTooltip.Frame, stillShowLastTooltip or foundTooltip)
        end
        unit = nil
    end

    local InitFramesCodeOnlyCreateButton = function(i, simpleButton)
        local obj = this.Frame[i]
        local frame
        local buttonFrame
        local overlayFrame
        buttonFrame = BlzCreateFrameByType("FRAME", "TasSpellViewButton", this.Parent, "", i)
        BlzFrameSetAllPoints(buttonFrame, simpleButton)
        obj.Button = buttonFrame
        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewButtonBackdrop", buttonFrame, "", i)
        BlzFrameSetAllPoints(frame, simpleButton)
        obj.Icon = frame
        overlayFrame = BlzCreateFrameByType("FRAME", "TasSpellViewButtonOverLayFrame", buttonFrame, "", i)
        BlzFrameSetAllPoints(frame, simpleButton)
        obj.OverLayFrame = overlayFrame
        frame = BlzCreateFrameByType("TEXT", "TasSpellViewButtonTextOverLay", overlayFrame, "", i)
        obj.OverLayText = frame
        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewButtonChargeBox", overlayFrame, "", i)
        obj.ChargeBox = frame
        BlzFrameSetSize(frame, 0.02, 0.02)
        BlzFrameSetTexture(frame, "UI/Widgets/Console/Human/CommandButton/human-button-lvls-overlay.blp", 0, true)
        BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, simpleButton, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
        frame = BlzCreateFrameByType("TEXT", "TasSpellViewButtonChargeText", overlayFrame, "", i)
        obj.ChargeBoxText = frame
        BlzFrameSetSize(frame, 0.02, 0.02)
        BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, simpleButton, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
        BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)
        frame = BlzCreateFrameByType("STATUSBAR", "TasSpellViewButtonCooldown", overlayFrame, "", i)
        obj.Cooldown = frame
        BlzFrameSetModel(frame, "UI/Feedback/Cooldown/UI-Cooldown-Indicator.mdl", 0)
        BlzFrameSetAllPoints(frame, simpleButton)
        BlzFrameSetVisible(frame, false)
        frame = BlzCreateFrameByType("TEXT", "TasSpellViewButtonCooldownText", frame, "TeamLadderRankValueTextTemplate", i)
        obj.TextCool = frame
        BlzFrameSetAllPoints(frame, simpleButton)
        BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)
    end

    local InitFramesCodeOnly = function()
        local  i
        local  frame
        local  frameB
        local  tooltipFrame
        this.ParentSimple = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewSimpleFrame", this.ParentFuncSimple(), "", 0)
        this.Parent = BlzCreateFrameByType("FRAME", "TasSpellViewFrame", this.ParentFunc(), "", 0)
        for i = 0, 11 do
            this.Frame[i] = {}
            frame = BlzCreateFrameByType("SIMPLEBUTTON", "TasSpellViewButtonCode", this.ParentSimple, "UpperButtonBarButtonTemplate", i)
            this.Frame[i].SimpleButton = frame
            BlzFrameSetPoint(frame, FRAMEPOINT_CENTER, BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, i), FRAMEPOINT_CENTER, 0, 0.0)
            BlzFrameSetSize(frame, 0.034, 0.034)
            BlzFrameSetLevel(frame, 6) -- reforged stuff
            BlzFrameSetAlpha(frame, 0)
            tooltipFrame = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewButtonToolTip", frame, "", i)
            this.Frame[i].SimpleTooltip = tooltipFrame
            BlzFrameSetTooltip(frame, tooltipFrame)
            BlzFrameSetVisible(tooltipFrame, false)

            InitFramesCodeOnlyCreateButton(i, frame)

        end

        -- create one ToolTip which shows data for current hovered inside a timer.
        -- also reserve handleIds to allow async usage
        tooltipFrame = BlzCreateFrameByType("FRAME", "TasSpellViewTooltipFrame", this.Parent, "", 0)
        thisTooltip.Frame = tooltipFrame
        --frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipBox", tooltipFrame, "QuestButtonDisabledBackdropTemplate", 0)
        frame = BlzCreateFrameByType("FRAME", "TasSpellViewTooltipBox", tooltipFrame, "Leaderboard", 0)
        thisTooltip.Box = frame

        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipIcon", tooltipFrame, "", 0)
        thisTooltip.Icon = frame
        BlzFrameSetSize(frame, 0.035, 0.035)

        frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipName", tooltipFrame, "TeamValueTextTemplate", 0)
        thisTooltip.Name = frame
        BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)

        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipSeperator", tooltipFrame, "", 0)
        thisTooltip.Sep = frame
        BlzFrameSetSize(frame, 0, 0.001)
        BlzFrameSetTexture(frame, "replaceabletextures/teamcolor/teamcolor08", 0, false)
        frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipText", tooltipFrame, "TeamValueTextTemplate", 0)
        thisTooltip.Text = frame

        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipManaIcon", tooltipFrame, "", 0)
        thisTooltip.IconMana = frame
        BlzFrameSetTexture(frame, "UI/Widgets/ToolTips/Human/ToolTipManaIcon.blp", 0, false)
        BlzFrameSetSize(frame, 0.015, 0.015)
        frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipManaText", tooltipFrame, "TeamValueTextTemplate", 0)
        thisTooltip.TextMana = frame
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconMana, FRAMEPOINT_RIGHT, 0.005, 0)

        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipCooldownIcon", tooltipFrame, "", 0)
        thisTooltip.IconCool = frame
        BlzFrameSetSize(frame, 0.015, 0.015)
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconMana, FRAMEPOINT_RIGHT, 0.042, 0)
        BlzFrameSetTexture(frame, "ui/widgets/battlenet/bnet-tournament-clock", 0, false)

        frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipCooldownText", tooltipFrame, "TeamValueTextTemplate", 0)
        thisTooltip.TextCool = frame
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconCool, FRAMEPOINT_RIGHT, 0.005, 0)

        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipRangeIcon", tooltipFrame, "", 0)
        thisTooltip.IconRange = frame
        BlzFrameSetSize(frame, 0.015, 0.015)
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconCool, FRAMEPOINT_RIGHT, 0.042, 0)
        BlzFrameSetTexture(frame, "replaceabletextures/commandbuttons/btnload", 0, false)

        frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipRangeText", tooltipFrame, "TeamValueTextTemplate", 0)
        thisTooltip.TextRange = frame
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconRange, FRAMEPOINT_RIGHT, 0.005, 0)

        frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipAreaIcon", tooltipFrame, "", 0)
        thisTooltip.IconArea = frame
        BlzFrameSetSize(frame, 0.015, 0.015)
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconRange, FRAMEPOINT_RIGHT, 0.042, 0)
        BlzFrameSetTexture(frame, "replaceabletextures/selection/spellareaofeffect_undead", 0, true)

        frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipAreaText", tooltipFrame, "TeamValueTextTemplate", 0)
        thisTooltip.TextArea = frame
        BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, thisTooltip.IconArea, FRAMEPOINT_RIGHT, 0.005, 0)
        

        BlzFrameSetPoint(thisTooltip.IconMana, FRAMEPOINT_BOTTOMLEFT, thisTooltip.Sep, FRAMEPOINT_TOPLEFT, 0, 0.005)

        BlzFrameSetPoint(thisTooltip.Sep, FRAMEPOINT_BOTTOMLEFT, thisTooltip.Text, FRAMEPOINT_TOPLEFT, 0, 0.005)
        BlzFrameSetPoint(thisTooltip.Sep, FRAMEPOINT_BOTTOMRIGHT, thisTooltip.Text, FRAMEPOINT_TOPRIGHT, 0, 0.005)

        BlzFrameSetPoint(thisTooltip.Name, FRAMEPOINT_TOPLEFT, thisTooltip.Icon, FRAMEPOINT_TOPRIGHT, 0.005, -0.002)
        BlzFrameSetPoint(thisTooltip.Name, FRAMEPOINT_BOTTOMRIGHT, thisTooltip.Sep, FRAMEPOINT_TOPRIGHT, -0.005, 0.021)

        BlzFrameSetPoint(thisTooltip.Icon, FRAMEPOINT_BOTTOMLEFT, thisTooltip.Sep, FRAMEPOINT_TOPLEFT, 0, 0.021)

        BlzFrameSetSize(thisTooltip.Text, this.ToolTipSizeX, 0)
        BlzFrameSetAbsPoint(thisTooltip.Text, this.ToolTipPos, this.ToolTipPosX, this.ToolTipPosY)
        BlzFrameSetPoint(thisTooltip.Box, FRAMEPOINT_TOPLEFT, thisTooltip.Icon, FRAMEPOINT_TOPLEFT, -0.009, 0.009)
        BlzFrameSetPoint(thisTooltip.Box, FRAMEPOINT_BOTTOMRIGHT, thisTooltip.Text, FRAMEPOINT_BOTTOMRIGHT, 0.009, -0.009)
        BlzFrameSetVisible(thisTooltip.Frame, false)

        BlzFrameSetVisible(this.ParentSimple, false)
        BlzFrameSetVisible(this.Parent, false)
    end

    local InitFrames = function()
        this.ParentSimple = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewSimpleFrame", this.ParentFuncSimple(), "", 0)
        this.Parent = BlzCreateFrameByType("FRAME", "TasSpellViewFrame", this.ParentFunc(), "", 0)
        for i = 0, 11 do
            this.Frame[i] = {}
            local obj = this.Frame[i]
            local frame = BlzCreateSimpleFrame("TasSpellViewButton", this.ParentSimple, i)
            obj.SimpleButton = frame
            obj.Button = frame
            BlzFrameSetPoint(frame, FRAMEPOINT_CENTER, BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, i), FRAMEPOINT_CENTER, 0, 0.0)
            local tooltipFrame = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewButtonToolTip", frame, "", i)
            obj.SimpleTooltip = tooltipFrame
            obj.OverLayFrame = BlzGetFrameByName("TasSpellViewButtonOverLayFrame", i)
            obj.Icon = BlzGetFrameByName("TasSpellViewButtonBackdrop", i)
            obj.OverLayText = BlzGetFrameByName("TasSpellViewButtonTextOverLay", i)
            obj.ChargeBox = BlzGetFrameByName("TasSpellViewButtonChargeBox", i)
            obj.ChargeBoxText = BlzGetFrameByName("TasSpellViewButtonChargeText", i)
            obj.Cooldown = BlzCreateFrame("TasSpellViewButtonCooldown", this.Parent, 0, i)
            obj.TextCool = BlzGetFrameByName("TasSpellViewButtonCooldownText", i)
            BlzFrameSetLevel(frame, 6) -- reforged stuff
            BlzFrameSetLevel(obj.OverLayFrame, 7) -- reforged stuff
            BlzFrameSetTooltip(frame, tooltipFrame)
            BlzFrameSetVisible(tooltipFrame, false)

            BlzFrameSetVisible(obj.Cooldown, false)

        end
        if  GetHandleId(BlzGetFrameByName("TasSpellViewButtonBackdrop", 1)) == 0 then
            print("|cffff0000TasSpellView - Error Create TasSpellViewButton|r")
            print("  Check Imported toc & fdf & TocPath in Map script")
            print("  Imported toc needs to have empty ending line")
            print("  fdf path in toc needs to match map imported path")
            print("  TocPath in Map script needs to match map imported path")
        end

        -- create one ToolTip which shows data for current hovered inside a timer.
        thisTooltip.Frame = BlzCreateFrame("TasSpellViewTooltipFrame", this.Parent, 0, 0)
        thisTooltip.Box = BlzGetFrameByName("TasSpellViewTooltipBox", 0)
        thisTooltip.Icon = BlzGetFrameByName("TasSpellViewTooltipIcon", 0)
        thisTooltip.Name = BlzGetFrameByName("TasSpellViewTooltipName", 0)
        thisTooltip.Sep = BlzGetFrameByName("TasSpellViewTooltipSeperator", 0)
        thisTooltip.Text = BlzGetFrameByName("TasSpellViewTooltipText", 0)
        thisTooltip.TextMana = BlzGetFrameByName("TasSpellViewTooltipManaText", 0)
        thisTooltip.TextCool = BlzGetFrameByName("TasSpellViewTooltipCooldownText", 0)
        thisTooltip.TextRange = BlzGetFrameByName("TasSpellViewTooltipRangeText", 0)
        thisTooltip.TextArea = BlzGetFrameByName("TasSpellViewTooltipAreaText", 0)
        
        BlzFrameSetSize(thisTooltip.Text, this.ToolTipSizeX, 0)
        BlzFrameSetAbsPoint(thisTooltip.Text, this.ToolTipPos, this.ToolTipPosX, this.ToolTipPosY)
        BlzFrameSetPoint(thisTooltip.Box, FRAMEPOINT_TOPLEFT, thisTooltip.Icon, FRAMEPOINT_TOPLEFT, -0.005, 0.005)
        BlzFrameSetPoint(thisTooltip.Box, FRAMEPOINT_BOTTOMRIGHT, thisTooltip.Text, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
        BlzFrameSetVisible(thisTooltip.Frame, false)

        
        BlzFrameSetVisible(this.ParentSimple, false)
        BlzFrameSetVisible(this.Parent, false)
        if  GetHandleId(thisTooltip.Frame) == 0 then
            print("TasSpellView - Error", "Create TasSpellViewTooltipFrame")
            print("Check Imported toc & fdf & TocPath")
        end
    end

    local InitFramesPre = function()
        if this.CodeOnly or not this.TocPath or this.TocPath == "" or not BlzLoadTOCFile(this.TocPath) then
            InitFramesCodeOnly()
        else
            InitFrames()
        end
    end
    function InitTasSpellView()
        for i= 0,11 do this.Data[i] = {} end
        this.Group = CreateGroup()
        this.Timer = CreateTimer()
        if not BlzGetAbilityId and this.IdData.Enabled and this.IdData.Enabled > 0 then
            -- Warcraft 3 V1.31.1 does not have BlzGetAbilityId, but i want to know the ability Ids of activ spells.
            local function ClearDeadSpells()
                for i=#this.IdData, 1,-1 do
                    abi = this.IdData[i]
                    skillCode = this.IdData[abi]
                    
                    local pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)*4
                    local posB = BlzGetAbilityPosX(skillCode) + BlzGetAbilityPosY(skillCode)*4
                    if pos ~= posB then
                        local lastIndex = #this.IdData
                        this.IdData[i] = this.IdData[lastIndex]
                        this.IdData[lastIndex] = nil
                        this.IdData[abi] = nil
                    end
                end
            end
            this.ClearDeadSpells = ClearDeadSpells

            this.TimerIdData = CreateTimer()
            TimerStart(this.TimerIdData, 20, true, ClearDeadSpells)

            local alocSkill = FourCC'Aloc'
            local function unitFilt(unit)
                if not BlzIsUnitSelectable(unit)
                 or IsUnitHidden(unit)
                 or GetUnitAbilityLevel(unit, alocSkill) > 0 then
                    return false
                end
                return true
            end
            local function addSkill(abi,skillCode)
                if this.IdData[abi] then return end
                local pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)*4
                if pos ~= 0 and BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y) ~= -11 then
                    if not this.IdData[abi] then table.insert(this.IdData, abi) end
                    this.IdData[abi] = skillCode
                end
            end

            if this.IdData.Enabled >= 3 then
                local realAddAbi = UnitAddAbility
                function UnitAddAbility(u, skillCode)
                    local returnValue = realAddAbi(u, skillCode)
                    if skillCode ~= alocSkill and unitFilt(u) then addSkill(BlzGetUnitAbility(u, skillCode),skillCode) end
                    return returnValue
                end
            end

            if this.IdData.Enabled >= 2 then
                this.TriggerId = CreateTrigger()
                TriggerAddAction(this.TriggerId, function()
                    if not unitFilt(GetTriggerUnit()) then return end
                    local skillCode = GetSpellAbilityId()
                    local abi = GetSpellAbility()
                    addSkill(abi,skillCode)
                end)
                TriggerRegisterAnyUnitEventBJ(this.TriggerId, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            end

            if this.IdData.Enabled >= 1 then
                this.TriggerId2 = CreateTrigger()
                TriggerAddAction(this.TriggerId2, function()
                    local skillCode = GetLearnedSkill()
                    local abi = BlzGetUnitAbility(GetTriggerUnit(), skillCode)
                    addSkill(abi,skillCode)
                end)
                TriggerRegisterAnyUnitEventBJ(this.TriggerId2, EVENT_PLAYER_HERO_SKILL)
            end
        end
        --TimerStart(this.Timer, this.UpdateTime, true,function()  xpcall(this.Update, print) end)
        TimerStart(this.Timer, this.UpdateTime, true, this.Update)
        InitFramesPre()
        if FrameLoaderAdd then FrameLoaderAdd(InitFramesPre) end
    end
    InitSpellView = InitTasSpellView
    if this.AutoRun then
        if OnInit then -- Total Initialization v5.2.0.1 by Bribe
            OnInit.final(InitTasSpellView)
        else -- without
            local real = MarkGameStarted
            function MarkGameStarted()
                real()
                InitTasSpellView()
            end
        end
    end
end
the vjass system
JASS:
library TasSpellView initializer init_function requires optional Ascii, optional FrameLoader
/* TasSpellView 1.2b  by Tasyen todo todo todo
displays with custom UI the abilites of not controled units in the command card

 when REFORGED = false you need to tell the abilityCodes used by units to have cooldown display
 the unit does not need to have the skills they are displayed when added that way.
 TasSpellView_AddUnitCodeData takes integer unitCode, string abiCodeString returns nothing
    call TasSpellView_AddUnitCodeData('Ulic', "AUfn,AUfu,AUdr,AUdd")
    this function requires Ascii
    
 TasSpellView_AddTechReq takes integer skill, integer tech, integer techLevel returns nothing
     call TasSpellView_AddTechReq('Ausm','Rusm',1)
     only the first entry for each skill is used
*/
    globals
        constant boolean REFORGED = false // have BlzGetAbilityId? otherwise false
        public boolean AutoRun = true //(true) will create Itself at 0s, (false) you need to InitSpellView()
        public string TocPath = "war3mapImported\\TasSpellView.toc" // when this fails or "" create by code.

        public string TextDisallowed = "X"

        public real UpdateTime = 0.1
        public boolean ShowCooldown = true // can be set async, needs BlzGetAbilityId for ability by index 
        public boolean ShowCooldownText = true // show remaining cooldown text overlay requires BlzGetAbilityId or setup in UnitSkills
        public boolean ShowAlly = true // can be set async, needs BlzGetAbilityId for ability by index 
        public boolean ShowEnemy = true // can see skills of enemies, includes hostile creeps
        public boolean ShowNeutral = true // can see skills of Neutral Players, includes hostile creeps
        public boolean ShowHero = true 
        public boolean UseCommandCardPos = true // display skills as object editor setup says, beaware each slot can only take 1 Skill
        public boolean UseCommandCardPosHero = true // ^^ for hero & hero-illusion
        public boolean ShortBigNumber = true // Display values greater than 9999, in thousands like 10k or 100k for Range,Mana,Area

        //ToolTip
        public real ToolTipSizeX = 0.26
        public real ToolTipPosX = 0.79
        public real ToolTipPosY = 0.165
        public framepointtype ToolTipPos = FRAMEPOINT_BOTTOMRIGHT

// currentSelected
        public integer array DataFourCC
        public string array DataMana
        public string array DataRange        
        public string array DataAoe
        public string array DataCool
        public string array DataName
        public string array DataText
        public string array DataIcon
        public boolean array DataUsed

        public framehandle ParentSimple
        public framehandle Parent

        public framehandle Tooltip
        public framehandle TooltipBox
        public framehandle TooltipIcon
        public framehandle TooltipName
        public framehandle TooltipSep
        public framehandle TooltipText
        public framehandle TooltipTextMana
        public framehandle TooltipTextRange
        public framehandle TooltipTextArea
        public framehandle TooltipTextCool

        public group Group
        public timer Timer

        public framehandle array Button
        public framehandle array Icon
        public framehandle array OverLayFrame
        public framehandle array OverLayText
        public framehandle array ChargeBox
        public framehandle array ChargeBoxText
        public framehandle array Cooldown
        public framehandle array TextCool
        public framehandle array SimpleButton
        public framehandle array SimpleTooltip


        public unit LastUnit = null
        public integer LastUnitCode = 0
        public integer LastHoveredIndex = -1
        


        public string array UnitCodeText
        public integer array UnitCodeType
        public integer UnitCodeCount = 0

        public integer TechCodeCount = 0
        public integer array TechCodeSkill
        public integer array TechCodeTech
        public integer array TechCodeTechLevel
    endglobals


    public function ParentFuncSimple takes nothing returns framehandle
        if GetHandleId(BlzGetFrameByName("CommandBarFrame", 0)) > 0 then
            return BlzGetFrameByName("CommandBarFrame",  0)
        endif
        return BlzGetFrameByName("ConsoleUI", 0)
    endfunction
    public function ParentFunc takes nothing returns framehandle
       // if GetHandleId(BlzGetFrameByName("ConsoleUIBackdrop", 0)) > 0 then
       //     return BlzGetFrameByName("ConsoleUIBackdrop",  0)
       // endif
        return BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0) 
    endfunction

    public function AbiFilter takes ability abi, string text returns boolean
        local integer pos
        local integer posY
        if BlzGetAbilityBooleanField(abi, ABILITY_BF_ITEM_ABILITY) then
            return false
        endif
        set posY = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)
        if posY == -11 then
             return false
        endif
        set pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + posY*4
        if pos < 0 or pos > 11 then
            return false
        endif
        if text == "Tool tip missing!" or text == "" or text == " " then
            return false
        endif
        return true
    endfunction

    public function GetTechReq takes integer skill returns integer
        local integer i = TechCodeCount
        loop            
            exitwhen i <= 0
            if skill == TechCodeSkill[i] then
                return i
            endif
            set i = i - 1
        endloop
        return -1
    endfunction

    public function AddTechReq takes integer skill, integer tech, integer techLevel returns nothing
        set TechCodeCount = TechCodeCount + 1
        set TechCodeSkill[TechCodeCount] = skill
        set TechCodeTech[TechCodeCount] = tech
        set TechCodeTechLevel[TechCodeCount] = techLevel
    endfunction

    public function TechFullFilled takes player p, integer skill returns boolean
        local integer data = GetTechReq(skill)
        if data <= 0 then
            return true
        else
            return GetPlayerTechCount(p, TechCodeTech[data], true) >= TechCodeTechLevel[data] 
        endif
    endfunction
    
    public function AddUnitCodeData takes integer unitCode, string abiCodeString returns nothing        
        set UnitCodeCount = UnitCodeCount + 1
        set UnitCodeType[UnitCodeCount] = unitCode
        set UnitCodeText[UnitCodeCount] = abiCodeString
    endfunction

    
    public function GetUnitCodeData takes integer unitCode returns string
        local integer i = UnitCodeCount
        loop            
            exitwhen i <= 0
            if unitCode == UnitCodeType[i] then
                return UnitCodeText[i]
            endif
            set i = i - 1
        endloop
        return ""
    endfunction
    public function ShowAllowed takes unit u, player localPlayer returns boolean
        local integer controlType = GetHandleId(GetPlayerController(GetOwningPlayer(u))) // user = 0 computer = 1, treat all above as Neutral
        if ShowNeutral and controlType >= 2 then 
            return true 
        endif

        if not ShowAlly and IsUnitAlly(u, localPlayer) then
             return false 
        endif
        if not ShowEnemy and IsUnitEnemy(u, localPlayer) then
             return false 
        endif
        if not ShowHero and IsHeroUnitId(GetUnitTypeId(u)) then 
            return false 
        endif

        return true
    endfunction
public function GetUnitDataAddSkill takes unit u, integer index, integer skill returns nothing
        local integer i = index        
        local ability abi = BlzGetUnitAbility(u, skill)
        local integer level = GetUnitAbilityLevel(u, skill)
        local integer mana
        local integer range
        local integer aoe

        set DataFourCC[i] = skill
        set DataUsed[i] = true
        set DataIcon[i] = BlzGetAbilityIcon(skill)
        call BlzFrameSetTexture(Icon[i], DataIcon[i], 0, false)

        if level > 0 then
            set mana = BlzGetUnitAbilityManaCost(u, skill, level - 1)
            set DataCool[i] = I2S(R2I(BlzGetUnitAbilityCooldown(u, skill, level - 1)))
            set range = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, level - 1))
            set aoe = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, level - 1))
            set DataName[i] = BlzGetAbilityTooltip(skill, level - 1)
            set DataText[i] = BlzGetAbilityExtendedTooltip(skill, level - 1)
        else
            set DataName[i] =  BlzGetAbilityResearchTooltip(skill, 0)
            set DataText[i] = BlzGetAbilityResearchExtendedTooltip(skill, 0)
            set mana = BlzGetAbilityManaCost(skill, 0)
            set DataCool[i] = I2S(R2I(BlzGetAbilityCooldown(skill, 0)))
            set range = 0
            set aoe = 0
        endif
        set DataMana[i] = I2S(mana)
        set DataRange[i] = I2S(range)
        set DataAoe[i] = I2S(aoe)
        if ShortBigNumber then
            if mana > 9999 then
                set DataMana[i] = I2S(mana/1000)+"k"
            endif
            if range > 9999 then
                set DataRange[i] = I2S(range/1000)+"k"
            endif
            if aoe > 9999 then
                set DataAoe[i] = I2S(aoe/1000)+"k"
            endif
        endif
        set abi = null
    endfunction
static if LIBRARY_Ascii then
    public function AddSpellString takes string abiString, boolean commandCardPos returns nothing
        local integer startIndex = 0
        local integer skillCode
        local integer addCount = 0
        local integer pos = 0
        loop
        exitwhen startIndex + 3 >= StringLength(abiString)
            set skillCode = S2A(SubString(abiString, startIndex, startIndex + 4))
            set startIndex = startIndex + 5
            if commandCardPos then
                set pos = BlzGetAbilityPosX(skillCode) + BlzGetAbilityPosY(skillCode)*4
                if pos >= 0 and pos <= 11 then 
                    set DataFourCC[pos] = skillCode
                endif
            else
                set DataFourCC[addCount] = skillCode
                set addCount = addCount + 1
            endif            
        endloop
    endfunction
endif

    public function GetUnitData takes unit u returns nothing
        local integer i = 0
        local integer addCount = 0
        local integer insertPos
        local integer pos
        local ability abi
        local string abiString
        local integer unitCode = GetUnitTypeId(u)
        local boolean isHero = IsHeroUnitId(unitCode)
        local boolean commandCardPos = (not isHero and UseCommandCardPos) or (isHero and UseCommandCardPosHero)
        local integer mana
        local integer range
        local integer aoe
        loop
            exitwhen i > 11
            set DataFourCC[i] = 0
            set DataUsed[i] = false
            set i = i + 1
        endloop
        if unitCode <= 0 then
            return 
        endif

        // have presaved Data
        set abiString = GetUnitCodeData(GetUnitTypeId(u))
        if abiString != "" then
            static if LIBRARY_Ascii then
                call AddSpellString(abiString, commandCardPos)
            endif
            set i = 0
            loop
                exitwhen i > 11
                if DataFourCC[i] > 0 then
                    call GetUnitDataAddSkill(u, i, DataFourCC[i])
                endif
                set i = i + 1
            endloop
        else
            set i = 0
            set addCount = 0
            loop        
                set abi = BlzGetUnitAbilityByIndex(u, i)
                exitwhen abi == null
                exitwhen i > 9999
                exitwhen addCount > 11
                if AbiFilter(abi, BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL, 0)) then
                    static if REFORGED then
                        // store abiCode treat it like MOD_ABI_CODE
                        if commandCardPos then
                            set pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)*4
                            if pos >= 0 and pos <= 11 then
                                set DataFourCC[pos] = BlzGetAbilityId(abi)
                            endif
                        else
                            set DataFourCC[addCount] = BlzGetAbilityId(abi)
                        endif
                        set i = 0
                        loop
                            exitwhen i > 11
                            if DataFourCC[i] > 0 then
                                call GetUnitDataAddSkill(u, i, DataFourCC[i])
                            endif
                            set i = i + 1
                        endloop
                    else
                        set insertPos = addCount
                        if commandCardPos then
                            set pos = BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_X) + BlzGetAbilityIntegerField(abi, ABILITY_IF_BUTTON_POSITION_NORMAL_Y)*4
                            if pos >= 0 and pos <= 11 then
                             set insertPos = pos 
                            endif
                        endif
                        // store the data
                        set DataUsed[insertPos] = true
                        set DataIcon[insertPos] = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_ICON_NORMAL, 0)
                        call BlzFrameSetTexture(Icon[insertPos], DataIcon[insertPos], 0, false)
                        set DataName[insertPos] = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL, 0)
                        set DataText[insertPos] = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL_EXTENDED, 0)
                        set mana = BlzGetAbilityIntegerLevelField(abi, ABILITY_ILF_MANA_COST, 0)
                        set DataCool[insertPos] = R2SW(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_COOLDOWN, 0),1,1)
                        set range = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, 0))
                        set aoe = R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, 0))

                        set DataMana[insertPos] = I2S(mana)
                        set DataRange[insertPos] = I2S(range)
                        set DataAoe[insertPos] = I2S(aoe)
                        if ShortBigNumber then
                            if mana > 9999 then
                                set DataMana[insertPos] = I2S(mana/1000)+"k"
                            endif
                            if range > 9999 then
                                set DataRange[insertPos] = I2S(range/1000)+"k"
                            endif
                            if aoe > 9999 then
                                set DataAoe[insertPos] = I2S(aoe/1000)+"k"
                            endif
                        endif
                    endif
                    
                    set addCount = addCount + 1
                endif
                set i = i + 1
            endloop
            set abi = null
        endif
    endfunction

    public function Update takes nothing returns nothing
        local boolean foundTooltip = false
        local unit u
        local boolean hasControl
        local boolean showSpellView
        local boolean stillShowLastTooltip
        local integer i
        local integer level
        local real cdRemain
        local real cdTotal
        local integer abiCode
        local ability abi
        local integer uCode
        // check for visible buttons, if any is visible then do not show TasSpellView
        set i = 0
        loop
            if BlzFrameIsVisible(BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, i)) then
                call BlzFrameSetVisible(ParentSimple, false)
                call BlzFrameSetVisible(Parent, false)
                return
            endif
            exitwhen i == 11
            set i = i + 1
        endloop
        
        call GroupEnumUnitsSelected(Group, GetLocalPlayer(), null)
        set u = FirstOfGroup(Group)
        call GroupClear(Group)
        set uCode = GetUnitTypeId(u)
        if u != LastUnit or LastUnitCode != uCode then
            set LastUnit = u
            set LastUnitCode = uCode
            call GetUnitData(u)
            set i = 0
            set LastHoveredIndex = -1
            loop
                call BlzFrameSetVisible(Button[i], DataUsed[i])
                if DataFourCC[i] > 0  then
                    call BlzFrameSetVisible(Cooldown[i], true)
                    call BlzFrameSetVisible(OverLayFrame[i], true)
                else
                    call BlzFrameSetVisible(Cooldown[i], false)
                    call BlzFrameSetVisible(OverLayFrame[i], false)
                endif              
                exitwhen i == 11
                set i = i + 1
            endloop
        endif

        if uCode > 0 then
            set hasControl = IsUnitOwnedByPlayer(u, GetLocalPlayer()) or GetPlayerAlliance(GetOwningPlayer(u), GetLocalPlayer(), ALLIANCE_SHARED_CONTROL)
            // user = 0 computer = 1, treat all above as Neutral
            set showSpellView = not hasControl
            if showSpellView then
                set showSpellView = ShowAllowed(u, GetLocalPlayer())
            endif
        else
            set showSpellView = false
        endif
        call BlzFrameSetVisible(ParentSimple, showSpellView)
        call BlzFrameSetVisible(Parent, showSpellView)
        if showSpellView then
            set stillShowLastTooltip = LastHoveredIndex >= 0 and BlzFrameIsVisible(SimpleTooltip[LastHoveredIndex])
            set i = 0
            loop
                if DataUsed[i] then 
                    if DataFourCC[i] > 0 then
                        set abiCode = DataFourCC[i]
                        set level = GetUnitAbilityLevel(u, abiCode)

                        if ShowCooldown then
                            set cdRemain = BlzGetUnitAbilityCooldownRemaining(u, abiCode)
                            if cdRemain > 0 then
                                if ShowCooldownText then
                                    call BlzFrameSetVisible(TextCool[i], true)
                                    if cdRemain > 5 then
                                        call BlzFrameSetText(TextCool[i], I2S(R2I(cdRemain)))
                                    else
                                        call BlzFrameSetText(TextCool[i], R2SW(cdRemain,1,1))
                                    endif
                                else
                                    call BlzFrameSetVisible(TextCool[i], false)
                                endif
                                // this be inaccurate when the map has systems to change cooldowns only during the casting.
                                set cdTotal = BlzGetUnitAbilityCooldown(u, abiCode, level - 1)
                                call BlzFrameSetVisible(Cooldown[i], true)
                                call BlzFrameSetValue(Cooldown[i], 100-(cdRemain/cdTotal)*100)
                            else
                                call BlzFrameSetVisible(Cooldown[i], false)
                                call BlzFrameSetVisible(TextCool[i], false)
                            endif
                        else
                            call BlzFrameSetVisible(Cooldown[i], false)
                        endif
                        
                        call BlzFrameSetVisible(OverLayFrame[i], true)
                        call BlzFrameSetText(ChargeBoxText[i], I2S(level))
                        if not TechFullFilled(GetOwningPlayer(u), abiCode) then
                            call BlzFrameSetText(ChargeBoxText[i], TextDisallowed)
                        else
                            call BlzFrameSetText(ChargeBoxText[i], I2S(level))
                        endif
                    endif

                    // hovered?
                    if not stillShowLastTooltip and not foundTooltip and BlzFrameIsVisible(SimpleTooltip[i]) then
                        set foundTooltip = true
                        if i != LastHoveredIndex then
                            set LastHoveredIndex = i
                            call BlzFrameSetTexture(TooltipIcon, DataIcon[i], 0, false)
                            call BlzFrameSetText(TooltipName, DataName[i])
                            call BlzFrameSetText(TooltipText, DataText[i])
                            call BlzFrameSetText(TooltipTextMana, DataMana[i])
                            call BlzFrameSetText(TooltipTextCool, DataCool[i])
                            call BlzFrameSetText(TooltipTextRange, DataRange[i])
                            call BlzFrameSetText(TooltipTextArea, DataAoe[i])
                        endif
                    endif
                endif

                
                exitwhen i == 11
                set i = i + 1
            endloop
            call BlzFrameSetVisible(Tooltip , stillShowLastTooltip or foundTooltip)
        endif
        set u = null
        set abi = null
    endfunction



    public function InitFramesCodeOnlyCreateButton takes integer i, framehandle simpleButton returns nothing
        local framehandle frame
        local framehandle buttonFrame
        local framehandle overlayFrame
        set buttonFrame = BlzCreateFrameByType("FRAME", "TasSpellViewButton", Parent, "", i)
        set Button[i] = buttonFrame
        call BlzFrameSetAllPoints(buttonFrame, simpleButton)
        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewButtonBackdrop", buttonFrame, "", i)
        set Icon[i] = frame
        call BlzFrameSetAllPoints(frame, simpleButton)
        set overlayFrame = BlzCreateFrameByType("FRAME", "TasSpellViewButtonOverLayFrame", buttonFrame, "", i)
        call BlzFrameSetAllPoints(frame, simpleButton)
        set OverLayFrame[i] = overlayFrame
        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewButtonTextOverLay", overlayFrame, "", i)
        set OverLayText[i] = frame
        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewButtonChargeBox", overlayFrame, "", i)
        set ChargeBox[i] = frame
        call BlzFrameSetSize(frame, 0.02, 0.02)
        call BlzFrameSetTexture(frame, "UI/Widgets/Console/Human/CommandButton/human-button-lvls-overlay.blp", 0, true)
        call BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, simpleButton, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewButtonChargeText", overlayFrame, "", i)
        set ChargeBoxText[i] = frame
        call BlzFrameSetSize(frame, 0.02, 0.02)
        call BlzFrameSetPoint(frame, FRAMEPOINT_BOTTOMRIGHT, simpleButton, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
        call BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)
        set frame = BlzCreateFrameByType("STATUSBAR", "TasSpellViewButtonCooldown", overlayFrame, "", i)
        set Cooldown[i] = frame
        call BlzFrameSetModel(frame, "UI/Feedback/Cooldown/UI-Cooldown-Indicator.mdl", 0)
        call BlzFrameSetAllPoints(frame, simpleButton)
        call BlzFrameSetVisible(frame, false)
        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewButtonCooldownText", frame, "TeamLadderRankValueTextTemplate", i)
        set TextCool[i] = frame
        call BlzFrameSetAllPoints(frame, simpleButton)
        call BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)
    endfunction

    public function InitFramesCodeOnly takes nothing returns nothing
        local integer i
        local framehandle frame
        local framehandle frameB
        local framehandle tooltipFrame
        
        set ParentSimple = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewSimpleFrame", ParentFuncSimple(), "", 0)
        set Parent = BlzCreateFrameByType("FRAME", "TasSpellViewFrame", ParentFunc(), "", 0)
        set i = 0
        loop
            //set frame = BlzCreateSimpleFrame("TasSpellViewButton", ParentSimple, i)
            set frame = BlzCreateFrameByType("SIMPLEBUTTON", "TasSpellViewButtonCode", ParentSimple, "UpperButtonBarButtonTemplate", i)
            set SimpleButton[i] = frame
            call BlzFrameSetPoint(frame, FRAMEPOINT_CENTER, BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, i), FRAMEPOINT_CENTER, 0, 0.0)
            call BlzFrameSetSize(frame, 0.034, 0.034)
            call BlzFrameSetLevel(frame, 6) // reforged stuff
            call BlzFrameSetAlpha(frame, 0)
            set tooltipFrame = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewButtonToolTip", frame, "", i)
            call BlzFrameSetTooltip(frame, tooltipFrame)
            call BlzFrameSetVisible(tooltipFrame, false)
            set SimpleTooltip[i] = tooltipFrame

            call InitFramesCodeOnlyCreateButton(i, frame)

            set i = i + 1
            exitwhen i > 11
        endloop

        // create one ToolTip which shows data for current hovered inside a timer.
        // also reserve handleIds to allow async usage
        set tooltipFrame = BlzCreateFrameByType("FRAME", "TasSpellViewTooltipFrame", Parent, "", 0)
        set Tooltip = tooltipFrame
        //set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipBox", tooltipFrame, "QuestButtonDisabledBackdropTemplate", 0)
        set frame = BlzCreateFrameByType("FRAME", "TasSpellViewTooltipBox", tooltipFrame, "Leaderboard", 0)
        set TooltipBox = frame

        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipIcon", tooltipFrame, "", 0)
        set TooltipIcon = frame
        call BlzFrameSetSize(frame, 0.035, 0.035)

        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipName", tooltipFrame, "TeamValueTextTemplate", 0)
        set TooltipName = frame
        call BlzFrameSetTextAlignment(frame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)

        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipSeperator", tooltipFrame, "", 0)
        set TooltipSep = frame
        call BlzFrameSetSize(frame, 0, 0.001)
        call BlzFrameSetTexture(frame, "replaceabletextures/teamcolor/teamcolor08", 0, false)
        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipText", tooltipFrame, "TeamValueTextTemplate", 0)
        set TooltipText = frame

        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipManaIcon", tooltipFrame, "", 0)
        call BlzFrameSetTexture(frame, "UI/Widgets/ToolTips/Human/ToolTipManaIcon.blp", 0, false)
        call BlzFrameSetSize(frame, 0.015, 0.015)
        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipManaText", tooltipFrame, "TeamValueTextTemplate", 0)
        set TooltipTextMana = frame
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipManaIcon", 0), FRAMEPOINT_RIGHT, 0.005, 0)

        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipCooldownIcon", tooltipFrame, "", 0)
        call BlzFrameSetSize(frame, 0.015, 0.015)
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipManaIcon", 0), FRAMEPOINT_RIGHT, 0.042, 0)
        call BlzFrameSetTexture(frame, "ui/widgets/battlenet/bnet-tournament-clock", 0, false)

        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipCooldownText", tooltipFrame, "TeamValueTextTemplate", 0)
        set TooltipTextCool = frame
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipCooldownIcon", 0), FRAMEPOINT_RIGHT, 0.005, 0)

        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipRangeIcon", tooltipFrame, "", 0)
        call BlzFrameSetSize(frame, 0.015, 0.015)
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipCooldownIcon", 0), FRAMEPOINT_RIGHT, 0.042, 0)
        call BlzFrameSetTexture(frame, "replaceabletextures/commandbuttons/btnload", 0, false)

        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipRangeText", tooltipFrame, "TeamValueTextTemplate", 0)
        set TooltipTextRange = frame
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipRangeIcon", 0), FRAMEPOINT_RIGHT, 0.005, 0)

        set frame = BlzCreateFrameByType("BACKDROP", "TasSpellViewTooltipAreaIcon", tooltipFrame, "", 0)
        call BlzFrameSetSize(frame, 0.015, 0.015)
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipRangeIcon", 0), FRAMEPOINT_RIGHT, 0.042, 0)
        call BlzFrameSetTexture(frame, "replaceabletextures/selection/spellareaofeffect_undead", 0, true)

        set frame = BlzCreateFrameByType("TEXT", "TasSpellViewTooltipAreaText", tooltipFrame, "TeamValueTextTemplate", 0)
        set TooltipTextArea = frame
        call BlzFrameSetPoint(frame, FRAMEPOINT_LEFT, BlzGetFrameByName("TasSpellViewTooltipAreaIcon", 0), FRAMEPOINT_RIGHT, 0.005, 0)
        

        call BlzFrameSetPoint(BlzGetFrameByName("TasSpellViewTooltipManaIcon", 0), FRAMEPOINT_BOTTOMLEFT, TooltipSep, FRAMEPOINT_TOPLEFT, 0, 0.005)

        call BlzFrameSetPoint(TooltipSep, FRAMEPOINT_BOTTOMLEFT, TooltipText, FRAMEPOINT_TOPLEFT, 0, 0.005)
        call BlzFrameSetPoint(TooltipSep, FRAMEPOINT_BOTTOMRIGHT, TooltipText, FRAMEPOINT_TOPRIGHT, 0, 0.005)

        call BlzFrameSetPoint(TooltipName, FRAMEPOINT_TOPLEFT, TooltipIcon, FRAMEPOINT_TOPRIGHT, 0.005, -0.002)
        call BlzFrameSetPoint(TooltipName, FRAMEPOINT_BOTTOMRIGHT, TooltipSep, FRAMEPOINT_TOPRIGHT, -0.005, 0.021)

        call BlzFrameSetPoint(TooltipIcon, FRAMEPOINT_BOTTOMLEFT, TooltipSep, FRAMEPOINT_TOPLEFT, 0, 0.021)

        call BlzFrameSetSize(TooltipText, ToolTipSizeX, 0)
        call BlzFrameSetAbsPoint(TooltipText, ToolTipPos, ToolTipPosX, ToolTipPosY)
        call BlzFrameSetPoint(TooltipBox, FRAMEPOINT_TOPLEFT, TooltipIcon, FRAMEPOINT_TOPLEFT, -0.009, 0.009)
        call BlzFrameSetPoint(TooltipBox, FRAMEPOINT_BOTTOMRIGHT, TooltipText, FRAMEPOINT_BOTTOMRIGHT, 0.009, -0.009)
        call BlzFrameSetVisible(Tooltip, false)

        call BlzFrameSetVisible(ParentSimple, false)
        call BlzFrameSetVisible(Parent, false)
    endfunction

    public function InitFrames takes nothing returns nothing
        local integer i
        local framehandle frame
        local framehandle tooltipFrame
        if not BlzLoadTOCFile(TocPath) then
            call BJDebugMsg("|cffff0000TasSpellView - Error Reading Toc File at: " + TocPath)
        endif
        set ParentSimple = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewSimpleFrame", ParentFuncSimple(), "", 0)
        set Parent = BlzCreateFrameByType("FRAME", "TasSpellViewFrame", ParentFunc(), "", 0)
        set i = 0
        loop
            set frame = BlzCreateSimpleFrame("TasSpellViewButton", ParentSimple, i)
            set SimpleButton[i] = frame
            set Button[i] = frame
            call BlzFrameSetPoint(frame, FRAMEPOINT_CENTER, BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, i), FRAMEPOINT_CENTER, 0, 0.0)
            call BlzFrameSetLevel(frame, 6) // reforged stuff
            set OverLayFrame[i] = BlzGetFrameByName("TasSpellViewButtonOverLayFrame", i)
            call BlzFrameSetLevel(OverLayFrame[i], 7) // reforged stuff
            set tooltipFrame = BlzCreateFrameByType("SIMPLEFRAME", "TasSpellViewButtonToolTip", frame, "", i)
            call BlzFrameSetTooltip(frame, tooltipFrame)
            call BlzFrameSetVisible(tooltipFrame, false)
            set SimpleTooltip[i] = tooltipFrame

            set Cooldown[i] = BlzCreateFrame("TasSpellViewButtonCooldown", Parent, 0, i)

            call BlzFrameSetVisible(Cooldown[i], false)
            // reserve HandleIds
            set TextCool[i] = BlzGetFrameByName("TasSpellViewButtonCooldownText", i)
            set Icon[i] = BlzGetFrameByName("TasSpellViewButtonBackdrop", i)
            set OverLayText[i] = BlzGetFrameByName("TasSpellViewButtonTextOverLay", i)            
            
            set ChargeBox[i] = BlzGetFrameByName("TasSpellViewButtonChargeBox", i)
            set ChargeBoxText[i] = BlzGetFrameByName("TasSpellViewButtonChargeText", i)
            set i = i + 1
            exitwhen i > 11
        endloop
        if GetHandleId(Icon[1]) == 0 then
            call BJDebugMsg("|cffff0000TasSpellView - Error Create TasSpellViewButton|r")
            call BJDebugMsg("  Check Imported toc & fdf & TocPath in Map script")
            call BJDebugMsg("  Imported toc needs to have empty ending line")
            call BJDebugMsg("  fdf path in toc needs to match map imported path")
            call BJDebugMsg("  TocPath in Map script needs to match map imported path")
        endif
        
        // create one ToolTip which shows data for current hovered inside a timer.
        // also reserve handleIds to allow async usage
        set Tooltip = BlzCreateFrame("TasSpellViewTooltipFrame", Parent, 0, 0)
        set TooltipBox = BlzGetFrameByName("TasSpellViewTooltipBox", 0)
        set TooltipIcon = BlzGetFrameByName("TasSpellViewTooltipIcon", 0)
        set TooltipName = BlzGetFrameByName("TasSpellViewTooltipName", 0)
        set TooltipSep = BlzGetFrameByName("TasSpellViewTooltipSeperator", 0)
        set TooltipText = BlzGetFrameByName("TasSpellViewTooltipText", 0)
        set TooltipTextMana = BlzGetFrameByName("TasSpellViewTooltipManaText", 0)
        set TooltipTextCool = BlzGetFrameByName("TasSpellViewTooltipCooldownText", 0)
        set TooltipTextRange = BlzGetFrameByName("TasSpellViewTooltipRangeText", 0)
        set TooltipTextArea = BlzGetFrameByName("TasSpellViewTooltipAreaText", 0)

        call BlzFrameSetSize(TooltipText, ToolTipSizeX, 0)
        call BlzFrameSetAbsPoint(TooltipText, ToolTipPos, ToolTipPosX, ToolTipPosY)
        call BlzFrameSetPoint(TooltipBox, FRAMEPOINT_TOPLEFT, TooltipIcon, FRAMEPOINT_TOPLEFT, -0.005, 0.005)
        call BlzFrameSetPoint(TooltipBox, FRAMEPOINT_BOTTOMRIGHT, TooltipText, FRAMEPOINT_BOTTOMRIGHT, 0.005, -0.005)
        call BlzFrameSetVisible(Tooltip, false)

        
        call BlzFrameSetVisible(ParentSimple, false)
        call BlzFrameSetVisible(Parent, false)
        if GetHandleId(Tooltip) == 0 then
            call BJDebugMsg("TasSpellView - Error - Create TasSpellViewTooltipFrame")
            call BJDebugMsg("Check Imported toc & fdf & TocPath")
        endif
    endfunction

    public function InitFramesPre takes nothing returns nothing
        if TocPath == null or TocPath == "" or not BlzLoadTOCFile(TocPath) then
            call InitFramesCodeOnly()
        else
            call InitFrames()
        endif
    endfunction
    function InitSpellView takes nothing returns nothing
        set Group = CreateGroup()
        set Timer = CreateTimer()
        call TimerStart(Timer, UpdateTime, true, function Update)
        call InitFramesPre()
        static if LIBRARY_FrameLoader then
            call FrameLoaderAdd(function InitFramesPre)
        endif
    endfunction

    private function init_function takes nothing returns nothing
        local real a = 5.1
        local integer i = 9999
        //reserve cooldown texts
        loop
            exitwhen i < 0
            set i = i - 1
            set a = a -0.1
            call R2SW(a,1,1)
            call I2S(i)
        endloop

        if AutoRun then
            call InitSpellView()
        endif
    endfunction
endlibrary


How to install


Requiers Warcraft 3 1.31+ or higher
Copy from the Lua script above, done

Or
  • Copy TasSpellView Map Script (trigger Editor).
  • export (without fdf/toc you get a black box instead of glass like tooltip box)
    • war3mapImported\TasSpellView.fdf
    • war3mapImported\TasSpellView.toc
    • WHEN USING THE EXPORT ALL BUTTON, IT CAN HAPPEN THAT THE CONTENT OF THIS FILES SWAP
    • import them into your map
  • Installed


ChangeLog


V1.2a) vjass version got most of V1.2 Lua
V1.2 Lua) performs better, UseCommandCardPosHero, ShortBigNumber, detect FourCC in Warcraft 3 V1.31.1
V1.1h) empty button tooltip Fix
V1.1g) fdf/Toc are optional
V1.1f) vjass updated, morph fix
V1.1d) (Lua) Only for some units, TechReq, Cooldown Text
V1.1c) buttonOverlay use ui scale options
V1.1b) vjass fixed a desync reason
V1.1a) added vjass Version
V1.1 First Release​
Previews
Contents

TasSpellView (Map)

TasSpellView (Map)

Updated to V1.1b)
vjass
Fixed a desync reason (Removed ReplayDetection it entered the game in async context which would lead to a dc when not all players were forced to select an unit in the begining)
considers FrameLoader (Warcraft 3 Save&Load)
Fixed the jass AddUnitCodeData example
 
This has so much potential , i wish it could be used on your own units or that has a way to customize it for certain units
(gui friendly would be a bless)
 
You mean like a custom tooltip system. meh that is not so easy or clean to do.

Because the map script api lacks something to know what uses a command button or what is displayed in the tooltip. Therefore one needs to guess it. The guess can fail, and group selection makes it more taxing/incorrect also excludes Warcraft3 V1.31.1 cause V1.31.1 cant know the current main selected unit in group selection, most of my stuff targets V1.31.1.
 
Uploaded V1.1c)
now uses the ui scale options for the command button overlay, that was done by adding a new default simple parent option. The tooltip will not scale.

It is only one line of change, if you want to change by yourself:
Lua:
,ParentFuncSimple = function()
            if GetHandleId(BlzGetFrameByName("CommandBarFrame", 0)) > 0 then return BlzGetFrameByName("CommandBarFrame",  0) end
            return BlzGetFrameByName("ConsoleUI", 0)
 end

JASS:
public function ParentFuncSimple takes nothing returns framehandle
        if GetHandleId(BlzGetFrameByName("CommandBarFrame", 0)) > 0 then
            return BlzGetFrameByName("CommandBarFrame",  0)
        endif
        return BlzGetFrameByName("ConsoleUI", 0)
    endfunction
 
Updated Lua version to V1.1d) according to a request
One can disable showing skills for Enemey, Ally, Neutral and Hero. (neutral hostile is is shown when enemy or Neutral is enabled). One can further customize it in a Lua function.
Skills can have a TechReq, need manual setup. Includes Melee Ability Req for Warcraft 3 V1.31.1. When a TechReq is not fullfilled it shows an X instead of the Level in the chargebox.
Can Show Cooldown as Text
Skills can now be displayed in the slot choosen in object Editor. Taking 1 slot twice shows less skills.

Includes a new fdf

Edit: small Hotfix V1.1e) forgot return true in TechReq.
 
Last edited:
Updated to V1.1g)
Does now work without the fdf & toc when wanted, this is done by a flag in the config of the system. On default it will work without fdf/toc.
Without fdf&Toc it will look a little bit different.

JASS:
public boolean CodeOnly = true // Create Frames by code only

Lua:
,CodeOnly = true -- Create Frames by code only

Edit: small fix 1.1h)
dont show tooltip for buttons without data.
 
Last edited:
Updated Lua Version to V1.2)
use frameVariables instead of FrameByName
the update function performs better, pushed more into the code that runs only when a new unit is detected
Autodetect CodeOnly by the tocPath path or if it fails.
Added UseCommandCardPosHero, UseCommandCardPos is now for none hero
added ShortBigNumber display 100k for 99999 (previous hardcoded into MOD_ABI)
ABILITY_IF_BUTTON_POSITION_NORMAL_Y = -11 is now an exclude reason for AbiFilter

running in Warcraft 3 V1.31.1
Detects FourCC for spells that were used once and trigger EVENT_PLAYER_UNIT_SPELL_EFFECT or learned by hero. can also detect UnitAddAbility when wanted. This feature is only enabled when BlzGetAbilityId is not found and can only find spells that have a command card pos that is not 0 and not y=-11. it forgets "dead" spells every 20s. it considers spells dead when the command card pos of the spell is not equal to the pos of the get ability pos using the FourCC of that spell.
can be disabled with a setting
Lua:
  ,IdData = { -- stores Ability to FourCC in Warcraft 3 V1.31.1, does nothing when BlzGetAbilityId is found
            Enabled = 2
            -- 0 -> disable this feature
            -- 1 -> create Learn_Skill Trigger
            -- 2 -> create SPELL_EFFECT Trigger ^^
            -- 3 -> hook UnitAddAbility ^^
        }


Edit: Uploaded V1.2a)
vjass got most of the V1.2Lua version except for running in Warcraft 3 V1.31.1 Detects FourCC
 
Last edited:
Back
Top