Unit Info Panels

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

Introduction

Unit Info Panels is an UI-Frame Resource, extending the default warcraft 3 UI. It upgrades the single Unit selection Frame into a Book with Pages. This only includes the normal view when the unit is not training, nor transporting.

Has a Lua and (v)jass version.
Requires Warcraft 3 V1.31 or higher.

Features

One can add additional custom Pages, showing other infos about the current Unit.
The pages also can contain interactive UI.
Each player can only see one page at the same time, that page doesn't have to be the same for them.
The current seen Page can be changed using up and down Buttons.
Includes a Framework to setup a Tooltiptext.
Probably one also don't want any unit be able to have access to all Pages. Therefore they can have a conditionfunction which prevents switching to it under such unwanted circumstances.
Supports using non-SimpleFrames you have to use SetUnitInfoPanelFrame, these non simpleframes don't become children of the UnitInfoPanels.

How to install


First you have to export and import the 2 Files in the demo map (using the export all Files function can bug in older Editor Versions).

war3mapImported\UnitInfoPanels.fdf
war3mapImported\UnitInfoPanels.toc
Now you copy UnitInfoPanels (trigger editor) into your map
Done.

Lua

(v)jass


Lua API
Code:
AddUnitInfoPanel(frame, update[, condition])
    frame is the containerPanel, update a function(unit) that runs every updateTick, condition is a function(unit) that returns true or false it is used to prevent rotating to this panel.
AddUnitInfoPanelEx(update, condition)
    wrapper for AddUnitInfoPanel, it creates and returns a new frame

SetUnitInfoPanelFrame(frame)
    makes a non SimpleFrame share visibility with the last Added InfoPanel, supports only one Frame per InfoPanel
SetUnitInfoPanelFrameEx()
    wrapper SetUnitInfoPanelFrame creates and returns a new empty Frame

UnitInfoPanelAddTooltipListener(frame, code)
    detects if this frame is visible if it is call the given function which should return a text which is the now wanted tooltipText.

UnitInfoCreateCustomInfo(parent, label, texture, tooltipCode)
    return createContext, infoFrame, iconFrame, labelFrame, textFrame
UnitInfoGetUnit([player])
    returns & recacls the current selected Unit
    without a player it will use the local player.
 
function UnitInfoPanelSetPage(newPage, updateWanted)
    ignores conditions, newPage can be "+" or "-" or a frame
Bounty Panel example in Lua. It creates 2 custom Unit Infos that display the gold and Lumber bounty on kill. This Panel can only be changed to when the owner of the current selected Unit gives bounty.
Lua:
-- Shows how much gold and Lumber bounty one gets when slaying an unit
do
    local realFunction = MarkGameStarted
    local lumberText, goldText, parent
    local createContext, infoFrame, iconFrame, labelFrame, textFrame
    local function Init()
        -- create a new Unit Info Panel, this panel can only be shown when the current selected unit's owner gives bounty
        parent = AddUnitInfoPanelEx(function(unit)
            local min, max
            min = BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_NUMBER_OF_DICE) + BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_BASE)
            max = BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_NUMBER_OF_DICE) *BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_SIDES_PER_DIE) + BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_BASE)
            BlzFrameSetText(goldText, min.." - "..max)
            min = BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_NUMBER_OF_DICE) + BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_BASE)
            max = BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_NUMBER_OF_DICE) *BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_SIDES_PER_DIE) + BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_BASE)
            BlzFrameSetText(lumberText, min.." - "..max)
        end,
        function(unit) return IsPlayerFlagSetBJ(PLAYER_STATE_GIVES_BOUNTY, GetOwningPlayer(unit)) end)
        -- define locals
   
        -- create a new custom Info and load all created frames into the locals
        createContext, infoFrame, iconFrame, labelFrame, textFrame = UnitInfoCreateCustomInfo(parent, " Gold:", "UI\\Widgets\\ToolTips\\Human\\ToolTipGoldIcon", function(unit)
        -- this function returns the text shown inside the tooltip when this UnitInfo is mouse hovered.
            local min, max
            min = BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_NUMBER_OF_DICE) + BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_BASE)
            max = BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_NUMBER_OF_DICE) *BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_SIDES_PER_DIE) + BlzGetUnitIntegerField(unit, UNIT_IF_GOLD_BOUNTY_AWARDED_BASE)
            return "Bounty Gold: "..min.." - "..max
            .."\nWhen an unit owned by you kills this unit, you gain this amount of Gold.\nOnly unallied unit give bounty."
        end)
        local prevIcon = iconFrame
        goldText = textFrame
        BlzFrameSetPoint(iconFrame, FRAMEPOINT_TOPLEFT, BlzGetFrameByName("SimpleHeroLevelBar", 0), FRAMEPOINT_BOTTOMLEFT, 0, -0.001)

        -- 2. Custom Info
        createContext, infoFrame, iconFrame, labelFrame, textFrame = UnitInfoCreateCustomInfo(parent, " Lumber:", "UI\\Widgets\\ToolTips\\Human\\ToolTipLumberIcon", function(unit)
            local min, max
            min = BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_NUMBER_OF_DICE) + BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_BASE)
            max = BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_NUMBER_OF_DICE) *BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_SIDES_PER_DIE) + BlzGetUnitIntegerField(unit, UNIT_IF_LUMBER_BOUNTY_AWARDED_BASE)
            return "Bounty Lumber: "..min.." - "..max
            .."\nWhen an unit owned by you kills this unit, you gain this amount of Lumber.\nOnly unallied unit give bounty."
        end)
        lumberText = textFrame
        BlzFrameSetPoint(iconFrame, FRAMEPOINT_TOPLEFT, prevIcon, FRAMEPOINT_TOPLEFT, 0.095, 0)
        prevIcon = nil
    end
    function MarkGameStarted()
        realFunction()
        realFunction = nil
        Init()
        if FrameLoaderAdd then FrameLoaderAdd(Init) end           
    end
end

The (v)jass API.
Code:
UnitInfoGetUnit(player p) -> unit
    returns & recacls the current selected Unit, unneeded in given actionfunctions
AddUnitInfoPanel(framehandle frame, code update, code condition)
    frame is the containerPanel, update a function() that runs every updateTick, condition is a function() that returns true or false it is used to prevent rotating to this panel.
    it is suggested to use UnitInfoUnit inside this functions
AddUnitInfoPanelEx(code update, code condition) -> framehandle
    wrapper for AddUnitInfoPanel, it creates and returns a new frame
SetUnitInfoPanelFrame(framehandle frame)
    makes a non SimpleFrame share visibility with the last Added InfoPanel, supports only one Frame per InfoPanel
SetUnitInfoPanelFrameEx() -> framehandle
    wrapper SetUnitInfoPanelFrame creates and returns a new empty Frame
UnitInfoPanelAddTooltipListener(framehandle frame, code func)
    detects if this frame is visible if it is call the given function which is expected to set string UnitInfoTooltipText to the now wanted tooltipText.
UnitInfoCreateCustomInfo(framehandle parent, string label, string texture, code tooltipCode) -> integer
    returns createContext
    you can get the frames over globals UnitInfoInfoFrame, UnitInfoIconFrame, UnitInfoLabelFrame, UnitInfoTextFrame
UnitInfoPanelSetPage(integer newPage)
    ignores conditions, using 0 will change to next page and -1 previous page
UnitInfoPanelSetPageByFrame(framehandle newPage, boolean updateWanted)
    searches the index of newPage and calls UnitInfoPanelSetPage when found
A vjass Demo contained by the Demo Map. It shows 8 abilities the current selected Unit got. (Lua also got that, but what use would it have to show the same example twice, on this page).

The demo Panels share a set of functions which you could copy paste, but change the content of this functions to fit you wanted Pages.
This would be private function condition, private function update, private function At0s, private function init_function.
init_function is the default vjass helper init, it starts a timer so At0s runs as soon the game started.
At0s creates the page and setups it.
condition is a simple function that tells, if one can change to this page. Beaware that this runs async.
update is called every update Tick by the main System, you use this if the displayed infos change based on the current situation.
tooltipAction is called when in the main system's update Tick the tooltip detector is hovered. Beaware that this runs async and every update Tick as long as hovered.
JASS:
library SkillPanel initializer init_function requires UnitInfoPanels
// Creates an UnitInfopanel showing the last 8 abilities the unit got, ignoring abilities having no tooltip.
// Ignores abilities without a Tooltip: When BlzGetAbilityStringLevelField returns "Tool tip missing!" or "" or " "
    globals
        private framehandle array Icon
        private framehandle array Text
        private framehandle array Button
        private framehandle array ToolTip
        private integer buttonCount = 8
        private integer array SkillIndex
        private framehandle parent
        private trigger buttonTrigger = CreateTrigger()  
    endglobals

    private function buttonAction takes nothing returns nothing
        // request currently used unit of the clicking player
        local integer i = buttonCount
        local framehandle frame = BlzGetTriggerFrame()
        call UnitInfoGetUnit(GetTriggerPlayer())
        // get the clicked buttonIndex

        // find the used Button
    call BJDebugMsg("Skill Panel")
        loop
            exitwhen i == 0
            if frame == Button[i] then
                call BJDebugMsg(GetPlayerName(GetTriggerPlayer()) + " Clicked: " + I2S(i) + " "+ GetUnitName(UnitInfoUnit))
                exitwhen true
            endif
            set i = i - 1
        endloop
        set frame = null
    endfunction

    private function tooltipAction takes nothing returns nothing
    // the tooltip function is async do not create or destroy here
        local integer i = buttonCount
        local ability abi
        // find the active tooltip
        loop
            exitwhen i == 0
            if UnitInfoTooltipFrame == ToolTip[i] then
                set abi = BlzGetUnitAbilityByIndex(UnitInfoUnit, SkillIndex[i])
                if BlzGetAbilityBooleanField(abi, ABILITY_BF_HERO_ABILITY) then
                    set UnitInfoTooltipText = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_LEARN, 0) + "\n" + BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_LEARN_EXTENDED, 0)
                else
                    set UnitInfoTooltipText = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL, 0) + "\n" + BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL_EXTENDED, 0)
                endif
                exitwhen true
            endif
            set i = i - 1
        endloop
        set abi = null
    endfunction

    private function condition takes nothing returns boolean
        return IsUnitOwnedByPlayer(UnitInfoUnit, Player(PLAYER_NEUTRAL_AGGRESSIVE))
    endfunction

    private function abiFilter takes ability abi, string text returns boolean
        if BlzGetAbilityBooleanField(abi, ABILITY_BF_ITEM_ABILITY) then
            return false
        endif
        if text == "Tool tip missing!" or text == "" or text == " " then
            return false
        endif
        return true
    endfunction
 
    private function update takes nothing returns nothing
        local ability abi
        local integer buttonIndex = 1
        local integer abiIndex = 0
        local string text
        loop
            exitwhen buttonIndex > buttonCount
            set abi = BlzGetUnitAbilityByIndex(UnitInfoUnit, abiIndex)
            if abi != null then
                set text = BlzGetAbilityStringLevelField(abi, ABILITY_SLF_TOOLTIP_NORMAL, 0)
                if abiFilter(abi, text) then
                    set SkillIndex[buttonIndex] = abiIndex
                    call BlzFrameSetVisible(Button[buttonIndex], true)
                    call BlzFrameSetTexture(Icon[buttonIndex], BlzGetAbilityStringLevelField(abi, ABILITY_SLF_ICON_NORMAL, 0), 0, false)
                    call BlzFrameSetText(Text[buttonIndex], text)
                    set buttonIndex = buttonIndex + 1
                endif
                set abiIndex = abiIndex + 1
            else
                call BlzFrameSetVisible(Button[buttonIndex], false)
                set buttonIndex = buttonIndex + 1
            endif
        endloop
    endfunction
    private function At0s takes nothing returns nothing
        local integer i = buttonCount
        set parent = BlzCreateSimpleFrame("CustomUnitInfoPanel2x4", BlzGetFrameByName("SimpleInfoPanelUnitDetail", 0), 0)
        call AddUnitInfoPanel(parent, function update, function condition)  
   
        loop
            exitwhen i == 0
            set Button[i] = BlzGetFrameByName("CustomUnitInfoButton" + I2S(i), 0)
            set ToolTip[i] = BlzCreateFrameByType("SIMPLEFRAME", "", Button[i], "", 0)
            set Icon[i] = BlzGetFrameByName("CustomUnitInfoButtonIcon" + I2S(i), 0)
            set Text[i] = BlzGetFrameByName("CustomUnitInfoButtonText" + I2S(i), 0)
            call BlzTriggerRegisterFrameEvent(buttonTrigger, Button[i], FRAMEEVENT_CONTROL_CLICK)
            call BlzFrameSetTooltip(Button[i], ToolTip[i])
            call BlzFrameSetVisible(ToolTip[i], false)

            call UnitInfoPanelAddTooltipListener(ToolTip[i], function tooltipAction)
            set i = i - 1
        endloop
 
    endfunction
    private function init_function takes nothing returns nothing
        call TimerStart(CreateTimer(), 0, false, function At0s)
        call TriggerAddAction(buttonTrigger, function buttonAction)
        call FrameLoaderAdd(function At0s)
    endfunction
endlibrary


ChangeLog

V4b) (Lua only) Save&Load Fix
V4a)
Added a safty check for Panel finding​
V4)
added wantedPage Feature
Changes current viewn Page if the condition fails
Hides the current non-SimpelFrame when another selection Type is changed to (Group, trainer etc)
(Lua) Fixed the down Button
(vjass) runs only the active update instead of all of them
SkillPanel, seperated the ability filter into an own function, on-default now blocks any ability with the item skill Flag
UnitInfoPanelSetPage has now a second argument to support the new wantedIndex feature.
UnitInfoPanelSetPage can evoke nextPanel PrevPanel with 0/-1 or in Lua "+" "-"
UnitInfoPanelSetPage increased lower limit to 1.
(Lua) UnitInfoPanelSetPage now can be called with a frame instead of a number
(vjass) added UnitInfoPanelSetPageByFrame finds the used index and swaps the page
The whole UnitInfo can now be a next Panel Button
Remove various initial values in the globals block​
V3)
Hides the Page Buttons when no other page can be selected.
Changed default Condtions for Skillpanel & CustomStat.​
V2)
fixed Load&Save Bug
Checks and Forces Panel Condition inside the update tick​
Previews
Contents

Unit Info Panels V4b VJass (Map)

Unit Info Panels V4c (Map)

Level 12
Joined
Mar 13, 2020
Messages
410
2 Questions tasyen my German Freund

1. how I remove the default one?

2. how I can use a integer for the Crit one if I use the name of the variable I made to test it shows ingame only a string (udg_Crit) (that’s the name of the variable) but I want that it shows the number set to the Variable...

i start today learning jass....
 
1. how I remove the default one?
You stop the custom panel managing the default from being part of the panels array.
That could be done that way:
one change inside globals the starting value from 1 to 0 (custom ones normaly only take indexes from 2 because of that)
private integer panelsCount = 0
then one hides the panel inside private function At0s in UnitInfoPanels.
call BlzFrameSetVisible(parent, false)

Finally one disables the line or remove it, that stops it from being placed into the array. With that it can not be swaped to anymore.
I made it into a comment with //
// set panels[1] = parent
If you hide the default Panel you also should enforce showing the first Panel after your custom panels were added with call UnitInfoPanelSetPage(1)

2. how I can use a integer for the Crit one if I use the name of the variable I made to test it shows ingame only a string (udg_Crit) (that’s the name of the variable) but I want that it shows the number set to the Variable...
This line is for the demo CustomStat one would add it inside private function update:
call BlzFrameSetText(Text[5], I2S(udg_Crit))
That would set the custom stat 5 text to the value of udg_Crit.
 
Updated to V2)
Inside the Update Tick the current Panels condition is checked and a change is forced, if it is not fullfilled.
Continues to work and won't crash anymore after the game is Saved & Loaded when having this system installed (changes to all Panels).


Recently someone told me that one of my UI systems broke when the game was saved and later loaded. I did some research about that and found out that custom created Frames and Frame modifications are not save nor loaded and that using references to the now broken custom Frames can crash the game. This applies to V1.31, V1.32.8 and V1.32.9 PTR.

I added a custom FrameLoader Trigger that redoes the whole system's Frame creation when the game is Loaded.
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,178
I am currently converting this to wurst for personal use as I see this as a potential auto-include in all future maps of mine.

The first thing I noticed is that the arrows appear even if there are no pages added.
In my case I only want the hero stats but the arrows appear on normal units who do not have any extra pages. In such a case shouldn't they be hidden by default?
 
Like you say it would be better to hide them when there is no other option to swap to. Somehow I didn't wanted to do so much page control in the update tick.
Updated to V3)
Inside the update tick the amount of possible pages is checked, hides the pageButtons when only 1 or 0 are useable right now.
The demo conditions are now the same in the Lua and vjass version.
SkillPanel can only be seen for unit's owned by neutral hostile, (the default condition was changed).
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,178
A bit buggy for me.

Although, as I said I am converting and modifying it slightly so it might be on me.

The hiding of arrows did not work for me.
At first it kept saying the hero had 3 pages and normal units 2 pages, even though the hero should have 2 (1 default and 1 stats)
I realized it was the panelsCondition[loopA] == null which I felt was a weird check because in the addUnitInfoPanel function you set a condition if there isn't one.
My guess is that it its there to add the default page.
So I removed that and set integer useAblePages = 1 instead of 0 to compensate

So it's currently working with these modifications.

I also noticed there is a lot of duplicate code, the createTriggers on init can be created at variable declaration, same for the timer.
I believe
tooltipListenerCount = 0 and
integer panelsCount = 1

Were also double-set.
 
Thanks for your feedback.

The null check was added to save trigger creations when unneeded, and TriggerEvalute returns false when the trigger is null. but true with an existing trigger without any condition. You also right I added that also for the default Panel which has no conditionTrigger. One could argue, always create a trigger and remove the null check, ends with min maxing ram usage vs calculation steps.

tooltipListenerCount and panelsCount are set again in the Init function to support warcraft 3 Save&Load which is buggy for frames. Because of that I reconstructed it in a way to be able to call the frame creation again with that overwritting the old existing.
 

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,178
Well in that case you should probably remove the values set at the declaration because if someone wants to modify it they change it there and then it gets overwritten at init.

Also because I am curious, any clue why the count kept saying 3 despite me only having 2 pages? I know it is 2 because when I cycled through them with clicks it just swaps between them
 
Also because I am curious, any clue why the count kept saying 3 despite me only having 2 pages? I know it is 2 because when I cycled through them with clicks it just swaps between them
Maybe one of the Panels has a condition that the unit does not fullfill.

Updated to V4)
Remembers the Panel activly changed to and tries to show it when possible.
Changes current viewn Page, if the condition fails
When wanted a big unseeable NextPanel Button is created below the UnitInfo. The Button will change the current Panel when clicked. It can only be clicked on spaces that are not taken by the current Panel's content. This Button breaks interactive non-SimpleFrame Panel content. Hence you should not enable it, if you have such.
private constant boolean HAVE_BIG_PAGE_BUTTON = true​
(vjass) has now one update trigger per panel and only calls that one. Therefore all update functions in the demo map will not check the visibility of the parent anymore. (Lua) already only called the current active update but checked visiblity.
Remove various initial values in the globals block, if they are set in the At0s/Init function
UnitInfoPanelSetPage has now a second argument to support the new wantedIndex feature.
UnitInfoPanelSetPage can evoke nextPanel PrevPanel with 0/-1 or in Lua "+" "-"
UnitInfoPanelSetPage increased lower limit to 1.
(Lua) The down Button did not what it should in V3.
 
Maybe not, you asked in version 2 which was before I modified it, to counter the Save&Load Bug. My old instructions won't work anymore. Now one has to do that in function At0s located in UnitInfoPanels.

Inside private function At0s takes nothing returns nothing you have to change some lines.
set panelsCount = 1
->
set panelsCount = 0
This makes your custom take the first index

set panels[1] = parent
->
//set panels[1] = parent
Stop the default one from being part of the useable Panels

JASS:
if activeIndex != 1 then
   call BlzFrameSetVisible(panels[1], false)
endif
->
call BlzFrameSetVisible(parent, false)
Hide the default Unit Info


After that the default is hidden and can not be swaped to anymore.
 
Level 2
Joined
May 5, 2013
Messages
7
Hi, @Tasyen, do you know how the buttons for normal abilities and orders are made? If you press and hold this button, its image becomes slightly smaller, and the standard MouseClick1 sound is played. In your example and others, I see buttons that don't have any visual effects other than Highlights or sounds... And I would like to repeat the behavior of standard buttons
 
Last edited:
Hi, @Tasyen, do you know how the buttons for normal abilities and orders are made? If you press and hold this button, its image becomes slightly smaller, and the standard MouseClick1 sound is played. In your example and others, I see buttons that don't have any visual effects other than Highlights or sounds... And I would like to repeat the behavior of standard buttons
Buttons (can) have images for each state default/disabled/disabled Pushed/Pushed. Each such would be an own functional BACKDROP child Frame, functional child can only be set in fdf and perform some taks for their parent. One of them is shown based on the current sate of the Button. Each of the Backdrops also have their own texture, if you want to change it you have to change it for all of them.
One could reduce the size of the Backdrop that manages the Pushed state. Then while pushing the button's image would become smaller.
fdf has a feature to do that for BACKDROP: BackdropBackgroundInsets real real real real. It reduces the size in which the given image is displayed, it does not make the frame itself smaller, with negative numbers it is displayed bigger.
The sides affected are: Right, TOP, Bottom, Left.

BackdropBackgroundInsets 0.002 0.002 0.002 0.002,
displays the image 0.004 smaller for x and y dimension.

BackdropBackgroundInsets survives BlzFrameSetTexture.

Code:
Frame "GLUEBUTTON" "TestIconButton" {
    Width 0.035,
    Height 0.035,
    ControlStyle "AUTOTRACK|HIGHLIGHTONMOUSEOVER",

    ControlBackdrop "TestIconButtonIcon",
    Frame "BACKDROP" "TestIconButtonIcon" {
        BackdropBackground "ReplaceableTextures\CommandButtons\BTNFootman",
    }

    ControlPushedBackdrop "TestIconButtonIconPushed",
    Frame "BACKDROP" "TestIconButtonIconPushed" {
        BackdropBackgroundInsets 0.002 0.002 0.002 0.002,
        BackdropBackground "ReplaceableTextures\CommandButtons\BTNFootman",
    }

    ControlDisabledBackdrop "TestIconButtonIconDisabled",
    Frame "BACKDROP" "TestIconButtonIconDisabled" {
        BackdropBackground "ReplaceableTextures\CommandButtonsDisabled\DISBTNFootman",
    }

    ControlMouseOverHighlight "TestIconButtonHighLight",
    Frame "HIGHLIGHT" "TestIconButtonHighLight" {
        HighlightType "FILETEXTURE",
        HighlightAlphaFile "UI\Glues\ScoreScreen\scorescreen-tab-hilight.blp",
        HighlightAlphaMode "ADD",
    }
}

In the attached maps in Lua mode this is done. There are 4 Buttons 2 disabled 2 enabled. The bottom buttons Texture was changed in code.

Somehow I hadn't the idea to do that :) , yet.

No idea, how one would do that for SimpleButtons used as IconButtons though.

I almost forgot to tell you that your system is cool, just like the previous ones. You're a genius!:)
Thanks, well I trained a long time.
 

Attachments

  • Buttonexample.w3x
    14.4 KB · Views: 83
Last edited:
Level 2
Joined
May 5, 2013
Messages
7
In the attached maps in Lua mode this is done. There are 4 Buttons 2 disabled 2 enabled. The bottom buttons Texture was changed in code.
Thanks! )
Another point, the sound on the Commandbutton Is MouseClick1, and not Big Button Click, as on the dialog button
No idea, how one would do that for SimpleButtons used as IconButtons though.
Is that what you mean?

And one more thing, if I want to add hints to these buttons? What is the best way to do this?
 
Another point, the sound on the Commandbutton Is MouseClick1, and not Big Button Click, as on the dialog button
Then one would change the FrameType in the fdf from GLUEBUTTON to BUTTON, To stop the automatic played big button sound.
After that you would define such a clicked sound in code and play it for the clicking Player in the control click event trigger.

And one more thing, if I want to add hints to these buttons? What is the best way to do this?
One can add additonal Text in boxes above the Button. Or a Tooltip, tooltip would only be visible while the Button is hovered.
A Text in a box Tooltip is shown here UI: Frames and Tooltips. The used box is not the best for Tooltips but does not require any custom TOC. I prefer "EscMenuControlBackdropTemplate", but that thing requires Loading "UI\escmenutemplates.fdf" over a custom TOC.
 
Level 2
Joined
May 5, 2013
Messages
7
Then one would change the FrameType in the fdf from GLUEBUTTON to BUTTON, To stop the automatic played big button sound.
After that you would define such a clicked sound in code and play it for the clicking Player in the control click event trigger.
Thank you, I didn't know how to do it without help )
One can add additonal Text in boxes above the Button. Or a Tooltip, tooltip would only be visible while the Button is hovered.
A Text in a box Tooltip is shown here UI: Frames and Tooltips. The used box is not the best for Tooltips but does not require any custom TOC. I prefer "EscMenuControlBackdropTemplate", but that thing requires Loading "UI\escmenutemplates.fdf" over a custom TOC.
Yes, I figured out the tooltips, thank you!)
 
Level 2
Joined
Feb 24, 2020
Messages
11
Hi. I realise this might be the wrong place to ask. If I want to combine this with "New bonus" how would I do so? I am currently trying to

set call BlzFrameSetText(Text[3], R2SW(GetUnitBonusReal(UnitInfoUnit, BONUS_SPELL_POWER_FLAT), 1, 1))

but it gives me a undeclared function GetUnitBonusReal when I do so.

Any clue how to do this?
 
Level 2
Joined
Feb 24, 2020
Messages
11
First of all, thanks for helping. I'd completely understand if you don't feel like helping me as New bonus isn't your system. Strangely, GetUnitBonusReal has worked for me earlier (for basic stuff like display text triggers :S).

I tried call BlzFrameSetText(Text[3], I2S(GetUnitBonus(UnitInfoUnit, BONUS_SPELL_POWER_FLAT))) and got the same return code, I also tried call BlzFrameSetText(Text[3], R2SW(GetUnitBonus(UnitInfoUnit, BONUS_SPELL_POWER_FLAT), 1, 1)) and got the same return error code. I might just be stupid and could be missing something I guess.
 
@Tasyen You can create a new dashboard for buffs
Not really, the api provided by blizzard for buffs does not allow to get the text/icon of buffs. Nor allows it to know which buffs an unit has right now. So one would have to hardcoded many things and write it twice, once in object editor and once for the custom buff UI.

One could loop all possible buffs and check, if the unit has the buffs, but that approach is kinda taxing (hundreds of checks per call). Still the icon/text is a problem.
 
Top