WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   AddOn Help/Support (https://www.wowinterface.com/forums/forumdisplay.php?f=3)
-   -   SwapRaidSubgroup with String... (https://www.wowinterface.com/forums/showthread.php?t=46375)

Anja 05-01-13 03:14 PM

SwapRaidSubgroup with String...
 
hi, i work on a little function that sorts my raid from a string that i give...

Code:

function doRaid()
        local msg = URLFrameEditBox:GetText();
        URLFrameEditBox:SetText("")
        URLFrame:Hide();
        rs = {}
        gr = {}
        cg = {}
        local num = GetRealNumRaidMembers();
                       
                for i = 1, 40 do
                        local u = "raid"..i;
                        name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML, combatRole = GetRaidRosterInfo(i);
                        if UnitExists(u) then
                                rs[UnitName(u)] = { index = i, subgroup = subgroup };
                                if cg[subgroup] then
                                        grpc = cg[subgroup];
                                else
                                        grpc = 0;
                                end
                                cg[subgroup] = tonumber(grpc)+1;
                        end
                end
               
                local positions = { strsplit("&", msg) }
                if msg ~= "" then
                        for i,ine in ipairs(positions) do
                                local ois = { strsplit(":", ine) }
                                local name = ois[1];
                                local group = ois[2];
                               
                                if rs[name] then                                       
                                        if tonumber(rs[name]['subgroup']) ~= tonumber(group) then
                                                if cg[group] == 5 then
                                                        for i, irs in pairs(rs) do
                                                                if tonumber(irs.subgroup) == tonumber(group) then
                                                                        if rs[i].subgroup ~= group then
                                                                                SwapRaidSubgroup(rs[name]['index'],irs.index);
                                                                                return true
                                                                        end
                                                                end
                                                        end
                                                else
                                                        SetRaidSubgroup(rs[name]['index'],group);
                                                end
                                        end
                                end
                        end
                end

end

the string is like that: Ikuria:4&Achot:2
it came from this page: http://absence-gilde.com/?p=raidposi&b=1&s=1&g=1&u=0&e

to swap Ikuria in Group 4 and Achot to 2, but now the problem - if the group is full, it doesnt work - so i test it to count the group and if full then use swap, but... hmmm i have not the skill to do it right... can someone help?

Phanx 05-01-13 07:51 PM

Not tested at all, but something like this should work. I think your main problems are that (1) you're not updating the current raid state table when you make a swap, and (2) you're quitting after making one swap.

Code:

local current, numInGroup = {}, {}

local function UpdateRaidState()
        wipe(raidState)
        wipe(numInGroup)
        for i = 1, GetNumGroupMembers() do
                local _, _, group = GetRaidRosterInfo(i)
                current[name] = { index = i, group = group }
                numInGroup[group] = (numInGroup[group] or 0) + 1
        end
end

function SortRaid(str)
        -- Get a snapshot of the current raid layout:
        UpdateRaidState()

        local wanted = {}
        -- Build a map of the desired raid layout:
        for name, group in string.gmatch(str, "([^&:]):(%d)") do
                -- Ignore named players not in the raid.
                if current[name] then
                        wanted[name] = group
                end
        end

        -- Look for players not in the wanted group and move them:
        for name, group in pairs(wanted) do
                if current[name].group ~= group then
                        if numInGroup[group] < 5 then
                                -- Just move them:
                                SetRaidSubgroup(current[name].index, group)
                        else
                                -- Look for someone to swap with:
                                for xname, xdata in pairs(current) do
                                        if xdata.group == group and wanted[xname] ~= group then
                                                -- Do the swap:
                                                SwapRaidSubgroup(current[name].index, xdata.index)
                                                -- Update the snapshot:
                                                UpdateRaidState()
                                        end
                                end
                        end
                end
        end
end


Anja 05-01-13 11:36 PM

theres is a problem with

Code:

local raidState, numInGroup = {}, {}
local function UpdateRaidState()
        wipe(raidState)
        wipe(numInGroup)
        for i = 1, GetNumGroupMembers() do
                local _, _, group = GetRaidRosterInfo(i)
                current[name] = { index = i, group = group }
                numInGroup[group] = (numInGroup[group] or 0) + 1
        end
end

index of current and numInGroup are nil or dont know...

testing with 2 other people in raid, and it doesnt work

Phanx 05-02-13 12:04 AM

Fixed; edited my previous post.

Anja 05-02-13 07:45 AM

thanks for help, but it doesnt work... i always find errors,

wipe(raidstate) raidstate is old array right?
current undefined index (name?) so there is no name in the updateraidstate funktion, same on numInGroup key (group) i think... so, if you have time, can you check this addon ingame?

Anja 05-02-13 12:35 PM

okay i killed the most errors, but now i think the regex is wrong, can you help with that?

name:2&name:5&name:1

name:group


[edit]
found:
Code:

"([^&:]+):(%d+)"
Next error:
3x Raidstring\Raidstring.lua:51: attempt to compare nil with number

Anja 05-02-13 12:55 PM

Done, worked (hope in raid too)

Code:

SLASH_RAIDSTRING1 = "/rs"
SLASH_MAKERAID1 = "/rm"

ClassTable = {
        ["WARRIOR"] = 1,
        ["ROGUE"] = 2,
        ["HUNTER"] = 3,
        ["PALADIN"] = 4,
        ["SHAMAN"] = 5,
        ["DRUID"] = 6,
        ["WARLOCK"] = 7,
        ["MAGE"] = 8,
        ["PRIEST"] = 9,
        ["DEATHKNIGHT"] = 10,
}

SlashCmdList["MAKERAID"] = function(msg, editBox)
        URLFrame:Show();
end

local current, numInGroup = {}, {}

local function UpdateRaidState()
        wipe(numInGroup)
        wipe(current)
        for i = 1, GetNumGroupMembers() do
                local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(i);
                current[name] = { index = i, group = subgroup }
                numInGroup[subgroup] = (numInGroup[subgroup] or 0) + 1
        end
end

function SortRaid()
        local str = URLFrameEditBox:GetText();
        -- Get a snapshot of the current raid layout:
        UpdateRaidState()

        local wanted = {}
        -- Build a map of the desired raid layout:
        for name, group in string.gmatch(str, "([^&:]+):(%d+)") do
                -- Ignore named players not in the raid.
                if current[name] then
                        wanted[name] = group
                end
        end

        -- Look for players not in the wanted group and move them:
        for name, group in pairs(wanted) do
                if current[name].group ~= group then
                        if numInGroup[group] then
                                if numInGroup[group] or numInGroup[group] < 5 then
                                        -- Just move them:
                                        SetRaidSubgroup(current[name].index, group)
                                else
                                        -- Look for someone to swap with:
                                        for xname, xdata in pairs(current) do
                                                if xdata.group == group and wanted[xname] ~= group then
                                                        -- Do the swap:
                                                        SwapRaidSubgroup(current[name].index, xdata.index)
                                                        -- Update the snapshot:
                                                        UpdateRaidState()
                                                end
                                        end
                                end
                        else
                                SetRaidSubgroup(current[name].index, group)
                        end
                end
        end
end

function setContains(set, key)
    return set[key] ~= nil
end

SlashCmdList["RAIDSTRING"] = function(msg, editBox)
        bool = UnitInRaid("player");
        name, realm = UnitName("player");
        if bool then
                local membercount = GetNumGroupMembers();
                guildName = GetGuildInfo("player");
                local realm = GetRealmName();
                xml = "<RaidInfo><Info>Raidassist</Info><Password>W2Any"..realm.."dEAv"..name.."2AxaS</Password><Realm>"..realm.."</Realm><Guild>"..guildName.."</Guild><Name>"..name.."</Name><PlayerInfos>";
                for i=1, membercount do
                        local localizedClass, englishClass = UnitClass("raid" .. i);
                        local name, online = UnitName("raid" .. i)
                       
                        xml = xml.. "<key"..i.."><name>"..name.."</name><class>"..englishClass.."</class></key"..i..">";
                end
                xml = xml.."</PlayerInfos></RaidInfo>";
                ShowDkpLink(xml);
        end
end

function ShowDkpLink(link)
        URLFrameEditBox:SetText(link);
        URLFrameEditBox:HighlightText();
        URLFrame:Show();
end

Download AddOn: **snip**
Raidassist Page: http://absence-gilde.com/?p=raidposi&b=1&s=1&g=1&u=0&e

Phanx 05-02-13 07:35 PM

Just a couple things:

1. You're creating a lot of generically named global variables like "ClassTable" and "setContains". Don't do this. Make those variables local instead, or (if they need to be accessed from other addons or via in-game /run commands) at least give them distinct names, like "MyAddonName_ClassTable" and "MyAddonName_SetContains".

Globals are slower to access than locals, and generically named globals have a tendency to overwrite (or be overwritten by) other generacally named globals from other addons or even the default UI. For example, at one point many authors were lazily putting a variable named "_" in the global namespace. Then Blizzard accidentally did the same thing, and suddenly there were hundreds of addons completely breaking parts of the default UI because they were tainting the "_" global.

Also, if users see an error message about "setContains" they won't have any idea what that means, or what's causing it. If they see an error about "MyAddonName_SetContains" they can immediately tell which addon is causing that error, and tell you about the problem.

2. Your "setContains" function in general is completely useless. Instead of if setContains(tbl, "x") then, just do if tbl["x"] then. There's no reason to explicitly check it against nil unless you need to distinguish between nil and false for some reason, and even then, you should just do it directly instead of wasting CPU time on an extra function call. Calling functions is about the slowest thing you can do in Lua, so you should avoid doing it when you don't need to do it.

3. After having said all that, you're not actually using either the "ClassTable" table or the "setContains" function so you should just remove them and clean up any other variables you're not using. :p

Anja 05-03-13 09:38 AM

please make it right, and post it for me :(

Tim 05-03-13 10:52 AM

Code:

SLASH_RAIDSTRING1 = "/rs"
SLASH_MAKERAID1 = "/rm"

local ClassTable = {
        ["WARRIOR"] = 1,
        ["ROGUE"] = 2,
        ["HUNTER"] = 3,
        ["PALADIN"] = 4,
        ["SHAMAN"] = 5,
        ["DRUID"] = 6,
        ["WARLOCK"] = 7,
        ["MAGE"] = 8,
        ["PRIEST"] = 9,
        ["DEATHKNIGHT"] = 10,
}

SlashCmdList["MAKERAID"] = function(msg, editBox)
        URLFrame:Show();
end

local current, numInGroup = {}, {}

local function UpdateRaidState()
        wipe(numInGroup)
        wipe(current)
        for i = 1, GetNumGroupMembers() do
                local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(i);
                current[name] = { index = i, group = subgroup }
                numInGroup[subgroup] = (numInGroup[subgroup] or 0) + 1
        end
end

local function SortRaid()
        local str = URLFrameEditBox:GetText();
        -- Get a snapshot of the current raid layout:
        UpdateRaidState()

        local wanted = {}
        -- Build a map of the desired raid layout:
        for name, group in string.gmatch(str, "([^&:]+):(%d+)") do
                -- Ignore named players not in the raid.
                if current[name] then
                        wanted[name] = group
                end
        end

        -- Look for players not in the wanted group and move them:
        for name, group in pairs(wanted) do
                if current[name].group ~= group then
                        if numInGroup[group] then
                                if numInGroup[group] or numInGroup[group] < 5 then
                                        -- Just move them:
                                        SetRaidSubgroup(current[name].index, group)
                                else
                                        -- Look for someone to swap with:
                                        for xname, xdata in pairs(current) do
                                                if xdata.group == group and wanted[xname] ~= group then
                                                        -- Do the swap:
                                                        SwapRaidSubgroup(current[name].index, xdata.index)
                                                        -- Update the snapshot:
                                                        UpdateRaidState()
                                                end
                                        end
                                end
                        else
                                SetRaidSubgroup(current[name].index, group)
                        end
                end
        end
end

local function setContains(set, key)
    return set[key] ~= nil
end

SlashCmdList["RAIDSTRING"] = function(msg, editBox)
        bool = UnitInRaid("player");
        name, realm = UnitName("player");
        if bool then
                local membercount = GetNumGroupMembers();
                guildName = GetGuildInfo("player");
                local realm = GetRealmName();
                xml = "<RaidInfo><Info>Raidassist</Info><Password>W2Any"..realm.."dEAv"..name.."2AxaS</Password><Realm>"..realm.."</Realm><Guild>"..guildName.."</Guild><Name>"..name.."</Name><PlayerInfos>";
                for i=1, membercount do
                        local localizedClass, englishClass = UnitClass("raid" .. i);
                        local name, online = UnitName("raid" .. i)
                       
                        xml = xml.. "<key"..i.."><name>"..name.."</name><class>"..englishClass.."</class></key"..i..">";
                end
                xml = xml.."</PlayerInfos></RaidInfo>";
                ShowDkpLink(xml);
        end
end

local function ShowDkpLink(link)
        URLFrameEditBox:SetText(link);
        URLFrameEditBox:HighlightText();
        URLFrame:Show();
end


Phanx 05-03-13 08:47 PM

Just blindly adding local keywords isn't a good idea, as that code has scoping issues and will throw errors about attempting to index nil values. Also, you didn't remove the unused stuff. :p

Code:

local current, numInGroup = {}, {}

local function UpdateRaidState()
        wipe(numInGroup)
        wipe(current)
        for i = 1, GetNumGroupMembers() do
                local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(i)
                current[name] = { index = i, group = subgroup }
                numInGroup[subgroup] = (numInGroup[subgroup] or 0) + 1
        end
end

local function SortRaid()
        local str = URLFrameEditBox:GetText()
        -- Get a snapshot of the current raid layout:
        UpdateRaidState()

        local wanted = {}
        -- Build a map of the desired raid layout:
        for name, group in string.gmatch(str, "([^&:]+):(%d+)") do
                -- Ignore named players not in the raid.
                if current[name] then
                        wanted[name] = group
                end
        end

        -- Look for players not in the wanted group and move them:
        for name, group in pairs(wanted) do
                if current[name].group ~= group then
                        if numInGroup[group] then
                                if numInGroup[group] or numInGroup[group] < 5 then
                                        -- Just move them:
                                        SetRaidSubgroup(current[name].index, group)
                                else
                                        -- Look for someone to swap with:
                                        for xname, xdata in pairs(current) do
                                                if xdata.group == group and wanted[xname] ~= group then
                                                        -- Do the swap:
                                                        SwapRaidSubgroup(current[name].index, xdata.index)
                                                        -- Update the snapshot:
                                                        UpdateRaidState()
                                                end
                                        end
                                end
                        else
                                SetRaidSubgroup(current[name].index, group)
                        end
                end
        end
end

------------------------------------------------------------------------

SLASH_RAIDSTRING1 = "/rs"

SlashCmdList["RAIDSTRING"] = function(msg, editBox)
        if not UnitInRaid("player") then
                return
        end
        local name, realm = UnitName("player")
        local membercount =
        local guildName = GetGuildInfo("player")
        local realm = GetRealmName()

        local xml = "<RaidInfo><Info>Raidassist</Info><Password>W2Any"..realm.."dEAv"..name.."2AxaS</Password><Realm>"..realm.."</Realm><Guild>"..guildName.."</Guild><Name>"..name.."</Name><PlayerInfos>"
        for i = 1, GetNumGroupMembers() do
                local localizedClass, englishClass = UnitClass("raid"..i)
                local name, online = UnitName("raid"..i)
                xml = xml.."<key"..i.."><name>"..name.."</name><class>"..englishClass.."</class></key"..i..">"
        end
        xml = xml.."</PlayerInfos></RaidInfo>"

        URLFrameEditBox:SetText(xml)
        URLFrameEditBox:HighlightText()
        URLFrame:Show()
end

------------------------------------------------------------------------

SLASH_MAKERAID1 = "/rm"

SlashCmdList["MAKERAID"] = function(msg, editBox)
        URLFrame:Show()
end


Anja 05-04-13 03:45 AM

Code:

local membercount =
Code:

1x <string>:"URLFrameEditBox:OnEnterPressed":1: attempt to call global "SortRaid" (a nil value)
i hate coding lua :( i have no idea why its so hard to make such a easy addon >.< please one step and make it in one zip file (the whole addon, errorfree), i'm on the end of my road :(

Phanx 05-04-13 02:04 PM

You need to post the other file(s). The code you posted doesn't create the URLEditBox frame, and that error is from that missing code.

Anja 05-05-13 02:12 PM

send you pm @ phanx

Phanx 05-05-13 08:20 PM

I don't provide any support or tutoring via PM, as that defeats the point of having a community forum, so I'm just replying here.

Quote:

Originally Posted by Anja
<link>

that was my last update stand, thanks for your help!!

I rewrote your frame creation code using only Lua (no XML). Not tested in an actual raid, but the window shows up fine in-game with no errors. Remove the reference to Raidstring.xml in your TOC file, and replace the contents of your Lua file with this.

Code:

local f = CreateFrame("Frame", "Raidstring", UIParent)
f:SetPoint("CENTER")
f:SetSize(400, 125)
f:Hide()

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

f.Header = f:CreateTexture(nil, "ARTWORK")
f.Header:SetPoint("CENTER", f, "TOP")
f.Header:SetSize(139, 40)
f.Header:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
f.Header:SetTexCoord(58/256, 196/256, 0, 39/64)

f.HeaderText = f:CreateFontString(nil, "OVERLAY", "GameFontNormal")
f.HeaderText:SetPoint("CENTER", f.Header)
f.HeaderText:SetText("Raidstring")

f:EnableMouse(true)
f:SetMovable(true)
f.TitleRegion = f:CreateTitleRegion()
f.TitleRegion:SetAllPoints(f.Header)

f.EditBox = CreateFrame("EditBox", "$parentEditBox", f, "InputBoxTemplate")
f.EditBox:SetPoint("TOP", f.Header, "BOTTOM")
f.EditBox:SetSize(300, 16)
f.EditBox:SetAltArrowKeyMode(false)
f.EditBox:SetAutoFocus(false)
f.EditBox:SetFontObject(GameFontHighlightSmall)
--f.EditBox:SetHistoryLines(0)
f.EditBox:SetMaxLetters(0) -- no limit

f.EditBox:SetScript("OnEnterPressed", function()
        f:Hide()
        f:SortRaid(self:GetText())
end)
f.EditBox:SetScript("OnEscapePressed", function()
        f:Hide()
end)

f.CloseButton = CreateFrame("Button", "$parentCloseButton", f, "OptionsButtonTemplate")
f.CloseButton:SetPoint("BOTTOM", 0, 20)
f.CloseButton:SetText(APPLY)
f.CloseButton:SetScript("OnClick", function()
        f:Hide()
        f:SortRaid(self:GetText())
end)

f:SetScript("OnHide", function()
        f.EditBox:ClearHistory()
end)

------------------------------------------------------------------------

local current, numInGroup = {}, {}

local function UpdateRaidState()
        wipe(numInGroup)
        wipe(current)
        for i = 1, GetNumGroupMembers() do
                local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(i)
                current[name] = { index = i, group = subgroup }
                numInGroup[subgroup] = (numInGroup[subgroup] or 0) + 1
        end
end

function f:SortRaid(str)
        if not str or strlen(str) == 0 or not IsInRaid() then
                return
        end
        if not UnitIsGroupLeader("player") and not UnitIsGroupAssistant("player") then
                return DEFAULT_CHAT_FRAME:AddMessage(format("%sRaidString:|r %s", NORMAL_FONT_COLOR_CODE, "You must be raid leader or promoted to sort the raid!"))
        end

        -- Get a snapshot of the current raid layout:
        UpdateRaidState()

        local wanted = {}
        -- Build a map of the desired raid layout:
        for name, group in string.gmatch(str, "([^&:]+):(%d+)") do
                -- Ignore named players not in the raid.
                if current[name] then
                        wanted[name] = group
                end
        end

        -- Look for players not in the wanted group and move them:
        for name, group in pairs(wanted) do
                if current[name].group ~= group then
                        if numInGroup[group] then
                                if not numInGroup[group] or numInGroup[group] < 5 then
                                        -- Just move them:
                                        SetRaidSubgroup(current[name].index, group)
                                else
                                        -- Look for someone to swap with:
                                        for xname, xdata in pairs(current) do
                                                if xdata.group == group and wanted[xname] ~= group then
                                                        -- Do the swap:
                                                        SwapRaidSubgroup(current[name].index, xdata.index)
                                                        -- Update the snapshot:
                                                        UpdateRaidState()
                                                end
                                        end
                                end
                        else
                                SetRaidSubgroup(current[name].index, group)
                        end
                end
        end
end

------------------------------------------------------------------------

SLASH_RAIDSTRING1 = "/rs"

SlashCmdList["RAIDSTRING"] = function()
        if not IsInRaid() then
                return
        end
        local name = UnitName("player")
        local realm = GetRealmName()
        local guild = IsInGuild and GetGuildInfo("player") or ""

        local xml = "<RaidInfo><Info>Raidassist</Info><Password>W2Any"..realm.."dEAv"..name.."2AxaS</Password><Realm>"..realm.."</Realm><Guild>"..guild.."</Guild><Name>"..name.."</Name><PlayerInfos>"
        for i = 1, GetNumGroupMembers() do
                local localizedClass, englishClass = UnitClass("raid"..i)
                local name, online = UnitName("raid"..i)
                xml = xml.."<key"..i.."><name>"..name.."</name><class>"..englishClass.."</class></key"..i..">"
        end
        xml = xml.."</PlayerInfos></RaidInfo>"

        f.EditBox:SetText(xml)
        f.EditBox:HighlightText()
        f:Show()
end

------------------------------------------------------------------------

SLASH_MAKERAID1 = "/rm"

SlashCmdList["MAKERAID"] = function()
        f:Show()
end


Anja 05-06-13 12:56 AM

thanks, i will test it... found a little error, but i can fixed it - thanks for your endurance ^^

Vlad 05-06-13 07:47 AM

Phanx' endurance makes even guys blush.

Phanx 05-06-13 03:49 PM

I lol'ed. :D

Anja 05-13-13 03:31 PM

it still said "group is full" so the switching is not right :(

Phanx 05-13-13 10:27 PM

Change this:
Code:

if numInGroup[group] or numInGroup[group] < 5 then
to this:
Code:

if not numInGroup[group] or numInGroup[group] < 5 then
I also updated the code in my previous post.


All times are GMT -6. The time now is 01:42 AM.

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