Thread Tools Display Modes
01-22-14, 02:21 PM   #1
Kaelynai
A Murloc Raider
Join Date: Jan 2014
Posts: 5
Confirm Money Dialogue?

Hello all,

I'm relatively inexperienced in writing AddOns for WoW, my only experience has been starting a tiny little stopwatch (for a specific timed world event, Tol Barad) with a slash command. I'm trying to write another simple AddOn, and I'm not sure if what I'm attempting is even possible.

The gist: when you open a Stable Master gossip window, it automatically selects the option to heal and revive your pets. Single-click laziness, and what have you.

The working: when you open a gossip window, it tests to see if there are only two options, confirms that the second option is a Stable Master-only option, then selects the heal my pets option, bringing up a confirmation dialogue.

The problem: I can't seem to figure out how to listen for the popup confirmation window, and then have it auto-accept the 10 silver charge.

The XML code (shortened):
Code:
      <OnLoad>self:RegisterEvent("GOSSIP_SHOW");</OnLoad>
      <OnEvent>StableHealer();</OnEvent>
The LUA code:
Code:
function StableHealer()
  local numOptions = GetNumGossipOptions();
  if numOptions == 2 then
    local opOneText, opOneType, opTwoText, opTwoType = GetGossipOptions();
    if opTwoText == "I'd like to heal and revive my battle pets." and opTwoType == "gossip" then
      print("You're at a stable master!");
      SelectGossipOption(2);
    end
  end
end
The questions: is it possible to automatically accept that fee, maybe while testing that the charge really is only 10 silver (so as not to accidentally accept larger fees from other money dialogues)? If it is possible, could I be provided with the names of the XML/LUA pieces/examples I should research in order to figure out how it's done?

The last bit: thank you to anyone and everyone who helps.
  Reply With Quote
01-22-14, 03:41 PM   #2
jeruku
A Cobalt Mageweaver
 
jeruku's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2010
Posts: 223
Does this help?

Hello.

The event GOSSIP_CONFIRM fires when the confirmation window for NPC dialogues appear. You could, in essence, use the Button:Click() function on the confirm button. There's a few ways you could get the button, the easiest may be using /fstack in game to see the name of the button while it's shown.

You can also use the events values; an index, the message and if there is a cost the cost.
__________________
"I have not failed, I simply found 10,000 ways that did not work." - Thomas Edison
  Reply With Quote
01-22-14, 03:47 PM   #3
Kaelynai
A Murloc Raider
Join Date: Jan 2014
Posts: 5
Thank you, jeruku!

I don't have time to test it right now, but this seems to be exactly the information I was looking for! I'll give it a whirl later tonight to see if I can get it working.

You're a... well, not life saver, but an extra-2-clicks-because-I'm-lazy saver!
  Reply With Quote
01-23-14, 12:39 AM   #4
Kaelynai
A Murloc Raider
Join Date: Jan 2014
Posts: 5
Thanks to help from jeruku (and a little Google-fu), I got this mini AddOn working like a charm.

The XML:
Code:
<Script File="StableHealer.lua"/>
  <Frame name="StableHealer">
    <Scripts>
      <OnLoad function="StableHealer_OnLoad" />
      <OnEvent>StableHealer_OnEvent(self, event);</OnEvent>
    </Scripts>
  </Frame>
The LUA:
Code:
function StableHealer_OnLoad(this)
  this:RegisterEvent("GOSSIP_SHOW");
  this:RegisterEvent("GOSSIP_CONFIRM");
end

function StableHealer_OnEvent(self, event)
  if event == "GOSSIP_SHOW" then
    local numOptions = GetNumGossipOptions();
    if numOptions == 2 then
      local opOneText, opOneType, opTwoText, opTwoType = GetGossipOptions();
      if opTwoText == "I'd like to heal and revive my battle pets." and opTwoType == "gossip" then
        --print("You're at a stable master, select the heal option!");
        SelectGossipOption(2, true);
      end
    end
  elseif event == "GOSSIP_CONFIRM" then
    --print("Confirm that choice!");
    StaticPopup1Button1:Click(LeftButton, down);
  end
end
Thanks again, I couldn't have done it without you!
  Reply With Quote
01-23-14, 01:48 AM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
You really don't need to use XML at all and/or dump everything into the global namespace; unfortunately there are a lot of outdated and just plain bad tutorials floating around.

Here is a cleaner way to do the same thing:
Code:
local StableHealer = CreateFrame("Frame")
StableHealer:RegisterEvent("GOSSIP_SHOW")

StableHealer:SetScript("OnEvent", function(self, event)
	if GetGossipNumOptions() == 2 then
		local _, _, gossipText, gossipType = GetGossipOptions()
		if gossipType == "gossip" and gossipText == "I'd like to heal and revive my battle pets." then
			SelectGossipOption(2, true)
		end
	end
end)

hooksecurefunc("StaticPopup_Show", function(which, text)
	if which == "GOSSIP_CONFIRM" and text == "A small fee for supplies is required." then
		local dialog = StaticPopup_Visible(which)
		if dialog then
			StaticPopup_OnClick(dialog, 1)
		end
	end
end)
Hooking StaticPopup_Show instead of responding to the "GOSSIP_CONFIRM" event will guarantee that your code always runs after the popup is shown; if you just respond to the event, your event handler could theoretically be run before the default UI's event handler has run and shown the popup.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 01-23-14 at 06:51 PM.
  Reply With Quote
01-23-14, 02:10 AM   #6
Kaelynai
A Murloc Raider
Join Date: Jan 2014
Posts: 5
Originally Posted by Phanx View Post
You really don't need to use XML at all and/or dump everything into the global namespace; unfortunately there are a lot of outdated and just plain bad tutorials floating around.
In an effort to show just how unfamiliar I am to all of this, I honestly had no idea you could run an AddOn without using XML.

I'll do some searching on my own of course, but if you know of any updated and just plain good tutorials floating around, I'd certainly like to get my eyes on them and would greatly appreciate any specific links I might miss on my own.

In your code example, what would my AddOn folder look like? I would assume I still use the TOC file and the Lua file - is the XML still necessary for the "<Script File="StableHealer.lua"/>" line? Sorry if these are considered too beginner of questions; I guess I just have no idea where to start learning it the "right" way.
  Reply With Quote
01-23-14, 03:28 AM   #7
Choonstertwo
A Chromatic Dragonspawn
 
Choonstertwo's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2011
Posts: 194
Originally Posted by Kaelynai View Post
In an effort to show just how unfamiliar I am to all of this, I honestly had no idea you could run an AddOn without using XML.

I'll do some searching on my own of course, but if you know of any updated and just plain good tutorials floating around, I'd certainly like to get my eyes on them and would greatly appreciate any specific links I might miss on my own.

In your code example, what would my AddOn folder look like? I would assume I still use the TOC file and the Lua file - is the XML still necessary for the "<Script File="StableHealer.lua"/>" line? Sorry if these are considered too beginner of questions; I guess I just have no idea where to start learning it the "right" way.
You can get rid of the XML file completely and just list the Lua file in the TOC.
  Reply With Quote
01-23-14, 03:30 AM   #8
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
No, you just call the Lua file in your TOC:

Code:
## Interface: 50400
## Title: MyAddon
## Notes: Does some stuff!

MyFile.lua
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-23-14, 12:09 PM   #9
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Originally Posted by Phanx View Post
[...]
Code:
local StableHealer = CreateFrame("Frame")
StableHealer:RegisterEvent("GOSSIP_SHOW")

StableHealer:SetScript("OnEvent", function(self, event)
	if GetGossipNumOptions() == 2 then
		local _, _, gossipText, gossipType = GetGossipOptions()
		if gossipType == "gossip" and gossipText == "I'd like to heal and revive my battle pets." then
			SelectGossipOption(2, true)
		end
	end
end)

hooksecurefunc("StaticPopup_Show", function(which, text)
	if which == "GOSSIP_CONFIRM" and text == "A small fee for supplies is required." then
		local dialog = StaticPopup_Visible(which)
		if dialog then
			StaticPopup_OnClick(dialog, 1)
		end
	end
end)
[...]
Shouldn't the comparison operator be used here instead of an assignment operator Phanx?
  Reply With Quote
01-23-14, 06:37 PM   #10
Nimhfree
A Frostmaul Preserver
AddOn Author - Click to view addons
Join Date: Aug 2006
Posts: 267
Originally Posted by Kaelynai View Post
In an effort to show just how unfamiliar I am to all of this, I honestly had no idea you could run an AddOn without using XML.
Usually it is easier to read/understand what an addon is doing if the frames and the code are together. The XML is where people have historically put frames. Nowadays, the XML file is really only needed for two things:

(1) virtual objects
(2) really complex frame setups that need the added speed of a native interpreter to generate efficiently

And technically I am not sure about #2 as I have never needed to create anything too complex.

I am not sure about places to find good tutorials, but reading code is a good place to get ideas. Phanx shows a good pattern for making a hidden frame that can handle an event to do something useful. The only difference I would make is I would set up the "OnEvent" script before I register for the event, but that is me. I will give another very similar example that I use to sell grey items automatically when I interact with a vendor:


Code:
--	Create a simple frame that allows grey quality items to be sold automatically
local sellFrame = CreateFrame("Frame")
sellFrame:SetScript("OnEvent", function()
		for bag = 0, 4 do
			for slot = 1, GetContainerNumSlots(bag) do
				local _, _, locked, _, _, _, link = GetContainerItemInfo(bag, slot)	-- will return -1 for quality a lot
				if nil ~= link then
					local _, _, realQuality, _, _, _, _, _, _, _, vendorPrice = GetItemInfo(link)
					if 0 == realQuality and 0 ~= vendorPrice and not locked then
						UseContainerItem(bag, slot)
					end
				end
			end
		end
	end)
sellFrame:RegisterEvent("MERCHANT_SHOW")
Now comments about this:

The "OnEvent" script is going to be run for EVERY event this frame receives. This frame only registers for one event, so we are ok since we know the script will only be run when we expect it. However, if more than one event were registered we may actually need to know what event is being sent. We would handle this by adding parameters to the function() defined so we could check those to determine what actions to take.

Note how sellFrame is considered a local variable. This means that it can only be referenced within this file. No one in the outside world can access this frame using the sellFrame name. This frame was created without giving it a global name. If you look at the CreateFrame() API it shows there are others parameters you can pass it including a name. If it were created with a global name you could access it from anywhere. So, you may ask how Blizzard is able to send us the events we want. That is done by us calling RegisterEvent. Basically our frame is added to the list of frames that are to receive "MERCHANT_SHOW" events. Blizzard does not need to refer to us by any specific name. Since we are not giving the frame a global name, and we are not assigning it to a non-local variable we are not polluting the global name space. A good goal is to minimize the amount of things that get put into the global name space, because you never know what other addons may add as well. If you were to create things in the global namespace you would probably want to name them based on your addon name or reverse DNS names if you have a domain you control.

Enough rambling. Enjoy.
  Reply With Quote
01-23-14, 06:59 PM   #11
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by ravagernl View Post
Shouldn't the comparison operator be used here instead of an assignment operator Phanx?
Yes; fixed. Good catch.

Originally Posted by Nimhfree View Post
Phanx shows a good pattern for making a hidden frame that can handle an event to do something useful. The only difference I would make is I would set up the "OnEvent" script before I register for the event, but that is me.
It doesn't matter, as long as both are done in the main chunk, as no events are fired in the middle of a file read anyway. I find it more readable to have the frame definition and event registration in one "blob" and the function separate.

Originally Posted by Nimhfree View Post
If you were to create things in the global namespace you would probably want to name them based on your addon name or reverse DNS names if you have a domain you control.
... what? Why are you using DNS names for UI objects in World of Warcraft? Just use your addon name so that a normal non-technical user can immediately identify error messages about it as belonging to your addon... also, who wants to type "net.phanx.PhanxChat.EventFrame" instead of just "PhanxChat" for in-game debugging? o_O
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.

Last edited by Phanx : 01-25-14 at 06:16 PM.
  Reply With Quote
01-24-14, 07:54 AM   #12
Vlad
A Molten Giant
 
Vlad's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2005
Posts: 793
Originally Posted by Phanx View Post
Why are you using DNS names for UI objects in World of Warcraft? Just use your addon name so that a normal non-technical user can immediately identify error messages about it as belonging to your addon... also, who wants to type "net.phanx.PhanxChat.EventFrame" instead of just "PhanxChat" for in-game debugging? o_O
http://en.wikipedia.org/wiki/Reverse..._name_notation
__________________
Profile: Curse | Wowhead
  Reply With Quote
01-24-14, 06:15 PM   #13
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Yes, I'm familiar with the naming convention itself. I just can't imagine why on earth you would ever use it for UI objects in a WoW addon.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
01-25-14, 01:57 AM   #14
Kaelynai
A Murloc Raider
Join Date: Jan 2014
Posts: 5
Thanks Nimhfree!

It took me a couple days to parse what started out looking like gibberish until it became more understandable. I still have a limited grasp of Lua - all my programming experience comes from JavaScript circa 1997.

It wasn't clear to me before Phanx and your code snippets that frames were only code objects. For some reason, I was under the impression that they were UI objects, and I couldn't figure out why I'd want to add more clutter to my screen. I am no longer under that impression.

Just the simple tip of knowing that I can create a frame to listen for my events is going to be a major help in my future endeavors, so I really appreciate both of you taking the time to elucidate.

I've since gone through this forum (and others) looking for the most up to date guides and tutorials, so hopefully the next time I'm stumped it won't be because I lack basic understanding.

Your help here has been an invaluable learning experience for me, and I just want you both to know that I really am grateful for it. This has been the best "ask strangers on the internet for help" experience I've had to date.
  Reply With Quote
01-25-14, 07:10 AM   #15
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Originally Posted by Phanx View Post
... what? Why are you using DNS names for UI objects in World of Warcraft? Just use your addon name so that a normal non-technical user can immediately identify error messages about it as belonging to your addon... also, who wants to type "net.phanx.PhanxChat.EventFrame" instead of just "PhanxChat" for in-game debugging? o_O
Eh? I haven't said that
  Reply With Quote
01-25-14, 02:11 PM   #16
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Phanx made a mistake in her quoting. It was Nimhfree who said that.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Confirm Money Dialogue?


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off