-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMI2_Search.lua
517 lines (457 loc) · 17.5 KB
/
MI2_Search.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
--
-- MI2_Search.lua
--
-- MobInfo module to control the Mob database search feature.
-- Search option settings and actual search algorithm are located in here.
--
--
-- start up defaults for search options settings
MI2_SearchOptions = {}
MI2_SearchOptions.MinLevel = 1
MI2_SearchOptions.MaxLevel = 110
MI2_SearchOptions.Normal = 1
MI2_SearchOptions.Elite = 0
MI2_SearchOptions.Boss = 0
MI2_SearchOptions.MinLoots = 0
MI2_SearchOptions.MaxLoots = 9999
MI2_SearchOptions.MobName = ""
MI2_SearchOptions.ItemName = ""
MI2_SearchOptions.CompactResult = 1
MI2_SearchOptions.ListMode = "Mobs"
MI2_SearchOptions.SortMode = "profit"
local MI2_SearchResultList = {}
MI2_ItemsIdxList = {}
MI2_SearchMode = 0
MI2_SearchCount = 0
MI2_NumMobsFound = 0
-----------------------------------------------------------------------------
-- MI2_SearchForItems()
--
-- Search for all items matching the item name entered in the search dialog.
-- Display the list of items in the result list control (if requested).
--
local function MI2_SearchForItems( itemName, enterItemsIntoList )
MI2_ItemsIdxList = {}
MI2_NumMobsFound = 0
if enterItemsIntoList then
MI2_SearchResultList = {}
end
if itemName ~= "" or enterItemsIntoList then
local itemFound, itemText, itemColor
itemName = string.lower(itemName)
MI2_ItemsIdxList[0] = 1
for idx in pairs(MI2_ItemNameTable) do
itemFound = true
itemText, itemColor = MI2_GetLootItem( idx )
--local itemText = MI2_ItemNameTable[idx]
if itemName ~= "*" then
itemFound = string.find( string.lower(itemText), itemName ) ~= nil
end
if itemFound then
if enterItemsIntoList then
MI2_NumMobsFound = MI2_NumMobsFound + 1
MI2_SearchResultList[MI2_NumMobsFound] = { idx = itemText, val = "", col = itemColor }
else
MI2_ItemsIdxList[idx] = 1
end
end
end
end
MI2_DisplaySearchResult( "Items" )
end -- MI2_SearchForItems()
-----------------------------------------------------------------------------
-- MI2_UpdateSearchResultList()
--
-- Update contents of search result list according to current search options
-- settings. This includes starting a new search run, sorting the result and
-- displaying the result in the scrollable result list.
--
local function MI2_UpdateSearchResultList( updateItems )
if updateItems then
local enterItemsIntoList = MI2_SearchOptions.ListMode == "Items"
MI2_SearchForItems( MI2_SearchOptions.ItemName, enterItemsIntoList )
end
if MI2_SearchOptions.ListMode == "Mobs" then
-- (re)start search for entire mob database
MI2_SearchCount = 0
MI2_SearchMode = 1
for mobIndex, mobInfo in pairs(MobInfoDB) do
mobInfo.sf = true
end
-- initialise search result list
MI2_SearchResultList = {}
MI2_NumMobsFound = 0
-- search first 500 database recors right away
MI2_SearchForMobs( 500 )
end
MI2_DisplaySearchResult( MI2_SearchOptions.ListMode )
end -- MI2_UpdateSearchResultList()
-----------------------------------------------------------------------------
-- MI2_SearchOptionsOnShow()
--
-- OnShow event handler for search options page
-- Write current search option settings into the search option controls.
-- Validate all values and update colors accordingly.
-- Allow Search only if all search options are valid.
--
function MI2_SearchOptionsOnShow()
MI2_OptSearchMinLoots:SetMaxLetters( 4 )
MI2_OptSearchMaxLoots:SetMaxLetters( 4 )
MI2_OptSearchMinLoots:SetWidth( 36 )
MI2_OptSearchMaxLoots:SetWidth( 36 )
MI2_OptSearchMinLevel:SetText( tostring(MI2_SearchOptions.MinLevel) )
MI2_OptSearchMaxLevel:SetText( tostring(MI2_SearchOptions.MaxLevel) )
MI2_OptSearchMinLoots:SetText( tostring(MI2_SearchOptions.MinLoots) )
MI2_OptSearchMaxLoots:SetText( tostring(MI2_SearchOptions.MaxLoots) )
MI2_OptSearchMobName:SetText( MI2_SearchOptions.MobName )
MI2_OptSearchItemName:SetText( MI2_SearchOptions.ItemName )
if not MI2_SearchOptions.Normal or MI2_SearchOptions.Normal == 0 then
MI2_OptSearchNormal:SetChecked( false )
else
MI2_OptSearchNormal:SetChecked( true )
end
if not MI2_SearchOptions.Elite or MI2_SearchOptions.Elite == 0 then
MI2_OptSearchElite:SetChecked( false )
else
MI2_OptSearchElite:SetChecked( true )
end
if not MI2_SearchOptions.Boss or MI2_SearchOptions.Boss == 0 then
MI2_OptSearchBoss:SetChecked( false )
else
MI2_OptSearchBoss:SetChecked( true )
end
MI2_UpdateSearchResultList()
end -- MI2_SearchOptionsOnShow()
-----------------------------------------------------------------------------
-- MI2_ValidateSearchOptions()
--
-- Validate all values and update colors accordingly.
-- Allow Search only if all search options are valid.
--
local function MI2_ValidateSearchOptions(self)
if MI2_SearchOptions.MinLevel < 1 then
MI2_SearchOptions.MinLevel = 1
if self:GetText() == "0" then
self:SetText( "1" )
end
end
if MI2_SearchOptions.MaxLevel < 1 then
MI2_SearchOptions.MaxLevel = 1
if self:GetText() == "0" then
self:SetText( "1" )
end
end
end -- MI2_ValidateSearchOptions()
-----------------------------------------------------------------------------
-- MI2_SearchCheckboxClicked()
--
-- OnClicked event handler for checkboxes on search options page
-- Store the checkbox state in the corresponding search options variable.
--
function MI2_SearchCheckboxClicked(self)
local checkboxName = self:GetName()
local optionName = string.sub( checkboxName, 14 )
local optionValue = self:GetChecked() or 0
MI2_SearchOptions[optionName] = optionValue
MI2_UpdateSearchResultList()
end -- MI2_SearchCheckboxClicked()
-----------------------------------------------------------------------------
-- MI2_SearchValueChanged()
--
-- OnChar event handler for editbox controls on search options page
-- This handler is called whenever the contents of an EditBox control changes.
-- It gets the new value and stores it in the corresponding search options
-- variable
--
function MI2_SearchValueChanged(self)
local editboxName = self:GetName()
local optionName = string.sub( editboxName, 14 )
local optionValue = tonumber(self:GetText()) or 0
if MI2_SearchOptions[optionName] ~= optionValue then
MI2_SearchOptions[optionName] = optionValue
MI2_ValidateSearchOptions(self)
MI2_UpdateSearchResultList()
end
end -- MI2_SearchValueChanged()
-----------------------------------------------------------------------------
-- MI2_SearchTextChanged()
--
-- OnChar event handler for textual editbox controls on search options page
-- This handler is called whenever the contents of an EditBox control changes.
-- It gets the new value and stores it in the corresponding search options
-- variable
--
function MI2_SearchTextChanged(self)
local editboxName = self:GetName()
local optionName = string.sub( editboxName, 14 )
if MI2_SearchOptions[optionName] ~= self:GetText() then
MI2_SearchOptions[optionName] = self:GetText()
MI2_UpdateSearchResultList( true )
end
end -- MI2_SearchTextChanged()
-----------------------------------------------------------------------------
-- MI2_CalculateRank()
--
-- Calculate ranking and corresponding actual value for a given mob.
-- Ranking depends on search mode. For search mode "profit" ranking is
-- based on the mobs total profit value plus bonus points for rare loot
-- items. For search mode "itemCount" ranking is identical to the overall
-- items count for the loot items being searched for (in this mode
-- rank and value are identical).
--
local function MI2_CalculateRank( mobData, mobLevel, sortMode )
local rank, value = 0, 0
if sortMode == "profit" then
-- calculate rank based on mob level and loot items quality
local bonusFactor = mobLevel / 20
if mobData.loots > 0 then
value = (mobData.copper or 0) + (mobData.itemValue or 0)
rank = value + ((mobData.r3 or 0) * 200 * bonusFactor) + ((mobData.r4 or 0) * 1000 * bonusFactor) + ((mobData.r5 or 0) * 2000 * bonusFactor)
rank = ceil( rank / mobData.loots )
value = copper2text( ceil(value / mobData.loots) )
end
elseif sortMode == "item" and mobData.itemList then
for idx, val in pairs(mobData.itemList) do
--local itemFound = string.find( MI2_ItemsIdxList, idx ) ~= nil
--if itemFound then rank = rank + val end
rank = rank + val
end
value = rank.." "
end
return rank, value
end -- MI2_CalculateRank()
-----------------------------------------------------------------------------
-- MI2_CheckMob()
--
-- Check a given Mob against the current search criteria. Return the
-- mob data if the mob matches the criteria, or return nil if the Mob
-- does not match.
--
local function MI2_CheckMob( mobInfo, mobName, mobLevel )
local levelOk, lootsOk, typeOk, itemsOK, mobData
local nameOk = true
-- check name and level of Mob
if MI2_SearchOptions.MobName ~= "" then
nameOk = string.find(string.lower(mobName),string.lower(MI2_SearchOptions.MobName),1,true) ~= nil
end
if nameOk and mobName ~= "" then
levelOk = mobLevel >= MI2_SearchOptions.MinLevel and mobLevel <= MI2_SearchOptions.MaxLevel
levelOk = levelOk or (mobLevel == -1)
end
-- check mob data related search conditions
if levelOk then
mobData = {}
MI2_DecodeBasicMobData( mobInfo, mobData )
mobData.loots = mobData.loots or 0
lootsOk = (mobData.loots >= MI2_SearchOptions.MinLoots) and (mobData.loots <= MI2_SearchOptions.MaxLoots)
typeOk = (MI2_SearchOptions.Normal == 1 and (mobData.mobType == 1 or not mobData.mobType)) or (MI2_SearchOptions.Elite == 1 and mobData.mobType == 2) or (MI2_SearchOptions.Boss == 1 and mobData.mobType == 3)
if lootsOk and typeOk then
MI2_DecodeItemList( mobInfo, mobData )
if MI2_ItemsIdxList[0] then
if mobData.itemList then
for idx, val in pairs(mobData.itemList) do
itemsOK = MI2_ItemsIdxList[idx] ~= nil
if itemsOK then break end
end
end
if not itemsOK then mobData = nil end
end
else
mobData = nil
end
end
return mobData
end -- MI2_CheckMob()
-----------------------------------------------------------------------------
-- MI2_DisplaySearchResult()
--
-- Display the result of a search in the search results scrollable list.
-- The mobs to be displayed depend on the current list scroll position.
--
function MI2_DisplaySearchResult( resultType )
-- update slider and get slider position
FauxScrollFrame_Update( MI2_SearchResultSlider, MI2_NumMobsFound, 15, 14 );
local sliderPos = FauxScrollFrame_GetOffset(MI2_SearchResultSlider)
if resultType then
MI2_TxtSearchCount:SetText( MI_SubWhite.."("..MI2_NumMobsFound.." "..resultType..")" )
end
-- update 15 search result lines with correct search result data
local resultLine
for i = 1, 15 do
if (i + sliderPos) <= MI2_NumMobsFound then
resultLine = _G[ "MI2_SearchResult"..i.."Index" ]
resultLine:SetText( i + sliderPos )
resultLine = _G[ "MI2_SearchResult"..i.."Value" ]
resultLine:SetText( MI2_SearchResultList[i + sliderPos].val )
resultLine = _G[ "MI2_SearchResult"..i.."Name" ]
local mobName = MI2_SearchResultList[i + sliderPos].idx
if MI2_SearchResultList[i + sliderPos].type then
mobName = mobName.."+"
elseif MI2_SearchResultList[i + sliderPos].col then
mobName = MI2_SearchResultList[i + sliderPos].col..mobName
end
resultLine:SetText( mobName )
else
resultLine = _G[ "MI2_SearchResult"..i.."Index" ]
resultLine:SetText( "" )
resultLine = _G[ "MI2_SearchResult"..i.."Value" ]
resultLine:SetText( "" )
resultLine = _G[ "MI2_SearchResult"..i.."Name" ]
resultLine:SetText( "" )
end
end
end -- MI2_DisplaySearchResult()
-----------------------------------------------------------------------------
-- MI2_SlashAction_SortByValue()
--
-- Sort the search result list by mob profit
--
function MI2_SlashAction_SortByValue()
MI2_SearchOptions.SortMode = "profit"
MI2_UpdateSearchResultList()
end -- end of MI2_SlashAction_SortByValue()
-----------------------------------------------------------------------------
-- MI2_SlashAction_SortByItem()
--
-- Sort the search result list by mob item count
--
function MI2_SlashAction_SortByItem()
MI2_SearchOptions.SortMode = "item"
MI2_UpdateSearchResultList()
end -- end of MI2_SlashAction_SortByItem()
-----------------------------------------------------------------------------
-- MI2_SearchResult_Update()
--
-- Update contents of search results list based on current scroll bar
-- position. Update tooltip for selected mob if tooltip is visible.
--
function MI2_SearchResult_Update()
FauxScrollFrame_Update( MI2_SearchResultSlider, MI2_NumMobsFound, 15, 14 );
MI2_DisplaySearchResult()
end -- end of MI2_SearchResult_Update()
-----------------------------------------------------------------------------
-- MI2_ShowSearchResultTooltip()
--
-- Show mob tooltip for search result mob currently under mouse cursor.
--
function MI2_ShowSearchResultTooltip(self)
local sliderPos = FauxScrollFrame_GetOffset(MI2_SearchResultSlider)
local selection = tonumber(string.sub(self:GetName(), 17)) + sliderPos
if selection <= MI2_NumMobsFound then
if MI2_SearchOptions.ListMode == "Mobs" then
local index = MI2_SearchResultList[selection].idx
local mobName, mobLevel = MI2_GetIndexComponents( index )
-- create Mob data tooltip with full location info
MI2_CreateTooltip( mobName, mobLevel, nil, true )
elseif MI2_SearchOptions.ListMode == "Items" then
GameTooltip_SetDefaultAnchor( GameTooltip, UIParent )
local itemName = MI2_SearchResultList[selection].idx
GameTooltip:SetText( MI2_SearchResultList[selection].col..itemName )
MI2_BuildItemDataTooltip( itemName )
GameTooltip:Show()
end
end
end -- end of MI2_ShowSearchResultTooltip()
-----------------------------------------------------------------------------
-- MI2_HideSearchResultTooltip()
--
function MI2_HideSearchResultTooltip()
MI2_HideTooltip()
end -- MI2_HideSearchResultTooltip()
-----------------------------------------------------------------------------
-- MI2_SearchTab_OnClick()
--
-- The "OnClick" event handler for the TAB buttons on the search result list.
-- These TAB buttons switch the list content between two modes: mob list
-- and item list
--
function MI2_SearchTab_OnClick(self)
PanelTemplates_Tab_OnClick( self, MI2_SearchResultFrame )
local selected = MI2_SearchResultFrame.selectedTab
if selected == 1 then
MI2_OptSortByValue:Enable()
MI2_OptSortByItem:Enable()
if MI2_NumMobsFound > 0 then
MI2_OptDeleteSearch:Enable()
else
MI2_OptDeleteSearch:Disable()
end
MI2_SearchOptions.ListMode = "Mobs"
MI2_UpdateSearchResultList( true )
elseif selected == 2 then
MI2_OptSortByValue:Disable()
MI2_OptSortByItem:Disable()
MI2_OptDeleteSearch:Disable()
MI2_SearchOptions.ListMode = "Items"
MI2_UpdateSearchResultList( true )
end
end -- MI2_SearchTab_OnClick()
-----------------------------------------------------------------------------
-- MI2_SearchForMobs()
--
-- Search through a limited number of Mobs. Think function is meant to be
-- called repeatedly (in the background) to incrementally build the overall
-- search result list.
--
function MI2_SearchForMobs( searchLimit )
local searchCount = 0
for mobIndex, mobInfo in pairs(MobInfoDB) do
if mobInfo.sf then
searchCount = searchCount + 1
MI2_SearchCount = MI2_SearchCount + 1
mobInfo.sf = nil
mobName, mobLevel = MI2_GetIndexComponents( mobIndex )
mobData = MI2_CheckMob( mobInfo, mobName, mobLevel )
-- if mob is identified as belonging into the search result its
-- search result sorting position is calculated based on a ranking
-- value which in turn is based on the search mode
if mobData then
rank, value = MI2_CalculateRank( mobData, mobLevel, MI2_SearchOptions.SortMode )
MI2_NumMobsFound = MI2_NumMobsFound + 1
-- insert mob at correct sorted position and store all info we need for printing the result list
MI2_SearchResultList[MI2_NumMobsFound] = { idx=mobIndex, val=value, rank=rank }
if mobData.mobType and mobData.mobType > 1 then
MI2_SearchResultList[MI2_NumMobsFound].type = mobData.mobType
end
end
end
if searchCount > searchLimit then
return false
end
end
return true
end -- MI2_SearchForMobs()
-----------------------------------------------------------------------------
-- MI2_SearchOnUpdate()
--
-- OnUpdate is called periodically (about 45 times per second) by the WoW
-- client.
--
function MI2_SearchOnUpdate( time )
if MI2_SearchMode == 1 then
local finished = MI2_SearchForMobs( 400 )
if ( finished ) then
MI2_SearchMode = 0
if MI2_NumMobsFound > 1 then
table.sort( MI2_SearchResultList, function(a,b) return (a.rank > b.rank) end )
end
MI2_DisplaySearchResult( MI2_SearchOptions.ListMode )
else
MI2_TxtSearchCount:SetText( MI_SubWhite.."(searching..."..MI2_SearchCount..")" )
end
end
end
-----------------------------------------------------------------------------
-- MI2_DeleteSearchResultMobs()
--
-- Delete all Mobs in the search result list from the MobInfo database.
-- This function is called when the user confirms the delete.
--
function MI2_DeleteSearchResultMobs()
for idx, val in pairs(MI2_SearchResultList) do
local mobIndex = val.idx
MI2_DeleteMobData( mobIndex, true )
end
chattext( "search result deleted : "..MI2_NumMobsFound.." Mobs" )
MI2_UpdateSearchResultList()
end -- MI2_DeleteSearchResultMobs()