vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | OUTFITDISPLAYFRAME_VERSION = "0.5.6"; |
2 | OUTFITDISPLAYFRAME_NAME = "Outfit Display Frame"; |
||
3 | OUTFITDISPLAYFRAME_TITLE = OUTFITDISPLAYFRAME_NAME.." v"..OUTFITDISPLAYFRAME_VERSION; |
||
4 | OUTFITDISPLAYFRAME_BANKDELAY = 0.5; |
||
5 | |||
6 | local PlayerSlotNames = { |
||
7 | [1] = { name = "HeadSlot", tooltip = HEADSLOT }; |
||
8 | [2] = { name = "NeckSlot", tooltip = NECKSLOT }, |
||
9 | [3] = { name = "ShoulderSlot", tooltip = SHOULDERSLOT }, |
||
10 | [4] = { name = "BackSlot", tooltip = BACKSLOT }, |
||
11 | [5] = { name = "ChestSlot", tooltip = CHESTSLOT }, |
||
12 | [6] = { name = "ShirtSlot", tooltip = SHIRTSLOT }, |
||
13 | [7] = { name = "TabardSlot", tooltip = TABARDSLOT }, |
||
14 | [8] = { name = "WristSlot", tooltip = WRISTSLOT }, |
||
15 | [9] = { name = "HandsSlot", tooltip = HANDSSLOT }, |
||
16 | [10] = { name = "WaistSlot", tooltip = WAISTSLOT }, |
||
17 | [11] = { name = "LegsSlot", tooltip = LEGSSLOT }, |
||
18 | [12] = { name = "FeetSlot", tooltip = FEETSLOT }, |
||
19 | [13] = { name = "Finger0Slot", tooltip = FINGER0SLOT }, |
||
20 | [14] = { name = "Finger1Slot", tooltip = FINGER1SLOT }, |
||
21 | [15] = { name = "Trinket0Slot", tooltip = TRINKET0SLOT }, |
||
22 | [16] = { name = "Trinket1Slot", tooltip = TRINKET1SLOT }, |
||
23 | [17] = { name = "MainHandSlot", tooltip = MAINHANDSLOT }, |
||
24 | [18] = { name = "SecondaryHandSlot", tooltip = SECONDARYHANDSLOT }, |
||
25 | [19] = { name = "RangedSlot", tooltip = RANGEDSLOT }, |
||
26 | } |
||
27 | |||
28 | local SavedPickupContainerItem = nil; |
||
29 | local SavedPickupInventoryItem = nil; |
||
30 | |||
31 | local LastOffSource = nil; |
||
32 | local PerformSlowerSwap = false; |
||
33 | local BankIsOpen = false; |
||
34 | |||
35 | local function tonil(val) |
||
36 | if ( not val ) then |
||
37 | return "nil"; |
||
38 | else |
||
39 | return val; |
||
40 | end |
||
41 | end |
||
42 | |||
43 | local function Print(msg, r, g, b) |
||
44 | if ( DEFAULT_CHAT_FRAME ) then |
||
45 | if ( not r ) then |
||
46 | DEFAULT_CHAT_FRAME:AddMessage(msg); |
||
47 | else |
||
48 | DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b); |
||
49 | end |
||
50 | end |
||
51 | end |
||
52 | |||
53 | -- Based on code in QuickMountEquip |
||
54 | local function SafeHookFunction(func, newfunc) |
||
55 | local oldValue = getglobal(func); |
||
56 | if ( oldValue ~= getglobal(newfunc) ) then |
||
57 | setglobal(func, getglobal(newfunc)); |
||
58 | return true; |
||
59 | end |
||
60 | return false; |
||
61 | end |
||
62 | |||
63 | -- this really ought to be in a library somewhere |
||
64 | local function SplitLink(link) |
||
65 | local _,_, color, item, name = string.find(link, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r"); |
||
66 | return color, item, name; |
||
67 | end |
||
68 | |||
69 | function OutfitDisplayFrame_OnLoad() |
||
70 | local temp = PickupContainerItem; |
||
71 | if ( SafeHookFunction("PickupContainerItem", "OutfitDisplayFrame_PickupContainerItem") ) then |
||
72 | SavedPickupContainerItem = temp; |
||
73 | end |
||
74 | |||
75 | temp = PickupInventoryItem; |
||
76 | if ( SafeHookFunction("PickupInventoryItem", "OutfitDisplayFrame_PickupInventoryItem") ) then |
||
77 | SavedPickupInventoryItem = temp; |
||
78 | end |
||
79 | |||
80 | local parent = this:GetName(); |
||
81 | for i=1,19,1 do |
||
82 | local slotName = PlayerSlotNames[i].name; |
||
83 | local button = getglobal(parent..slotName); |
||
84 | button.tooltip = PlayerSlotNames[i].tooltip; |
||
85 | OutfitDisplayItemButton_Draw(button); |
||
86 | PlayerSlotNames[i].id = GetInventorySlotInfo(slotName); |
||
87 | end |
||
88 | |||
89 | -- ideas borrowed from "WeaponQuickSwap - by CapnBry" |
||
90 | this:RegisterEvent("ITEM_LOCK_CHANGED"); |
||
91 | this:RegisterEvent("BANKFRAME_OPENED"); |
||
92 | this:RegisterEvent("BANKFRAME_CLOSED"); |
||
93 | |||
94 | Print(OUTFITDISPLAYFRAME_TITLE.." loaded."); |
||
95 | end |
||
96 | |||
97 | local function DressUpItem(model, thing) |
||
98 | if ( not model or not thing or thing == "" ) then |
||
99 | return; |
||
100 | end |
||
101 | local item = gsub(thing, "(%d+).*", "%1", 1); |
||
102 | model:TryOn(item); |
||
103 | end |
||
104 | |||
105 | local BankFrameClosedTime = 0; |
||
106 | |||
107 | function OutfitDisplayFrame_OnEvent(...) |
||
108 | if ( arg[1] == "BANKFRAME_OPENED" or arg[1] == "BANKFRAME_CLOSED" ) then |
||
109 | BankFrameIsOpen = ( arg[1] == "BANKFRAME_OPENED" ); |
||
110 | local frame = getglobal(this:GetName().."MessageUpdateFrame"); |
||
111 | if ( frame ) then |
||
112 | BankFrameClosedTime = OUTFITDISPLAYFRAME_BANKDELAY; |
||
113 | frame:Show(); |
||
114 | end |
||
115 | elseif (arg[1] == "ITEM_LOCK_CHANGED") and not arg[2] then |
||
116 | return OutfitDisplayFrame_ExecuteSwapIteration(); |
||
117 | end |
||
118 | end |
||
119 | |||
120 | function OutfitDisplayFrame_MessageUpdate(elapsed) |
||
121 | BankFrameClosedTime = BankFrameClosedTime - elapsed; |
||
122 | if ( BankFrameClosedTime <= 0 ) then |
||
123 | this:Hide(); |
||
124 | OutfitDisplayFrame_UpdateMessage(this:GetParent()); |
||
125 | BankFrameClosedTime = 0; |
||
126 | end |
||
127 | end |
||
128 | |||
129 | local function GetSlotButton(button, slotName) |
||
130 | local parent = button:GetParent():GetName(); |
||
131 | return getglobal(parent..slotName); |
||
132 | end |
||
133 | |||
134 | local function IsItemOneHanded(item) |
||
135 | if ( item ) then |
||
136 | local _,_,_,_,_,_,_,bodyslot = GetItemInfo("item:"..item); |
||
137 | if ( bodyslot == "INVTYPE_2HWEAPON" or bodyslot == INVTYPE_2HWEAPON ) then |
||
138 | return false; |
||
139 | end |
||
140 | end |
||
141 | return true; |
||
142 | end |
||
143 | |||
144 | function OutfitDisplayFrame_CursorCanGoInSlot(button) |
||
145 | if ( button.forced ) then |
||
146 | return false; |
||
147 | end |
||
148 | local secondary = GetSlotButton(button, "SecondaryHandSlot"); |
||
149 | local mainbutton = GetSlotButton(button, "MainHandSlot"); |
||
150 | if ( button == secondary and mainbutton and mainbutton.item ) then |
||
151 | return IsItemOneHanded(mainbutton.item); |
||
152 | end |
||
153 | return CursorCanGoInSlot(button:GetID()) |
||
154 | end |
||
155 | |||
156 | -- much hackery to know what actually is in the cursor when somebody drops it on us |
||
157 | local OD_Track_Bag = nil; |
||
158 | local OD_Track_Slot = nil; |
||
159 | |||
160 | -- whatever we think the user picked up, apply it to our stuff |
||
161 | local function AcceptCursorItem(button) |
||
162 | local parent = button:GetParent(); |
||
163 | local pname = parent:GetName(); |
||
164 | if ( not OutfitDisplayFrame_CursorCanGoInSlot(button) ) then |
||
165 | button = nil; |
||
166 | for i=1,19,1 do |
||
167 | local temp = getglobal(pname..PlayerSlotNames[i].name); |
||
168 | if ( temp and OutfitDisplayFrame_CursorCanGoInSlot(temp) ) then |
||
169 | button = temp; |
||
170 | end |
||
171 | end |
||
172 | end |
||
173 | |||
174 | if ( button ) then |
||
175 | local link, texture; |
||
176 | if ( OD_Track_Bag ) then |
||
177 | link = GetContainerItemLink(OD_Track_Bag, OD_Track_Slot); |
||
178 | texture = GetContainerItemInfo(OD_Track_Bag, OD_Track_Slot); |
||
179 | else |
||
180 | link = GetInventoryItemLink("player", OD_Track_Slot); |
||
181 | texture = GetInventoryItemTexture("player", OD_Track_Slot); |
||
182 | end |
||
183 | button.color, button.item, button.name = SplitLink(link); |
||
184 | button.texture = texture; |
||
185 | button.used = true; |
||
186 | button.empty = nil; |
||
187 | button.missing = false; |
||
188 | if ( OD_Track_Bag and (OD_Track_Bag == BANK_CONTAINER or |
||
189 | OD_Track_Bag > NUM_BAG_SLOTS) ) then |
||
190 | button.banked = true; |
||
191 | end |
||
192 | OutfitDisplayItemButton_Change(button); |
||
193 | end |
||
194 | |||
195 | -- clear the cursor item |
||
196 | if ( OD_Track_Bag ) then |
||
197 | SavedPickupContainerItem(OD_Track_Bag, OD_Track_Slot); |
||
198 | elseif ( OD_Track_Slot ) then |
||
199 | SavedPickupInventoryItem(OD_Track_Slot); |
||
200 | end |
||
201 | OD_Track_Bag = nil; |
||
202 | OD_Track_Slot = nil; |
||
203 | end |
||
204 | |||
205 | -- figure out what the user picked up, so that if they drop it on us we can deal with it |
||
206 | function OutfitDisplayFrame_TrackItemPickup(bag, slot) |
||
207 | OD_Track_Bag = bag; |
||
208 | OD_Track_Slot = slot; |
||
209 | end |
||
210 | |||
211 | function OutfitDisplayFrame_PickupContainerItem(bag, slot) |
||
212 | if ( SavedPickupContainerItem ) then |
||
213 | SavedPickupContainerItem(bag, slot); |
||
214 | end |
||
215 | OutfitDisplayFrame_TrackItemPickup(bag, slot); |
||
216 | end |
||
217 | |||
218 | function OutfitDisplayFrame_PickupInventoryItem(slot) |
||
219 | if ( SavedPickupInventoryItem ) then |
||
220 | SavedPickupInventoryItem(slot); |
||
221 | end |
||
222 | OutfitDisplayFrame_TrackItemPickup(nil, slot); |
||
223 | end |
||
224 | |||
225 | -- handle making the items in the outfit pane do nice things |
||
226 | function OutfitDisplayItemButton_OnEnter() |
||
227 | if ( GameTooltip.finished ) then |
||
228 | return; |
||
229 | end |
||
230 | GameTooltip.finished = 1; |
||
231 | GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); |
||
232 | if (this.item) then |
||
233 | local link = "item:"..this.item; |
||
234 | if ( GetItemInfo(link) ) then |
||
235 | GameTooltip:SetHyperlink(link); |
||
236 | elseif ( this.name ) then |
||
237 | GameTooltip:SetText(this.name); |
||
238 | elseif ( this.tooltip ) then |
||
239 | GameTooltip:SetText(this.tooltip); |
||
240 | else |
||
241 | GameTooltip:SetText("<unlinkable item>", 1, 0, 0); |
||
242 | end |
||
243 | elseif ( this.tooltip ) then |
||
244 | GameTooltip:AddLine(this.tooltip); |
||
245 | else |
||
246 | local parentlen = string.len(this:GetParent():GetName())+1; |
||
247 | local slotName = strsub(this:GetName(), parentlen); |
||
248 | slotName = strsub(slotName, 1, string.len(slotName) - 4); |
||
249 | this.tooltip = slotName; |
||
250 | GameTooltip:AddLine(this.tooltip); |
||
251 | end |
||
252 | GameTooltip:AddLine(OUTFITDISPLAYFRAME_ALTCLICK,.8,.8,.8,1); |
||
253 | GameTooltip:Show(); |
||
254 | end |
||
255 | |||
256 | function OutfitDisplayItemButton_OnEvent(event) |
||
257 | if ( event == "CURSOR_UPDATE" ) then |
||
258 | if ( not this.forced ) then |
||
259 | if ((this.CursorCanGoInSlot and this.CursorCanGoInSlot(this)) or |
||
260 | OutfitDisplayFrame_CursorCanGoInSlot(this)) then |
||
261 | this:LockHighlight(); |
||
262 | else |
||
263 | this:UnlockHighlight(); |
||
264 | end |
||
265 | end |
||
266 | end |
||
267 | end |
||
268 | |||
269 | function OutfitDisplayItemButton_OnClick(clicked, ignoreModifiers) |
||
270 | if ( clicked == "LeftButton" ) then |
||
271 | if( not ignoreModifiers or ignoreModifiers == 0 ) then |
||
272 | if ( IsShiftKeyDown() ) then |
||
273 | if ( this.item and ChatFrameEditBox:IsVisible() ) then |
||
274 | local color = this.color; |
||
275 | if ( not color ) then |
||
276 | color = "ffffffff"; |
||
277 | end |
||
278 | local link = "|c"..color.."|Hitem"..this.item.."|h["..this.name.."]|h|r"; |
||
279 | ChatFrameEditBox:Insert(link); |
||
280 | return; |
||
281 | end |
||
282 | elseif ( IsAltKeyDown() ) then |
||
283 | OutfitDisplayItemButton_Clear(this, false, false); |
||
284 | OutfitDisplayItemButton_Change(this); |
||
285 | return; |
||
286 | end |
||
287 | end |
||
288 | -- fall through for drags and non-modified clicks |
||
289 | if ( CursorHasItem() ) then |
||
290 | AcceptCursorItem(this); |
||
291 | end |
||
292 | end |
||
293 | end |
||
294 | |||
295 | function OutfitDisplayItemButton_OnLoad() |
||
296 | local parentlen = string.len(this:GetParent():GetName())+1; |
||
297 | local slotName = strsub(this:GetName(), parentlen); |
||
298 | local id; |
||
299 | local textureName; |
||
300 | id, textureName = GetInventorySlotInfo(slotName); |
||
301 | this:SetID(id); |
||
302 | this.backgroundTextureName = textureName; |
||
303 | SetItemButtonTexture(this, this.backgroundTextureName); |
||
304 | this:RegisterForDrag("LeftButton"); |
||
305 | this:RegisterForClicks("LeftButtonUp", "RightButtonUp"); |
||
306 | this:RegisterEvent("CURSOR_UPDATE"); |
||
307 | end |
||
308 | |||
309 | function OutfitDisplayItemButton_Draw(button) |
||
310 | if ( button.texture ) then |
||
311 | SetItemButtonTexture(button, button.texture); |
||
312 | else |
||
313 | SetItemButtonTexture(button, button.backgroundTextureName); |
||
314 | end |
||
315 | if ( button.missing ) then |
||
316 | SetItemButtonTextureVertexColor(button, 1.0, 0.1, 0.1); |
||
317 | elseif ( button.banked ) then |
||
318 | SetItemButtonTextureVertexColor(button, 0.1, 0.1, 1.0); |
||
319 | else |
||
320 | SetItemButtonTextureVertexColor(button, 1.0, 1.0, 1.0); |
||
321 | end |
||
322 | local checkbox = getglobal(button:GetName().."CheckBox"); |
||
323 | if (checkbox) then |
||
324 | local pname = button:GetParent():GetName(); |
||
325 | local showhelm = getglobal(pname.."ShowHelm"); |
||
326 | local showcloak = getglobal(pname.."ShowCloak"); |
||
327 | if ( button.forced ) then |
||
328 | checkbox:SetChecked(true); |
||
329 | checkbox:Disable(); |
||
330 | checkbox:Show(); |
||
331 | elseif ( button.empty or not button.used ) then |
||
332 | if ( checkbox.slotName == "HeadSlot" ) then |
||
333 | showhelm:Hide(); |
||
334 | showhelm:SetChecked(false); |
||
335 | elseif ( checkbox.slotName == "BackSlot" ) then |
||
336 | showcloak:Hide(); |
||
337 | showcloak:SetChecked(false); |
||
338 | end |
||
339 | checkbox:Enable(); |
||
340 | checkbox:SetChecked(button.empty); |
||
341 | checkbox:Show(); |
||
342 | elseif ( button.used ) then |
||
343 | checkbox:Hide(); |
||
344 | if ( checkbox.slotName == "HeadSlot" ) then |
||
345 | showhelm:Show(); |
||
346 | elseif ( checkbox.slotName == "BackSlot" ) then |
||
347 | showcloak:Show(); |
||
348 | end |
||
349 | end |
||
350 | end |
||
351 | end |
||
352 | |||
353 | function OutfitDisplayItemButton_Change(button) |
||
354 | OutfitDisplayItemButton_Draw(button); |
||
355 | -- handle two handed weapons |
||
356 | local parent = button:GetParent(); |
||
357 | local pname = parent:GetName(); |
||
358 | local parentlen = string.len(pname)+1; |
||
359 | local slotName = strsub(button:GetName(), parentlen); |
||
360 | if ( slotName == "MainHandSlot" ) then |
||
361 | local secondary = getglobal(pname.."SecondaryHandSlot"); |
||
362 | if ( not button.used and secondary.forced ) then |
||
363 | OutfitDisplayItemButton_Clear(secondary, false, false); |
||
364 | elseif ( button.used and not IsItemOneHanded(button.item) ) then |
||
365 | OutfitDisplayItemButton_Clear(secondary, true); |
||
366 | secondary.forced = true; |
||
367 | end |
||
368 | OutfitDisplayItemButton_Draw(secondary); |
||
369 | end |
||
370 | OutfitDisplayFrame_UpdateMessage(parent); |
||
371 | OutfitDisplayFrame_UpdateModel(parent, button); |
||
372 | if( parent.OutfitChanged ) then |
||
373 | parent.OutfitChanged( button ); |
||
374 | end |
||
375 | end |
||
376 | |||
377 | function OutfitDisplayItemButton_Clear(button, empty, used) |
||
378 | button.name = nil; |
||
379 | button.item = nil; |
||
380 | button.texture = nil; |
||
381 | button.color = nil; |
||
382 | button.missing = nil; |
||
383 | button.banked = nil; |
||
384 | button.forced = nil; |
||
385 | button.empty = empty; |
||
386 | button.used = used or empty; |
||
387 | end |
||
388 | |||
389 | -- override ShowHelm and ShowCloak |
||
390 | function OutfitDisplayOverrideBox_OnLoad() |
||
391 | local parentlen = string.len(this:GetParent():GetName())+1; |
||
392 | this.slotName = strsub(this:GetName(), parentlen); |
||
393 | end |
||
394 | |||
395 | function OutfitDisplayOverrideBox_OnEnter() |
||
396 | GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); |
||
397 | local text; |
||
398 | if ( this.slotName == "ShowHelm" ) then |
||
399 | text = OUTFITDISPLAYFRAME_OVERRIDEHELM; |
||
400 | else |
||
401 | text = OUTFITDISPLAYFRAME_OVERRIDECLOAK; |
||
402 | end |
||
403 | GameTooltip:SetText(text, nil, nil, nil, nil, 1); |
||
404 | GameTooltip:Show(); |
||
405 | end |
||
406 | |||
407 | -- check box handling |
||
408 | function OutfitDisplayCheckBox_OnEnter() |
||
409 | GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); |
||
410 | GameTooltip:SetText(OUTFITDISPLAYFRAME_USECHECKBOX, nil, nil, nil, nil, 1); |
||
411 | GameTooltip:Show(); |
||
412 | end |
||
413 | |||
414 | function OutfitDisplayCheckBox_OnLoad() |
||
415 | local parentlen = string.len(this:GetParent():GetName())+1; |
||
416 | local name = strsub(this:GetName(), parentlen); |
||
417 | this.slotName = strsub(name, 1, -9); |
||
418 | end |
||
419 | |||
420 | function OutfitDisplayCheckBox_OnClick() |
||
421 | local pname = this:GetParent():GetName(); |
||
422 | local button = getglobal(pname..this.slotName); |
||
423 | OutfitDisplayItemButton_Clear(button, this:GetChecked()); |
||
424 | OutfitDisplayItemButton_Change(button); |
||
425 | end |
||
426 | |||
427 | local function UpdateModel_ThisSlot(pname, model, idx) |
||
428 | local slotName = PlayerSlotNames[idx].name; |
||
429 | local what = getglobal(pname..slotName); |
||
430 | local item = nil; |
||
431 | if ( what and what.used ) then |
||
432 | if ( not what.empty ) then |
||
433 | item = what.item; |
||
434 | end |
||
435 | else |
||
436 | local slot = PlayerSlotNames[idx].id; |
||
437 | local link = GetInventoryItemLink("player", slot); |
||
438 | if ( link ) then |
||
439 | _, item, _ = SplitLink(link); |
||
440 | end |
||
441 | end |
||
442 | if ( item ) then |
||
443 | DressUpItem(model, item); |
||
444 | end |
||
445 | end |
||
446 | |||
447 | function OutfitDisplayFrame_UpdateModel(frame, button) |
||
448 | local pname = frame:GetName(); |
||
449 | local model = getglobal(pname.."Model"); |
||
450 | local empty = false; |
||
451 | if ( not model ) then |
||
452 | return; |
||
453 | end |
||
454 | if ( button and button.used ) then |
||
455 | if ( button.empty and not button.forced ) then |
||
456 | empty = true; |
||
457 | end |
||
458 | else |
||
459 | for i=1,19,1 do |
||
460 | local what = getglobal(pname..PlayerSlotNames[i].name); |
||
461 | if ( what and what.empty ) then |
||
462 | empty = true; |
||
463 | end |
||
464 | end |
||
465 | end |
||
466 | if ( empty ) then |
||
467 | model:Undress(); |
||
468 | end |
||
469 | for i=19,1,-1 do |
||
470 | UpdateModel_ThisSlot(pname, model, i); |
||
471 | end |
||
472 | end |
||
473 | |||
474 | function OutfitDisplayFrame_SetOutfit(frame, outfit) |
||
475 | if not outfit then |
||
476 | return; |
||
477 | end |
||
478 | local pname = frame:GetName(); |
||
479 | for i=1,19,1 do |
||
480 | local slotName = PlayerSlotNames[i].name; |
||
481 | local button = getglobal(pname..slotName); |
||
482 | if ( button and outfit[slotName] and outfit[slotName].used ) then |
||
483 | OutfitDisplayItemButton_Clear(button); |
||
484 | if ( outfit[slotName].used ) then |
||
485 | button.name = outfit[slotName].name; |
||
486 | button.item = outfit[slotName].item; |
||
487 | button.texture = outfit[slotName].texture; |
||
488 | button.color = outfit[slotName].color; |
||
489 | button.missing = outfit[slotName].missing; |
||
490 | button.banked = outfit[slotName].banked; |
||
491 | button.forced = outfit[slotName].forced; |
||
492 | button.empty = outfit[slotName].empty; |
||
493 | button.used = true; |
||
494 | else |
||
495 | OutfitDisplayItemButton_Clear(button, true, true); |
||
496 | end |
||
497 | OutfitDisplayItemButton_Draw(button); |
||
498 | end |
||
499 | end |
||
500 | if ( outfit["Options"] ) then |
||
501 | local showhelm = getglobal(pname.."ShowHelm"); |
||
502 | local showcloak = getglobal(pname.."ShowCloak"); |
||
503 | showhelm:SetChecked(outfit["Options"].helm); |
||
504 | showcloak:SetChecked(outfit["Options"].cloak); |
||
505 | end |
||
506 | OutfitDisplayFrame_UpdateModel(frame); |
||
507 | OutfitDisplayFrame_UpdateMessage(frame, outfit); |
||
508 | end |
||
509 | |||
510 | function OutfitDisplayFrame_GetOutfit(frame, puthere) |
||
511 | local pname = frame:GetName(); |
||
512 | local outfit = puthere or nil; |
||
513 | local showhelm = getglobal(pname.."ShowHelm"); |
||
514 | local showcloak = getglobal(pname.."ShowCloak"); |
||
515 | local setOptions = false; |
||
516 | if not outfit then |
||
517 | outfit = {}; |
||
518 | end |
||
519 | outfit["Options"] = {}; |
||
520 | for i=1,19,1 do |
||
521 | local slotName = PlayerSlotNames[i].name; |
||
522 | local button = getglobal(pname..slotName); |
||
523 | |||
524 | if ( button and button.used ) then |
||
525 | outfit[slotName] = {}; |
||
526 | if ( not button.empty ) then |
||
527 | outfit[slotName].name = button.name; |
||
528 | outfit[slotName].item = button.item; |
||
529 | outfit[slotName].texture = button.texture; |
||
530 | outfit[slotName].color = button.color; |
||
531 | outfit[slotName].missing = button.missing; |
||
532 | outfit[slotName].banked = button.banked; |
||
533 | outfit[slotName].forced = button.forced; |
||
534 | end |
||
535 | outfit[slotName].empty = button.empty; |
||
536 | outfit[slotName].used = true; |
||
537 | if ( not button.empty ) then |
||
538 | if ( slotName == "HeadSlot" ) then |
||
539 | if ( showhelm and showhelm:GetChecked() ) then |
||
540 | outfit["Options"].helm = true; |
||
541 | setOptions = true; |
||
542 | end |
||
543 | elseif ( slotName == "BackSlot" ) then |
||
544 | if ( showcloak and showcloak:GetChecked() ) then |
||
545 | outfit["Options"].cloak = true; |
||
546 | setOptions = true; |
||
547 | end |
||
548 | end |
||
549 | end |
||
550 | elseif ( outfit and outfit.used ) then |
||
551 | outfit[slotName] = nil; |
||
552 | end |
||
553 | end |
||
554 | if ( not setOptions ) then |
||
555 | outfit["Options"] = nil; |
||
556 | end |
||
557 | if ( outfit ) then |
||
558 | -- check for two-handed weapon |
||
559 | local mainhand = outfit["MainHandSlot"]; |
||
560 | if ( mainhand and not IsItemOneHanded(mainhand.item) ) then |
||
561 | outfit["SecondaryHandSlot"] = {}; |
||
562 | outfit["SecondaryHandSlot"].forced = true; |
||
563 | outfit["SecondaryHandSlot"].empty = true; |
||
564 | outfit["SecondaryHandSlot"].used = true; |
||
565 | end |
||
566 | end |
||
567 | return outfit; |
||
568 | end |
||
569 | |||
570 | function OutfitDisplayFrame_GetItemInfo(bag, slot) |
||
571 | local link; |
||
572 | local c, i, n; |
||
573 | if ( bag ) then |
||
574 | link = GetContainerItemLink (bag,slot); |
||
575 | else |
||
576 | link = GetInventoryItemLink("player", slot); |
||
577 | end |
||
578 | if (link) then |
||
579 | c, i, n = SplitLink(link); |
||
580 | end |
||
581 | return c, i, n; |
||
582 | end |
||
583 | |||
584 | -- get a snapshot of the current state of the player |
||
585 | function OutfitDisplayFrame_GetBagInfo() |
||
586 | local contents = {}; |
||
587 | local empties = {}; |
||
588 | |||
589 | local numSlots = 0; |
||
590 | -- check each of the bags on the player |
||
591 | for bag=0, NUM_BAG_FRAMES do |
||
592 | -- get the number of slots in the bag (0 if no bag) |
||
593 | numSlots = GetContainerNumSlots(bag); |
||
594 | if (numSlots > 0) then |
||
595 | -- check each slot in the bag |
||
596 | for slot=1, numSlots do |
||
597 | local c, i, n = OutfitDisplayFrame_GetItemInfo(bag, slot); |
||
598 | if ( i ) then |
||
599 | contents[i] = {}; |
||
600 | contents[i].bag = bag; |
||
601 | contents[i].slot = slot; |
||
602 | contents[i].color = c; |
||
603 | contents[i].name = n; |
||
604 | else |
||
605 | local what = {}; |
||
606 | what.bag = bag; |
||
607 | what.slot = slot; |
||
608 | tinsert(empties, what); |
||
609 | end |
||
610 | end |
||
611 | end |
||
612 | end |
||
613 | |||
614 | for idx=1,19,1 do |
||
615 | local slot = PlayerSlotNames[idx].id; |
||
616 | local c, i, n = OutfitDisplayFrame_GetItemInfo(nil, slot); |
||
617 | if ( i ) then |
||
618 | contents[i] = {}; |
||
619 | contents[i].slot = slot; |
||
620 | contents[i].color = c; |
||
621 | contents[i].name = n; |
||
622 | end |
||
623 | end |
||
624 | |||
625 | return contents, empties; |
||
626 | end |
||
627 | |||
628 | -- look in a particular bag |
||
629 | local function CheckThisBag(bag, id, skipcount) |
||
630 | -- get the number of slots in the bag (0 if no bag) |
||
631 | local numSlots = GetContainerNumSlots(bag); |
||
632 | if (numSlots > 0) then |
||
633 | -- check each slot in the bag |
||
634 | for slot=1, numSlots do |
||
635 | local c, i, n = OutfitDisplayFrame_GetItemInfo(bag, slot); |
||
636 | if ( i and id == i ) then |
||
637 | if ( skipcount == 0 ) then |
||
638 | return slot, skipcount; |
||
639 | end |
||
640 | skipcount = skipcount - 1; |
||
641 | end |
||
642 | end |
||
643 | end |
||
644 | return nil, skipcount; |
||
645 | end |
||
646 | |||
647 | -- look for the outfit anywhere we can find it |
||
648 | local function FindThisItem(id, skipcount) |
||
649 | if ( not id ) then |
||
650 | return nil,nil,nil; |
||
651 | end |
||
652 | local skipcount = skipcount or 0; |
||
653 | -- check each of the bags on the player |
||
654 | for bag=0, NUM_BAG_FRAMES do |
||
655 | local slot; |
||
656 | slot, skipcount = CheckThisBag(bag, id, skipcount); |
||
657 | if ( slot ) then |
||
658 | return bag, slot, false; |
||
659 | end |
||
660 | end |
||
661 | |||
662 | for idx=1,19,1 do |
||
663 | local slot = PlayerSlotNames[idx].id; |
||
664 | local c, i, n = OutfitDisplayFrame_GetItemInfo(nil, slot); |
||
665 | if ( (id and i and id == i) or (name and n and name == n) ) then |
||
666 | if ( skipcount == 0 ) then |
||
667 | return nil, slot, false; |
||
668 | end |
||
669 | skipcount = skipcount - 1; |
||
670 | end |
||
671 | end |
||
672 | |||
673 | -- look in the bank |
||
674 | -- Geez, this is ugly |
||
675 | local bankbags = { BANK_CONTAINER, 5, 6, 7, 8, 9, 10 }; |
||
676 | for b=1,7 do |
||
677 | local slot; |
||
678 | slot, skipcount = CheckThisBag(bankbags[b], id, skipcount); |
||
679 | if ( slot ) then |
||
680 | return bankbags[b], slot, true; |
||
681 | end |
||
682 | end |
||
683 | -- return nil, nil, nil; |
||
684 | end |
||
685 | |||
686 | -- look for the outfit anywhere we can find it |
||
687 | -- we should look in the bank someday |
||
688 | function OutfitDisplayFrame_FindOutfit(outfit) |
||
689 | -- look for every item, if we find everything return a table of locations |
||
690 | -- otherwise don't return anything |
||
691 | if ( not outfit ) then |
||
692 | return nil; |
||
693 | end |
||
694 | local spots = { }; |
||
695 | for slotName in outfit do |
||
696 | if ( outfit[slotName].use and not outfit[slotName].empty ) then |
||
697 | local bag, slot = FindThisItem( outfit[slotName].item ); |
||
698 | if ( not bag and not slot ) then |
||
699 | spots = nil; |
||
700 | return nil; |
||
701 | else |
||
702 | spots[slotName] = { }; |
||
703 | spots[slotName].bag = bag; |
||
704 | spots[slotName].slot = slot; |
||
705 | end |
||
706 | end |
||
707 | end |
||
708 | return spots; |
||
709 | end |
||
710 | |||
711 | function OutfitDisplayFrame_CanFindOutfit(outfit) |
||
712 | if ( not outfit ) then |
||
713 | return false; |
||
714 | end |
||
715 | for slotName in outfit do |
||
716 | if ( outfit[slotName].used and not outfit[slotName].empty ) then |
||
717 | local bag, slot = FindThisItem( outfit[slotName].item ); |
||
718 | if ( not bag and not slot ) then |
||
719 | return false; |
||
720 | end |
||
721 | end |
||
722 | end |
||
723 | return true; |
||
724 | end |
||
725 | |||
726 | local function CheckSwitchWillFail(frame, outfit) |
||
727 | local contents, empties = OutfitDisplayFrame_GetBagInfo(); |
||
728 | local numfree = table.getn(empties); |
||
729 | local needfree = 0; |
||
730 | local missing = false; |
||
731 | local banked = false; |
||
732 | for i=1,19,1 do |
||
733 | local slotName = PlayerSlotNames[i].name; |
||
734 | local check; |
||
735 | if ( outfit ) then |
||
736 | check = outfit[slotName]; |
||
737 | else |
||
738 | check = getglobal(frame:GetName()..slotName); |
||
739 | end |
||
740 | if ( check and check.used ) then |
||
741 | if ( not check.empty ) then |
||
742 | local bag, slot, inbank = FindThisItem( check.item ); |
||
743 | if ( not bag and not slot ) then |
||
744 | -- pretend it's still in the bank and we just can't get it |
||
745 | if ( check.banked ) then |
||
746 | check.banked = true; |
||
747 | banked = true; |
||
748 | else |
||
749 | missing = true; |
||
750 | end |
||
751 | check.missing = not check.banked; |
||
752 | else |
||
753 | check.missing = nil; |
||
754 | check.banked = inbank; |
||
755 | end |
||
756 | else |
||
757 | local slot = PlayerSlotNames[i].id; |
||
758 | if ( OutfitDisplayFrame_GetItemInfo(nil, slot) ) then |
||
759 | needfree = needfree + 1; |
||
760 | end |
||
761 | end |
||
762 | end |
||
763 | end |
||
764 | if ( missing ) then |
||
765 | return OUTFITDISPLAYFRAME_ITEMSNOTFOUND; |
||
766 | end |
||
767 | if ( banked and not BankIsOpen ) then |
||
768 | return OUTFITDISPLAYFRAME_ITEMSINBANK; |
||
769 | end |
||
770 | if ( needfree > numfree ) then |
||
771 | return OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE; |
||
772 | end |
||
773 | return nil; |
||
774 | end |
||
775 | |||
776 | function OutfitDisplayFrame_SwitchWillFail(frame, outfit) |
||
777 | if ( not outfit ) then |
||
778 | return OUTFITDISPLAYFRAME_INVALIDOUTFIT; |
||
779 | end |
||
780 | -- if we're swapping, fail early |
||
781 | if ( OutfitDisplayFrame_IsSwapping() ) then |
||
782 | return OUTFITDISPLAYFRAME_TOOFASTMSG; |
||
783 | end |
||
784 | return CheckSwitchWillFail(frame, outfit); |
||
785 | end |
||
786 | |||
787 | function OutfitDisplayFrame_IsWearing(outfit) |
||
788 | if ( not outfit ) then |
||
789 | return false; |
||
790 | end |
||
791 | for slotName in outfit do |
||
792 | if ( outfit[slotName].used and not outfit[slotName].empty ) then |
||
793 | local slot = GetInventorySlotInfo(slotName); |
||
794 | local link = GetInventoryItemLink("player", slot); |
||
795 | local foundit = false; |
||
796 | if ( link ) then |
||
797 | local color, item, name = SplitLink(link); |
||
798 | if ( item == outfit[slotName].item ) then |
||
799 | foundit = true; |
||
800 | end |
||
801 | end |
||
802 | if ( not foundit ) then |
||
803 | return false; |
||
804 | end |
||
805 | end |
||
806 | end |
||
807 | return true; |
||
808 | end |
||
809 | |||
810 | function OutfitDisplayFrame_UpdateMessage(frame, outfit) |
||
811 | if ( frame and outfit ) then |
||
812 | local msg = CheckSwitchWillFail(frame, outfit); |
||
813 | local messages = getglobal(frame:GetName().."Message"); |
||
814 | if ( msg ) then |
||
815 | messages:Show(); |
||
816 | messages:SetText(msg); |
||
817 | messages:SetTextColor(1, 1, 1); |
||
818 | else |
||
819 | messages:SetText(""); |
||
820 | messages:Hide(); |
||
821 | end |
||
822 | end |
||
823 | end |
||
824 | |||
825 | function OutfitDisplayFrame_GetSlotContents(slotName, returnEmpty) |
||
826 | if ( slotName ~= "Options" ) then |
||
827 | local slot = GetInventorySlotInfo(slotName); |
||
828 | local link = GetInventoryItemLink("player", slot); |
||
829 | if ( link ) then |
||
830 | local contents = {}; |
||
831 | local color, item, name = SplitLink(link); |
||
832 | contents.item = item; |
||
833 | contents.name = name; |
||
834 | contents.color = color; |
||
835 | contents.texture = texture; |
||
836 | contents.used = true; |
||
837 | local bag, slot = FindThisItem( item ); |
||
838 | contents.bag = bag; |
||
839 | contents.slot = slot; |
||
840 | return contents; |
||
841 | end |
||
842 | end |
||
843 | -- return nil; |
||
844 | end |
||
845 | |||
846 | function OutfitDisplayFrame_GetWearing(check) |
||
847 | local wearing = {}; |
||
848 | if ( check ) then |
||
849 | for slotName in check do |
||
850 | wearing[slotName] = OutfitDisplayFrame_GetSlotContents(slotName); |
||
851 | end |
||
852 | -- make sure we pick up the off hand if we're going to put something |
||
853 | -- two-handed in the main hand slot |
||
854 | local mainhand = check["MainHandSlot"]; |
||
855 | local offhand = wearing["SecondaryHandSlot"]; |
||
856 | if ( not offhand and mainhand and not IsItemOneHanded(mainhand.item) ) then |
||
857 | wearing["SecondaryHandSlot"] = OutfitDisplayFrame_GetSlotContents("SecondaryHandSlot"); |
||
858 | end |
||
859 | else |
||
860 | for i=1,19,1 do |
||
861 | local slotName = PlayerSlotNames[i].name; |
||
862 | wearing[slotName] = OutfitDisplayFrame_GetSlotContents(slotName); |
||
863 | end |
||
864 | end |
||
865 | if ( not ShowingCloak() or not ShowingHelm() ) then |
||
866 | wearing["Options"] = {} |
||
867 | wearing["Options"].cloak = not(not ShowingCloak()); |
||
868 | wearing["Options"].helm = not(not ShowingHelm()); |
||
869 | end |
||
870 | return wearing; |
||
871 | end |
||
872 | |||
873 | function OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount, bag_affinity, slot_affinity) |
||
874 | skipcount = skipcount or 0; |
||
875 | |||
876 | -- try to put the item in the requested affinity, if possible |
||
877 | if bag_affinity and slot_affinity and |
||
878 | not GetContainerItemInfo(bag_affinity, slot_affinity) then |
||
879 | return bag_affinity, slot_affinity; |
||
880 | end |
||
881 | |||
882 | -- if we couldn't get the bag and slot we wanted, just try the same bag |
||
883 | if bag_affinity then |
||
884 | for j=GetContainerNumSlots(bag_affinity),1,-1 do |
||
885 | if not GetContainerItemInfo(bag_affinity,j) then |
||
886 | if skipcount == 0 then return bag_affinity,j; end |
||
887 | skipcount = skipcount - 1; |
||
888 | end |
||
889 | end |
||
890 | end |
||
891 | |||
892 | -- no affinity, check all bags |
||
893 | for i=NUM_BAG_FRAMES,0,-1 do |
||
894 | -- but skip any bag we already have affinity for (because it might have |
||
895 | -- already modified skipcount) |
||
896 | if bag_affinity ~= i then |
||
897 | -- Make sure this isn't a quiver, those won't hold shit |
||
898 | local bagName = GetBagName(i); |
||
899 | if ( bagName ) then |
||
900 | local texture = GetInventoryItemTexture("player", |
||
901 | ContainerIDToInventoryID(i)); |
||
902 | |||
903 | if ( string.find(texture, "INV_Misc_Bag_%d") and not string.find(bagName, AMMOSLOT) ) then |
||
904 | for j=GetContainerNumSlots(i),1,-1 do |
||
905 | if not GetContainerItemInfo(i,j) then |
||
906 | if skipcount == 0 then return i,j; end |
||
907 | skipcount = skipcount - 1; |
||
908 | end -- if empty |
||
909 | end -- for slots |
||
910 | end -- if normal bag |
||
911 | end -- if there is a bag |
||
912 | end -- if not affinity bag |
||
913 | end -- for bags |
||
914 | |||
915 | -- not found return nil,nil implicitly |
||
916 | end |
||
917 | |||
918 | -- okay, let's switch to the specified outfit |
||
919 | -- code liberally borrowed from "WeaponQuickSwap - by CapnBry" |
||
920 | |||
921 | -- list functions |
||
922 | local function swapentry_print(entry) |
||
923 | if ( DEFAULT_CHAT_FRAME ) then |
||
924 | local msg = "Entry "..tonil(entry.sb)..","..tonil(entry.si)..","..tonil(entry.db)..","..tonil(entry.di); |
||
925 | DEFAULT_CHAT_FRAME:AddMessage(msg, 1.0,0,0); |
||
926 | end |
||
927 | end |
||
928 | |||
929 | local function swaplist_print(list) |
||
930 | while ( list ) do |
||
931 | swapentry_print(list); |
||
932 | list = list.next; |
||
933 | end |
||
934 | end |
||
935 | |||
936 | local function swaplist_push(list, sb, si, db, di, helm, cloak) |
||
937 | list = { next = list, sb = sb, si = si, db = db, di = di, |
||
938 | helm = helm, cloak = cloak }; |
||
939 | return list; |
||
940 | end |
||
941 | |||
942 | local function swaplist_popfirst(list) |
||
943 | if not list then return; end |
||
944 | list = list.next; |
||
945 | return list; |
||
946 | end |
||
947 | |||
948 | -- Unit variable to hold the stack of swaps |
||
949 | local outfitswap = nil; |
||
950 | |||
951 | function OutfitDisplayFrame_IsSwapping() |
||
952 | if ( outfitswap or OutfitDisplayFrame_AnyItemLocked() ) then |
||
953 | return true; |
||
954 | else |
||
955 | return false; |
||
956 | end |
||
957 | end |
||
958 | |||
959 | -- First we do everything except the main hand and secondary hand |
||
960 | -- Then we do the hard stuff |
||
961 | |||
962 | function OutfitDisplayFrame_ItemIsLocked(bag, slot) |
||
963 | if not bag and not slot then |
||
964 | return false; |
||
965 | end |
||
966 | |||
967 | if not bag then |
||
968 | return IsInventoryItemLocked(slot); |
||
969 | else |
||
970 | local _,_,locked = GetContainerItemInfo(bag,slot); |
||
971 | return locked; |
||
972 | end |
||
973 | end |
||
974 | |||
975 | function OutfitDisplayFrame_AnyItemLocked() |
||
976 | -- Checks all the bags and the equipped slots to see if any are still locked |
||
977 | for i=0,NUM_BAG_FRAMES do |
||
978 | for j=1,GetContainerNumSlots(i) do |
||
979 | local _,_,locked = GetContainerItemInfo(i,j); |
||
980 | if ( locked ) then |
||
981 | return true; |
||
982 | end |
||
983 | end |
||
984 | end |
||
985 | for i=1,19,1 do |
||
986 | if ( IsInventoryItemLocked(PlayerSlotNames[i].id) ) then |
||
987 | return true; |
||
988 | end |
||
989 | end |
||
990 | return false; |
||
991 | end |
||
992 | |||
993 | function OutfitDisplayFrame_ExecuteSwapIteration() |
||
994 | if not outfitswap then |
||
995 | PerformSlowerSwap = false; |
||
996 | return; |
||
997 | end |
||
998 | |||
999 | if OutfitDisplayFrame_ItemIsLocked(outfitswap.sb, outfitswap.si) or |
||
1000 | OutfitDisplayFrame_ItemIsLocked(outfitswap.db, outfitswap.di) then |
||
1001 | return; |
||
1002 | end |
||
1003 | |||
1004 | if not outfitswap.sb then |
||
1005 | SavedPickupInventoryItem(outfitswap.si); |
||
1006 | else |
||
1007 | SavedPickupContainerItem(outfitswap.sb, outfitswap.si); |
||
1008 | end |
||
1009 | |||
1010 | if not outfitswap.db then |
||
1011 | if not outfitswap.di then |
||
1012 | PutItemInBackpack(); |
||
1013 | else |
||
1014 | SavedPickupInventoryItem(outfitswap.di); |
||
1015 | end |
||
1016 | else |
||
1017 | SavedPickupContainerItem(outfitswap.db, outfitswap.di); |
||
1018 | end |
||
1019 | |||
1020 | if ( outfitswap.cloak ~= nil ) then |
||
1021 | ShowCloak(outfitswap.cloak); |
||
1022 | elseif ( outfitswap.helm ~= nil ) then |
||
1023 | ShowHelm(outfitswap.helm); |
||
1024 | end |
||
1025 | |||
1026 | outfitswap = swaplist_popfirst(outfitswap); |
||
1027 | if ( outfitswap and not PerformSlowerSwap ) then |
||
1028 | return OutfitDisplayFrame_ExecuteSwapIteration(); |
||
1029 | end |
||
1030 | end |
||
1031 | |||
1032 | function OutfitDisplayFrame_SwitchOne(outfit, index, skipcount, showhelm, showcloak) |
||
1033 | local slotName = PlayerSlotNames[index].name; |
||
1034 | if ( outfit and outfit[slotName] ) then |
||
1035 | local invslot = GetInventorySlotInfo(slotName); |
||
1036 | if ( outfit[slotName].empty ) then |
||
1037 | local bag, slot = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount); |
||
1038 | outfitswap = swaplist_push(outfitswap, nil, invslot, bag, slot); |
||
1039 | skipcount = skipcount + 1; |
||
1040 | else |
||
1041 | local helmflag, cloakflag; |
||
1042 | if ( slotName == "HeadSlot" ) then |
||
1043 | helmflag = showhelm; |
||
1044 | elseif ( slotName == "BackSlot" ) then |
||
1045 | cloakflag = showcloak; |
||
1046 | end |
||
1047 | local bag, slot = FindThisItem( outfit[slotName].item ); |
||
1048 | -- either we couldn't find it, or it's where it should be |
||
1049 | if ( bag ~= nil or slot ~= invslot ) then |
||
1050 | outfitswap = swaplist_push(outfitswap, bag, slot, nil, invslot, helmflag, cloakflag); |
||
1051 | end |
||
1052 | end |
||
1053 | end |
||
1054 | return skipcount; |
||
1055 | end |
||
1056 | |||
1057 | local function OnSwapError(error) |
||
1058 | outfitswap = nil; |
||
1059 | if ( UIErrorsFrame ) then |
||
1060 | UIErrorsFrame:AddMessage(error, 1.0, 0.1, 0.1, 1.0, UIERRORS_HOLD_TIME); |
||
1061 | end |
||
1062 | return; |
||
1063 | end |
||
1064 | |||
1065 | function OutfitDisplayFrame_SwitchOutfit(outfit) |
||
1066 | if ( CursorHasItem() or OutfitDisplayFrame_IsSwapping() ) then |
||
1067 | return OnSwapError(OUTFITDISPLAYFRAME_TOOFASTMSG); |
||
1068 | end |
||
1069 | if ( not outfit ) then |
||
1070 | return OnSwapError(OUTFITDISPLAYFRAME_INVALIDOUTFIT); |
||
1071 | end |
||
1072 | |||
1073 | -- might not need to swap slowly |
||
1074 | PerformSlowerSwap = false; |
||
1075 | |||
1076 | -- need to check to see that we have enough room |
||
1077 | local old = OutfitDisplayFrame_GetWearing(outfit); |
||
1078 | |||
1079 | local showcloak; |
||
1080 | local showhelm; |
||
1081 | if ( outfit["Options"] ) then |
||
1082 | showhelm = outfit["Options"].helm; |
||
1083 | showcloak = outfit["Options"].cloak; |
||
1084 | end |
||
1085 | |||
1086 | -- do everything except weapon slots |
||
1087 | local skipcount = 0; |
||
1088 | for i=1,16,1 do |
||
1089 | skipcount = OutfitDisplayFrame_SwitchOne(outfit, i, skipcount, showhelm, showcloak); |
||
1090 | end |
||
1091 | OutfitDisplayFrame_SwitchOne(outfit, 19, skipcount); |
||
1092 | |||
1093 | if ( not outfit["MainHandSlot"] and not outfit["SecondaryHandSlot"] ) then |
||
1094 | OutfitDisplayFrame_ExecuteSwapIteration(); |
||
1095 | return old; |
||
1096 | end |
||
1097 | |||
1098 | local mainhandslot = GetInventorySlotInfo("MainHandSlot"); |
||
1099 | local secondaryslot = GetInventorySlotInfo("SecondaryHandSlot"); |
||
1100 | local mainhand = outfit["MainHandSlot"]; |
||
1101 | local offhand = outfit["SecondaryHandSlot"]; |
||
1102 | -- now do hands |
||
1103 | local m_sb; |
||
1104 | local m_si; |
||
1105 | local o_sb; |
||
1106 | local o_si; |
||
1107 | local m_ok = not mainhand or not mainhand.item; |
||
1108 | local o_ok = not offhand or not offhand.item; |
||
1109 | |||
1110 | if ( mainhand and mainhand.item ) then |
||
1111 | m_sb, m_si = FindThisItem(mainhand.item); |
||
1112 | m_ok = ( not m_sb and m_si == mainhandslot ); |
||
1113 | end |
||
1114 | if ( offhand and offhand.item ) then |
||
1115 | local multiples = 0; |
||
1116 | if ( mainhand and mainhand.item == offhand.item ) then |
||
1117 | multiples = 1; |
||
1118 | end |
||
1119 | o_sb, o_si = FindThisItem( offhand.item, multiples); |
||
1120 | o_ok = ( not o_sb and o_si == secondaryslot ); |
||
1121 | end |
||
1122 | |||
1123 | if ( not m_ok ) then |
||
1124 | -- do we need two of these? |
||
1125 | if ( o_ok and not m_sb and m_si == secondaryslot ) then |
||
1126 | m_sb, m_si = FindThisItem( mainhand.item, 1); |
||
1127 | end |
||
1128 | end |
||
1129 | |||
1130 | -- moving from bags |
||
1131 | if ( m_sb and o_sb ) then |
||
1132 | -- insert them backwards, since they get popped off |
||
1133 | -- main hand has to get done first in case it's currently |
||
1134 | -- a two hander |
||
1135 | outfitswap = swaplist_push(outfitswap, o_sb, o_si, nil, secondaryslot); |
||
1136 | outfitswap = swaplist_push(outfitswap, m_sb, m_si, nil, mainhandslot); |
||
1137 | elseif ( not m_sb and m_si == secondaryslot and not o_sb and o_si == mainhandslot ) then |
||
1138 | outfitswap = swaplist_push(outfitswap, nil, mainhandslot, nil, secondaryslot); |
||
1139 | else |
||
1140 | -- Install main hand |
||
1141 | if not m_ok then |
||
1142 | -- if nothing going to the main hand |
||
1143 | if ( not m_sb and not m_si ) then |
||
1144 | -- and the main is not going to the off: put it in a bag |
||
1145 | if not ( not o_sb and o_si == mainhandslot) then |
||
1146 | local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount); |
||
1147 | if not (bb and bi) then |
||
1148 | return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE); |
||
1149 | end |
||
1150 | skipcount = skipcount + 1; |
||
1151 | outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi); |
||
1152 | -- when moving A,"" -> "",B where A is a 2h, the offhand |
||
1153 | -- doesn't lock properly, so work around it by swapping |
||
1154 | -- slowly (only one swap per lock notify) |
||
1155 | PerformSlowerSwap = not IsItemOneHanded(mainhand.item); |
||
1156 | end |
||
1157 | else |
||
1158 | outfitswap = swaplist_push(outfitswap, m_sb, m_si, nil, mainhandslot); |
||
1159 | end |
||
1160 | end |
||
1161 | |||
1162 | -- Load offhand if not already there |
||
1163 | if not o_ok then |
||
1164 | if ( not o_sb and not o_si ) then |
||
1165 | if not (not m_sb and m_si == secondaryslot) then |
||
1166 | local bb, bi; |
||
1167 | if LastOffSource then |
||
1168 | bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount, |
||
1169 | LastOffSource.bag, LastOffSource.slot); |
||
1170 | else |
||
1171 | bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount); |
||
1172 | end |
||
1173 | |||
1174 | if not (bb and bi) then |
||
1175 | return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE); |
||
1176 | end |
||
1177 | skipcount = skipcount + 1; |
||
1178 | outfitswap = swaplist_push(outfitswap, nil, secondaryslot, bb, bi); |
||
1179 | end |
||
1180 | else |
||
1181 | -- if the main hand weapon is coming from the offhand slot |
||
1182 | -- we need to fix up its source to be where the offhand is |
||
1183 | -- GOING to be after the bag->off swap |
||
1184 | if outfitswap and ( not m_sb and m_si == secondaryslot) then |
||
1185 | outfitswap.sb = o_sb; |
||
1186 | outfitswap.si = o_si; |
||
1187 | -- don't set o_sb, o_si they're tested later |
||
1188 | end |
||
1189 | |||
1190 | outfitswap = swaplist_push(outfitswap, o_sb, o_si, nil, secondaryslot); |
||
1191 | end |
||
1192 | end |
||
1193 | |||
1194 | -- Special Case: Moving off to main, and not main to off |
||
1195 | -- This is because maybe the main hand weapon is main only |
||
1196 | if (not m_sb and m_si == secondaryslot) and not ( not o_sb and o_si == mainhandslot) then |
||
1197 | local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount); |
||
1198 | if not (bb and bi) then |
||
1199 | return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE); |
||
1200 | end |
||
1201 | skipcount = skipcount + 1; |
||
1202 | outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi); |
||
1203 | end |
||
1204 | |||
1205 | -- Same thing for off hand |
||
1206 | if (not o_sb and o_si == mainhandslot) and not (not m_sb and m_si == secondaryslot) then |
||
1207 | local bb, bi = OutfitDisplayFrame_FindLastEmptyBagSlot(skipcount); |
||
1208 | if not (bb and bi) then |
||
1209 | return OnSwapError(OUTFITDISPLAYFRAME_NOTENOUGHFREESPACE); |
||
1210 | end |
||
1211 | skipcount = skipcount + 1; |
||
1212 | outfitswap = swaplist_push(outfitswap, nil, mainhandslot, bb, bi); |
||
1213 | end |
||
1214 | |||
1215 | if o_sb then |
||
1216 | LastOffSource = { bag = o_sb, slot = o_si }; |
||
1217 | end |
||
1218 | end |
||
1219 | -- Start moving |
||
1220 | OutfitDisplayFrame_ExecuteSwapIteration(); |
||
1221 | return old; |
||
1222 | end |