Inviting a person to a guild is a hassle, leaving the party can slow you down, inviting someone to join your party is also a little slower than it needs to be.
I was thinking, I want to create and AddOn, where it will always be on the UI, but movable, And has the options of:
Leave Party
Invite to Party
Invite to Guild
Follow
(and maybe more)
But since this is my first time creating an AddOn, i was wondering a few things.
Is the .xml file written by you, or does it create itself after writing the .lua?
How would i 'write' an outside frame, the size, color, transparency, etc etc. In the .xml?
I have what i think would be right for the Leave party inside the .lua:
-- Author : wwwDot
-- Create Date : 11/14/2010 5:05:10 PM
function LeaveParty_OnClick()
if (LeaveParty())
SetText("You have left the party!");
elseif (!LeaveParty())
SetText("You are not in a party!");
end
I'm not sure about the elseif (!LeaveParty()), In JavaScript that would be if it can't leave party.
-- Author : wwwDot
-- Create Date : 11/14/2010 5:05:10 PM
-- function OutsideFrame_OnLoad()
-- OutSideFrame:RegisterEvent("
-- end
function Leave_Party_OnClick()
LeaveParty()
end
-- function InviteGuild_OnClick()
-- end
I used AddOn Studio first, which made the xml but i'm trying to edit it.
but creating the template for the AddOn is what is confusing me.
you dont *have* to have a .lua file, if what you want is fairly simple you can code the whole thing in the xml file - its not totally normal (as in how blizzard do it) but it would work fine.
even if you added a .lua file all youd be doing is pulling the scripts out of the .xml file and putting them into the .lua file (and maybe creating all the xml via lua as well if youre up to it) eg;
Inviting a person to a guild is a hassle, leaving the party can slow you down, inviting someone to join your party is also a little slower than it needs to be.
Yeah, but how often do you really do these things? And, when you do them, when are you really in such a hurry that taking 0.5 seconds to right-click someone's name in chat to bring up a menu and left-click the Invite button "too slow" compared to taking 0.3 seconds to click on an already-visible Invite button? Plus, are you really inviting people to groups so often that you want a button always taking up space on your screen?
If you're inviting people to your guild so often that typing "/ginvite Johnsmith" has become a "hassle", I have absolutely no idea what kind of guild you are running. A button won't really speed this up, either, as you'll still have to type the person's name, unless you want to run to wherever they are in the game world and target them first.** In any case, there are a number of addons that add Guild Invite to the player name right-click menu, and that's probably the fastest way to /ginvite someone.
Finally, there's at least one addon that adds a short slash command ("/lp") for leaving the party, but again, I can't remember the last time I needed to leave a party so fast that right-clicking on my unit frame and then left-clicking the "Leave Party" button in the popup menu really "slowed me down" from anything I actually needed to do in a hurry.
Learning to write addons is great, but the specific addon you're wanting to write seems kind of silly...
-----------------
**And if you're one of those people who spam unsolicited guild invites at every unguilded person you see, well, I hope your account is stolen by gold sellers and your house burns down.
This really was just going to be a test AddOn, it's my first time creating one, so i went simple.
I'm still going to create this, and post what i have so far. I kept going with the .xml file. I am having trouble however, getting the AddOn to 'hide' when entering combat.
EasyControl.lua:
-- Author : wwwDot
-- Create Date : 11/14/2010 5:05:10 PM
function OutsideFrame_OnLoad()
this:RegisterEvent("ENTERING_COMBAT");
end
function OutsideFrame_OnEvent()
if (event == "ENTERING_COMBAT") then
OutsideFrame:Hide()
end
end
function Leave_Party_OnClick()
LeaveParty()
end
function Invite_Guild_OnClick()
GuildInvite(UnitName("target"))
end
function Follow_Target_OnClick()
FollowUnit(UnitName("target"))
end
I'm still going to create this, and post what i have so far. I kept going with the .xml file. I am having trouble however, getting the AddOn to 'hide' when entering combat.
One problem that immediately jumps out is your use of "this" in your OnLoad function and "event" in OnEvent. Whatever reference you're looking at (possibly Addon Studio?) is sorely outdated; WoW no longer sets the global "this", "event", and "argN" variables.
Instead, the arguments are passed directly to your function, in which scope they are local variables.
Your OnLoad function should look like this:
function OutsideFrame_OnLoad([B]self[/B])
[B]self[/B]:RegisterEvent("ENTERING_COMBAT")
end
Your OnEvent function should look like this:
function OutsideFrame_OnEvent([B]self, event[/B])
if [B]event[/B] == "ENTERING_COMBAT" then
[B]self[/B]:Hide()
end
end
A couple other things to mention:
(1) "ENTERING_COMBAT" is not a real event name. "PLAYER_REGEN_DISABLED" is what you're looking for.
(2) If you're only listening for one event, or if you're running the same code in response to every event you're listening for, you don't need to wrap your code in an "if event == X then ... end" check.
(3)However, I think you'll probably also want to listen for "PLAYER_REGEN_ENABLED" to detect when combat ends, so you can show the frame again, in which case you'll want to leave in the check for which event you're handling.
(4) In your OnEvent handler, it's faster to use the local variable "self" to refer to your frame, rather than its global variable "OutsideFrame".
(5) In addition to semicolons, parentheses around comparisons are also unnecessary in Lua. You can use them for clarity in complex statements, but generally they just add clutter to your code. So, "if (event == X) then" should just be "if event == X then", unless you're really used to some other language where parentheses are required and can't break the habit.
(6) In your OnClick functions that look up the target's name, you should add a check to make sure your target is valid for use with the function you're calling, or that it exists at all; otherwise you'll get errors:
function Invite_Guild_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
GuildInvite(UnitName("target"))
end
end
In your follow function, you may also want to check that the target is in range for following, and print a message if not so the user knows why nothing happened when they clicked the button:
function Follow_Target_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
if CheckInteractDistance("target", 4) then
FollowUnit(UnitName("target"))
else
DEFAULT_CHAT_FRAME:AddMessage("Your target is too far away to follow!")
end
end
end
Finally, if you ever release your addon, you should definitely rename most of your UI objects. Names like "FontString1" are super generic; not only are they susceptible to being overwritten by other addons using equally generic names, but if a user is looking at an error message, or using the "/framestack" command to try to identify a problem, seeing a name like "FontString1" doesn't give them any clues as to which addon the object belongs to. Even "OutsideFrame" is pretty generic.
"AddonNameFrame" is good, as are "AddonNameLeavePartyButton", "AddonNameTitleText", and anything else that both identifies which addon created the object, and what the object's intended purpose is.
:Hide() and :Show() cant be called in combat
I suggest using :SetAlpha() and :GetAlpha() instead
Edit: nvm me, got owned by Phanx =.=
@wwwDot: i actually meant self:SetAlpha(0) and originalAlpha = self:GetAlpha() or self:SetAlpha(1) for restoring to original alpha but nvm that again
That's not correct. Hide and Show cannot be called in combat on secure frames such as unit frames or action buttons. You can freely Hide and Show all other (insecure) frames in combat, or at any other time.
Even for secure frames, you can often work around this limitation by using visibility conditions with a secure state driver (which isn't nearly as complicated and scary as it sounds). You could, for example, have a secure frame only show up while you held down the Ctrl key, or while you had a friendly target.
Using SetAlpha is not a good solution, because while it will visually hide the frame, it will not actually hide the frame, so you will end up with an invisible region on the screen that still intercepts mouse clicks.
-- Author : wwwDot
-- Create Date : 11/14/2010 5:05:10 PM
function OutsideFrame_OnLoad(self)
self:RegisterEvent("PLAYER_REGEN_DISABLED")
end
function OutsideFrame_OnEvent(self, event)
if event == "PLAYER_REGEN_DISABLED" then
-- self:Hide()
self:SetAlpha()
-- else
-- if event == "PLAYER_REGEN_ENABLED" then
-- self:GetAlpha()
end
end
function Leave_Party_OnClick()
LeaveParty()
end
function Invite_Guild_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
GuildInvite(UnitName("target"))
end
end
function Follow_Target_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
if CheckInteractDistance("target", 4) then
FollowUnit(UnitName("target"))
else
DEFAULT_CHAT_FRAME:AddMessage("Your target is too far away to follow!")
end
end
end
function Invite_Party_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
InviteUnit(UnitName("target"))
end
end
function Grant_Level_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
GrantLevel(UnitName("target"))
end
end
The hiding still doesn't work :( I'll keep messing around with it.
1. You have to actually register for an event before your frame will receive it.
2. The SetAlpha method requires a number value from 0-1 (inclusive) to be passed with it, and (as per my last post) will not do what you want anyway.
3. I'm not sure why Ketho suggested using the GetAlpha method, as it doesn't actually do anything to the object it's called on; it just returns a number value describing the object's current opacity level.
function OutsideFrame_OnLoad(self)
self:RegisterEvent("PLAYER_REGEN_DISABLED")
self:RegisterEvent("PLAYER_REGEN_ENABLED")
end
function OutsideFrame_OnEvent(self, event)
if event == "PLAYER_REGEN_DISABLED" then
self:Hide()
else
-- You don't need to explicitly check that the event
-- is PLAYER_REGEN_ENABLED, since your frame is
-- only registered for 2 events; if it's not one, then it
-- logically must be the other!
self:Show()
end
end
-- Author : wwwDot
-- Create Date : 11/14/2010 5:05:10 PM
function EasyControlMainFrame_OnLoad(self)
self:RegisterEvent("PLAYER_REGEN_DISABLED")
self:RegisterEvent("PLAYER_REGEN_ENABLED")
end
function EasyControlMainFrame_OnEvent(self, event)
if event == "PLAYER_REGEN_DISABLED" then
self:Hide()
else
self:Show()
end
end
function Leave_Party_OnClick()
LeaveParty()
end
function Invite_Guild_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
GuildInvite(UnitName("target"))
end
end
function Follow_Target_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
if CheckInteractDistance("target", 4) then
FollowUnit(UnitName("target"))
else
DEFAULT_CHAT_FRAME:AddMessage("Your target is too far away to follow!")
end
end
end
function Invite_Party_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
InviteUnit(UnitName("target"))
end
end
function Grant_Level_OnClick()
if UnitIsPlayer("target") and UnitIsFriend("target") then
GrantLevel(UnitName("target"))
end
end
what are those onclicks supposed to be for in there? youve already created onclick scripts for the buttons, im not sure why youre duplicating them here - and creating multiples.
check logs\framexml.log to see if youve got errors in your xml code but those onclicks are probably going to cause issues when you miss a button and click on the frame instead.
btw, youll probably want to use EasyControlMainFrame_OnEvent( self, event ) instead otherwise youre not passing anything in and nothing will happen
it hasnt errored there (nil self) because you dont call EasyControlMainFrame_OnLoad(self), ie youre missing an <OnLoad> script for your main frame
you dont have to wrap each button in its own <Frames></Frames> tags, they can all be in one tag (presuming thats how you want to set it up), so you may want to lose all the extras
might want to post your .toc file - just in case theres something wrong in there.
also, everywhere in your xml where youve got <Button name="xyz"
change it to <Button name="$parent_xyz"
otherwise youll potentially overwrite something of blizzards you shouldnt. the above will end up naming your buttons "EasyControlMainFrame_xyz" because thats the buttons parent frame name.
I was thinking, I want to create and AddOn, where it will always be on the UI, but movable, And has the options of:
Leave Party
Invite to Party
Invite to Guild
Follow
(and maybe more)
But since this is my first time creating an AddOn, i was wondering a few things.
Is the .xml file written by you, or does it create itself after writing the .lua?
How would i 'write' an outside frame, the size, color, transparency, etc etc. In the .xml?
I have what i think would be right for the Leave party inside the .lua:
I'm not sure about the elseif (!LeaveParty()), In JavaScript that would be if it can't leave party.
Can anyone help me out?
and
Neither of them work, I click the button and it delays for about a second and does nothing.
I used AddOn Studio first, which made the xml but i'm trying to edit it.
I got the leave party to work, this part:
<Scripts>
<OnClick>();</OnClick>
</Scripts>
Needed to be:
<OnClick>Leave_Party_OnClick();</OnClick>
I see that now lol, but what is it you guys use for creating the .xml file?
Off the top of your head?
Most of us don't - we generally create our frames in Lua, and eschew XML unless it's absolutely necessary for certain templates.
How would you go about creating it in LUA?
What me and my friend Kaovex are trying to do is create like a grid type thing..
I have the button's down, i think lol, but creating the template for the AddOn is what is confusing me.
you dont *have* to have a .lua file, if what you want is fairly simple you can code the whole thing in the xml file - its not totally normal (as in how blizzard do it) but it would work fine.
even if you added a .lua file all youd be doing is pulling the scripts out of the .xml file and putting them into the .lua file (and maybe creating all the xml via lua as well if youre up to it) eg;
and in EasyControl.lua
if youve got helper functions and other code then youre better off putting it all into the .lua file so its easier to find and update when required.
Your whole addon (at least that you've posted) would be written as:
I think it's much easier to read than XML; it's certanly less verbose.
Also note that semicolons are unnecessary, don't have any actual function, and just make your code more cluttered.
Edit: wowpedia.org (formerly wowwiki) has a great widget API reference that explains all of the functions used in the code above.
Yeah, but how often do you really do these things? And, when you do them, when are you really in such a hurry that taking 0.5 seconds to right-click someone's name in chat to bring up a menu and left-click the Invite button "too slow" compared to taking 0.3 seconds to click on an already-visible Invite button? Plus, are you really inviting people to groups so often that you want a button always taking up space on your screen?
If you're inviting people to your guild so often that typing "/ginvite Johnsmith" has become a "hassle", I have absolutely no idea what kind of guild you are running. A button won't really speed this up, either, as you'll still have to type the person's name, unless you want to run to wherever they are in the game world and target them first.** In any case, there are a number of addons that add Guild Invite to the player name right-click menu, and that's probably the fastest way to /ginvite someone.
Finally, there's at least one addon that adds a short slash command ("/lp") for leaving the party, but again, I can't remember the last time I needed to leave a party so fast that right-clicking on my unit frame and then left-clicking the "Leave Party" button in the popup menu really "slowed me down" from anything I actually needed to do in a hurry.
Learning to write addons is great, but the specific addon you're wanting to write seems kind of silly...
-----------------
** And if you're one of those people who spam unsolicited guild invites at every unguilded person you see, well, I hope your account is stolen by gold sellers and your house burns down.
This really was just going to be a test AddOn, it's my first time creating one, so i went simple.
I'm still going to create this, and post what i have so far. I kept going with the .xml file. I am having trouble however, getting the AddOn to 'hide' when entering combat.
EasyControl.lua:
EasyControl.xml:
Get an umbrella. :)
One problem that immediately jumps out is your use of "this" in your OnLoad function and "event" in OnEvent. Whatever reference you're looking at (possibly Addon Studio?) is sorely outdated; WoW no longer sets the global "this", "event", and "argN" variables.
Instead, the arguments are passed directly to your function, in which scope they are local variables.
Your OnLoad function should look like this:
Your OnEvent function should look like this:
A couple other things to mention:
(1) "ENTERING_COMBAT" is not a real event name. "PLAYER_REGEN_DISABLED" is what you're looking for.
(2) If you're only listening for one event, or if you're running the same code in response to every event you're listening for, you don't need to wrap your code in an "if event == X then ... end" check.
(3)However, I think you'll probably also want to listen for "PLAYER_REGEN_ENABLED" to detect when combat ends, so you can show the frame again, in which case you'll want to leave in the check for which event you're handling.
(4) In your OnEvent handler, it's faster to use the local variable "self" to refer to your frame, rather than its global variable "OutsideFrame".
(5) In addition to semicolons, parentheses around comparisons are also unnecessary in Lua. You can use them for clarity in complex statements, but generally they just add clutter to your code. So, "if (event == X) then" should just be "if event == X then", unless you're really used to some other language where parentheses are required and can't break the habit.
(6) In your OnClick functions that look up the target's name, you should add a check to make sure your target is valid for use with the function you're calling, or that it exists at all; otherwise you'll get errors:
In your follow function, you may also want to check that the target is in range for following, and print a message if not so the user knows why nothing happened when they clicked the button:
Finally, if you ever release your addon, you should definitely rename most of your UI objects. Names like "FontString1" are super generic; not only are they susceptible to being overwritten by other addons using equally generic names, but if a user is looking at an error message, or using the "/framestack" command to try to identify a problem, seeing a name like "FontString1" doesn't give them any clues as to which addon the object belongs to. Even "OutsideFrame" is pretty generic.
"AddonNameFrame" is good, as are "AddonNameLeavePartyButton", "AddonNameTitleText", and anything else that both identifies which addon created the object, and what the object's intended purpose is.
I suggest using :SetAlpha() and :GetAlpha() instead
Edit: nvm me, got owned by Phanx =.=
@wwwDot: i actually meant self:SetAlpha(0) and originalAlpha = self:GetAlpha() or self:SetAlpha(1) for restoring to original alpha but nvm that again
Even for secure frames, you can often work around this limitation by using visibility conditions with a secure state driver (which isn't nearly as complicated and scary as it sounds). You could, for example, have a secure frame only show up while you held down the Ctrl key, or while you had a friendly target.
Using SetAlpha is not a good solution, because while it will visually hide the frame, it will not actually hide the frame, so you will end up with an invisible region on the screen that still intercepts mouse clicks.
The hiding still doesn't work :( I'll keep messing around with it.
2. The SetAlpha method requires a number value from 0-1 (inclusive) to be passed with it, and (as per my last post) will not do what you want anyway.
3. I'm not sure why Ketho suggested using the GetAlpha method, as it doesn't actually do anything to the object it's called on; it just returns a number value describing the object's current opacity level.
Still will not work.
Is there something wrong inside my .xml?
what are those onclicks supposed to be for in there? youve already created onclick scripts for the buttons, im not sure why youre duplicating them here - and creating multiples.
check logs\framexml.log to see if youve got errors in your xml code but those onclicks are probably going to cause issues when you miss a button and click on the frame instead.
btw, youll probably want to use EasyControlMainFrame_OnEvent( self, event ) instead otherwise youre not passing anything in and nothing will happen
it hasnt errored there (nil self) because you dont call EasyControlMainFrame_OnLoad(self), ie youre missing an <OnLoad> script for your main frame
you dont have to wrap each button in its own <Frames></Frames> tags, they can all be in one tag (presuming thats how you want to set it up), so you may want to lose all the extras
might want to post your .toc file - just in case theres something wrong in there.
also, everywhere in your xml where youve got <Button name="xyz"
change it to <Button name="$parent_xyz"
otherwise youll potentially overwrite something of blizzards you shouldnt. the above will end up naming your buttons "EasyControlMainFrame_xyz" because thats the buttons parent frame name.
I have no framexml.log and no error's happened on a miss-click.
They were there originally from when I first made it, didn't really know what I was doing, and I thought that was what I had to do.