--[[ Wardrobe-AL By AnduinLothar karlkfi@yahoo.com Wardrobe lets you define up to 20 distinct equipment profiles (called "outfits") and lets you switch among them on the fly. For example, you can define a Normal Outfit that consists of your regular equipment, an Around Town Outfit that consists of what you'd like to wear when inside a city or roleplaying, a Stamina Outfit that consists of all your best +stam gear, etc. You can then switch amongst these outfits using a simple slash chat command (/wardrobe wear Around Town Outfit), or using a small interactive button docked beneath your radar. ]]-- Wardrobe = {}; --------------------------------------------------------------------------------- -- Info --------------------------------------------------------------------------------- local WARDROBE_VERSION = "1.82-AL"; --------------------------------------------------------------------------------- -- Localization Registration --------------------------------------------------------------------------------- Localization.SetAddonDefault("Wardrobe", "enUS"); Localization.AssignAddonGlobalStrings("Wardrobe"); --For Bindings local function TEXT(key) return Localization.GetString("Wardrobe", key) end local Wardrobe_XMLTextAssignment = { NamePopupText = "POPUP_TITLE"; PopupConfirmText = "POPUP_TITLE"; NamePopupAcceptButton = "TXT_ACCEPT"; PopupConfirmAcceptButton = "TXT_ACCEPT"; NamePopupCancelButton = "TXT_CANCEL"; PopupConfirmCancelButton = "TXT_CANCEL"; CheckboxToggle = "TXT_TOGGLE"; CheckboxAccept = "TXT_ACCEPT"; CheckboxColorpick = "TXT_COLOR"; MainMenuFrameTitle = "TXT_EDITOUTFITS"; MainMenuFrameNewButton = "TXT_NEW"; MainMenuFrameCloseButton = "TXT_CLOSE"; ColorPickFrameTitle = "TXT_SELECTCOLOR"; ColorPickFrameOKButton = "TXT_OK"; ColorPickFrameCancelButton = "TXT_CANCEL"; } function Wardrobe.UpdateXMLText() for frameName, key in Wardrobe_XMLTextAssignment do if (Wardrobe[frameName]) then Wardrobe[frameName]:SetText(TEXT(key)); else --print(frameName) end end end Localization.RegisterCallback("WardrobeXML", Wardrobe.UpdateXMLText); --------------------------------------------------------------------------------- -- Variables --------------------------------------------------------------------------------- WARDROBE_DEBUG = false; WARDROBE_NUM_OUTFITS = 20; WARDROBE_NUM_POPUP_FUNCTION_BUTTONS = 1; WARDROBE_TEMP_OUTFIT_NAME = "#temp#"; local WARDROBE_UNMOUNT_OUTFIT_NAME = "#unmount#"; local WARDROBE_UNPLAGUE_OUTFIT_NAME = "#unplague#"; local WARDROBE_DONEEATING_OUTFIT_NAME = "#uneating#"; local WARDROBE_DONESWIMMING_OUTFIT_NAME = "#unswimming#"; Wardrobe.SpecialOutfitVirtualNames = { -- [specialID] -> virtualOutfitName ["mounted"] = WARDROBE_UNMOUNT_OUTFIT_NAME, ["chowing"] = WARDROBE_DONEEATING_OUTFIT_NAME, ["plague"] = WARDROBE_UNPLAGUE_OUTFIT_NAME, ["swimming"] = WARDROBE_DONESWIMMING_OUTFIT_NAME }; Wardrobe.SpecialOutfitVirtualIDs = { -- [virtualOutfitName] -> specialID [WARDROBE_UNMOUNT_OUTFIT_NAME] = "mounted", [WARDROBE_DONEEATING_OUTFIT_NAME] = "chowing", [WARDROBE_UNPLAGUE_OUTFIT_NAME] = "plague", [WARDROBE_DONESWIMMING_OUTFIT_NAME] = "swimming" }; Wardrobe.WaitingListVirtualNames = { -- [specialID] -> virtualOutfitName ["mount"] = {id="mounted",toggle=true}, ["unmount"] = {id="mounted",toggle= false}, ["eating"] = {id="chowing",toggle=true}, ["uneating"] = {id="chowing",toggle=false}, ["plague"] = {id="plague",toggle=true}, ["unplague"] = {id="plague",toggle=false}, ["swim"] = {id="swimming",toggle=true}, ["unswim"] = {id="swimming",toggle= false} }; WARDROBE_MAX_SCROLL_ENTRIES = 9; WARDROBE_NOISY = false; function Wardrobe.GetPlagueZones() return { TEXT("TXT_WPLAGUELANDS"), TEXT("TXT_EPLAGUELANDS"), TEXT("TXT_STRATHOLME"), TEXT("TXT_SCHOLOMANCE") } end WARDROBE_DEFAULT_BUTTON_COLOR = 11; -- corresponds to the entry in WARDROBE_CONSTANTS_TEXTCOLORS (in this case, #11 is green) Wardrobe.InventorySlots = { "HeadSlot", "NeckSlot", "ShoulderSlot", "BackSlot", "ChestSlot", "ShirtSlot", "TabardSlot", "WristSlot", "HandsSlot", "WaistSlot", "LegsSlot", "FeetSlot", "Finger0Slot", "Finger1Slot", "Trinket0Slot", "Trinket1Slot", "MainHandSlot", "SecondaryHandSlot", "RangedSlot" }; Wardrobe.InventorySlotsSize = table.getn( Wardrobe.InventorySlots ) -- the variable that stores all the wardrobe info -- and gets saved when you quit the game Wardrobe_Config = {}; Wardrobe_Config.Enabled = true; Wardrobe_Config.xOffset = 10; Wardrobe_Config.yOffset = 39; Wardrobe_Config.DefaultCheckboxState = 1; -- default state for the checkboxes when specifying what equipment slots make up an outfit on the character paperdoll screen Wardrobe_Config.MustClickUIButton = false; -- default state for the checkboxes when specifying what equipment slots make up an outfit on the character paperdoll screen Wardrobe_Config.version = WARDROBE_VERSION; Wardrobe.Current_Outfit = 0; Wardrobe.InventorySearchForward = 1; Wardrobe.AlreadySetCharactersWardrobeID = false; -- set this to true once we've looked up this character's wardrobe info Wardrobe.PopupFunction = ""; -- tells the popup confirmation box what it's confirming (deleting an outfit, adding one, etc) WARDROBE_CONSTANTS_POPUP_TITLE = ""; -- the title of the popup confirmation box Wardrobe.Rename_OldName = ""; -- remembers original outfit name in case we cancel a rename Wardrobe.BeingDragged = false; -- flag for dragging the wardrobe UI button Wardrobe.DragLock = false; -- true if we're not allowed to drag the wardrobe UI button Wardrobe.InCombat = false; -- true if we're in combat Wardrobe.RegenEnabled = true; -- true if we can't regen (usually means we're in combat) Wardrobe.ShowingCharacterPanel = false; -- true if the character paperdoll frame is visible Wardrobe.PressedAcceptButton = false; -- remembers if we pressed the accept button in case the character paperdoll frame closes via other means Wardrobe.WaitingList = {}; --============================================================================================-- --============================================================================================-- -- -- -- INITIALIZATION FUNCTIONS -- -- -- --============================================================================================-- --============================================================================================-- --------------------------------------------------------------------------------- -- Stuff done when the plugin first loads --------------------------------------------------------------------------------- function Wardrobe.OnLoad() -- watch our bags and update our wardrobe availability this:RegisterEvent("BAG_UPDATE"); this:RegisterEvent("PLAYER_REGEN_DISABLED"); this:RegisterEvent("PLAYER_REGEN_ENABLED"); this:RegisterEvent("PLAYER_ENTER_COMBAT"); this:RegisterEvent("PLAYER_LEAVE_COMBAT"); this:RegisterEvent("PLAYER_ENTERING_WORLD"); this:RegisterEvent("PLAYER_AURAS_CHANGED"); this:RegisterEvent("ZONE_CHANGED_NEW_AREA"); --this:RegisterEvent("MIRROR_TIMER_START"); --Swimming Currently Disabled Wardrobe.RegisterXMLRefrences(); Wardrobe.DropDown_OnLoad(); Wardrobe.RegisterOptionConfigs(); end --------------------------------------------------------------------------------- -- Convert all XML frames with the prefix "Wardrobe_Blah" to be refrenced by the Wardrobe.Blah equiv -- An experiment in global namespace minimization --------------------------------------------------------------------------------- function Wardrobe.RegisterXMLRefrences() local globalNameSpace = getfenv(0); local tempTable = {}; local newName, newValue, foundString, number; local globalName, globalValue = next(globalNameSpace); while (globalName ~= nil) do newName, newValue = next(globalNameSpace, globalName); if ( type(globalName) == "string" ) and ( type(globalValue) == "table" ) and ( strfind(globalName, "Wardrobe_") ) then foundString, number = string.gsub(globalName, "^Wardrobe_", "") if (number > 0) and (globalValue.GetName) then tempTable[foundString] = globalValue; if (foundString ~= "MainMenuFrameTitle") and (foundString ~= "IconFrame") and (foundString ~= "PopupTitle") and (not strfind(foundString, "SortScrollFrame")) and (not strfind(foundString, "MainMenuFrameEntry")) then --Leave ScrollFrame refrences for template Compatibility --Leave Minimap Button refrences for MobileMinimapFrame Use --Leave PopupTitle refrences for ColorCycle Use --Leave MainMenuFrameTitle refrences for ColorCycle Use --Leave MainMenuFrameEntrys refrences for ColorCycle Use globalNameSpace[globalName] = nil; end end end globalName,globalValue = newName,newValue; end for n, v in tempTable do globalNameSpace.Wardrobe[n] = v; end end --------------------------------------------------------------------------------- -- Register Option Configs --------------------------------------------------------------------------------- function Wardrobe.RegisterOptionConfigs() if (Khaos) then Wardrobe.RegisterKhaos(); end local WardrobeCommands = {"/wardrobe","/wd"}; if (Sky) then Sky.registerSlashCommand( { id="Wardrobe"; commands = WardrobeCommands; onExecute = Wardrobe.ChatCommandHandler; helpText = function() return TEXT("CHAT_COMMAND_INFO") end; } ); else SlashCmdList["WARDROBESLASH"] = Wardrobe.ChatCommandHandler; for i, slash in WardrobeCommands do setglobal("SLASH_WARDROBESLASH"..i, slash); end end -- makes sure we have a Print() command if(not Print) then function Print(msg, r, g, b, frame) if (not r) then r = 1.0; end if (not g) then g = 1.0; end if (not b) then b = 1.0; end if ( frame ) then frame:AddMessage(msg, r, g, b); else if ( DEFAULT_CHAT_FRAME ) then DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b); end end end end end function Wardrobe.RegisterKhaos() local optionSet = { id="Wardrobe"; text=function() return TEXT("CONFIG_HEADER") end; helptext=function() return TEXT("CONFIG_HEADER_INFO") end; callback=function(state) Wardrobe.Toggle(state and 1); end; feedback=function(state) return state and TEXT("TXT_ENABLED") or TEXT("TXT_DISABLED") end; difficulty=1; default={checked=true}; options={ { id = "Header"; text = function() return TEXT("CONFIG_HEADER").." "..Wardrobe_Config.version end; helptext = function() return TEXT("CONFIG_HEADER_INFO") end; type = K_HEADER; }; { id = "WearOutfit"; text = function() return TEXT("CONFIG_WEAROUTFIT") end; helptext = function() return TEXT("CONFIG_WEAROUTFIT_INFO") end; feedback = function(state) return format(TEXT("CONFIG_WEAROUTFIT_FEEDBACK"), Wardrobe_Config[WD_realmID][WD_charID].Outfit[state.value].OutfitName) end; callback = function(state) if (state.value) then Wardrobe.WearOutfit(state.value); end end; setup = { options = Wardrobe.GetListOfOutfits; orderedOptions = true; multiSelect = false; noSelect = true; }; default = { value = nil; }; disabled = { value = nil; }; type = K_PULLDOWN; }; { id = "EditOutfits"; text = function() return TEXT("CONFIG_EDIT") end; helptext = function() return TEXT("CONFIG_EDIT_INFO") end; feedback = function() return TEXT("CONFIG_EDIT_FEEDBACK") end; callback = Wardrobe.ShowMainMenu; type = K_BUTTON; setup = { buttonText = function() return TEXT("CONFIG_EDIT_BUTTON") end; }; }; { id = "OutfitKeyHeader"; text = function() return TEXT("CONFIG_KEY_HEADER") end; helptext = function() return TEXT("CONFIG_KEY_HEADER") end; type = K_HEADER; }; { id = "HelpText1"; text = function() return TEXT("HELP_13") end; helptext = function() return TEXT("HELP_13") end; type = K_TEXT; }; { id = "HelpText2"; text = function() return TEXT("HELP_14") end; helptext = function() return TEXT("HELP_14") end; type = K_TEXT; }; { id = "HelpText3"; text = function() return TEXT("HELP_15") end; helptext = function() return TEXT("HELP_15") end; type = K_TEXT; }; { id = "HelpText4"; text = function() return TEXT("HELP_16") end; helptext = function() return TEXT("HELP_16") end; type = K_TEXT; }; { id = "OptionsHeader"; text = function() return TEXT("CONFIG_OPTIONS_HEADER") end; helptext = function() return TEXT("CONFIG_OPTIONS_HEADER") end; type = K_HEADER; }; { id = "RequireClick"; text = function() return TEXT("CONFIG_REQCLICK") end; helptext = function() return TEXT("CONFIG_REQCLICK_INFO") end; feedback = function(state) if (state.checked) then return TEXT("TXT_BUTTONONCLICK"); else return TEXT("TXT_BUTTONONMOUSEOVER"); end end; callback = function(state) Wardrobe_Config.MustClickUIButton = (state.checked) end; check = true; type = K_CHECKBOX; default = { checked = false; }; disabled = { checked = false; }; }; { id = "LockButton"; text = function() return TEXT("CONFIG_LOCKBUTTON") end; helptext = function() return TEXT("CONFIG_LOCKBUTTON_INFO") end; feedback = function(state) if (state.checked) then return TEXT("TXT_BUTTONLOCKED"); else return TEXT("TXT_BUTTONUNLOCKED"); end end; callback = function(state) Wardrobe.DragLock = (state.checked) end; check = true; type = K_CHECKBOX; default = { checked = false; }; disabled = { checked = false; }; }; { id = "DropDownScale"; text = function() return TEXT("CONFIG_DROPDOWNSCALE") end; helptext = function() return TEXT("CONFIG_DROPDOWNSCALE_INFO") end; feedback = function(state) return format(TEXT("CONFIG_DROPDOWNSCALE_FEEDBACK"), state.slider*100); end; callback = function(state) Wardrobe.SetDropDownScale(state.slider) end; check = true; type = K_SLIDER; dependencies = {["DropDownScale"]={checked=true}}; default = { checked = false; slider = UIParent:GetScale(); }; disabled = { checked = false; slider = UIParent:GetScale(); }; setup = { sliderMin = 0.5; sliderMax = 1.0; sliderStep = 0.1; sliderSignificantDigits = 1; }; }; { id = "Reset"; text = function() return TEXT("CONFIG_RESET") end; helptext = function() return TEXT("CONFIG_RESET_INFO") end; feedback = function() return TEXT("CONFIG_RESET_FEEDBACK") end; callback = Wardrobe.EraseAllOutfits; type = K_BUTTON; setup = { buttonText = function() return TEXT("CONFIG_RESET_BUTTON") end; }; }; }; }; Khaos.registerOptionSet( "inventory", optionSet ); end --------------------------------------------------------------------------------- -- Event handler --------------------------------------------------------------------------------- function Wardrobe.OnEvent(event) if (Wardrobe_Config.Enabled) then if (event == "PLAYER_REGEN_DISABLED") then --Sea.io.print("PLAYER_REGEN_DISABLED"); Wardrobe.RegenEnabled = false; elseif (event == "PLAYER_REGEN_ENABLED") then Wardrobe.RegenEnabled = true; --Sea.io.print("PLAYER_REGEN_ENABLED ", Wardrobe.IsPlayerInCombat()); if (not Wardrobe.IsPlayerInCombat()) then Wardrobe.CheckWaitingList(); Wardrobe.CheckForMounted(); Wardrobe.CheckForEatDrink(); end elseif (event == "PLAYER_ENTER_COMBAT") then --Sea.io.print("PLAYER_ENTER_COMBAT"); Wardrobe.InCombat = true; elseif (event == "PLAYER_LEAVE_COMBAT") then Wardrobe.InCombat = false; --Sea.io.print("PLAYER_LEAVE_COMBAT ", Wardrobe.IsPlayerInCombat()); if (not Wardrobe.IsPlayerInCombat()) then --Wardrobe.CheckWaitingList(); end elseif (event == "PLAYER_AURAS_CHANGED") then --if (not Wardrobe.IsPlayerInCombat()) then if (Chronos) then Chronos.scheduleByName("WardrobeAuraCheck", .2, Wardrobe.AuraCheck); else Wardrobe.CheckForMounted(); Wardrobe.CheckForEatDrink(); end --end elseif (event == "ZONE_CHANGED_NEW_AREA") then Wardrobe.ChangedZone(); elseif (event == "MIRROR_TIMER_START") then Wardrobe.CheckForSwimming(); elseif (event == "PLAYER_ENTERING_WORLD") then Wardrobe.UpdateOldConfigVersions(); Wardrobe.CheckForMounted(); Wardrobe.CurrentZone = GetZoneText(); Wardrobe.ChangedZone(); Wardrobe.SetDropDownScale(Wardrobe_Config.DropDownScale); end end end function Wardrobe.AuraCheck() Wardrobe.CheckForMounted(); Wardrobe.CheckForEatDrink(); end --------------------------------------------------------------------------------- -- Return true if we're in combat --------------------------------------------------------------------------------- function Wardrobe.IsPlayerInCombat() if (Wardrobe.InCombat) or (not Wardrobe.RegenEnabled) then return true; else return false; end end --------------------------------------------------------------------------------- -- Update outdated config information --------------------------------------------------------------------------------- function Wardrobe.UpdateOldConfigVersions() if (Wardrobe_Config.DefaultCheckboxState == nil) then Wardrobe.Debug("Adding DefaultCheckboxState to Wardrobe_Config."); Wardrobe_Config.DefaultCheckboxState = 1; else Wardrobe.Debug("Wardrobe_Config.DefaultCheckboxState = "..tostring(Wardrobe_Config.DefaultCheckboxState)); end -- Clear out unused items Wardrobe.CheckForOurWardrobeID(); for i, outfit in Wardrobe_Config[WD_realmID][WD_charID].Outfit do for j = 1, Wardrobe.InventorySlotsSize do if (outfit.Item[j]) then if (outfit.Item[j].IsSlotUsed ~= 1) then outfit.Item[j] = nil; elseif (outfit.Item[j].Name == "") then outfit.Item[j] = {IsSlotUsed = 1}; end end end end Wardrobe_Config.version = WARDROBE_VERSION; end --============================================================================================-- --============================================================================================-- -- -- -- CHAT COMMAND FUNCTIONS -- -- -- --============================================================================================-- --============================================================================================-- --------------------------------------------------------------------------------- -- Break a chat command into its command and variable parts (i.e. "debug on" -- will break into command = "debug" and variable = "on", or "add my spiffy wardrobe" -- breaks into command = "add" and variable = "my spiffy wardrobe" --------------------------------------------------------------------------------- function Wardrobe.ParseCommand(msg) firstSpace = string.find(msg, " ", 1, true); if (firstSpace) then local command = string.sub(msg, 1, firstSpace - 1); local var = string.sub(msg, firstSpace + 1); return command, var else return msg, nil; end end --------------------------------------------------------------------------------- -- A simple chat command handler. takes commands in the form "/wardrobe command var" --------------------------------------------------------------------------------- function Wardrobe.ChatCommandHandler(msg) local command, var = Wardrobe.ParseCommand(msg); if ((not command) and msg) then command = msg; end if (command) then command = string.lower(command); if (command == TEXT("CMD_RESET")) then Wardrobe.EraseAllOutfits(); elseif (command == TEXT("CMD_LIST")) then Wardrobe.ListOutfits(var); elseif (command == TEXT("CMD_WEAR") or command == TEXT("CMD_WEAR2") or command == TEXT("CMD_WEAR3")) then Wardrobe.WearOutfit(var); elseif (command == TEXT("CMD_ON")) then Wardrobe.Toggle(1); elseif (command == TEXT("CMD_OFF")) then Wardrobe.Toggle(0); elseif (command == TEXT("CMD_LOCK")) then Wardrobe.ToggleLockButton(true); elseif (command == TEXT("CMD_UNLOCK")) then Wardrobe.ToggleLockButton(false); elseif (command == TEXT("CMD_CLICK")) then Wardrobe.ToggleClickButton(true); elseif (command == TEXT("CMD_MOUSEOVER")) then Wardrobe.ToggleClickButton(false); elseif (command == TEXT("CMD_SCALE")) then Wardrobe.SetDropDownScale(var); elseif (command == TEXT("CMD_VERSION")) then Wardrobe.Print(TEXT("TXT_WARDROBEVERSION").." "..WARDROBE_VERSION); elseif (command == "testcheck") then Wardrobe.ShowWardrobe_ConfigurationScreen(); elseif (command == "testsort") then Wardrobe.ShowMainMenu(); elseif (command == "debug") then Wardrobe.ToggleDebug(); elseif (command == "report") then Wardrobe.DumpDebugReport(); elseif (command == "itemlist") then Wardrobe.BuildItemList(); elseif (command == "struct") then Wardrobe.DumpDebugStruct(); else Wardrobe.ShowHelp(); end end end --============================================================================================-- --============================================================================================-- -- -- -- WARDROBE MAIN FUNCTIONS -- -- -- --============================================================================================-- --============================================================================================-- --------------------------------------------------------------------------------- -- Each character on an account has an ID assigned to it that specifies its wardrobes -- This function returns the ID associated with this character --------------------------------------------------------------------------------- function Wardrobe.GetThisCharactersWardrobeID() Wardrobe.Debug("Looking up this character's wardrobe number..."); -- upgrade old versions if ( Wardrobe_Config.version == nil ) then Wardrobe_Config = nil; Wardrobe_Config = { }; Wardrobe_Config.Enabled = true; Wardrobe_Config.xOffset = 10; Wardrobe_Config.yOffset = 39; Wardrobe_Config.DefaultCheckboxState = 1; -- default state for the checkboxes when specifying what equipment slots make up an outfit on the character paperdoll screen Wardrobe_Config.MustClickUIButton = false; -- default state for the checkboxes when specifying what equipment slots make up an outfit on the character paperdoll screen Wardrobe_Config.version = WARDROBE_VERSION; Wardrobe.Print("Erasing old Wardrobe_Config because it don't support realm"); elseif ( not Wardrobe_Config.version == WARDOBE_VERSION ) then Wardrobe_Config.version = WARDROBE_VERSION; end -- Look for this realm in the wardrobe table WD_RealmName = GetRealmName(); WD_realmID = nil; for i = 1, table.getn(Wardrobe_Config) do if ( Wardrobe_Config[i].RealmName == WD_RealmName ) then WD_realmID = i; break; end end -- if we didn't find this realm, add us to the wardrobe table if (not WD_realmID) then Wardrobe.AddThisRealmToWardrobeTable(); WD_realmID = table.getn(Wardrobe_Config); end -- look for this character in the wardrobe table WD_charID = nil; WD_PlayerName = UnitName("player") for i = 1, table.getn(Wardrobe_Config[WD_realmID]) do if (Wardrobe_Config[WD_realmID][i].PlayerName == WD_PlayerName) then WD_charID = i; break; end end -- if we didn't find this character, add us to the wardrobe table if (not WD_charID) then Wardrobe.AddThisCharacterToWardrobeTable(); WD_charID = table.getn(Wardrobe_Config[WD_realmID]); end Wardrobe.ButtonUpdateVisibility(); Wardrobe.Debug("This character's wardrobe number is: "..WD_charID); -- flag that we've already found / created this character's wardrobe entry Wardrobe.AlreadySetCharactersWardrobeID = true; end --------------------------------------------------------------------------------- -- Checks to see if we've already looked up the number associated with this character -- If not, grab the number --------------------------------------------------------------------------------- function Wardrobe.CheckForOurWardrobeID() if (not Wardrobe.AlreadySetCharactersWardrobeID) then Wardrobe.GetThisCharactersWardrobeID(); end end -- NOTES ABOUT DATASTRUCTURES: -- -- For each character, the wardrobes are stored in a datastructure that looks like this -- -- x = total number of outfits -- y = total slots on a character (head, feet, hands, etc) -- -- Outfit[x] -- the datastructure for a single outfit -- -- SortNumber -- specifies the position this outfit will appear in the list of outfits when the list is sorted -- OutfitName -- the name of this outfit -- Available -- true if all of the items in this outfit are in our bags or equiped -- Mounted -- true if this is the outfit to be worn when we mount -- Virtual -- true if this outfit is virtual (not a real outfit, but only used as temporary storage) -- Selected -- true if this outfit is the currently selected outfit on the menu screen (highlighted white) -- Item[1] -- the data structure for all the items in this outfit -- Name -- the name of the item -- IsSlotUsed -- 1 if this outfit uses this slot, 0 if not (i.e. an outfit might not involve your trinkets, or might only consist of your rings) -- . -- . -- . -- Item[y] -- -- So, let's say you have two outfits in your wardrobe. Wardrobe[1] represents outfit 1, and Wardrobe[2] -- represents outfit 2. for outfit 1, Wardrobe[1].OutfitName would be the name of this outfit (say, "In town outfit"). -- the item on your character slot 5 would be Wardrobe[1].Item[5].Name. Since all these are stored per character, the -- actual datastructure would look like: -- -- Wardrobe_Config[WD_realmID][3].Wardrobe[1].Item[5].Name --> for character 3, outfit 1, item 5 --------------------------------------------------------------------------------- -- Add an entry for this realm to the main table of wardrobes --------------------------------------------------------------------------------- function Wardrobe.AddThisRealmToWardrobeTable() Wardrobe.Debug("Didn't find a wardrobe ID for this realm. Adding this realm to the table..."); -- build the structure for this realm's wardrobe tempTable = { }; tempTable.RealmName = WD_RealmName; -- stick this structure into the main table of wardrobes table.insert(Wardrobe_Config, tempTable); end --------------------------------------------------------------------------------- -- Add an entry for this character to the main table of wardrobes --------------------------------------------------------------------------------- function Wardrobe.AddThisCharacterToWardrobeTable() Wardrobe.Debug("Didn't find a wardrobe ID for this character. Adding this character to the table..."); -- build the structure for this char's wardrobe tempTable = { }; tempTable.PlayerName = WD_PlayerName tempTable.Outfit = { }; -- stick this structure into the main table of wardrobes table.insert(Wardrobe_Config[WD_realmID], tempTable); end --------------------------------------------------------------------------------- -- Create and return a blank outfit structure --------------------------------------------------------------------------------- function Wardrobe.CreateBlankOutfit() local tempTable2 = { }; tempTable2.SortNumber = nil; tempTable2.OutfitName = ""; tempTable2.Available = false; tempTable2.Special = ""; tempTable2.Virtual = false; tempTable2.Selected = false; tempTable2.ButtonColor = WARDROBE_DEFAULT_BUTTON_COLOR; tempTable2.Item = { }; --[[ for i = 1, Wardrobe.InventorySlotsSize do tempTable3 = { }; tempTable3.Name = ""; tempTable3.IsSlotUsed = Wardrobe_Config.DefaultCheckboxState; table.insert(tempTable2.Item, tempTable3); end ]]-- return tempTable2; end --------------------------------------------------------------------------------- -- Add the named outfit to our wardrobe --------------------------------------------------------------------------------- function Wardrobe.AddNewOutfit(outfitName, buttonColor) if (Wardrobe_Config.Enabled) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); if (not outfitName) then return; end -- make sure we don't already have an outfit with the same name if (Wardrobe.FoundOutfitName(outfitName)) then Wardrobe.Print(TEXT("TXT_OUTFITNAMEEXISTS")); return; end Wardrobe.Debug("Trying to set this wardrobe as \""..outfitName.."\""); -- if we found a free outfit slot local outfitNum = Wardrobe.GetNextFreeOutfitSlot(); if (outfitNum ~= 0) then -- store our current equipment in this outfit Wardrobe.StoreItemsInOutfit(outfitName, outfitNum, "added"); Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNum].ButtonColor = buttonColor; -- otherwise we've used the maximum number of outfits else Wardrobe.Print(TEXT("TXT_USEDUPALL").." "..WARDROBE_NUM_OUTFITS.." "..TEXT("TXT_OFYOUROUTFITS"), 1.0, 0.0, 0.0); end end end --------------------------------------------------------------------------------- -- Create and return the index of the next free outfit slot --------------------------------------------------------------------------------- function Wardrobe.GetNextFreeOutfitSlot(virtualOutfitName) -- find next unused outfit slot local outfitNum = 0; local outfitCount = 0; local outfits = Wardrobe_Config[WD_realmID][WD_charID].Outfit; local duplicate = false; for i, oufit in outfits do if (not oufit.Virtual) then outfitCount = outfitCount + 1; end if (oufit.OutfitName == virtualOutfitName) then table.remove(outfits, i); duplicate = true; end end if (duplicate) then Wardrobe.RenumberSortNumbers(); end -- if we aren't already using our max number of outfits if (outfitCount < WARDROBE_NUM_OUTFITS or addingVirtualOutfit) then -- add another outfit to the list and return its index table.insert(outfits, Wardrobe.CreateBlankOutfit()); outfitNum = table.getn(outfits); outfits[outfitNum].SortNumber = outfitNum; end return outfitNum; end --------------------------------------------------------------------------------- -- Store our currently equipped items in the specified outfit name --------------------------------------------------------------------------------- function Wardrobe.StoreItemsInOutfit(outfitName, outfitNum, printMessage) -- store the name of this outfit local outfit = Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNum]; outfit.OutfitName = outfitName; outfit.Special = nil; outfit.Virtual = false; -- for each slot on our character's person (hands, feet, etc) for i = 1, Wardrobe.InventorySlotsSize do if (Wardrobe.ItemCheckState[i] == 1) then if (not outfit.Item[i]) then outfit.Item[i] = {}; end local item = outfit.Item[i]; item.IsSlotUsed = 1 local itemID, permEnchant, tempEnchant, suffix, itemName = Wardrobe.GetItemInfoAtInventorySlotNumber(i); item.Name = itemName; item.ItemID = itemID; item.Suffix = suffix; item.PermEnchant = permEnchant; Wardrobe.Debug(" Setting USED slot "..Wardrobe.InventorySlots[i].." = ["..tostring(item.Name).."]"); else outfit.Item[i] = nil; Wardrobe.Debug(" Setting unused slot "..Wardrobe.InventorySlots[i]); end end -- all the items in this outfit are currently available in the player's inventory outfit.Available = true; if (printMessage) then Wardrobe.Print(TEXT("TXT_OUTFIT").." \""..outfitName.."\" "..printMessage.."."); end end --------------------------------------------------------------------------------- -- Update an outfit --------------------------------------------------------------------------------- function Wardrobe.UpdateOutfit(outfitName, buttonColor) if (Wardrobe_Config.Enabled) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); -- check to see if the wardrobe doesn't exist if (outfitName == nil or outfitName == "") then Wardrobe.Print(TEXT("TXT_PLEASEENTERNAME")); elseif (not Wardrobe.FoundOutfitName(outfitName)) then Wardrobe.Print(TEXT("TXT_OUTFITNOTEXIST")); UIErrorsFrame:AddMessage(TEXT("TXT_NOTEXISTERROR"), 1.0, 0.0, 0.0, 1.0, UIERRORS_HOLD_TIME); else -- find the outfit to update for i, outfit in Wardrobe_Config[WD_realmID][WD_charID].Outfit do -- if we found the outfit, store our equipment if (outfit.OutfitName == outfitName) then Wardrobe.StoreItemsInOutfit(outfitName, i, TEXT("TXT_UPDATED")); outfit.ButtonColor = buttonColor; end end end end end --------------------------------------------------------------------------------- -- Erase the named outfit --------------------------------------------------------------------------------- function Wardrobe.EraseOutfit(outfitName, silent, eraseAll) if (Wardrobe_Config.Enabled) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); Wardrobe.Debug("Trying to delete outfit \""..outfitName.."\""); local found = false; -- find the outfit to erase local outfits = Wardrobe_Config[WD_realmID][WD_charID].Outfit; for i = 1, table.getn(outfits) do -- if we found the outfit if (outfits[i]) and (outfits[i].OutfitName == outfitName) then -- remove the outfit table.remove(outfits, i); --Wardrobe.RemoveAPopupButton(outfitName); found = true; if (not eraseAll) then break; else i = 1; end end end Wardrobe.RenumberSortNumbers(); if (found) then if (not eraseAll) and (not silent) then Wardrobe.Print(TEXT("TXT_OUTFIT").." \""..outfitName.."\" "..TEXT("TXT_DELETED")); Wardrobe.ListOutfits(); UIErrorsFrame:AddMessage(TEXT("TXT_OUTFIT").." \""..outfitName.."\" "..TEXT("TXT_DELETED"), 0.0, 1.0, 0.0, 1.0, UIERRORS_HOLD_TIME); end else Wardrobe.Print(TEXT("TXT_UNABLETOFIND").." \""..outfitName.."!\""); UIErrorsFrame:AddMessage(TEXT("TXT_UNABLEFINDERROR"), 1.0, 0.0, 0.0, 1.0, UIERRORS_HOLD_TIME); end return found; end end --------------------------------------------------------------------------------- -- Erase all our outfits --------------------------------------------------------------------------------- function Wardrobe.EraseAllOutfits() if (Wardrobe_Config.Enabled) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); -- delete all the outfits Wardrobe_Config[WD_realmID][WD_charID].Outfit = { }; -- hide the main menu Wardrobe.ToggleMainMenuFrameVisibility(false); Wardrobe.Print(TEXT("TXT_ALLOUTFITSDELETED")); UIErrorsFrame:AddMessage(TEXT("TXT_ALLOUTFITSDELETED"), 0.0, 1.0, 0.0, 1.0, UIERRORS_HOLD_TIME); end end --------------------------------------------------------------------------------- -- Print a list of our outfits --------------------------------------------------------------------------------- function Wardrobe.ListOutfits(var) if (Wardrobe_Config.Enabled) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); local foundOutfits = false; Wardrobe.Print(TEXT("TXT_YOURCURRENTARE")); -- for each outfit for i, outfit in Wardrobe_Config[WD_realmID][WD_charID].Outfit do -- if it has a name and isn't virtual if (outfit.OutfitName ~= "" and (not outfit.Virtual)) then Wardrobe.Print(" o ".. outfit.OutfitName); foundOutfits = true; -- if we asked for a detailed printout, show all the items if (var == "items") then for j = 1, Wardrobe.InventorySlotsSize do local item = outfit.Item[j]; if (item) and (item.Name) and (item.Name ~= "") then Wardrobe.Print(" ["..Wardrobe.InventorySlots[j].." -> ".. item.Name.."]"); end end end end end if (not foundOutfits) then Wardrobe.Print(" "..TEXT("TXT_NOOUTFITSFOUND")); end end end --------------------------------------------------------------------------------- -- Wear an outfit --------------------------------------------------------------------------------- function Wardrobe.WearOutfit(wardrobeName, silent) if (Wardrobe_Config.Enabled) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); local outfit; -- if the user didn't specify a wardrobe to wear if (not wardrobeName) then Wardrobe.Print(TEXT("TXT_SPECIFYOUTFITTOWEAR")); return; -- else use the specified wardrobe elseif (type(wardrobeName) == "number") then local outfitNumber = wardrobeName; wardrobeName = Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNumber].OutfitName; if (wardrobeName) then Wardrobe.Debug("Wardrobe.WearOutfit: Found outfit at #".. outfitNumber); outfit = Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNumber]; else Wardrobe.Print(TEXT("TXT_UNABLEFIND").." \""..wardrobeName.."\" "..TEXT("TXT_INYOURLISTOFOUTFITS")); return; end else local outfitNumber = 0; for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do Wardrobe.Debug("In WearOutfit, Looking at outfit #"..i.." name = ["..Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].OutfitName.."]"); if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].OutfitName == wardrobeName) then outfitNumber = i; Wardrobe.Debug("Wardrobe.WearOutfit: Found outfit at #"..outfitNumber); break; end end if (outfitNumber == 0) then Wardrobe.Print(TEXT("TXT_UNABLEFIND").." \""..wardrobeName.."\" "..TEXT("TXT_INYOURLISTOFOUTFITS")); return; end outfit = Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNumber]; end Wardrobe.Debug(TEXT("TXT_SWITCHINGTOOUTFIT").." \""..wardrobeName.."\""); -- this variable "freeBagSpacesUsed" lets us track which empty pack spaces we've -- already assigned an item to be put into. we need to do this because when we remove -- items from our character and put them into our bags, the server takes time to actually -- move the item into the bag. during this delay, we may be still removing items, and we -- may see a slot that LOOKS empty but really the server just hasn't gotten around to moving -- a previous item into the slot. this variable lets us mark each empty slot once we've assigned -- an item to it so that we don't try to use the same empty slot for another item. local freeBagSpacesUsed = { }; -- tracks how our switching is going. if at any point we can't remove an item (bags are full, etc), -- this will get set to false local switchResult = true; local itemID, permEnchant, tempEnchant, suffix, invItemName, theSlotID, outfitItemName, outfitItemID, outfitPermEnchant, equipingTwoHandWeapon; -- for each slot on our character (hands, neck, head, feet, etc) for i = 1, Wardrobe.InventorySlotsSize do local outfitItem = outfit.Item[i]; -- if this slot is used in this outfit if (equipingTwoHandWeapon) and (Wardrobe.InventorySlots[i] == "SecondaryHandSlot") then itemID, permEnchant, tempEnchant, suffix, invItemName = Wardrobe.GetItemInfoAtInventorySlotNumber(i); if (itemID) and (Chronos) then Wardrobe.Debug(" Moving offhand to back of bags: "..invItemName); Chronos.scheduleByName("ReBag:"..invItemName, 1, ReBagContainerItem, invItemName); end elseif (outfitItem) and (outfitItem.IsSlotUsed == 1) then theSlotID = GetInventorySlotInfo(Wardrobe.InventorySlots[i]); outfitItemName = outfitItem.Name; outfitItemID = outfitItem.ItemID; outfitSuffix = outfitItem.Suffix; outfitPermEnchant = outfitItem.PermEnchant; Wardrobe.Debug("Working on slot -> "..Wardrobe.InventorySlots[i]); itemID, permEnchant, tempEnchant, suffix, invItemName = Wardrobe.GetItemInfoAtInventorySlotNumber(i); -- if we've set an item for this slot if (((outfitItemID) and (outfitSuffix) and (outfitPermEnchant)) and ((outfitItemID ~= itemID) or (outfitSuffix ~= suffix) or (outfitPermEnchant ~= permEnchant))) or ((outfitItemName) and (outfitItemName ~= "") and (outfitItemName ~= invItemName)) then -- equip the correct item Wardrobe.Debug(" Didn't match! Switching out "..Wardrobe.InventorySlots[i].." for ["..outfitItemName.."]"); if (not Wardrobe.Equip(outfitItemName, theSlotID, outfitItemID, outfitSuffix, outfitPermEnchant)) then Wardrobe.Print(TEXT("TXT_WARNINGUNABLETOFIND").." \""..outfitItemName.."\" "..TEXT("TXT_INYOURBAGS")); elseif (not outfitItemID) or (not outfitSuffix) or (not outfitPermEnchant) then -- Item not stored with itemID info --outfitItem.ItemID = itemID; --outfitItem.Suffix = suffix; --outfitItem.PermEnchant = permEnchant; --outfitItem.TempEnchant = tempEnchant; end -- Check for 2h weapon if (Wardrobe.InventorySlots[i] == "MainHandSlot") and (outfitItemID) then local _, _, _, _, _, _, _, equipLoc = GetItemInfo(outfitItemID); equipingTwoHandWeapon = (equipLoc == "INVTYPE_2HWEAPON"); end -- Forced Empty Slot, slot currently has an item in it elseif (invItemName) and ((not outfitItemName) or (outfitItemName == "")) then -- if inventory slot has an item equipped and it's a duel slot then check the next slots for swapping local swapped = false; if (equipingTwoHandWeapon) and (Wardrobe.InventorySlots[i] == "SecondaryHandSlot") then -- Should never be hit, is caught in first escape clause. swapped = true; result = true; elseif (Wardrobe.InventorySlots[i] == "MainHandSlot") or (Wardrobe.InventorySlots[i] == "Finger0Slot") or (Wardrobe.InventorySlots[i] == "Trinket0Slot") then -- Next Inv Slot outfitItem = outfit.Item[i+1]; outfitItemName = outfitItem.Name; outfitItemID = outfitItem.ItemID; outfitSuffix = outfitItem.Suffix; outfitPermEnchant = outfitItem.PermEnchant; if ((outfitItemID) and (outfitSuffix) and (outfitPermEnchant) and (outfitItemID == itemID) and (outfitSuffix == suffix) and (outfitPermEnchant == permEnchant)) or ((outfitItemName) and (outfitItemName == invItemName)) then -- Put secondary slot item in bag local secondarySlotID = GetInventorySlotInfo(Wardrobe.InventorySlots[i+1]); PickupInventoryItem(secondarySlotID); result, freeBagSpacesUsed = BagItem(freeBagSpacesUsed); switchResult = switchResult and result; Wardrobe.Debug(" Trying to remove "..Wardrobe.InventorySlots[i].." ( slot ID #"..theSlotID..")"); -- Equip primary slot item to secondary slot PickupInventoryItem(theSlotID); EquipCursorItem(secondarySlotID); Wardrobe.Debug(" Matched Next Slot! Moving "..Wardrobe.InventorySlots[i].." item to "..Wardrobe.InventorySlots[i+1].."."); swapped = true; end end -- this outfit doesn't use an item for this inventory slot (i.e. no gloves in this wardrobe) if (not swapped) then -- grab the inventory item and bag it PickupInventoryItem(theSlotID); result, freeBagSpacesUsed = BagItem(freeBagSpacesUsed); Wardrobe.Debug(" Trying to remove "..Wardrobe.InventorySlots[i].." ( slot ID #"..theSlotID..")"); end -- if we failed to switch, this will let us know switchResult = switchResult and result; -- Item found was item desired else Wardrobe.Debug(" Matched! No need to switch out "..Wardrobe.InventorySlots[i].."."); end end end -- only errorcheck when dealing with non-virtual outfits if (not outfit.Virtual and not silent) then -- if everything went OK if (switchResult) then if ( WARDROBE_NOISY ) then Wardrobe.Print(TEXT("TXT_SWITCHEDTOOUTFIT").." \""..wardrobeName..".\""); end Wardrobe.Current_Outfit = outfitNumber; else Wardrobe.Print(TEXT("TXT_PROBLEMSCHANGING")); end end if (mrpOnMRPEvent) then --MyRolePlay support for swapping outfits mrpOnMRPEvent("CHANGE_OUTFIT", wardrobeName); end end end --------------------------------------------------------------------------------- -- Rename an outfit --------------------------------------------------------------------------------- function Wardrobe.RenameOutfit(oldName, newName) if (Wardrobe_Config.Enabled) then -- check to see if the new name is already being used if (not Wardrobe.FoundOutfitName(newName) and newName ~= "") then for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].OutfitName == oldName) then Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].OutfitName = newName; break; end end UIErrorsFrame:AddMessage(TEXT("TXT_OUTFITRENAMEDERROR"), 0.0, 1.0, 0.0, 1.0, UIERRORS_HOLD_TIME); Wardrobe.Print(TEXT("TXT_OUTFITRENAMEDTO").." \""..oldName.."\" "..TEXT("TXT_TOWORDONLY").." \""..newName.."\""); end end end --------------------------------------------------------------------------------- -- Comparison function for sorting outfits --------------------------------------------------------------------------------- function Wardrobe.SortOutfitCompare(outfit1, outfit2) if (Wardrobe.SpecialOutfitVirtualIDs[outfit1.Name]) then return false elseif (outfit1.SortNumber < outfit2.SortNumber) then return true; else return false; end end --------------------------------------------------------------------------------- -- Sort the outfits based on the .SortNumber property --------------------------------------------------------------------------------- function Wardrobe.SortOutfits() table.sort(Wardrobe_Config[WD_realmID][WD_charID].Outfit, Wardrobe.SortOutfitCompare); Wardrobe.RenumberSortNumbers(); end --------------------------------------------------------------------------------- -- Re-number the .SortNumbers so they start at 1 and go up by 1 --------------------------------------------------------------------------------- function Wardrobe.RenumberSortNumbers() for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].SortNumber = i; end end --------------------------------------------------------------------------------- -- Re-order an outfit in the list of outfits --------------------------------------------------------------------------------- function Wardrobe.OrderOutfit(outfitNum, direction) if (outfitNum == 1 and direction < 0) then return; end if (outfitNum == table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) and direction > 0) then return; end local outfit = Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNum]; if (direction > 0) then swapNum = 0; for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].SortNumber == outfit.SortNumber + 1) then swapNum = i; break; end end Wardrobe_Config[WD_realmID][WD_charID].Outfit[swapNum].SortNumber = outfit.SortNumber outfit.SortNumber = outfit.SortNumber + 1; else swapNum = 0; for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].SortNumber == outfit.SortNumber - 1) then swapNum = i; break; end end Wardrobe_Config[WD_realmID][WD_charID].Outfit[swapNum].SortNumber = outfit.SortNumber outfit.SortNumber = outfit.SortNumber - 1; end return swapNum; end --------------------------------------------------------------------------------- -- return the index of the selected outfit, or nil if none --------------------------------------------------------------------------------- function Wardrobe.FindSelectedOutfit() local outfitNum = nil; for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].Selected) then outfitNum = i; break; end end return outfitNum; end --------------------------------------------------------------------------------- -- Tag this outfit to be worn when mounted --------------------------------------------------------------------------------- function Wardrobe.SetMountedOutfit(outfitName) local outfitNumber; for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].Special = ""; if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].OutfitName == outfitName) then outfitNumber = i; end end if (not outfitNumber) then Wardrobe.Print(TEXT("TXT_UNABLETOFINDOUTFIT").." \""..outfitName..".\""); else Wardrobe_Config[WD_realmID][WD_charID].Outfit[outfitNumber].Special = "mounted"; Wardrobe.Print(TEXT("TXT_OUTFIT").." \""..outfitName.."\" "..TEXT("TXT_WILLBEWORNWHENMOUNTED")); end end --------------------------------------------------------------------------------- -- See if we're mounted --------------------------------------------------------------------------------- function Wardrobe.PlayerIsMounted() if (not IsMounted) then return end return UnitIsMounted("player"); end function Wardrobe.CheckForMounted() --Sea.io.print("CheckForMounted"); if (not IsMounted) then return end local mounted = Wardrobe.PlayerIsMounted(); Wardrobe.EventTaskToggle(mounted, "MountState", "mount", "unmount"); end --------------------------------------------------------------------------------- -- See if we're eating/drinking --------------------------------------------------------------------------------- function Wardrobe.PlayerIsEatingOrDrinking() -- check our buffs for an eat or drink buff for i = 1, 16 do local texture = UnitBuff("player", i); if (texture) then if (string.find(texture,"INV_Misc_Fork") or string.find(texture,"INV_Drink")) then return 1; end end end end function Wardrobe.CheckForEatDrink() local chowing = Wardrobe.PlayerIsEatingOrDrinking(); Wardrobe.EventTaskToggle(chowing, "ChowingState", "eating", "uneating"); end --------------------------------------------------------------------------------- -- See if we switched into or out of the plaguelands --------------------------------------------------------------------------------- function Wardrobe.PlayerIsInPlagueZone() local currZone = GetZoneText(); Wardrobe.CurrentZone = currZone; local plaguezones = Wardrobe.GetPlagueZones(); for i = 1, table.getn(plaguezones) do if (currZone == plaguezones[i]) then return 1; end end end function Wardrobe.ChangedZone() if (Wardrobe.CurrentZone ~= GetZoneText()) then local inPlagueZone = Wardrobe.PlayerIsInPlagueZone(); Wardrobe.EventTaskToggle(inPlagueZone, nil, "plague", "unplague"); end end --------------------------------------------------------------------------------- -- See if we're swimming, or at least if the breath bar is up. --------------------------------------------------------------------------------- function Wardrobe.PlayerIsSwimming() local breathBar; for i=1,3 do breathBar = getglobal("MirrorTimer"..i.."Text"); if (breathBar:IsVisible()) and (breathBar:GetText() == BREATH_LABEL) then return 1; end end end function Wardrobe.CheckForSwimming() local swimming = Wardrobe.PlayerIsSwimming(); Wardrobe.EventTaskToggle(swimming, nil, "swim", "unswim"); end --------------------------------------------------------------------------------- -- Wear the outfit specially tagged as indicated --------------------------------------------------------------------------------- function Wardrobe.WearSpecialOutfit(specialID, virtualOutfitName, wearIt) Wardrobe.CheckForOurWardrobeID(); local outfitNumber; for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do if (Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].Special == specialID) then outfitNumber = i; break; end end if (outfitNumber) then if (wearIt) then -- remember what we're wearing before we put on the special outfit Wardrobe.StoreVirtualOutfit(virtualOutfitName, outfitNumber); -- wear our special outfit Wardrobe.WearOutfit(outfitNumber, true); else -- re-equip the virtual outfit Wardrobe.CheckForEquipVirtualOutfit(virtualOutfitName); end end end --------------------------------------------------------------------------------- -- Trigger special outfits or add task to task list based on event trigger --------------------------------------------------------------------------------- function Wardrobe.EventTaskToggle(value, variableName, trueTaskID, falseTaskID) local taskID; -- toggle the state and schedule wearing our tasked outfit if (variableName) then --Sea.io.print("Value: ", value, " ", variableName, " ", Wardrobe[variableName]); if (value) and (not Wardrobe_Config[variableName]) then taskID = trueTaskID; elseif (not value) and (Wardrobe_Config[variableName]) then taskID = falseTaskID; end else if (value) then taskID = trueTaskID; else taskID = falseTaskID; end end if (taskID) then local taskInfo = Wardrobe.WaitingListVirtualNames[taskID]; if (variableName) then Wardrobe_Config[variableName] = taskInfo.toggle; end if (Wardrobe.IsPlayerInCombat()) then Wardrobe.AddToWaitingList(taskID); else local eventID = taskInfo.id; Wardrobe.WearSpecialOutfit(eventID, Wardrobe.SpecialOutfitVirtualNames[eventID], taskInfo.toggle); end end end --------------------------------------------------------------------------------- -- Waiting Task List Functions --------------------------------------------------------------------------------- function Wardrobe.AddToWaitingList(theTask) --Sea.io.print("Adding "..theTask.." to waiting list!"); table.insert(Wardrobe.WaitingList, theTask); end function Wardrobe.CheckWaitingList() --Sea.io.print("Checking Wardrobe.WaitingList: "..asText(Wardrobe.WaitingList)); for i = 1, table.getn(Wardrobe.WaitingList) do local theTask = table.remove(Wardrobe.WaitingList, 1); --Sea.io.print("Popped "..theTask.." from waiting list!"); local taskID; for taskName, taskInfo in Wardrobe.WaitingListVirtualNames do if (theTask == taskName) then --Sea.io.print("Putting on ".. taskName.." from virtual outfits."); Wardrobe.WearSpecialOutfit(taskInfo.id, Wardrobe.SpecialOutfitVirtualNames[taskInfo.id], taskInfo.toggle); break; end end end end --------------------------------------------------------------------------------- -- Store what we're currently wearing in a virtual outfit --------------------------------------------------------------------------------- function Wardrobe.StoreVirtualOutfit(virtualOutfitName, currentOutfitName) local currentOutfitNum; if (type(currentOutfitName) == "number") then currentOutfitNum = currentOutfitName; else currentOutfitNum = Wardrobe.GetOutfitNum(currentOutfitName); end Wardrobe.ItemCheckState = { }; local outfit = Wardrobe_Config[WD_realmID][WD_charID].Outfit[currentOutfitNum]; for i = 1, Wardrobe.InventorySlotsSize do local item = outfit.Item[i]; if (item) and (item.IsSlotUsed == 1) then Wardrobe.ItemCheckState[i] = 1; end end local newOutfitNum = Wardrobe.GetNextFreeOutfitSlot(true); -- this new outfit will remember what we're about to remove in order to wear our special outfit Wardrobe.StoreItemsInOutfit(virtualOutfitName, newOutfitNum); -- set this outfit to virtual so it'll be hidden and not show up as a normal outfit Wardrobe_Config[WD_realmID][WD_charID].Outfit[newOutfitNum].Virtual = true; end --------------------------------------------------------------------------------- -- If we have a virtual outfit, wear it and delete it --------------------------------------------------------------------------------- function Wardrobe.CheckForEquipVirtualOutfit(virtualOutfitName) if (not virtualOutfitName) then virtualOutfitName = WARDROBE_TEMP_OUTFIT_NAME; end if (Wardrobe.FoundOutfitName(virtualOutfitName)) then Wardrobe.WearOutfit(virtualOutfitName, true); Wardrobe.EraseOutfit(virtualOutfitName, true, true); end end --------------------------------------------------------------------------------- -- Update whether we have all the items for our outfits in our bags --------------------------------------------------------------------------------- function Wardrobe.UpdateOutfitAvailability() if (Wardrobe_Config.Enabled and not Wardrobe.InCombat) then -- if we haven't already looked up our character's number Wardrobe.CheckForOurWardrobeID(); Wardrobe.Debug("Wardrobe Availability:"); local masterItemList = Wardrobe.BuildItemList(); -- for each outfit --for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do for i, outfit in Wardrobe_Config[WD_realmID][WD_charID].Outfit do -- if it has a name if (outfit.OutfitName) and (outfit.OutfitName ~= "") then local foundAllItems = true; -- for each item in the outfit --for j = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit[i].Item) do for j, item in outfit.Item do -- if this slot is used in this outfit if (item) and (item.IsSlotUsed == 1) then if (item.ItemID) and (item.Suffix) and (item.PermEnchant) then local foundTheItem = false; for k = 1, table.getn(masterItemList) do if (item.ItemID == masterItemList[k].ItemID) and (item.Suffix == masterItemList[k].Suffix) and (item.PermEnchant == masterItemList[k].PermEnchant) then foundTheItem = true; break; end end if (not foundTheItem) then foundAllItems = false; break; end elseif (item.Name) and (item.Name ~= "") then local foundTheItem = false; for k = 1, table.getn(masterItemList) do --{Name = itemName, ItemID = itemID, TempEnchant = tempEnchant} if (item.Name == masterItemList[k].Name) then foundTheItem = true; break; end end if (not foundTheItem) then foundAllItems = false; break; end end end end -- if we found all items in our inventory outfit.Available = foundAllItems; Wardrobe.Debug(" Outfit \"".. outfit.OutfitName.."\" -- found all items = "..tostring(foundAllItems)); end end end end --------------------------------------------------------------------------------- -- Determine which outfit we're currently wearing --------------------------------------------------------------------------------- function Wardrobe.DetermineActiveOutfit() Wardrobe.Debug("Wardrobe.DetermineActiveOutfit: Updating Active Outfit"); local ActiveOutfitList = { }; local foundOutfit = false; -- build a reference table of the currently equipped items Wardrobe.CurrentlyEquippedItemList = { }; for j = 1, Wardrobe.InventorySlotsSize do local itemID, permEnchant, tempEnchant, suffix, itemName = Wardrobe.GetItemInfoAtInventorySlotNumber(j); if (itemID) then Wardrobe.CurrentlyEquippedItemList[j] = {Name = itemName, ItemID = itemID, PermEnchant = permEnchant, TempEnchant = tempEnchant, Suffix = suffix}; end end -- for each outfit for i, outfit in Wardrobe_Config[WD_realmID][WD_charID].Outfit do Wardrobe.Debug(" Working on outfit "..i..": "..outfit.OutfitName); foundOutfit = true; -- for each slot on our character (hands, neck, head, feet, etc) for j = 1, Wardrobe.InventorySlotsSize do local item = outfit.Item[j]; -- if this slot is used in this outfit if (item) and (item.IsSlotUsed == 1) then local thisItem = Wardrobe.CurrentlyEquippedItemList[j]; -- if this item is different from what we're already wearing Wardrobe.Debug(" Working on slot -> "..Wardrobe.InventorySlots[j]); -- item in inv slot if (thisItem) and (thisItem.Name) then Wardrobe.Debug(" Comparing ["..tostring(item.Name).."] with ["..tostring(thisItem.Name).."]"); if (item.ItemID) and (item.Suffix) and (item.PermEnchant) then if (item.ItemID ~= thisItem.ItemID) or (item.Suffix ~= thisItem.Suffix) or (item.PermEnchant ~= thisItem.PermEnchant) then foundOutfit = false; break; end elseif (item.Name) and (item.Name ~= "") then if (item.Name ~= thisItem.Name) then foundOutfit = false; break; end else -- Forced empty slot foundOutfit = false; break; end -- no item in inv slot elseif (item.Name) and (item.Name ~= "") then foundOutfit = false; break; end end end if (foundOutfit) then table.insert(ActiveOutfitList, i); end end return ActiveOutfitList; end function Wardrobe.GetActiveOutfitsTextList() local activeOutfitList = Wardrobe.DetermineActiveOutfit(); local outfitText = ""; local outfits = Wardrobe_Config[WD_realmID][WD_charID].Outfit; for i, outfitID in activeOutfitList do -- don't match special outfits local buttonColorTable = WARDROBE_TEXTCOLORS[outfits[outfitID].ButtonColor]; local name = outfits[outfitID].OutfitName; if (strsub(name, 1, 1) ~= "#") then outfitText = outfitText..", |c"..Wardrobe.colorToString(buttonColorTable)..name.."|r"; end end if (outfitText == "") then return TEXT("TXT_NO_OUTFIT"); else return strsub(outfitText, 3); end end function Wardrobe.GetListOfOutfits() Wardrobe.CheckForOurWardrobeID(); Wardrobe.UpdateOutfitAvailability(); local activeOutfits = Wardrobe.DetermineActiveOutfit(); Wardrobe.ActiveOutfitList = activeOutfits; local outfitTable = {}; for i, outfit in Wardrobe_Config[WD_realmID][WD_charID].Outfit do local nameString = outfit.OutfitName; if (strsub(nameString, 1, 1) ~= "#") then if ( Wardrobe.isInList(activeOutfits, i) ) then nameString = "|c"..Wardrobe.colorToString(WARDROBE_TEXTCOLORS[outfit.ButtonColor])..nameString.."|r"; elseif ( outfit.Available ) then nameString = "|c"..Wardrobe.colorToString(WARDROBE_DRABCOLORS[outfit.ButtonColor])..nameString.."|r"; else nameString = "|c"..Wardrobe.colorToString(WARDROBE_UNAVAILIBLECOLOR)..nameString.."|r"; end tinsert(outfitTable, nameString); end end return outfitTable; end --============================================================================================-- --============================================================================================-- -- -- -- UTILITY FUNCTIONS -- -- -- --============================================================================================-- --============================================================================================-- ----------------------------------------------------------------------------------- -- for in-line coloring (from Sea) ----------------------------------------------------------------------------------- function Wardrobe.colorToString( color ) if ( not color ) then return "FFFFFFFF"; end return format( "%.2X%.2X%.2X%.2X", 255, color[1]*255, color[2]*255, color[3]*255 ); end ----------------------------------------------------------------------------------- -- value comparison, returns key/index ----------------------------------------------------------------------------------- function Wardrobe.isInList( list, value ) if ( not list or not value ) then return; end for k, v in list do if (v == value) then return k; end end end ----------------------------------------------------------------------------------- -- Our own print function ----------------------------------------------------------------------------------- function Wardrobe.Print(theMsg, r, g, b) -- 0.50, 0.50, 1.00 if (not r) then r = 0.50; end if (not g) then g = 0.50; end if (not b) then b = 1.00; end if (type(theMsg) == "table") then Print(asText(theMsg), r, g, b); else Print(theMsg, r, g, b); end end ----------------------------------------------------------------------------------- -- Toggle the plugin on and off ----------------------------------------------------------------------------------- function Wardrobe.Toggle(toggle) if (toggle == 1) then if (not Khaos) then Wardrobe.Print(TEXT("TXT_ENABLED")); end Wardrobe_Config.Enabled = true; Wardrobe.TitanUpdateMinimapStatus(true); else if (not Khaos) then Wardrobe.Print(TEXT("TXT_DISABLED")); end Wardrobe_Config.Enabled = false; Wardrobe.TitanUpdateMinimapStatus(false); end end ----------------------------------------------------------------------------------- -- Nifty little function to view any lua object as text ----------------------------------------------------------------------------------- function asText(obj) visitRef = {} visitRef.n = 0 asTxRecur = function(obj, asIndex) if type(obj) == "table" then if visitRef[obj] then return "@"..visitRef[obj] end visitRef.n = visitRef.n +1 visitRef[obj] = visitRef.n local begBrac, endBrac if asIndex then begBrac, endBrac = "[{", "}]" else begBrac, endBrac = "{", "}" end local t = begBrac local k, v = nil, nil repeat k, v = next(obj, k) if k ~= nil then if t > begBrac then t = t..", " end t = t..asTxRecur(k, 1).."="..asTxRecur(v) end until k == nil return t..endBrac else if asIndex then -- we're on the left side of an "=" if type(obj) == "string" then return obj else return "["..obj.."]" end else -- we're on the right side of an "=" if type(obj) == "string" then return '"'..obj..'"' else return tostring(obj) end end end end -- asTxRecur return asTxRecur(obj) end -- asText --------------------------------------------------------------------------------- -- Display the help text --------------------------------------------------------------------------------- function Wardrobe.ShowHelp() Wardrobe.Print(TEXT("HELP_1")..WARDROBE_VERSION); Wardrobe.Print(TEXT("HELP_2")); Wardrobe.Print(TEXT("HELP_3")); Wardrobe.Print(TEXT("HELP_4")); Wardrobe.Print(TEXT("HELP_5")); Wardrobe.Print(TEXT("HELP_6")); Wardrobe.Print(TEXT("HELP_7")); Wardrobe.Print(TEXT("HELP_8")); Wardrobe.Print(TEXT("HELP_9")); Wardrobe.Print(TEXT("HELP_10")); Wardrobe.Print(TEXT("HELP_11")); Wardrobe.Print(TEXT("HELP_12")); Wardrobe.Print(TEXT("HELP_13")); Wardrobe.Print(TEXT("HELP_14")); Wardrobe.Print(TEXT("HELP_15")); Wardrobe.Print(TEXT("HELP_16")); end --============================================================================================-- --============================================================================================-- -- -- -- DEBUG FUNCTIONS -- -- -- --============================================================================================-- --============================================================================================-- ----------------------------------------------------------------------------------- -- Print out a debug statement if the WARDROBE_DEBUG flag is set ----------------------------------------------------------------------------------- function Wardrobe.Debug(theMsg) if (WARDROBE_DEBUG) then ChatFrame1:AddMessage(theMsg, 1.0, 1.0, 0.7); end end --------------------------------------------------------------------------------- -- Toggle debug output --------------------------------------------------------------------------------- function Wardrobe.ToggleDebug() WARDROBE_DEBUG = not WARDROBE_DEBUG; if (WARDROBE_DEBUG) then Print("Wardrobe: Debug ON",1.0,1.0,0.5); else Print("Wardrobe: Debug OFF",1.0,1.0,0.5); end end --------------------------------------------------------------------------------- -- Debug routine to print the current state of the plugin --------------------------------------------------------------------------------- function Wardrobe.DumpDebugReport() Wardrobe.CheckForOurWardrobeID(); Wardrobe.Debug("Wardrobe.DumpDebugReport: Character's wardrobe database"); local WardrobeDatabase = Wardrobe_Config[WD_realmID][WD_charID]; for outfitNum, outfit in WardrobeDatabase.Outfit do Wardrobe.Debug("Outfit: "..tostring(outfit.OutfitName)); for i, item in outfit.Item do if (item) then Wardrobe.Debug(Wardrobe.InventorySlots[i].." = "..tostring(item.Name)); end end end end --------------------------------------------------------------------------------- -- Print a debug report --------------------------------------------------------------------------------- function Wardrobe.DumpDebugStruct() for i = 1, table.getn(Wardrobe_Config[WD_realmID][WD_charID].Outfit) do Print("Outfit #"..i..":"); Print(asText(Wardrobe_Config[WD_realmID][WD_charID].Outfit[i])); Print("--------------------"); end end