Hi there, first post here and a newbie member so thank you for taking the time to read this..

I am an experienced asm/c/c++ programmer that loves wow and am having a go at writing my first addon. I have no problems with events, frames, textures and understanding coding in general.

The problem I have is this.. I am creating a target unit frame ( a simple one ) and all I want it to do right now is dynamically change its width based on the width of the targets name. I have the frame with some text for the name of the target all doing what it should except for combat... now you see my problem, I can't change the width of the frame whilst in combat to match the width of the new targets name, not allowed and I get why.

Thing is I have seen frames dynamically resize whilst in combat.. i.e raid frames, so it must be possible...

Now I think I need to be involved with RegisterStateDriver and secure frame wrapscript etc.. I mean I have a secure frame, that's easy, and I understand setting attributes, however I don't know how to respond to a change of target in the frames secure environment. I do hope this makes sense.. or you get the idea of what i'm trying to do.... should be simple to do I think, but I just can't see it.

Thank you all for reading

Kind regards

v

p.s I have posted this in the wrong forum, I'm very sorry, could a mod please move it for me? Thank you.

Anything clickable for combat, such as buttons or in this case the target frame, cannot be altered while in combat. The raid frames adding people in combat is Blizzard's secure code, which is why they can change. There is very limited options for custom secure code, and moving/resizing is not included.

If you're okay with making a custom target frame that can't be clicked, then you can do whatever you want to it in combat. It could also be possible for a custom static frame with 0 alpha overlaying a frame that can't be clicked, so you can make it look like the target frame is clickable but can still resize visually, but that's beyond me.

Oh, so it's not possible. That's a pain! The problem with an overlay frame is that it would have to be anchored to the secure frame, which as I understand it would make the overlay frame implicitly secure too, if I have understood correctly.

It'a a shame it can't be done. I've seen examples of wrapping arbitrary insecure snippets using 'secureFrame:WrapScript' which essentially executes addon insecure code in a secure environment, actually SUF does exactly that, but it would take a long time to pick out how it works. I just can't find enough information on it to know if it's something I can use.

You wouldn't need to anchor the overlay. Just make two separate frames with manually set coordinates relative to something like UIParent at the same location. The secure frame on top doesn't resize, has 0 alpha, and accepts the clicks while the unsecure frame underneath acts like a background displaying the target name and resizes width accordingly. I'm just tossing the idea out.

Yea, it's a good idea, and it's very likely that it would work fine. I haven't tested it yet but I can't think of a reason why it wouldn't work. You know when you start down a path have to have to solve the problem? That's where I got to with this.... as much as I wanted to understand secure frame handling better. It's going to be a bigger and bigger part of wow I would imagine and it seems important to understand it.

I will try your idea, thank you. In the mean time could you help me with understanding secure frames a bit better... with a snippet I can try? Preferably using the WrapScript method so I can start to understand what it would be used for.

I will try your idea, thank you. In the mean time could you help me with understanding secure frames a bit better... with a snippet I can try? Preferably using the WrapScript method so I can start to understand what it would be used for.

I myself can't really help all that much (I don't understand it well enough yet), but a while ago I had a problem to solve for which MunkDev gave me a ready sollution, which showcases the use of securestatedriver() and restricted environment pretty well, I believe.
For context, my purpose was: when in an actionbar page other than 1, after clicking a button on said page, automatically switch back to page 1 (something you can do with a macro, for each button, like /cast <spell> /changeactionbar 1).
This is what I got from MunkDev:

Originally Posted by MunkDev

I tinkered a bit more with this and you can actually do the same thing with just one button that uses a state driver, a wrapped PreClick and a custom identifier passed as the 'button' argument to the click script.

This solution only uses one secure button, does what you want, and the only drawback is that it won't trigger the first time if you're on a swap page when changing key bindings. This method also works when changing key bindings in combat.

-- append the list for the default bar (1) when none of the conditions apply.

driver = driver .. (#conditions + 1)

-- register the state driver to handle page updates

RegisterStateDriver(header, 'actionpage', driver)

end

-- set up the _onstate-actionpage function body that sets the new actionpage ID.

-- this is a rewrite of the response in ActionBarController_UpdateAll.

-- state drivers use the _onstate-<name> attribute when looking for the function body to run.

-- 'newstate' is the argument passed to all state drivers expressing the outcome

-- of the registered condition, but in this case it's overwritten by the page calculation.

-- note that all code in a restricted environment is written as strings and compiled in

-- real time using loadstring(), to ensure you don't have access to unrestricted API.

header:SetAttribute('_onstate-actionpage', [[

-- update actionpage

if HasVehicleActionBar()then

newstate = GetVehicleBarIndex()

elseif HasOverrideActionBar()then

newstate = GetOverrideBarIndex()

elseif HasTempShapeshiftActionBar()then

newstate = GetTempShapeshiftBarIndex()

elseif GetBonusBarOffset()>0then

newstate = GetBonusBarOffset() + 6

else

newstate = GetActionBarPage()

end

self:SetAttribute('actionpage', newstate)

-- update bindings

self:ClearBindings()

for i=1, 12do

local key = GetBindingKey('ACTIONBUTTON' .. i)

if key then

self:SetBindingClick(false, key, self, tostring(i))

end

end

]])

-- wrap the preclick script on the header

-- use the inherent 'button' argument to tell the header

-- which action button you want to simulate.

-- since PreClick runs before OnClick, you're able to change

-- what the button should do while you're pressing it.

header:WrapScript(header, 'PreClick', [[

if down then

-- set up the downpress attributes to perform the action first

self:SetID(tonumber(button))-- see ActionButton_CalculateAction

self:SetAttribute('type', 'action')

else

-- set the type to actionbar on release, which swaps the bar back

self:SetAttribute('type', 'actionbar')

end

self:CallMethod('OnButtonPressed', down, button)

]])

-- finally, execute the actionpage response on load,

-- to set the correct action page and your override bindings.

-- 'Execute' is included in the SecureHandlerBaseTemplate,

-- and allows you to execute code in a restricted environment.

header:Execute(header:GetAttribute('_onstate-actionpage'))

-- this function is called from the preclick script,

-- which visually indicates a button press on your bar.

-- this part isn't functionally necessary,

-- it just makes it look like you're pressing regular buttons,

-- when you're actually pressing your hidden button.

function header:OnButtonPressed(down, id)

local button = GetActionButtonForID(id)

if button then

if down and button:GetButtonState()=='NORMAL'then

button:SetButtonState('PUSHED')

elseifnot down and button:GetButtonState()=='PUSHED'then

button:SetButtonState('NORMAL')

end

end

end

I have done some very minor tweaking to it since (the code above borks OverrideActionBar - easy to fix; I also tried printing to the UIErrorsFrame ( UIErrorsFrame:AddMessage() ) on which page I was on but that didn't work - works fine with print() to the chat frame though - global frames don't seem to "exist" in the restricted environment).
You can see a list of attributes to use in: https://wow.gamepedia.com/SecureActionButtonTemplate
MunkDev also linked a very helpful (albeit not enough for my lack of coding-skills ) free ebook about the restricted environment: Iriel's Field Guide to Secure Handlers

Thanks, and interesting that you posted that link, as it was the very one I was just reading! and it gives me hope... according to the article it is possible to SetWidth and SetHeight of frames during combat. It says so clearly in the article... the restriction is.. as far as I can tell without testing that..

a) It must be a precompiled "snippet" string of lua code.
b) the frame must be first made available to the secure environment ( which now I know is nothing but a sandbox ) by using Header.SetFrameRef(..) and then inside the snippet the frame can be referenced with Header.GetFrameRef(..)

From there the handle returned can ( if i'm correct ) be used to manipulate many of the frames properties..

i.e Width/Height/Show/Hide/Alpha to name just a few... No moving though.. but that makes sense.

I will try to make a test addon tonight and have it changed the width of a frame during combat, and see if it works.. If so I'll post the code here for anyone to use.

Incidentally, I was way off with thinking WrapScript was the answer..... all it does it "wrap" an existing script handler allowing you to place pre and post snippets of code around it. Kinda makes sense I suppose.

You can change secure attributes in combat, however only in under certain conditions (everything that a macro can do), and you can only access certain functions in the restricted environment, and you can only access your own secure references that you can only set out of combat and while logging into the game, or if your secure reference is a frame you can only access it's sub-methods limited too. UnitName() which would be the handler here for the changes you want to make, is not accessible. So it's not possible.

And... you have the "source" (if I'm not mistaken: the source is actualy in C, I believe, and unavailable; these are the Lua equivalents of the proper source). There is a Blizzard-provided tool for the purpose of extracting the data but I forgot what it is. I do remember it is a lengthy process (lots of data) and some people have kindly posted it on the Internet anyway. For example: https://www.townlong-yak.com/framexml/ptr - RestrictedEnvironment.lua and other Restricted*.lua files should be of interest.

Rightio, for anyone that might be interested in how to accomplish this, here is the quicker and much dirtier answer.....

No need to worry about changing the size of the frame itself. Since texture are not clipped to the frame and they can "live" outside of it, one solution is to have the frame the size of your portrait and then set textures for the fill and border. Simply then anchor the textures to the right side of the fontstring and hey presto. The frame then appears to change size in response to the width of the string ( the targets name in this case ) The only caveat is that the only part of the frame that is clickable is the portrait itself, which in and of itself is desirable is this case... less chance of a random, mid-battle misclick.

Wait a sec... you're saying that the Blizzard function UnitName is not callable from a secure snippet? But why not, that actually doesn't make sense at all.

If you're saying that because said function isn't on the list provided in Wowpedia, well... that's a user-maintained wiki, it's NOT official. It may, and often will, be incomplete or out of date.
The FrameXML source is The Book for that. Only, it can be a pain to get...

Rightio, for anyone that might be interested in how to accomplish this, here is the quicker and much dirtier answer.....

No need to worry about changing the size of the frame itself. Since texture are not clipped to the frame and they can "live" outside of it, one solution is to have the frame the size of your portrait and then set textures for the fill and border. Simply then anchor the textures to the right side of the fontstring and hey presto. The frame then appears to change size in response to the width of the string ( the targets name in this case ) The only caveat is that the only part of the frame that is clickable is the portrait itself, which in and of itself is desirable is this case... less chance of a random, mid-battle misclick.

If you're saying that because said function isn't on the list provided in Wowpedia, well... that's a user-maintained wiki, it's NOT official. It may, and often will, be incomplete or out of date.
The FrameXML source is The Book for that. Only, it can be a pain to get...

Not really, you just add -console argument to your game settings on battle.net app and "exportInterfaceFiles code" on character select screen. Takes the better part of 30 seconds.

Townlong-Yak is useful though for the diffs, and you can probably just work straight off of it without dumping the files yourself. But dumping it yourself you get more than just the FrameXML too, so there's that.

Townlong-Yak is useful though for the diffs, and you can probably just work straight off of it without dumping the files yourself. But dumping it yourself you get more than just the FrameXML too, so there's that.

Another very useful part of townlong-yak is the "Helix" folder, included alongside all the other FrameXML folders. It's where the maintainer of t-y keeps special extracts, such as a full list of every event, every function, all "constants" (ALL_CAPS variables containing only numbers and IDs), widgets and their functions (like FontString, buttons, etc), "atlas" info (basically a bunch of tiny icons within larger images, like how Minecraft stores their icons), and a list of texture paths matched with their new file IDs. Unfortunately, they only have the texture IDs, atlasinfo, and event list available. They haven't extracted the others in a few months.

Wait a sec... you're saying that the Blizzard function UnitName is not callable from a secure snippet? But why not, that actually doesn't make sense at all.

It makes sense since somebody could come up with an secure automation based on the unit's name. CC unit X, nuke unit Y, heal unit Z with a single button. This was entirely possible (and even a lot nastier things too) up to WotLK.

Wait a sec... you're saying that the Blizzard function UnitName is not callable from a secure snippet? But why not, that actually doesn't make sense at all.

This actually makes perfect sense. This is the type of data that can be used to extend the functionality of the environment, which is why it's intentionally left out. For example, you could map buttons to do specific things when targeting specific mobs, instead of having to make the decision of what to cast yourself.