TasToolTipBox

Introduction


TasToolTipBox is a custom UI addition for Warcraft 3 V1.31 or higher in Lua & vjass.
It displays some generic spell values in a additional tooltip-box.

Details


Creates an custom TooltipBox with "multiple" rows of custom Icon-Text-Frames.
When an activ Spell or item is hovered it shows the box and displays MissileSpeed, Cooldown, Range, Area & CastTime.
One can adjust the used Icons and amount of infos. To make them display different data you need to edit the system code.
For items only the first skill is considered, which should be activ one anyway.
Does not work correctly in group selection.
Does not work correctly for sub menues like hero skill, built or spellbooks.
In V1.31.1 always display values of Level 1.

How to install


Requiers Warcraft 3 1.31+ or higher
  • Copy TasToolTipBox Lua (trigger Editor).
  • Copy required lib HoverOriginButton Lua.
  • Or Copy TasToolTipBox vjass (trigger Editor).
  • Copy required lib HoverOriginButton vjass.
  • export
    • war3mapImported\TasTooltipBox.fdf
    • war3mapImported\TasTooltipBox.toc
    • WHEN USING THE EXPORT ALL BUTTON, IT CAN HAPPEN THAT THE CONTENT OF THIS FILES SWAP
    • import them into your map
  • Installed

The system code this post, only contains the parts your as "user" care about.
At top some config.
Inside function StartUI the displayed text is set.
function endUI happens when the user stops pointing at a command button
When you want to change the displayed text, Beaware that both StartUI & endUI run in async context. Some things you should not do in this functions:
dont keep references to objects (that are going to be destroyed)
dont random
dont make new handleId
dont create
dont destroy
dont change gamestate

Lua:
--[[ TasToolTipBox V4e by Tasyen
  An additional TooltipBox for buttons in the command card/inventory which displays MissileSpeed, Cooldown, Range & Area values

  changes position of ORIGIN_FRAME_UBERTOOLTIP

  function TasToolTipBox.AddData(array, unitCode, objectCode)
    Tell the TasToolTipBox that units of unitTypeId UnitCode have objectCode inside array. This is needed for BuiltMenu, LearnMenu & Selling/Training.
    array should be one of the TasTooltipBox dataSets:
        TasToolTipBox.DataBuilt
        TasToolTipBox.DataLearn
        TasToolTipBox.DataDefault
    unitCode is the unitTypeId of the unit using this data.
    objectCode is one RawCode in a string or a number 'Hpal'.
    uses x/y coords of objectCode, therefore with colisions you get unwanted results

  function TasToolTipBox.AddDataBatch(array, unitCode, objectCodeString)
    uses TasToolTipBox.AddData with many rawCodes at once.
        TasToolTipBox.AddDataBatch(TasToolTipBox.DataBuilt, 'hpea', "htow,hhou,hbar,hbla,hwtw,halt,harm,hars,hlum,hgra,hvlt")
        TasToolTipBox.AddDataBatch(TasToolTipBox.DataDefault, 'htow', "hpea,Rhpm,hkee")
    to get this string open the unit in object editor navigate to the field hold shift press enter which opens the field in text input, copy paste it.

  works incorrect when multiple skills use 1 slot in the command card
  works incorrect in group selection
  works incorrect with spellbooks

  requires BlzGetAbilityId for skills with more than 1 level (not Warcraft V1.31.1)
  requires HoverOriginButton
]]
do
    TasToolTipBox = {
--config start
        TocPath = "war3mapImported\\TasToolTipBox.toc"
        ,AutoRun = true --(true) will create Itself at 0s, (false) you need to TasToolTipBox.Init()
        ,ParentFunc = function() return BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0) end -- should not be simple, called when TasToolTipBox is created the returned frame is used as parent
        ,Hide0Text = true -- hide a Slot when the displayed Text would be 0/0s/0.0s
        ,InfoCount = 5 -- how many Infos you want, every 4 are one row
        ,FixedPos = false -- true default tooltip pos does not change when TasToolTipBox is not shown
        ,ExcludSlots = {[7] = true} -- the buttonIndexes set, are not used in the auto ability detection -> this.ActionSpell; [7] = true -> ignore command button 7, 0 is the Top Left button 11 the bottom right
        ,Icon = { -- filePaths used for the icons, Indexes should fit the data used in this.ActionXxxx functions
            "replaceabletextures/passivebuttons/pasbtntrueshot"
            ,"ui/widgets/battlenet/bnet-tournament-clock"
            ,"replaceabletextures/commandbuttons/btnload"
            ,"replaceabletextures/selection/spellareaofeffect_undead"
            ,"replaceabletextures/commandbuttons/btnreplay-speedup"
            ,"UI/Widgets/ToolTips/Human/ToolTipManaIcon"
        }
        ,FilterItemSkills = true -- true items are never in the command card in your map
        ,EnableSubMenu = true -- true creates events/timer; changing it after the Init run is not supported/recommented.        
        ,YPos = 0.17

        --
        -- manual stored data Display Actions
        --
        ---@param buttonIndex integer active commandButton Index
        ---@param data type manual stored Data at buttonIndex for Learning
        ---@param unit unit active unit
        ---@param unitCode integer of unit
        ---@return boolean use/show the custom UI
        ,ActionSubMenuHero = function(buttonIndex, data, unit, unitCode)
            -- requires EnableSubMenu
            -- inside hero skill menu
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
            return true
        end
        ,ActionSubMenuBuilt = function(buttonIndex, data, unit, unitCode)
            -- requires EnableSubMenu
            -- inside built menu
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
            return true
        end
        ,ActionDefaultData = function(buttonIndex, data, unit, unitCode)
            -- mostly meant for shops/trainers
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
            return true
        end

        --
        -- autoDetect Actions
        --
        ---@param buttonIndex integer active commandButton Index
        ---@param abi ability ability that uses the button
        ---@param abiCode integer rawCode of abi requires BlzGetAbilityId
        ---@param unit unit active unit
        ---@param unitCode integer of unit
        ---@param level integer abi index for abilityInstance api requires BlzGetAbilityId
        ---@return boolean use/show the custom UI
        ,ActionSpell = function(buttonIndex, abi, unit, abiCode, level, unitCode)
            -- displayed data in autoDetect ability
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), BlzGetAbilityIntegerField(abi, ABILITY_IF_MISSILE_SPEED))
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 2), R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_COOLDOWN, level)).."s")
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 3), R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, level)))
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 4), R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, level)))
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 5), BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CASTING_TIME, level).."s")
            --BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 6), BlzGetAbilityIntegerLevelField(abi, ABILITY_ILF_MANA_COST, level))    
            return true
        end
        ,ActionItemSpell = function(buttonIndex, abi, unit, abiCode, level, unitCode, item)
            -- displayed data autoDetect inventoryButton-ability
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), BlzGetAbilityIntegerField(abi, ABILITY_IF_MISSILE_SPEED))
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 2), R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_COOLDOWN, level)).."s")
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 3), R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, level)))
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 4), R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, level)))
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 5), BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CASTING_TIME, level).."s")
            --BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 6), BlzGetAbilityIntegerLevelField(abi, ABILITY_ILF_MANA_COST, level))
            return true
        end
-- config ende
Code:
 = "replaceabletextures/passivebuttons/pasbtntrueshot"
    set Icon[2] = "ui/widgets/battlenet/bnet-tournament-clock"
    set Icon[3] = "replaceabletextures/commandbuttons/btnload"
    set Icon[4] = "replaceabletextures/selection/spellareaofeffect_undead"
    set Icon[5] = "replaceabletextures/commandbuttons/btnreplay-speedup"
    set Icon[6] = "UI/Widgets/ToolTips/Human/ToolTipManaIcon"

    set ExcludSlots[7] = true // the buttonIndexes set, are not used in the auto ability detection -> ActionSpell; [7] = true -> ignore command button 7, 0 is the Top Left button 11 the bottom right
endfunction

public function ActionSubMenuHero takes integer buttonIndex, integer data, unit u, integer unitCode returns boolean
        // requires EnableSubMenu
        // what to display inside hero skill menu        
        call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
        return true
endfunction
public function ActionSubMenuBuilt takes integer buttonIndex, integer data, unit u, integer unitCode returns boolean
        // what to display inside built menu
        call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
        return true
endfunction
public function ActionDefaultData takes integer buttonIndex, integer data, unit u, integer unitCode returns boolean
        // what to display with manual written data
        call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
        return true
endfunction
public function ActionSpell takes integer buttonIndex, ability abi, unit u, integer abiCode, integer level, integer unitCode returns boolean
    // this is the place you can change the displayed data
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), I2S(BlzGetAbilityIntegerField(abi, ABILITY_IF_MISSILE_SPEED)))
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 2), I2S(R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_COOLDOWN, level)))+"s")
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 3), I2S(R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, level))))
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 4), I2S(R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, level))))
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 5), R2SW(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CASTING_TIME, level),1,1)+"s")
    //call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 6), I2S(BlzGetAbilityIntegerLevelField(abi, ABILITY_ILF_MANA_COST, level)))

    return true
endfunction

public function ActionItemSpell takes integer buttonIndex, ability abi, unit u, integer abiCode, integer level, integer unitCode, item it returns boolean
    // Update displayed Text
    // this is the place you can change the displayed data
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), I2S(BlzGetAbilityIntegerField(abi, ABILITY_IF_MISSILE_SPEED)))
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 2), I2S(R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_COOLDOWN, level)))+"s")
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 3), I2S(R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CAST_RANGE, level))))
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 4), I2S(R2I(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_AREA_OF_EFFECT, level))))
    call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 5), R2SW(BlzGetAbilityRealLevelField(abi, ABILITY_RLF_CASTING_TIME, level),1,1)+"s")
    //call BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 6), I2S(BlzGetAbilityIntegerLevelField(abi, ABILITY_ILF_MANA_COST, level)))
    return true
endfunction

// ==========
// Confg Ende
// ==========


ChangeLog


V4c&d&e&f improved api/setup comments, fixed a bug with Hide0Text
V4a AddBatch - Hero Learn assumes now fill card from top left, Filter -coords
V4

can detect built & Hero Learn sub menu, this does not work 100% in all cases
can manual set data for default, subMenu Built & Hero Learn​
V3 Improved Skill detection (can ignore ItemSkills in the command card detection)
V2

Hide the box in more cases like shops
Can make default Tooltip repos itself when Box is not shown
Works now for Inventory Items​

Tags: Custom UI, Spell Info, Tooltip​
Previews
Contents

TasToolTipBox (Map)

Reviews
Antares
Nice system for displaying additional spell information. Very customizable. Approved
Updated vjass to V3)
Improved Skill detection (can ignore ItemSkills in the command card detection)

Updated Lua to V4)
can detect peon built & Hero Learn sub menu, this does not work 100% in all cases
can manual set data for default, subMenu Built & Hero Learn
need to do it when you want to know stuff inside built or shops .
Manual data overpowers the ability detection.

uploaded map still includes Lua V3 because V4 differs quite from V3.

In the demo map only the 4 melee workers goblin shop and townhall have manual data.
goblin shop has colisions hence it will show wrong infos even when working.



not sure how to do the vjass V4 version with the data setup.

edit: Update both to V4a)
V4a AddBatch - Hero Learn assumes now fill card from top left, AddData Filters -coord abilities

vjass uses now an array and loops it to find the index of an unitcode in the system, but each dataset needs 12 slots. therefore the vjass version only supports upto 32k/12 unitcodes -> ~2.6k
 
Last edited:
Lua:
--[[
function TasToolTipBox.AddData(array, unitCode, objectCode)
    make unitCode use inside array objectCode as manual data
    uses x/y coords of objectCode, therefore with colisions you get unwanted results
]]
This is quite confusing. What is array and what are the possible options? You need to list them.
"make unitCode use inside array objectCode as manual data" Please try to rephrase that sentence.

The frames for ability tooltips are working well. For the build tooltips, the names in the tooltip box seem to get clipped on many of them. I also don't quite understand the intent here. Is this working as intended? What is the use of listing the name of the object again?

For the TasToolTipBox table, you should separate configurables from non-configurables. I don't know what to with ExcludSlots = {[7] = true}, so I don't want to touch it. Same for EventCount, TimerUnit, LastAction, and TimerCount. Separate these visually from the configurables.

I noticed that when I turned off Hide0Text, the ability tooltips remained displayed when I hovered over a build button from one of the workers. Also, a small comment about what this does would be appreciated. It took me some time to get what it does.

For the Icon table, you could do a dictionary with "range", "cooldown" etc. keys or put a comment behind it which index is pointing to which info.

It would be great if the order of the items could be customized. As far as I understand it, if you want cast time displayed, you need to display all other values and you can't pick and choose. Shrinking down the tooltip box and removing holes when some of the items aren't being displayed could be a nice option for the config.

A nice system that enables the display of spell information automatically and with just a few clicks, but there appear to be a few bugs and some features are not explained well.

Awaiting Update
 
Updated to 4c added some comments to the api and setup.

I have to tell that this system is a port from my map and the whole submenu stuff is not part of the design goal for my map. They were added as Afterthought because for a general system they are likely needed.
This is quite confusing. What is array and what are the possible options? You need to list them.
"make unitCode use inside array objectCode as manual data" Please try to rephrase that sentence.
yes, bad explained will add more info. I think one should use the batch version below which has examples. In reality one copy pastes the sold Items/Units Learn field from object Editor.

The frames for ability tooltips are working well. For the build tooltips, the names in the tooltip box seem to get clipped on many of them. I also don't quite understand the intent here. Is this working as intended? What is the use of listing the name of the object again?
The names are an example and proof of concept that it also works in built menu. The text is clipped because each Icon slot only displays a limited amount of space on screen (~0.06 x-screen space) This Size limits is caused by the Size of "TasTooltipBoxInfo" which is 0.06/0.015 from fdf. one could change that in map script but I did not implement that.


For the Icon table, you could do a dictionary with "range", "cooldown" etc. keys or put a comment behind it which index is pointing to which info.
The idea is that this indexes match the indexes one uses when one writes onto the text frames inside the this.Action functions, and as user of this System one can change the action functions. With keys, i would suggest a meaning which i dont want to do.

It would be great if the order of the items could be customized. As far as I understand it, if you want cast time displayed, you need to display all other values and you can't pick and choose. Shrinking down the tooltip box and removing holes when some of the items aren't being displayed could be a nice option for the config.
One can customize the icons and the order. Thats what the this.Action functions are about one sets the displayed texts one could set the icon textures but I dont.
I prefere when the positions are static. Then the position itself has a meaning by itself and one does not need to interpret the icon. When one packs and reorganizes them one needs to learn for each ability what Slot 1, 2, ... mean. While with fixed slot indexes, the first is always MissileSpeed.
 
Right, it's slowly coming together for me. I think I get now what's going on with most of the options. Listen, you have a --config start and a -- config end and then there is more config stuff below it.

You could put the functions directly into the table definition, like:
Lua:
--[...]
        ,FilterItemSkills = true -- true items are never in the command card in your map
        ,EnableSubMenu = true -- true creates events/timer; changing it after the Init run is not supported/recommented.        
        ,YPos = 0.17

        ,ActionSubMenuHero = function(buttonIndex, data, unit, unitCode)
            -- requires EnableSubMenu
            -- what to display inside hero skill menu        
            BlzFrameSetText(BlzGetFrameByName("TasTooltipBoxInfoText", 1), GetObjectName(data))
            return true
        end,

        --[...]

and then have all the non-configurable parts after local this = TasToolTipBox line.

On the ExcludSlots line, maybe mention that 0 is the bottom-left button.

"unitCode will use inside array, objectCode as manual data."

I still don't understand that sentence. It would really help if you used an AI to proof-read your descriptions.

In the this.Action functions, type annotations would help with making it clearer what each parameter means. I assume data is the type id? I'm unfamiliar with the GetObjectName function. Does it work with unit ids, ability ids etc.?

I know I could figure this out by digging into your code, but I'm giving you the average user experience of someone as dense as me.

What about the fact that the "Blacksmith", "Town Hall" field is hidden when you hover over the build buttons when you have Hide0Text disabled. Is that a bug?
 
Updated Lua to 4d)
moved the action functions into the config
added Emmy Annotation for the action functions
mentions that buttonIndex 0 is topLeft and 11 bottomRight, i think that is overkill as that is just command card coords.
reworded TasToolTipBox.AddData

What about the fact that the "Blacksmith", "Town Hall" field is hidden when you hover over the build buttons when you have Hide0Text disabled. Is that a bug?
The hover system does not work for disabled command buttons. Normal Gold/Mana costs are not displayed for such aswell.
 
mentions that buttonIndex 0 is topLeft and 11 bottomRight, i think that is overkill as that is just command card coords.
It's still worth clarifying because some people do not know that by heart or the index could start at 1 in your system because of Lua's 1-based indexing.

The hover system does not work for disabled command buttons. Normal Gold/Mana costs are not displayed for such aswell.
That's not what I'm refering to. Here is the tooltip for Town Hall with and without "Hide0Text" flag enabled.

The first info is no longer visible.
 

Attachments

  • disabled.png
    disabled.png
    1.2 MB · Views: 15
error.png
Please use the full type names or put an ---@alias somewhere in your script.

If the unitCode/abiCode variables are integers, unitId/abiId would be better, less confusing variable names. These are the names that Blizzard uses for their functions.

There is a small bug with the frame position when FixedPos = false. When you hover over one with a TasTooltipBox and move the mouse over one without a box, if you do it really fast, it doesn't adjust the position. When you do it slower, it does. Not a big deal, but maybe you can fix that.

For the vJASS version, please also make sure that the config is clearly delimited from the rest.

Other than that, looking good.
 
Level 33
Joined
Aug 6, 2015
Messages
686
Can i please ask for a small change that would allow the system to easily do the next thing.
Give any value+icon for various object descriptions. (would be very useful imo)

In my case - I want to make special upgrades in a forge that would require a custom resource, and I want to show that custom resource in the box) - it is just i cannot do that easily - and I can see the potential in this system to allow me to do such thing
Ex12.png
 
Last edited:
Top