1287 lines
38 KiB
Lua
1287 lines
38 KiB
Lua
OUTFITDISPLAYFRAME_VERSION = GetAddOnMetadata("OutfitDisplayFrame", "Version");
|
|
|
|
OUTFITDISPLAYFRAME_NAME = "Outfit Display Frame";
|
|
OUTFITDISPLAYFRAME_TITLE = OUTFITDISPLAYFRAME_NAME.." v"..OUTFITDISPLAYFRAME_VERSION;
|
|
OUTFITDISPLAYFRAME_BANKDELAY = 0.5;
|
|
|
|
local PlayerSlotNames = {
|
|
[1] = { name = "HeadSlot", tooltip = HEADSLOT };
|
|
[2] = { name = "NeckSlot", tooltip = NECKSLOT },
|
|
[3] = { name = "ShoulderSlot", tooltip = SHOULDERSLOT },
|
|
[4] = { name = "BackSlot", tooltip = BACKSLOT },
|
|
[5] = { name = "ChestSlot", tooltip = CHESTSLOT },
|
|
[6] = { name = "ShirtSlot", tooltip = SHIRTSLOT },
|
|
[7] = { name = "TabardSlot", tooltip = TABARDSLOT },
|
|
[8] = { name = "WristSlot", tooltip = WRISTSLOT },
|
|
[9] = { name = "HandsSlot", tooltip = HANDSSLOT },
|
|
[10] = { name = "WaistSlot", tooltip = WAISTSLOT },
|
|
[11] = { name = "LegsSlot", tooltip = LEGSSLOT },
|
|
[12] = { name = "FeetSlot", tooltip = FEETSLOT },
|
|
[13] = { name = "Finger0Slot", tooltip = FINGER0SLOT },
|
|
[14] = { name = "Finger1Slot", tooltip = FINGER1SLOT },
|
|
[15] = { name = "Trinket0Slot", tooltip = TRINKET0SLOT },
|
|
[16] = { name = "Trinket1Slot", tooltip = TRINKET1SLOT },
|
|
[17] = { name = "MainHandSlot", tooltip = MAINHANDSLOT },
|
|
[18] = { name = "SecondaryHandSlot", tooltip = SECONDARYHANDSLOT },
|
|
[19] = { name = "RangedSlot", tooltip = RANGEDSLOT },
|
|
}
|
|
|
|
local SavedPickupContainerItem = nil;
|
|
local SavedPickupInventoryItem = nil;
|
|
|
|
local LastOffSource = nil;
|
|
local PerformSlowerSwap = false;
|
|
local BankIsOpen = false;
|
|
|
|
local function tonil(val)
|
|
if ( not val ) then
|
|
return "nil";
|
|
else
|
|
return val;
|
|
end
|
|
end
|
|
|
|
local function Print(msg, r, g, b)
|
|
if ( DEFAULT_CHAT_FRAME ) then
|
|
if ( not r ) then
|
|
DEFAULT_CHAT_FRAME:AddMessage(msg);
|
|
else
|
|
DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b);
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Based on code in QuickMountEquip
|
|
local function SafeHookFunction(func, newfunc)
|
|
local oldValue = getglobal(func);
|
|
if ( oldValue ~= getglobal(newfunc) ) then
|
|
setglobal(func, getglobal(newfunc));
|
|
return true;
|
|
end
|
|
return false;
|
|
end
|
|
|
|
-- this really ought to be in a library somewhere
|
|
local function SplitLink(link)
|
|
local _,_, color, item, name = string.find(link, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r");
|
|
return color, item, name;
|
|
end
|
|
|
|
function OutfitDisplayFrame_OnLoad()
|
|
local temp = PickupContainerItem;
|
|
if ( SafeHookFunction("PickupContainerItem", "OutfitDisplayFrame_PickupContainerItem") ) then
|
|
SavedPickupContainerItem = temp;
|
|
end
|
|
|
|
temp = PickupInventoryItem;
|
|
if ( SafeHookFunction("PickupInventoryItem", "OutfitDisplayFrame_PickupInventoryItem") ) then
|
|
SavedPickupInventoryItem = temp;
|
|
end
|
|
|
|
local parent = this:GetName();
|
|
for i=1,19,1 do
|
|
local slotName = PlayerSlotNames[i].name;
|
|
local button = getglobal(parent..slotName);
|
|
button.tooltip = PlayerSlotNames[i].tooltip;
|
|
OutfitDisplayItemButton_Draw(button);
|
|
PlayerSlotNames[i].id = GetInventorySlotInfo(slotName);
|
|
end
|
|
|
|
-- ITEM_LOCK_CHANGED gets invoked a lot -- let's optimize it
|
|
this:RegisterEvent("PLAYER_ENTERING_WORLD");
|
|
this:RegisterEvent("PLAYER_LEAVING_WORLD");
|
|
|
|
-- ideas borrowed from "WeaponQuickSwap - by CapnBry"
|
|
this:RegisterEvent("BANKFRAME_OPENED");
|
|
this:RegisterEvent("BANKFRAME_CLOSED");
|
|
|
|
Print(OUTFITDISPLAYFRAME_TITLE.." loaded.");
|
|
end
|
|
|
|
local function DressUpItem(model, thing)
|
|
if ( not model or not thing or thing == "" ) then
|
|
return;
|
|
end
|
|
local item = gsub(thing, "(%d+).*", "%1", 1);
|
|
model:TryOn(item);
|
|
end
|
|
|
|
local BankFrameClosedTime = 0;
|
|
|
|
function OutfitDisplayFrame_OnEvent(...)
|
|
if (arg[1] == "ITEM_LOCK_CHANGED") and not arg[2] then
|
|
OutfitDisplayFrame_ExecuteSwapIteration();
|
|
elseif ( arg[1] == "BANKFRAME_OPENED" or arg[1] == "BANKFRAME_CLOSED" ) then
|
|
BankFrameIsOpen = ( arg[1] == "BANKFRAME_OPENED" );
|
|
local frame = getglobal(this:GetName().."MessageUpdateFrame");
|
|
if ( frame ) then
|
|
BankFrameClosedTime = OUTFITDISPLAYFRAME_BANKDELAY;
|
|
frame:Show();
|
|
end
|
|
elseif ( arg[1] == "PLAYER_ENTERING_WORLD" ) then
|
|
this:RegisterEvent("ITEM_LOCK_CHANGED");
|
|
elseif ( arg[1] == "PLAYER_LEAVING_WORLD" ) then
|
|
this:UnregisterEvent("ITEM_LOCK_CHANGED");
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_MessageUpdate(elapsed)
|
|
BankFrameClosedTime = BankFrameClosedTime - elapsed;
|
|
if ( BankFrameClosedTime <= 0 ) then
|
|
this:Hide();
|
|
OutfitDisplayFrame_UpdateMessage(this:GetParent());
|
|
BankFrameClosedTime = 0;
|
|
end
|
|
end
|
|
|
|
local function GetSlotButton(button, slotName)
|
|
local parent = button:GetParent():GetName();
|
|
return getglobal(parent..slotName);
|
|
end
|
|
|
|
local WOW = nil;
|
|
local function _GetItemInfo(link)
|
|
if ( not WOW ) then
|
|
WOW = {};
|
|
local v, b, d = GetBuildInfo();
|
|
WOW.build = b;
|
|
WOW.date = d;
|
|
local s,e,maj,min,dot = string.find(v, "(%d+).(%d+).(%d+)");
|
|
FishingBuddy.Debug("Version "..v);
|
|
WOW.major = tonumber(maj);
|
|
WOW.minor = tonumber(min);
|
|
WOW.dot = tonumber(dot);
|
|
end
|
|
-- name, link, rarity, itemlevel, minlevel, itemtype
|
|
-- subtype, stackcount, equiploc, texture
|
|
local nm,li,ra,il,ml,it,st,sc,el,tx;
|
|
if ( WOW.major > 1 ) then
|
|
nm,li,ra,il,ml,it,st,sc,el,tx = GetItemInfo(link);
|
|
else
|
|
nm,li,ra,ml,it,st,sc,el,tx = GetItemInfo(link);
|
|
end
|
|
return nm,li,ra,ml,it,st,sc,el,tx,il;
|
|
end
|
|
|
|
local function IsItemOneHanded(item)
|
|
if ( item ) then
|
|
local _,_,_,_,_,_,_,bodyslot = _GetItemInfo("item:"..item);
|
|
if ( bodyslot == "INVTYPE_2HWEAPON" or bodyslot == INVTYPE_2HWEAPON ) then
|
|
return false;
|
|
end
|
|
end
|
|
return true;
|
|
end
|
|
|
|
function OutfitDisplayFrame_CursorCanGoInSlot(button)
|
|
if ( button.forced ) then
|
|
return false;
|
|
end
|
|
local secondary = GetSlotButton(button, "SecondaryHandSlot");
|
|
local mainbutton = GetSlotButton(button, "MainHandSlot");
|
|
if ( button == secondary and mainbutton and mainbutton.item ) then
|
|
return IsItemOneHanded(mainbutton.item);
|
|
end
|
|
return CursorCanGoInSlot(button:GetID())
|
|
end
|
|
|
|
-- much hackery to know what actually is in the cursor when somebody drops it on us
|
|
local OD_Track_Bag = nil;
|
|
local OD_Track_Slot = nil;
|
|
|
|
-- whatever we think the user picked up, apply it to our stuff
|
|
local function AcceptCursorItem(button)
|
|
local parent = button:GetParent();
|
|
local pname = parent:GetName();
|
|
if ( not OutfitDisplayFrame_CursorCanGoInSlot(button) ) then
|
|
button = nil;
|
|
for i=1,19,1 do
|
|
local temp = getglobal(pname..PlayerSlotNames[i].name);
|
|
if ( temp and OutfitDisplayFrame_CursorCanGoInSlot(temp) ) then
|
|
button = temp;
|
|
end
|
|
end
|
|
end
|
|
|
|
if ( button ) then
|
|
local link, texture;
|
|
if ( OD_Track_Bag ) then
|
|
link = GetContainerItemLink(OD_Track_Bag, OD_Track_Slot);
|
|
texture = GetContainerItemInfo(OD_Track_Bag, OD_Track_Slot);
|
|
else
|
|
link = GetInventoryItemLink("player", OD_Track_Slot);
|
|
texture = GetInventoryItemTexture("player", OD_Track_Slot);
|
|
end
|
|
button.color, button.item, button.name = SplitLink(link);
|
|
button.texture = texture;
|
|
button.used = true;
|
|
button.empty = nil;
|
|
button.missing = false;
|
|
if ( OD_Track_Bag and (OD_Track_Bag == BANK_CONTAINER or
|
|
OD_Track_Bag > NUM_BAG_SLOTS) ) then
|
|
button.banked = true;
|
|
end
|
|
OutfitDisplayItemButton_Change(button);
|
|
end
|
|
|
|
-- clear the cursor item
|
|
if ( OD_Track_Bag ) then
|
|
SavedPickupContainerItem(OD_Track_Bag, OD_Track_Slot);
|
|
elseif ( OD_Track_Slot ) then
|
|
SavedPickupInventoryItem(OD_Track_Slot);
|
|
end
|
|
OD_Track_Bag = nil;
|
|
OD_Track_Slot = nil;
|
|
end
|
|
|
|
-- figure out what the user picked up, so that if they drop it on us we can deal with it
|
|
function OutfitDisplayFrame_TrackItemPickup(bag, slot)
|
|
OD_Track_Bag = bag;
|
|
OD_Track_Slot = slot;
|
|
end
|
|
|
|
function OutfitDisplayFrame_PickupContainerItem(bag, slot)
|
|
if ( SavedPickupContainerItem ) then
|
|
SavedPickupContainerItem(bag, slot);
|
|
end
|
|
OutfitDisplayFrame_TrackItemPickup(bag, slot);
|
|
end
|
|
|
|
function OutfitDisplayFrame_PickupInventoryItem(slot)
|
|
if ( SavedPickupInventoryItem ) then
|
|
SavedPickupInventoryItem(slot);
|
|
end
|
|
OutfitDisplayFrame_TrackItemPickup(nil, slot);
|
|
end
|
|
|
|
-- handle making the items in the outfit pane do nice things
|
|
function OutfitDisplayItemButton_OnEnter()
|
|
if ( GameTooltip.finished ) then
|
|
return;
|
|
end
|
|
GameTooltip.finished = 1;
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
|
|
if (this.item) then
|
|
local link = "item:"..this.item;
|
|
if ( GetItemInfo(link) ) then
|
|
GameTooltip:SetHyperlink(link);
|
|
elseif ( this.name ) then
|
|
GameTooltip:SetText(this.name);
|
|
elseif ( this.tooltip ) then
|
|
GameTooltip:SetText(this.tooltip);
|
|
else
|
|
GameTooltip:SetText("<unlinkable item>", 1, 0, 0);
|
|
end
|
|
elseif ( this.tooltip ) then
|
|
GameTooltip:AddLine(this.tooltip);
|
|
else
|
|
local parentlen = string.len(this:GetParent():GetName())+1;
|
|
local slotName = strsub(this:GetName(), parentlen);
|
|
slotName = strsub(slotName, 1, string.len(slotName) - 4);
|
|
this.tooltip = slotName;
|
|
GameTooltip:AddLine(this.tooltip);
|
|
end
|
|
local parent = this:GetParent();
|
|
if ( parent.CustomTooltip ) then
|
|
parent.CustomTooltip(this);
|
|
end
|
|
GameTooltip:AddLine(OUTFITDISPLAYFRAME_ALTCLICK,.8,.8,.8,1);
|
|
GameTooltip:Show();
|
|
end
|
|
|
|
function OutfitDisplayItemButton_OnEvent(event)
|
|
if ( event == "CURSOR_UPDATE" ) then
|
|
if ( not this.forced ) then
|
|
if ((this.CursorCanGoInSlot and this.CursorCanGoInSlot(this)) or
|
|
OutfitDisplayFrame_CursorCanGoInSlot(this)) then
|
|
this:LockHighlight();
|
|
else
|
|
this:UnlockHighlight();
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayItemButton_OnClick(clicked, ignoreModifiers)
|
|
if ( clicked == "LeftButton" ) then
|
|
if( not ignoreModifiers or ignoreModifiers == 0 ) then
|
|
if ( IsShiftKeyDown() ) then
|
|
if ( this.item and ChatFrameEditBox:IsVisible() ) then
|
|
local color = this.color;
|
|
if ( not color ) then
|
|
color = "ffffffff";
|
|
end
|
|
local link = "|c"..color.."|Hitem"..this.item.."|h["..this.name.."]|h|r";
|
|
ChatFrameEditBox:Insert(link);
|
|
return;
|
|
end
|
|
elseif ( IsAltKeyDown() ) then
|
|
OutfitDisplayItemButton_Clear(this, false, false);
|
|
OutfitDisplayItemButton_Change(this);
|
|
return;
|
|
end
|
|
end
|
|
-- fall through for drags and non-modified clicks
|
|
if ( CursorHasItem() ) then
|
|
AcceptCursorItem(this);
|
|
end
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayItemButton_OnLoad()
|
|
local parentlen = string.len(this:GetParent():GetName())+1;
|
|
local slotName = strsub(this:GetName(), parentlen);
|
|
local id;
|
|
local textureName;
|
|
id, textureName = GetInventorySlotInfo(slotName);
|
|
this:SetID(id);
|
|
this.backgroundTextureName = textureName;
|
|
SetItemButtonTexture(this, this.backgroundTextureName);
|
|
this:RegisterForDrag("LeftButton");
|
|
this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
|
this:RegisterEvent("CURSOR_UPDATE");
|
|
end
|
|
|
|
function OutfitDisplayItemButton_Draw(button)
|
|
if ( button.texture ) then
|
|
SetItemButtonTexture(button, button.texture);
|
|
else
|
|
SetItemButtonTexture(button, button.backgroundTextureName);
|
|
end
|
|
if ( button.missing ) then
|
|
SetItemButtonTextureVertexColor(button, 1.0, 0.1, 0.1);
|
|
elseif ( button.banked ) then
|
|
SetItemButtonTextureVertexColor(button, 0.1, 0.1, 1.0);
|
|
else
|
|
SetItemButtonTextureVertexColor(button, 1.0, 1.0, 1.0);
|
|
end
|
|
local checkbox = getglobal(button:GetName().."CheckBox");
|
|
if (checkbox) then
|
|
local pname = button:GetParent():GetName();
|
|
local showhelm = getglobal(pname.."ShowHelm");
|
|
local showcloak = getglobal(pname.."ShowCloak");
|
|
if ( button.forced ) then
|
|
checkbox:SetChecked(true);
|
|
checkbox:Disable();
|
|
checkbox:Show();
|
|
elseif ( button.empty or not button.used ) then
|
|
if ( checkbox.slotName == "HeadSlot" ) then
|
|
showhelm:Hide();
|
|
showhelm:SetChecked(false);
|
|
elseif ( checkbox.slotName == "BackSlot" ) then
|
|
showcloak:Hide();
|
|
showcloak:SetChecked(false);
|
|
end
|
|
checkbox:Enable();
|
|
checkbox:SetChecked(button.empty);
|
|
checkbox:Show();
|
|
elseif ( button.used ) then
|
|
checkbox:Hide();
|
|
if ( checkbox.slotName == "HeadSlot" ) then
|
|
showhelm:Show();
|
|
elseif ( checkbox.slotName == "BackSlot" ) then
|
|
showcloak:Show();
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayItemButton_Change(button)
|
|
OutfitDisplayItemButton_Draw(button);
|
|
-- handle two handed weapons
|
|
local parent = button:GetParent();
|
|
local pname = parent:GetName();
|
|
local parentlen = string.len(pname)+1;
|
|
local slotName = strsub(button:GetName(), parentlen);
|
|
if ( slotName == "MainHandSlot" ) then
|
|
local secondary = getglobal(pname.."SecondaryHandSlot");
|
|
if ( not button.used and secondary.forced ) then
|
|
OutfitDisplayItemButton_Clear(secondary, false, false);
|
|
elseif ( button.used and not IsItemOneHanded(button.item) ) then
|
|
OutfitDisplayItemButton_Clear(secondary, true);
|
|
secondary.forced = true;
|
|
end
|
|
OutfitDisplayItemButton_Draw(secondary);
|
|
end
|
|
OutfitDisplayFrame_UpdateMessage(parent);
|
|
OutfitDisplayFrame_UpdateModel(parent, button);
|
|
if( parent.OutfitChanged ) then
|
|
parent.OutfitChanged( button );
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayItemButton_Clear(button, empty, used)
|
|
button.name = nil;
|
|
button.item = nil;
|
|
button.texture = nil;
|
|
button.color = nil;
|
|
button.missing = nil;
|
|
button.banked = nil;
|
|
button.forced = nil;
|
|
button.empty = empty;
|
|
button.used = used or empty;
|
|
end
|
|
|
|
-- override ShowHelm and ShowCloak
|
|
function OutfitDisplayOverrideBox_OnLoad()
|
|
local parentlen = string.len(this:GetParent():GetName())+1;
|
|
this.slotName = strsub(this:GetName(), parentlen);
|
|
end
|
|
|
|
function OutfitDisplayOverrideBox_OnEnter()
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
|
|
local text;
|
|
if ( this.slotName == "ShowHelm" ) then
|
|
text = OUTFITDISPLAYFRAME_OVERRIDEHELM;
|
|
else
|
|
text = OUTFITDISPLAYFRAME_OVERRIDECLOAK;
|
|
end
|
|
GameTooltip:SetText(text, nil, nil, nil, nil, 1);
|
|
GameTooltip:Show();
|
|
end
|
|
|
|
-- check box handling
|
|
function OutfitDisplayCheckBox_OnEnter()
|
|
GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
|
|
GameTooltip:SetText(OUTFITDISPLAYFRAME_USECHECKBOX, nil, nil, nil, nil, 1);
|
|
GameTooltip:Show();
|
|
end
|
|
|
|
function OutfitDisplayCheckBox_OnLoad()
|
|
local parentlen = string.len(this:GetParent():GetName())+1;
|
|
local name = strsub(this:GetName(), parentlen);
|
|
this.slotName = strsub(name, 1, -9);
|
|
end
|
|
|
|
function OutfitDisplayCheckBox_OnClick()
|
|
local pname = this:GetParent():GetName();
|
|
local button = getglobal(pname..this.slotName);
|
|
OutfitDisplayItemButton_Clear(button, this:GetChecked());
|
|
OutfitDisplayItemButton_Change(button);
|
|
end
|
|
|
|
local function UpdateModel_ThisSlot(pname, model, idx)
|
|
local slotName = PlayerSlotNames[idx].name;
|
|
local what = getglobal(pname..slotName);
|
|
local item = nil;
|
|
if ( what and what.used ) then
|
|
if ( not what.empty ) then
|
|
item = what.item;
|
|
end
|
|
else
|
|
local slot = PlayerSlotNames[idx].id;
|
|
local link = GetInventoryItemLink("player", slot);
|
|
if ( link ) then
|
|
_, item, _ = SplitLink(link);
|
|
end
|
|
end
|
|
if ( item ) then
|
|
DressUpItem(model, item);
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_UpdateModel(frame, button)
|
|
local pname = frame:GetName();
|
|
local model = getglobal(pname.."Model");
|
|
local empty = false;
|
|
if ( not model ) then
|
|
return;
|
|
end
|
|
if ( button and button.used ) then
|
|
if ( button.empty and not button.forced ) then
|
|
empty = true;
|
|
end
|
|
else
|
|
for i=1,19,1 do
|
|
local what = getglobal(pname..PlayerSlotNames[i].name);
|
|
if ( what and what.empty ) then
|
|
empty = true;
|
|
end
|
|
end
|
|
end
|
|
if ( empty ) then
|
|
model:Undress();
|
|
end
|
|
for i=19,1,-1 do
|
|
UpdateModel_ThisSlot(pname, model, i);
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_SetOutfit(frame, outfit)
|
|
if not outfit then
|
|
return;
|
|
end
|
|
local pname = frame:GetName();
|
|
for i=1,19,1 do
|
|
local slotName = PlayerSlotNames[i].name;
|
|
local button = getglobal(pname..slotName);
|
|
if ( button and outfit[slotName] and outfit[slotName].used ) then
|
|
OutfitDisplayItemButton_Clear(button);
|
|
if ( outfit[slotName].used ) then
|
|
button.name = outfit[slotName].name;
|
|
button.item = outfit[slotName].item;
|
|
button.texture = outfit[slotName].texture;
|
|
button.color = outfit[slotName].color;
|
|
button.missing = outfit[slotName].missing;
|
|
button.banked = outfit[slotName].banked;
|
|
button.forced = outfit[slotName].forced;
|
|
button.empty = outfit[slotName].empty;
|
|
button.used = true;
|
|
else
|
|
OutfitDisplayItemButton_Clear(button, true, true);
|
|
end
|
|
OutfitDisplayItemButton_Draw(button);
|
|
end
|
|
end
|
|
if ( outfit["Options"] ) then
|
|
local showhelm = getglobal(pname.."ShowHelm");
|
|
local showcloak = getglobal(pname.."ShowCloak");
|
|
showhelm:SetChecked(outfit["Options"].helm);
|
|
showcloak:SetChecked(outfit["Options"].cloak);
|
|
end
|
|
OutfitDisplayFrame_UpdateModel(frame);
|
|
OutfitDisplayFrame_UpdateMessage(frame, outfit);
|
|
end
|
|
|
|
function OutfitDisplayFrame_GetOutfit(frame, puthere)
|
|
local pname = frame:GetName();
|
|
local outfit = puthere or nil;
|
|
local showhelm = getglobal(pname.."ShowHelm");
|
|
local showcloak = getglobal(pname.."ShowCloak");
|
|
local setOptions = false;
|
|
if not outfit then
|
|
outfit = {};
|
|
end
|
|
outfit["Options"] = {};
|
|
for i=1,19,1 do
|
|
local slotName = PlayerSlotNames[i].name;
|
|
local button = getglobal(pname..slotName);
|
|
|
|
if ( button and button.used ) then
|
|
outfit[slotName] = {};
|
|
if ( not button.empty ) then
|
|
outfit[slotName].name = button.name;
|
|
outfit[slotName].item = button.item;
|
|
outfit[slotName].texture = button.texture;
|
|
outfit[slotName].color = button.color;
|
|
outfit[slotName].missing = button.missing;
|
|
outfit[slotName].banked = button.banked;
|
|
outfit[slotName].forced = button.forced;
|
|
end
|
|
outfit[slotName].empty = button.empty;
|
|
outfit[slotName].used = true;
|
|
if ( not button.empty ) then
|
|
if ( slotName == "HeadSlot" ) then
|
|
if ( showhelm ) then
|
|
if ( showhelm:GetChecked() ) then
|
|
outfit["Options"].helm = 1;
|
|
end
|
|
setOptions = true;
|
|
end
|
|
elseif ( slotName == "BackSlot" ) then
|
|
if ( showcloak ) then
|
|
if ( showcloak:GetChecked() ) then
|
|
outfit["Options"].cloak = 1;
|
|
end
|
|
setOptions = true;
|
|
end
|
|
end
|
|
end
|
|
elseif ( outfit and outfit.used ) then
|
|
outfit[slotName] = nil;
|
|
end
|
|
end
|
|
if ( not setOptions ) then
|
|
outfit["Options"] = nil;
|
|
end
|
|
if ( outfit ) then
|
|
-- check for two-handed weapon
|
|
local mainhand = outfit["MainHandSlot"];
|
|
if ( mainhand and not IsItemOneHanded(mainhand.item) ) then
|
|
outfit["SecondaryHandSlot"] = {};
|
|
outfit["SecondaryHandSlot"].forced = true;
|
|
outfit["SecondaryHandSlot"].empty = true;
|
|
outfit["SecondaryHandSlot"].used = true;
|
|
end
|
|
end
|
|
return outfit;
|
|
end
|
|
|
|
function OutfitDisplayFrame_GetItemInfo(bag, slot)
|
|
local link;
|
|
local c, i, n;
|
|
if ( bag ) then
|
|
link = GetContainerItemLink (bag,slot);
|
|
else
|
|
link = GetInventoryItemLink("player", slot);
|
|
end
|
|
if (link) then
|
|
c, i, n = SplitLink(link);
|
|
end
|
|
return c, i, n;
|
|
end
|
|
|
|
-- get a snapshot of the current state of the player
|
|
function OutfitDisplayFrame_GetBagInfo()
|
|
local contents = {};
|
|
local empties = {};
|
|
|
|
local numSlots = 0;
|
|
-- check each of the bags on the player
|
|
for bag=0, NUM_BAG_FRAMES do
|
|
-- get the number of slots in the bag (0 if no bag)
|
|
numSlots = GetContainerNumSlots(bag);
|
|
if (numSlots > 0) then
|
|
-- check each slot in the bag
|
|
for slot=1, numSlots do
|
|
local c, i, n = OutfitDisplayFrame_GetItemInfo(bag, slot);
|
|
if ( i ) then
|
|
contents[i] = {};
|
|
contents[i].bag = bag;
|
|
contents[i].slot = slot;
|
|
contents[i].color = c;
|
|
contents[i].name = n;
|
|
else
|
|
local what = {};
|
|
what.bag = bag;
|
|
what.slot = slot;
|
|
tinsert(empties, what);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
for idx=1,19,1 do
|
|
local slot = PlayerSlotNames[idx].id;
|
|
local c, i, n = OutfitDisplayFrame_GetItemInfo(nil, slot);
|
|
if ( i ) then
|
|
contents[i] = {};
|
|
contents[i].slot = slot;
|
|
contents[i].color = c;
|
|
contents[i].name = n;
|
|
end
|
|
end
|
|
|
|
return contents, empties;
|
|
end
|
|
|
|
-- look in a particular bag
|
|
local function CheckThisBag(bag, id, skipcount)
|
|
-- get the number of slots in the bag (0 if no bag)
|
|
local numSlots = GetContainerNumSlots(bag);
|
|
if (numSlots > 0) then
|
|
-- check each slot in the bag
|
|
for slot=1, numSlots do
|
|
local c, i, n = OutfitDisplayFrame_GetItemInfo(bag, slot);
|
|
if ( i and id == i ) then
|
|
if ( skipcount == 0 ) then
|
|
return slot, skipcount;
|
|
end
|
|
skipcount = skipcount - 1;
|
|
end
|
|
end
|
|
end
|
|
return nil, skipcount;
|
|
end
|
|
|
|
-- look for the outfit anywhere we can find it
|
|
local function FindThisItem(id, skipcount)
|
|
if ( not id ) then
|
|
return nil,nil,nil;
|
|
end
|
|
local skipcount = skipcount or 0;
|
|
-- check each of the bags on the player
|
|
for bag=0, NUM_BAG_FRAMES do
|
|
local slot;
|
|
slot, skipcount = CheckThisBag(bag, id, skipcount);
|
|
if ( slot ) then
|
|
return bag, slot, false;
|
|
end
|
|
end
|
|
|
|
for idx=1,19,1 do
|
|
local slot = PlayerSlotNames[idx].id;
|
|
local c, i, n = OutfitDisplayFrame_GetItemInfo(nil, slot);
|
|
if ( (id and i and id == i) or (name and n and name == n) ) then
|
|
if ( skipcount == 0 ) then
|
|
return nil, slot, false;
|
|
end
|
|
skipcount = skipcount - 1;
|
|
end
|
|
end
|
|
|
|
-- look in the bank
|
|
-- Geez, this is ugly
|
|
local bankbags = { BANK_CONTAINER, 5, 6, 7, 8, 9, 10 };
|
|
for b=1,7 do
|
|
local slot;
|
|
slot, skipcount = CheckThisBag(bankbags[b], id, skipcount);
|
|
if ( slot ) then
|
|
return bankbags[b], slot, true;
|
|
end
|
|
end
|
|
-- return nil, nil, nil;
|
|
end
|
|
|
|
-- look for the outfit anywhere we can find it
|
|
-- we should look in the bank someday
|
|
function OutfitDisplayFrame_FindOutfit(outfit)
|
|
-- look for every item, if we find everything return a table of locations
|
|
-- otherwise don't return anything
|
|
if ( not outfit ) then
|
|
return nil;
|
|
end
|
|
local spots = { };
|
|
for slotName in pairs(outfit) do
|
|
if ( outfit[slotName].use and not outfit[slotName].empty ) then
|
|
local bag, slot = FindThisItem( outfit[slotName].item );
|
|
if ( not bag and not slot ) then
|
|
spots = nil;
|
|
return nil;
|
|
else
|
|
spots[slotName] = { };
|
|
spots[slotName].bag = bag;
|
|
spots[slotName].slot = slot;
|
|
end
|
|
end
|
|
end
|
|
return spots;
|
|
end
|
|
|
|
function OutfitDisplayFrame_CanFindOutfit(outfit)
|
|
if ( not outfit ) then
|
|
return false;
|
|
end
|
|
for slotName in pairs(outfit) do
|
|
if ( outfit[slotName].used and not outfit[slotName].empty ) then
|
|
local bag, slot = FindThisItem( outfit[slotName].item );
|
|
if ( not bag and not slot ) then
|
|
return false;
|
|
end
|
|
end
|
|
end
|
|
return true;
|
|
end
|
|
|
|
local function CheckSwitchWillFail(frame, outfit)
|
|
local contents, empties = OutfitDisplayFrame_GetBagInfo();
|
|
local numfree = table.getn(empties);
|
|
local needfree = 0;
|
|
local missing = false;
|
|
local banked = false;
|
|
for i=1,19,1 do
|
|
local slotName = PlayerSlotNames[i].name;
|
|
local check;
|
|
if ( outfit ) then
|
|
check = outfit[slotName];
|
|
else
|
|
check = getglobal(frame:GetName()..slotName);
|
|
end
|
|
if ( check and check.used ) then
|
|
if ( not check.empty ) then
|
|
local bag, slot, inbank = FindThisItem( check.item );
|
|
if ( not bag and not slot ) then
|
|
-- pretend it's still in the bank and we just can't get it
|
|
if ( check.banked ) then
|
|
check.banked = true;
|
|
banked = true;
|
|
else
|
|
missing = true;
|
|
end
|
|
check.missing = not check.banked;
|
|
else
|
|
check.missing = nil;
|
|
check.banked = inbank;
|
|
end
|
|
else
|
|
local slot = PlayerSlotNames[i].id;
|
|
if ( OutfitDisplayFrame_GetItemInfo(nil, slot) ) then
|
|
needfree = needfree + 1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if ( missing ) then
|
|
return OUTFITDISPLAYFRAME_ITEMSNOTFOUND;
|
|
end
|
|
if ( banked and not BankIsOpen ) then
|
|
return OUTFITDISPLAYFRAME_ITEMSINBANK;
|
|
end
|
|
if ( needfree > numfree ) then
|
|
return OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE;
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
function OutfitDisplayFrame_SwitchWillFail(frame, outfit)
|
|
if ( not outfit ) then
|
|
return OUTFITDISPLAYFRAME_INVALIDOUTFIT;
|
|
end
|
|
if ( not next(outfit) ) then
|
|
return OUTFITDISPLAYFRAME_EMPTYOUTFIT;
|
|
end
|
|
-- if we're swapping, fail early
|
|
if ( OutfitDisplayFrame_IsSwapping() ) then
|
|
return OUTFITDISPLAYFRAME_TOOFASTMSG;
|
|
end
|
|
return CheckSwitchWillFail(frame, outfit);
|
|
end
|
|
|
|
function OutfitDisplayFrame_IsWearing(outfit)
|
|
if ( not outfit ) then
|
|
return false;
|
|
end
|
|
for slotName in pairs(outfit) do
|
|
if ( outfit[slotName].used and not outfit[slotName].empty ) then
|
|
local slot = GetInventorySlotInfo(slotName);
|
|
local link = GetInventoryItemLink("player", slot);
|
|
local foundit = false;
|
|
if ( link ) then
|
|
local color, item, name = SplitLink(link);
|
|
if ( item == outfit[slotName].item ) then
|
|
foundit = true;
|
|
end
|
|
end
|
|
if ( not foundit ) then
|
|
return false;
|
|
end
|
|
end
|
|
end
|
|
return true;
|
|
end
|
|
|
|
function OutfitDisplayFrame_UpdateMessage(frame, outfit)
|
|
if ( frame ) then
|
|
local msg;
|
|
if ( outfit ) then
|
|
msg = CheckSwitchWillFail(frame, outfit);
|
|
end
|
|
local messages = getglobal(frame:GetName().."Message");
|
|
if ( msg ) then
|
|
messages:SetText(msg);
|
|
messages:SetTextColor(1, 1, 1);
|
|
messages:Show();
|
|
else
|
|
messages:SetText("");
|
|
messages:Hide();
|
|
end
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_GetSlotContents(slotName, returnEmpty)
|
|
if ( slotName ~= "Options" ) then
|
|
local slot = GetInventorySlotInfo(slotName);
|
|
local link = GetInventoryItemLink("player", slot);
|
|
if ( link ) then
|
|
local contents = {};
|
|
local color, item, name = SplitLink(link);
|
|
contents.item = item;
|
|
contents.name = name;
|
|
contents.color = color;
|
|
contents.texture = texture;
|
|
contents.used = true;
|
|
local bag, slot = FindThisItem( item );
|
|
contents.bag = bag;
|
|
contents.slot = slot;
|
|
return contents;
|
|
end
|
|
end
|
|
-- return nil;
|
|
end
|
|
|
|
function OutfitDisplayFrame_GetWearing(check)
|
|
local wearing = {};
|
|
if ( check ) then
|
|
for slotName in pairs(check) do
|
|
wearing[slotName] = OutfitDisplayFrame_GetSlotContents(slotName);
|
|
end
|
|
-- make sure we pick up the off hand if we're going to put something
|
|
-- two-handed in the main hand slot
|
|
local mainhand = check["MainHandSlot"];
|
|
local offhand = wearing["SecondaryHandSlot"];
|
|
if ( not offhand and mainhand and not IsItemOneHanded(mainhand.item) ) then
|
|
wearing["SecondaryHandSlot"] = OutfitDisplayFrame_GetSlotContents("SecondaryHandSlot");
|
|
end
|
|
else
|
|
for i=1,19,1 do
|
|
local slotName = PlayerSlotNames[i].name;
|
|
wearing[slotName] = OutfitDisplayFrame_GetSlotContents(slotName);
|
|
end
|
|
end
|
|
wearing["Options"] = {}
|
|
if ( ShowingCloak() ) then
|
|
wearing["Options"].cloak = 1;
|
|
else
|
|
wearing["Options"].cloak = 0;
|
|
end
|
|
if ( ShowingHelm() ) then
|
|
wearing["Options"].helm = 1;
|
|
else
|
|
wearing["Options"].helm = 0;
|
|
end
|
|
return wearing;
|
|
end
|
|
|
|
function OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount, bag_affinity, slot_affinity)
|
|
skipcount = skipcount or 0;
|
|
|
|
-- try to put the item in the requested affinity, if possible
|
|
if bag_affinity and slot_affinity and
|
|
not GetContainerItemInfo(bag_affinity, slot_affinity) then
|
|
return bag_affinity, slot_affinity;
|
|
end
|
|
|
|
-- if we couldn't get the bag and slot we wanted, just try the same bag
|
|
if bag_affinity then
|
|
for j=GetContainerNumSlots(bag_affinity),1,-1 do
|
|
if not GetContainerItemInfo(bag_affinity,j) then
|
|
if skipcount == 0 then return bag_affinity,j; end
|
|
skipcount = skipcount - 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
-- no affinity, check all bags
|
|
for i=NUM_BAG_FRAMES,0,-1 do
|
|
-- but skip any bag we already have affinity for (because it might have
|
|
-- already modified skipcount)
|
|
if bag_affinity ~= i then
|
|
-- Make sure this isn't a quiver, those won't hold shit
|
|
local bagName = GetBagName(i);
|
|
if ( bagName ) then
|
|
local texture = GetInventoryItemTexture("player",
|
|
ContainerIDToInventoryID(i));
|
|
|
|
if ( string.find(texture, "INV_Misc_Bag_%d") and not string.find(bagName, AMMOSLOT) ) then
|
|
for j=GetContainerNumSlots(i),1,-1 do
|
|
if not GetContainerItemInfo(i,j) then
|
|
if skipcount == 0 then return i,j; end
|
|
skipcount = skipcount - 1;
|
|
end -- if empty
|
|
end -- for slots
|
|
end -- if normal bag
|
|
end -- if there is a bag
|
|
end -- if not affinity bag
|
|
end -- for bags
|
|
|
|
-- not found return nil,nil implicitly
|
|
end
|
|
|
|
-- okay, let's switch to the specified outfit
|
|
-- code liberally borrowed from "WeaponQuickSwap - by CapnBry"
|
|
|
|
-- list functions
|
|
local function swapentry_print(entry)
|
|
if ( DEFAULT_CHAT_FRAME ) then
|
|
local msg = "Entry "..tonil(entry.sb)..","..tonil(entry.si)..","..tonil(entry.db)..","..tonil(entry.di);
|
|
DEFAULT_CHAT_FRAME:AddMessage(msg, 1.0,0,0);
|
|
end
|
|
end
|
|
|
|
local function swaplist_print(list)
|
|
while ( list ) do
|
|
swapentry_print(list);
|
|
list = list.next;
|
|
end
|
|
end
|
|
|
|
local function swaplist_push(list, sb, si, db, di, helm, cloak)
|
|
list = { next = list, sb = sb, si = si, db = db, di = di,
|
|
helm = helm, cloak = cloak };
|
|
return list;
|
|
end
|
|
|
|
local function swaplist_popfirst(list)
|
|
if not list then return; end
|
|
list = list.next;
|
|
return list;
|
|
end
|
|
|
|
-- Unit variable to hold the stack of swaps
|
|
local outfitswap = nil;
|
|
|
|
function OutfitDisplayFrame_IsSwapping()
|
|
if ( outfitswap or OutfitDisplayFrame_AnyItemLocked() ) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end
|
|
end
|
|
|
|
-- First we do everything except the main hand and secondary hand
|
|
-- Then we do the hard stuff
|
|
|
|
function OutfitDisplayFrame_ItemIsLocked(bag, slot)
|
|
if not bag and not slot then
|
|
return false;
|
|
end
|
|
|
|
if not bag then
|
|
return IsInventoryItemLocked(slot);
|
|
else
|
|
local _,_,locked = GetContainerItemInfo(bag,slot);
|
|
return locked;
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_AnyItemLocked()
|
|
-- Checks all the bags and the equipped slots to see if any are still locked
|
|
for i=0,NUM_BAG_FRAMES do
|
|
for j=1,GetContainerNumSlots(i) do
|
|
local _,_,locked = GetContainerItemInfo(i,j);
|
|
if ( locked ) then
|
|
return true;
|
|
end
|
|
end
|
|
end
|
|
for i=1,19,1 do
|
|
if ( IsInventoryItemLocked(PlayerSlotNames[i].id) ) then
|
|
return true;
|
|
end
|
|
end
|
|
return false;
|
|
end
|
|
|
|
local function ShowCheck(dohelm, flag)
|
|
if ( flag ) then
|
|
if ( dohelm ) then
|
|
ShowHelm(flag);
|
|
else
|
|
ShowCloak(flag);
|
|
end
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_ExecuteSwapIteration()
|
|
if not outfitswap then
|
|
PerformSlowerSwap = false;
|
|
return;
|
|
end
|
|
|
|
if OutfitDisplayFrame_ItemIsLocked(outfitswap.sb, outfitswap.si) or
|
|
OutfitDisplayFrame_ItemIsLocked(outfitswap.db, outfitswap.di) then
|
|
return;
|
|
end
|
|
|
|
local beslow = PerformSlowerSwap;
|
|
|
|
if ( outfitswap.helm ~= nil or outfitswap.cloak ~= nil ) then
|
|
|
|
ShowCheck ( true, outfitswap.helm);
|
|
ShowCheck ( false, outfitswap.cloak);
|
|
|
|
beslow = false;
|
|
|
|
else
|
|
|
|
if not outfitswap.sb then
|
|
SavedPickupInventoryItem(outfitswap.si);
|
|
else
|
|
SavedPickupContainerItem(outfitswap.sb, outfitswap.si);
|
|
end
|
|
|
|
if not outfitswap.db then
|
|
if not outfitswap.di then
|
|
PutItemInBackpack();
|
|
else
|
|
SavedPickupInventoryItem(outfitswap.di);
|
|
end
|
|
else
|
|
SavedPickupContainerItem(outfitswap.db, outfitswap.di);
|
|
end
|
|
|
|
end
|
|
|
|
outfitswap = swaplist_popfirst(outfitswap);
|
|
if ( outfitswap and not beslow ) then
|
|
return OutfitDisplayFrame_ExecuteSwapIteration();
|
|
end
|
|
end
|
|
|
|
function OutfitDisplayFrame_SwitchOne(outfit, index, skipcount)
|
|
local slotName = PlayerSlotNames[index].name;
|
|
if ( outfit and outfit[slotName] ) then
|
|
local invslot = GetInventorySlotInfo(slotName);
|
|
if ( outfit[slotName].empty ) then
|
|
local bag, slot = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
|
|
outfitswap = swaplist_push(outfitswap, nil, invslot, bag, slot);
|
|
skipcount = skipcount + 1;
|
|
else
|
|
local bag, slot = FindThisItem( outfit[slotName].item );
|
|
-- either we couldn't find it, or it's where it should be
|
|
if ( bag ~= nil or slot ~= invslot ) then
|
|
outfitswap = swaplist_push(outfitswap, bag, slot, nil, invslot);
|
|
end
|
|
end
|
|
end
|
|
return skipcount;
|
|
end
|
|
|
|
local function OnSwapError(error)
|
|
outfitswap = nil;
|
|
if ( UIErrorsFrame ) then
|
|
UIErrorsFrame:AddMessage(error, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME);
|
|
end
|
|
return;
|
|
end
|
|
|
|
function OutfitDisplayFrame_SwitchOutfit(outfit)
|
|
if ( CursorHasItem() or OutfitDisplayFrame_IsSwapping() ) then
|
|
return OnSwapError(OUTFITDISPLAYFRAME_TOOFASTMSG);
|
|
end
|
|
if ( not outfit ) then
|
|
return OnSwapError(OUTFITDISPLAYFRAME_INVALIDOUTFIT);
|
|
end
|
|
|
|
-- might not need to swap slowly
|
|
PerformSlowerSwap = false;
|
|
|
|
-- need to check to see that we have enough room
|
|
local old = OutfitDisplayFrame_GetWearing(outfit);
|
|
|
|
if ( outfit["Options"] ) then
|
|
-- do cloak and helm setting last
|
|
outfitswap = swaplist_push(outfitswap, nil, nil, nil, nil,
|
|
outfit["Options"].helm,
|
|
outfit["Options"].cloak);
|
|
end
|
|
|
|
-- do everything except weapon slots
|
|
local skipcount = 0;
|
|
for i=1,16,1 do
|
|
skipcount = OutfitDisplayFrame_SwitchOne(outfit, i, skipcount);
|
|
end
|
|
OutfitDisplayFrame_SwitchOne(outfit, 19, skipcount);
|
|
|
|
if ( not outfit["MainHandSlot"] and not outfit["SecondaryHandSlot"] ) then
|
|
OutfitDisplayFrame_ExecuteSwapIteration();
|
|
return old;
|
|
end
|
|
|
|
local mainhandslot = GetInventorySlotInfo("MainHandSlot");
|
|
local secondaryslot = GetInventorySlotInfo("SecondaryHandSlot");
|
|
local mainhand = outfit["MainHandSlot"];
|
|
local offhand = outfit["SecondaryHandSlot"];
|
|
-- now do hands
|
|
local m_sb;
|
|
local m_si;
|
|
local o_sb;
|
|
local o_si;
|
|
local m_ok = not mainhand or not mainhand.item;
|
|
local o_ok = not offhand or not offhand.item;
|
|
|
|
if ( mainhand and mainhand.item ) then
|
|
m_sb, m_si = FindThisItem(mainhand.item);
|
|
m_ok = ( not m_sb and m_si == mainhandslot );
|
|
end
|
|
if ( offhand and offhand.item ) then
|
|
local multiples = 0;
|
|
if ( mainhand and mainhand.item == offhand.item ) then
|
|
multiples = 1;
|
|
end
|
|
o_sb, o_si = FindThisItem( offhand.item, multiples);
|
|
o_ok = ( not o_sb and o_si == secondaryslot );
|
|
end
|
|
|
|
if ( not m_ok ) then
|
|
-- do we need two of these?
|
|
if ( o_ok and not m_sb and m_si == secondaryslot ) then
|
|
m_sb, m_si = FindThisItem( mainhand.item, 1);
|
|
end
|
|
end
|
|
|
|
-- moving from bags
|
|
if ( m_sb and o_sb ) then
|
|
-- insert them backwards, since they get popped off
|
|
-- main hand has to get done first in case it's currently
|
|
-- a two hander
|
|
outfitswap = swaplist_push(outfitswap, o_sb, o_si, nil, secondaryslot);
|
|
outfitswap = swaplist_push(outfitswap, m_sb, m_si, nil, mainhandslot);
|
|
elseif ( not m_sb and m_si == secondaryslot and not o_sb and o_si == mainhandslot ) then
|
|
outfitswap = swaplist_push(outfitswap, nil, mainhandslot, nil, secondaryslot);
|
|
else
|
|
-- Install main hand
|
|
if not m_ok then
|
|
-- if nothing going to the main hand
|
|
if ( not m_sb and not m_si ) then
|
|
-- and the main is not going to the off: put it in a bag
|
|
if not ( not o_sb and o_si == mainhandslot) then
|
|
local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
|
|
if not (bb and bi) then
|
|
return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
|
|
end
|
|
skipcount = skipcount + 1;
|
|
outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi);
|
|
-- when moving A,"" -> "",B where A is a 2h, the offhand
|
|
-- doesn't lock properly, so work around it by swapping
|
|
-- slowly (only one swap per lock notify)
|
|
PerformSlowerSwap = not IsItemOneHanded(mainhand.item);
|
|
end
|
|
else
|
|
outfitswap = swaplist_push(outfitswap, m_sb, m_si, nil, mainhandslot);
|
|
end
|
|
end
|
|
|
|
-- Load offhand if not already there
|
|
if not o_ok then
|
|
if ( not o_sb and not o_si ) then
|
|
if not (not m_sb and m_si == secondaryslot) then
|
|
local bb, bi;
|
|
if LastOffSource then
|
|
bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount,
|
|
LastOffSource.bag, LastOffSource.slot);
|
|
else
|
|
bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
|
|
end
|
|
|
|
if not (bb and bi) then
|
|
return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
|
|
end
|
|
skipcount = skipcount + 1;
|
|
outfitswap = swaplist_push(outfitswap, nil, secondaryslot, bb, bi);
|
|
end
|
|
else
|
|
-- if the main hand weapon is coming from the offhand slot
|
|
-- we need to fix up its source to be where the offhand is
|
|
-- GOING to be after the bag->off swap
|
|
if outfitswap and ( not m_sb and m_si == secondaryslot) then
|
|
outfitswap.sb = o_sb;
|
|
outfitswap.si = o_si;
|
|
-- don't set o_sb, o_si they're tested later
|
|
end
|
|
|
|
outfitswap = swaplist_push(outfitswap, o_sb, o_si, nil, secondaryslot);
|
|
end
|
|
end
|
|
|
|
-- Special Case: Moving off to main, and not main to off
|
|
-- This is because maybe the main hand weapon is main only
|
|
if (not m_sb and m_si == secondaryslot) and not ( not o_sb and o_si == mainhandslot) then
|
|
local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
|
|
if not (bb and bi) then
|
|
return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
|
|
end
|
|
skipcount = skipcount + 1;
|
|
outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi);
|
|
end
|
|
|
|
-- Same thing for off hand
|
|
if (not o_sb and o_si == mainhandslot) and not (not m_sb and m_si == secondaryslot) then
|
|
local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount);
|
|
if not (bb and bi) then
|
|
return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE);
|
|
end
|
|
skipcount = skipcount + 1;
|
|
outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi);
|
|
end
|
|
|
|
if o_sb then
|
|
LastOffSource = { bag = o_sb, slot = o_si };
|
|
end
|
|
end
|
|
|
|
-- Start moving
|
|
OutfitDisplayFrame_ExecuteSwapIteration();
|
|
return old;
|
|
end
|