• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] how to create new custom UI like talents selection?

Level 8
Joined
May 12, 2018
Messages
106
Hi, I want to make Unique Upgrade Tab before starting campaign chapters that in style between SC2 WoL Campaigns Armory and WoW Talents.
But I don't know anything about UI and frame, and I'm new to it.
I want to learn the basics one by one, such as how to adjust the size of the background and its tab, and how to create and position buttons, and click recognition.
The following images are the directions that I want to create.
1687920148702.png

WC3ScrnShot_062823_004141_000.jpg
 
Level 8
Joined
May 12, 2018
Messages
106
His introduction is a very good one, but it's too vast and too difficult for me, and most of them consists lua. (I'm using Jass).

I succeeded in making it to this by investigating and referring to the_spellweaver's Talent kitchen one by one. (but not functioning yet)

1687963538127.png

But the problem I've encountered right now is that I don't know how to print texts about the "talent points" on the bottom left. Is there a way to output only text, not buttons?
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,544
This tool can help:

You can create frames for just about anything you want.

Also, his Lua code is pretty easy to change to Jass. It's the same exact API, you're just adding back a few words like "call" or "set".

For example this Lua function for creating a text frame is easily converted to Jass like so:
Lua:
 function Test()
    -- create a TEXT Frame
    local frame = BlzCreateFrameByType("TEXT", "MyTextFrame", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
    -- Set the current Text, you can use the Warcraft 3 Color Code
    BlzFrameSetText(frame, "Text on |cffffcc00Screen|r")
    -- pos the frame
    BlzFrameSetAbsPoint(frame, FRAMEPOINT_CENTER, 0.4, 0.3)
    -- stop this frame from taking control of the mouse input, Might have sideeffects if the TEXT-Frame has an enable Color (but this does not have such).
    BlzFrameSetEnable(frame, false)
    -- the text is kinda small, but one can not use the FontNative onto TEXT-Frames (nether in V1.31 nor V1.32). Therefore one could scale it.
    BlzFrameSetScale(frame, 2)
 end
Change the function name to use the Jass syntax, replace -- with //, replace end with endfunction, declare the local variable type, and call your functions:
vJASS:
 function Test takes nothing returns nothing
    // create a TEXT Frame
    local framehandle frame = BlzCreateFrameByType("TEXT", "MyTextFrame", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
    // Set the current Text, you can use the Warcraft 3 Color Code
    call BlzFrameSetText(frame, "Text on |cffffcc00Screen|r")
    // pos the frame
    call BlzFrameSetAbsPoint(frame, FRAMEPOINT_CENTER, 0.4, 0.3)
    // stop this frame from taking control of the mouse input, Might have sideeffects if the TEXT-Frame has an enable Color (but this does not have such).
    call BlzFrameSetEnable(frame, false)
    // the text is kinda small, but one can not use the FontNative onto TEXT-Frames (nether in V1.31 nor V1.32). Therefore one could scale it.
    call BlzFrameSetScale(frame, 2)
 endfunction
Note how the API is the same, we're still using BlzFrameSetX() for all of our frame related stuff. It's really not that difficult of a switch.

Or use a tool to do it for you (can't guarantee success):
 
Last edited:
Level 24
Joined
Jun 26, 2020
Messages
1,852
His introduction is a very good one, but it's too vast and too difficult for me, and most of them consists lua. (I'm using Jass).

I succeeded in making it to this by investigating and referring to the_spellweaver's Talent kitchen one by one. (but not functioning yet)

View attachment 438051
But the problem I've encountered right now is that I don't know how to print texts about the "talent points" on the bottom left. Is there a way to output only text, not buttons?
The tutorial is not that hard, is long, but straightforward, maybe the examples are some confusing, so I will give you the basic of what you asked in the beginning to let you know how to use properly that system:

How to create frames
There are 3 functions for that:
JASS:
native BlzCreateFrame takes string name, framehandle owner, integer priority, integer createContext returns framehandle
native BlzCreateSimpleFrame takes string name, framehandle owner, integer createContext returns framehandle
native BlzCreateFrameByType takes string typeName, string name, framehandle owner, string inherits, integer createContext returns framehandle
But just concentrate in the 1st and 3rd.
BlzCreateFrame creates a frame defined in an FDF file (not need to learn it now), in the name parameter you write the name of the template, some of those templates are:
Code:
"EscMenuBackdrop"
"QuestButtonBaseTemplate"
"ScoreScreenButtonBackdropTemplate"
"QuestButtonDisabledBackdropTemplate"
"QuestButtonPushedBackdropTemplate"
"ScriptDialogButton"
"DebugButton"
"IconButtonTemplate"
"QuestCheckBox"
"QuestCheckBox2"
"QuestCheckBox3"
"ScoreScreenBottomCheckButtonTemplate"
BlzCreateFrameByType creates a fresh frame that you should define its atributes via scripts, here are the types:
Code:
BACKDROP
BUTTON
CHATDISPLAY
CHECKBOX
CONTROL
DIALOG
EDITBOX
FRAME
GLUEBUTTON
GLUECHECKBOX
GLUEEDITBOX
GLUEPOPUPMENU
GLUETEXTBUTTON
HIGHLIGHT
LISTBOX
MENU
MODEL
POPUPMENU
SCROLLBAR
SIMPLEBUTTON
SIMPLECHECKBOX
SIMPLEFRAME
SIMPLESTATUSBAR
SLASHCHATBOX
SLIDER
SPRITE
STATUSBAR
TEXT
TEXTAREA
TEXTBUTTON
TIMERTEXT
In the parent argument you set the frame parent of the new frame, this frame will be subjected to the visibility and focus of its parent, you can use any frame, but for main frame you create you could use 1 of 3 options:
JASS:
BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0) // Frames appears above the game UI and under the messages and can't be placed in the top right and top left of the screen
BlzGetOriginFrame(ORIGIN_FRAME_WORLD_FRAME, 0) // Frames appears under the game UI and above the messages and can't be placed in the top right and top left of the screen
BlzGetFrameByName("ConsoleUIBackdrop", 0) // Frames appears under the game UI and above the messages and can be placed in the top right and top left of the screen
So an example would be:
JASS:
local framehandle mybutton = BlzCreateFrame("IconButtonTemplate", BlzGetFrameByName("ConsoleUIBackdrop", 0), 0, 0)

Position buttons:
First you have to know how are the coords of the frames:
1688003806422.png

And then set a point of the frame:
JASS:
native BlzFrameSetAbsPoint takes framehandle frame, framepointtype point, real x, real y returns nothing
This function sets the position of a point of the frame in the screen, the points are:
JASS:
FRAMEPOINT_TOPLEFT
FRAMEPOINT_TOP
FRAMEPOINT_TOPRIGHT
FRAMEPOINT_LEFT
FRAMEPOINT_CENTER
FRAMEPOINT_RIGHT
FRAMEPOINT_BOTTOMLEFT
FRAMEPOINT_BOTTOM
FRAMEPOINT_BOTTOMRIGHT
For example, if you wanna the top left of your frame was in the coordinates (0.3, 0.5), you should do:
JASS:
call BlzFrameSetAbsPoint(myFrame, FRAMEPOINT_TOPLEFT, 0.3, 0.5)
In case you wanna the position of the frame was relative to another frame, there is the function:
JASS:
native BlzFrameSetPoint takes framehandle frame, framepointtype point, framehandle relative, framepointtype relativePoint, real x, real y returns nothing
This will make that the frame moves its point whenever the point of the relative frame moves, ideal for menus with buttons, for example, if you wanna the bottom center of a frame was always 0.1 units above another frame you should do:
JASS:
call BlzFrameSetPoint(myFrame, FRAMEPOINT_BOTTOM, relative, FRAMEPOINT_BOTTOM, 0, 0.1)

Adjust the size
There is the function:
JASS:
native BlzFrameSetSize takes framehandle frame, real width, real height returns nothing
is very intuitive how to use it if you understood the previous point, but there is another option, you can set 2 different points and the size will be automatically set (This is how the RUID works and you can test it):
JASS:
// Example of a frame inside the relative frame
BlzFrameSetPoint(myFrame, FRAMEPOINT_TOPLEFT, relative, FRAMEPOINT_TOPLEFT, 0.23, -0.02)
BlzFrameSetPoint(myFrame, FRAMEPOINT_BOTTOMRIGHT, relative, FRAMEPOINT_BOTTOMRIGHT, -0.04, 0.29)
The advantage is you can guarantee that the frame won't have a strange relative size in case the relative frame changes its size, the disadvantage is it is very hard to calculate the sizes you should put.

Frame events
To control the events of the frame is the function:
JASS:
native BlzTriggerRegisterFrameEvent takes trigger whichTrigger, framehandle frame, frameeventtype eventId returns event
For the clicking event is FRAMEEVENT_CONTROL_CLICK, and you should use the function GetTriggerPlayer() to get the player who clicked the frame, an example of this is:
JASS:
function onClick takes nothing returns nothing
    // Prints the name of the player who clicked the frame (is synced to all players)
    call BJDebugMsg(GetPlayerName(GetTriggerPlayer()))
endfunction

function init takes nothing returns nothing
    local framehandle myFrame = BlzCreateFrame("IconButtonTemplate", BlzGetFrameByName("ConsoleUIBackdrop", 0), 0, 0)
    local trigger t = CreateTrigger()
    call BlzTriggerRegisterFrameEvent(t, myFrame, FRAMEEVENT_CONTROL_CLICK)
    call TriggerAddAction(t, function onClick)
endfunction
I insist, if you wanna learn about the frames read the tutorial, because you won't learn that well in another place.
 
Last edited:
Top