• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Wurst] Ability Tooltip Generator

Level 23
Joined
Jan 1, 2009
Messages
1,615
Allows you to create tooltips like these:
457LOcF.png


Repo dep: Frotty/Ability-Tooltip-Generator

The value for the current level is highlighted, supports custom patterns.

Use the stdlib api of ChannelAbilityPreset with tooltipStartListen() and tooltipStopListen().

Example:

Wurst:
package Snowball
import AbilityTooltipGenerator

public constant SNOWBALL_SPELL_ID = compiletime(ABIL_ID_GEN.next())

constant SPEED = 19.5
constant RealLevelClosure RANGE = lvl -> 900. + lvl * 100

@compiletime function getObjs()
    let tgen = new AbilityTooltipGenerator("An ordinary snowball.")
    new ChannelAbilityPreset(SNOWBALL_SPELL_ID, 4, true, tgen)
    ..setHeroAbility(false)
    ..presetButtonPosNormal(0, 2)
    ..presetTargetTypes(Targettype.POINT)
    ..tooltipStartListen()
    ..presetHotkey("Q")
    ..setName("Snowball")
    ..presetIcon("BTNFrostBolt")
    ..presetCooldown(lvl -> 1.75 - (lvl / 4))
    ..presetManaCost(lvl -> 4 - (lvl / 3).toInt())
    ..presetCastRange(RANGE)
    ..setLevelSkipRequirement(0)
    ..tooltipStopListen()

RANGE is external here so it can be used in the actual spell mechanic as well.

Code:
Wurst:
package AbilityTooltipGenerator
import public ChannelAbilityPreset
import HashMap

@configurable constant TITLE_COLOR = "|cff3B97D3"
@configurable constant TITLE_TTYPE = "Targettype:"
@configurable constant MAX_TITLES = 10
@configurable constant LEARN_PATTERN = "[|cffFFCC00$hotkey$|r] |cffFFCC00Learn|r $name$ - [|cffffcc00Level %d|r]"
@configurable constant NORMAL_ACTIVE_PATTERN = "$name$ - Level $lvl$ [|cffFFCC00$hotkey$|r]"
@configurable constant NORMAL_PASSIVE_PATTERN = "$name$ - Level $lvl$"

public class AbilityTooltipGenerator implements TooltipGenerator
    private constant propMap = new IterableMap<string, StringLevelClosure>
    private var description = ""

    private var levels = 1
    private var hotkey = ""
    private var name = ""
    private var targettype = Targettype.NONE

    construct(string description)
        this.description = description

    construct()

    override function addProperty(string title, StringLevelClosure lc)
        propMap.put(title, lc)

    override function applyToDef(AbilityDefinition def)
        levels = propMap.has("Levels") ? fixValue(propMap.getAndRemove("Levels").run(0)).toInt() : 1
        name = propMap.has("Name") ? propMap.getAndRemove("Name").run(0) : "unnamed"
        hotkey = propMap.has("Hotkey") ? propMap.getAndRemove("Hotkey").run(0) : "Q"
        targettype = propMap.has("Targettype") ? propMap.get("Targettype").run(0).toInt() castTo Targettype : Targettype.NONE
        def..setTooltipLearn(generateTooltipLearn())
        ..setTooltipLearnExtended(generateTooltipExtended(-1, true))
        for i = 1 to levels
            def..setTooltipNormal(i, generateTooltipNormal(i))
            ..setTooltipNormalExtended(i, generateTooltipExtended(i, false))

    private function generateTooltipLearn() returns string
        return replaceRefs(LEARN_PATTERN)

    private function generateTooltipNormal(int lvl) returns string
        if targettype == Targettype.PASSIVE
            return replaceRefs(NORMAL_PASSIVE_PATTERN, lvl)
        else
            return replaceRefs(NORMAL_ACTIVE_PATTERN, lvl)

    private function replaceRefs(string old, int lvl) returns string
        var newString = old
        newString = newString.replace("$name$", name)
        newString = newString.replace("$hotkey$", hotkey.toUpperCase())
        newString = newString.replace("$lvl$", lvl.toString())
        return newString

    private function replaceRefs(string old) returns string
        var newString = old
        newString = newString.replace("$name$", name)
        newString = newString.replace("$hotkey$", hotkey.toUpperCase())
        return newString

    private function generateTooltipExtended(int lvl, boolean learn) returns string
        var s = ""
        if targettype == Targettype.PASSIVE
            s += TITLE_COLOR + "Passive|r\n"
        else
            if learn
                s += TITLE_COLOR + TITLE_TTYPE + "|r " + targettype.toString() + "\n"
            else
                s += TITLE_COLOR + TITLE_TTYPE + " |cffFFCC00" + targettype.toString() + "|r\n"

        for key in propMap
            var tmp = ""
            for i = 1 to levels
                tmp += fixValue(propMap.get(key).run(i)) + "/"
            s += TITLE_COLOR + key + ":|r " + colorLevelValue(tmp.substring(0, tmp.length() - 1), lvl, levels) + "\n"
        s+= "\n"
        s+= description
        return s

    private static function fixValue(string value) returns string
        var s = value
        if s.endsWith(".")
            s = s.substring(0, s.length()-1)
        else if s.length() > 1 and s.endsWith(".0")
            s = s.substring(0, s.length()-2)
        return s

    private static function colorLevelValue(string oldString, int lvl, int maxLevel) returns string
        var _newString = ""
        var charCount = 0
        var charPosCount = 0
        int array charPos
        for char in oldString
            if char == "/"
                charPos[charPosCount] = charCount
                charPosCount++
            charCount++
        if lvl == -1
            _newString = oldString
        else if charPosCount <= 0
            _newString = "|cffFFCC00" + oldString
        else if maxLevel <= 1
            _newString = "|cffFFCC00" + oldString
        else if lvl == 1
            _newString = "|cffFFCC00" + oldString.substring(0, charPos[0]) + "|r" + oldString.substring(charPos[0], oldString.length())
        else if lvl == maxLevel
            _newString = oldString.substring(0, charPos[lvl-2]) + "|cffFFCC00" + oldString.substring(charPos[lvl-2], oldString.length()) + "|r"
        else
            _newString = oldString.substring(0, charPos[lvl-2]) + "|cffFFCC00" + oldString.substring(charPos[lvl-2], charPos[lvl-1]) + "|r" + oldString.substring(charPos[lvl-1], oldString.length())
        return _newString
 
Last edited:
Level 6
Joined
Jan 12, 2011
Messages
110
Funny someone is still using this!
Originally I didn't want to continue, since HappyTauren was working on a better version, but it doesn't look like he will finish that.
So I might bring something like this back as git repo dependency and up to date.
Thanks in any case, glad you like it ;)

Glad to hear that!

I will actually have to alter the system a bit, cause I am implementing so called "Ranks" for abilities- meaning, I have one ability definition, and after certain level, another Rank takes place (1-3, 4-6 ex...), and each rank needs to have different values (and possibly effects).
The problem arises when the ability has over 8 or so levels (I have 12 so far and gonna be more maybe...). The text is just getting wrapped and it does not look so neat and pretty.

But besides that, its really awesome!
 
Level 3
Joined
Mar 16, 2011
Messages
21
Hello, how can I format real value with percent? e.g. "40%/60%" instead of "0.4/0.6"?
I do it like this:
JASS:
..addTooltipProperty("Damage Reduction", lvl -> (DAMAGE_REDUCTION.run(lvl) * 100).percRound())
where percRound() function is:
JASS:
public function real.percRound() returns string
  return (this.toString(0) + "%")

The result is: (actual real values are 0.1, 0.15, etc)
1697360949526.png
 
Top