Quantcast
auto SetLootMethod - WoWInterface
Thread Tools Display Modes
10-30-16, 12:55 PM   #1
EKE
An Aku'mai Servant
 
EKE's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2011
Posts: 33
auto SetLootMethod

i'm trying make a addon for my guild because they almost always forget to change loot method in raid.

Code:
local frame = CreateFrame("Frame")
frame:RegisterEvent("GROUP_ROSTER_UPDATE")
local function eventHandler(self, event, ...)
    if IsInRaid() and UnitInRaid("player") and UnitIsGroupLeader("player") then
	if event == "GROUP_ROSTER_UPDATE" then
	if InGuildParty()
	then
          SetLootMethod("master", UnitName("player"))
	  print("master")
	else
	  SetLootMethod("freeforall")
	  print("free")
        end
        end
  end
end
frame:SetScript("OnEvent", eventHandler)
it can auto select loot method now, but it'll try to select every second never end

i think something wrong in code but dont know how to fix it, wrong event? which should i use?
  Reply With Quote
10-30-16, 01:05 PM   #2
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,292
You need to check for GetLootMethod before SetLootMethod.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
10-30-16, 08:48 PM   #3
EKE
An Aku'mai Servant
 
EKE's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2011
Posts: 33
thanks, it works now:
Code:
local frame = CreateFrame("Frame")
frame:RegisterEvent("PARTY_LOOT_METHOD_CHANGED")
local function eventHandler(self, event, ...)
	local method, _, _ = GetLootMethod()	
	if event == "PARTY_LOOT_METHOD_CHANGED" then	
	if method ~= master or freeforall then	
	if IsInRaid() and UnitInRaid("player") and UnitIsGroupLeader("player") then
	if InGuildParty()
	then
      SetLootMethod("master", UnitName("player"))
	else
	  SetLootMethod("freeforall")
  end
  end 
  end

  end
end
frame:SetScript("OnEvent", eventHandler)
but now they ask a PopupDialogs frame to check because dont need this when doing a premade-group, should keep personal loot.

i have no idea to do that. maybe slash command to enable/disable is better way?
  Reply With Quote
10-31-16, 04:03 AM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
You can check for normal vs instance (premade) group by passing a specifier to IsInRaid:
http://wow.gamepedia.com/API_IsInRaid

However, your code will currently not work, for several reasons. Most importantly:

Code:
if method ~= master or freeforall then
This is the equivalent of saying "if the value of the method variable is different than the value of the master variable, or if the value of the freeforall variable is not false/nil, then..." which is not what you want at all. The words "master" and "freeforall" should be quoted, since they are strings, not variables. Also, you need to explicitly compare each one against the method variable; Lua doesn't have a shorthand "compare X against multiple values" syntax. Here's the correct syntax:

Code:
if method ~= "master" or method ~= "freeforall" then
Less importantly, you probably don't want to check like this at this level anyway. Currently, if you become the leader of a guild raid, and the loot method is already "freeforall", then your code will not change it to "master". Likewise, if the method is "master" and someone from outside the guild joins (making it no longer a guild raid) then your code will not change the loot method to "freeforall".

Apart from that, some other issues / suggestions / hints:
  • Indentation. Yours is mostly missing, and makes your code very hard to read. Each "if/end" statement should add another level of indentation for everything inside of it. You shouldn't write "then" keywords on a separate line, but if you really want to for some reason, at least be consistent and do it everywhere (but really, just don't do it!).
  • PARTY_LOOT_METHOD_CHANGED is not the correct event to listen for in your case; it will not fire when you become the group leader, or when your group becomes a guild/non-guild group, etc. Use GROUP_ROSTER_UPDATE like in your original code. That is the correct event to use when you want to know about group state changes.
  • You don't need to check the event inside your handler. Your frame only registered for one event, so it will never receive any other events.
  • You don't need to define the event handler function outside of the SetScript call. The only reason to do so would be to make it easier to call the same function from some other place in your code.
  • You don't need to check both IsInRaid() and UnitInRaid("player") -- they both do (essentially) the same thing. Just check IsInRaid().
  • You shouldn't define the method variable until after you've checked if you're the leader in a raid -- if you're not, then you won't use this variable, so there's no reason to have spent CPU time calling GetLootMethod() and memory storing its return value in the variable at that point. Generally speaking, you should always define variables in the most limited scope possible.
  • You should also check, and not call SetLootMethod again, if the current loot method is already what you want.
  • Since you only use the first value returned by GetLootMethod, and you only use it once, there's no need to assign it to a variable; just call it directly in the comparison statement.
  • You can just store the value from UnitName("player") in a variable, so you don't have to call it again each time.
  • Since you know your event doesn't have any arguments, and you don't use the self and event arguments, you can save some typing by not naming any arguments in the function declaration.

Here's an updated version:

Code:
local player = UnitName("player")

local frame = CreateFrame("Frame")
frame:RegisterEvent("GROUP_ROSTER_UPDATED")
frame:SetScript("OnEvent", function()
	if IsInRaid(LE_INSTANCE_TYPE_HOME) and UnitIsGroupLeader("player") then
		local wanted = InGuildParty() and "master" or "freeforall"
		if GetLootMethod() ~= wanted then
			SetLootMethod(wanted, player)
		end
	end
end)
(Passing a player name to SetLootMethod has no effect if the method isn't "master", so you don't need two different code paths to call it with or without the second argument.)
__________________
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
11-01-16, 05:13 AM   #5
EKE
An Aku'mai Servant
 
EKE's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2011
Posts: 33
However, your code will currently not work, for several reasons. Most importantly:
awwww I'm stupid!
for my bad lua knowledge i usually forget correct logic lol
so that code magically worked as a wrong way.....

Apart from that, some other issues / suggestions / hints:
thank you i've learn lots from this!

Indentation was lost when i copy to thread (i delete some note when copy it).

what thay need -- sloved:
1.auto select master loot in guild team.
2.auto select freeforall if not in a guild team.
they are release now.
------
what thay need -- now doing:
3.need keep personal loot when sometimes make a premade group, so need a function to disable it.
>do not auto select, creat a frame show option just like "wanna change loot method? [presonal] [master] [freeforall]" when leader make a group or get into a instance.
>a slash cmd to enable/disable addon.

form this, in fact i think they just need a Popup frame to "remind them change loot method if need".

so i try another thing: make a frame to remind ppl when they get into raid.
is this way correct?

Code:
local f = CreateFrame("Frame")
f:SetPoint("CENTER", UIParent, "CENTER", 0, 120)
f:SetSize(150, 70)
f:Hide()
f.Text = f:CreateFontString(nil, "OVERLAY")
f.Text:SetFont(STANDARD_TEXT_FONT, 16, OUTLINE)
f.Text:SetPoint("CENTER", f)

f:RegisterEvent("ZONE_CHANGED_NEW_AREA")
f:RegisterEvent("PLAYER_ENTERING_WORLD")

f:SetScript("OnEvent", function()
	if IsInRaid() and UnitIsGroupLeader("player") then
		f:Show()
		f.Text:SetText("check loot method!")
	else
		f:Hide()
	end
end)
f:SetScript("OnMouseUp", function()
	f:Hide()
end)

Last edited by EKE : 11-01-16 at 05:57 AM.
  Reply With Quote
11-02-16, 12:30 AM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
That will work... but it will only trigger when you either (a) move from one zone map to another or (b) enter or leave an instance. To make it trigger only when you change from "leader of a raid" to "not leader of a raid" you'd need to (a) listen for a different event and (b) keep track of which state you were in (to avoid triggering it repeatedly if the state wasn't changing). Example:

Code:
f:RegisterEvent("GROUP_ROSTER_UPDATE")

local isLeader = false

f:SetScript("OnEvent", function()
	local isLeaderNow = IsInRaid() and UnitIsGroupLeader("player")
	if IsLeaderNow == isLeader then return end
	isLeader = isLeaderNow

	if isLeaderNow then
		f:Show()
		f.Text:SetText("check loot method!")
	else
		f:Hide()
	end
end)
Other stuff:

When you create a frame that's visible on screen, it must be parented to the UIParent, or to something else whose parentage traces back to the UIParent. Otherwise, it will (a) not be hidden with Alt-Z and (b) won't respect the user's UI scale setting.
Code:
local f = CreateFrame("Frame", nil, UIParent)
You can just set the frame's text once when you create it. Since you only ever show one message, there's no need to set and un-set it when you show and hide the frame. While the frame is hidden, you won't see the message either!

If you want to be able to click on the frame, you need to turn on mouse interactivity:
Code:
f:EnableMouse(true)
If you do that, I'd recommend also resizing the frame so it's exactly the size of the message text (after you set the text):
Code:
f:SetWidth(f.Text:GetStringWidth())
f:SetHeight(f.Text:GetStringHeight())
Instead of needing to click to hide the message, you could also make it hide automatically after a certain amount of time:
Code:
f:Show()
C_Timer.After(10, function() f:Hide() end)
Or you could make a more traditional dialog-type frame with buttons. Here's an example that mimics the static popup dialog. You could just inherit from the template, but then you'd have to hide things and remove scripts you don't need, so it's better just to copy the parts you need. I've written them out here in Lua in the same order they appear in the XML, so you can follow along and see how XML is translated into Lua. Green highlights things that are specific to your addon, and not from the template.
Code:
local f = CreateFrame("Frame", "LeaderLootReminder", UIParent)
f:SetToplevel(true)
f:EnableKeyboard(true)
f:EnableMouse(true)
f:SetFrameStrata("DIALOG")
f:Hide()

f:SetSize(320, 72)

f:SetBackdrop({
	bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]],
	edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]],
	tile = "true",
	insets = { left="11", right="12", top="12", bottom="11" },
	tileSize = 32,
	edgeSize = 32
})

f.text = f:CreateFontString("$parentText", "ARTWORK", "GameFontHighlight")
f.text:SetWidth(290)
f.text:SetPoint("TOP", 0, -16)
f.text:SetText("You are now a raid leader!\nPick your loot method:")

f.close = CreateFrame("Button", "$parentCloseButton", f, "UIPanelCloseButton")
f.close:SetPoint("TOPRIGHT", -3, -3)

local function Button_OnClick(self)
	local me = UnitName("player")
	SetLootMethod(self.lootType, me)
end

f.button1 = CreateFrame("Button", "$parentButton1", f, "StaticPopupButtonTemplate")
f.button1:SetPoint("BOTTOMRIGHT", f, "BOTTOM", -72, 16)
f.button1:SetText("Group Loot")
f.button1.lootType = "group"

f.button2 = CreateFrame("Button", "$parentButton2", f, "StaticPopupButtonTemplate")
f.button2:SetPoint("LEFT", f.button1, "RIGHT", 13, 0) -- (source)
f.button2:SetText("Free For All")
f.button2.lootType = "freeforall"

f.button3 = CreateFrame("Button", "$parentButton3", f, "StaticPopupButtonTemplate")
f.button3:SetPoint("LEFT", f.button2, "RIGHT", 13, 0)
f.button3:SetText("Master Looter")
f.button3.lootType = "master"

f:SetScript("OnEscapePressed", function(self)
	self:Hide()
end)

function f:SetAnchor(self)
	for i = 1, STATICPOPUP_NUMDIALOGS do
		local popup = _G["StaticPopup"..i]
		if popup:IsShown() then
			return self:SetPoint("TOP", popup, "BOTTOM")
		end
	end
	self:SetPoint("TOP", UIParent, 0, -135)
end

f:SetScript("OnShow", f.SetAnchor)
hooksecurefunc("StaticPopup_Show", f.SetAnchor)

-- Handle events here
__________________
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 : 11-02-16 at 12:41 AM.
  Reply With Quote
11-06-16, 11:05 PM   #7
EKE
An Aku'mai Servant
 
EKE's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2011
Posts: 33
Originally Posted by Phanx View Post
That will work...
sorry for late reply, thank you very much,

i just thinking about a remind at first, learn a lot from this thread.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » auto SetLootMethod

Thread Tools
Display Modes

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