WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   auto SetLootMethod (https://www.wowinterface.com/forums/showthread.php?t=54762)

EKE 10-30-16 12:55 PM

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:confused:

i think something wrong in code but dont know how to fix it, wrong event? which should i use?

Fizzlemizz 10-30-16 01:05 PM

You need to check for GetLootMethod before SetLootMethod.

EKE 10-30-16 08:48 PM

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?

Phanx 10-31-16 04:03 AM

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.)

EKE 11-01-16 05:13 AM

Quote:

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.....

Quote:

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)


Phanx 11-02-16 12:30 AM

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


EKE 11-06-16 11:05 PM

Quote:

Originally Posted by Phanx (Post 320592)
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.


All times are GMT -6. The time now is 06:10 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI