@@ -123,6 +123,7 @@ local state = {
123123 activeSection = " autokick" ,
124124 selectedKickIndex = nil ,
125125 selectedClassIndex = nil ,
126+ selectedBannedClassIndex = nil ,
126127 kickPage = 1 ,
127128 scanElapsed = SCAN_INTERVAL_MS ,
128129 distanceElapsed = DISTANCE_SCAN_INTERVAL_MS ,
@@ -152,7 +153,11 @@ local buffMissingRows = {}
152153local buffMissingResults = {}
153154local buffMissingOffset = 1
154155local bannedClassInput
156+ local bannedClassDropdown
155157local bannedClassLabel
158+ local bannedClassRemoveButton
159+ local bannedClassRows = {}
160+ local allClassNames
156161local fixgardenButton
157162local distanceKickButton
158163local distanceKickInput
@@ -1183,6 +1188,119 @@ local function IsBannedClass(className)
11831188 return false
11841189end
11851190
1191+ local function GetAllClassNames ()
1192+ if allClassNames ~= nil then
1193+ return allClassNames
1194+ end
1195+ allClassNames = {}
1196+ local seen = {}
1197+ for first = 1 , 14 do
1198+ for second = first + 1 , 14 do
1199+ for third = second + 1 , 14 do
1200+ local key = string.format (" name_%d_%d_%d" , first , second , third )
1201+ local className = X2Locale :LocalizeUiText (COMBINED_ABILITY_NAME_TEXT , key , " " )
1202+ if className ~= nil and className ~= " " and className ~= key then
1203+ local normalized = Normalize (className )
1204+ if normalized ~= " " and not seen [normalized ] then
1205+ seen [normalized ] = true
1206+ table.insert (allClassNames , className )
1207+ end
1208+ end
1209+ end
1210+ end
1211+ end
1212+ table.sort (allClassNames )
1213+ return allClassNames
1214+ end
1215+
1216+ local function FindClassSuggestions (query , limit )
1217+ local suggestions = {}
1218+ local normalizedQuery = Normalize (query )
1219+ if normalizedQuery == " " then
1220+ return suggestions
1221+ end
1222+ local classes = GetAllClassNames ()
1223+ for _ , className in ipairs (classes ) do
1224+ if string.find (Normalize (className ), normalizedQuery , 1 , true ) == 1 then
1225+ table.insert (suggestions , className )
1226+ if # suggestions >= limit then
1227+ return suggestions
1228+ end
1229+ end
1230+ end
1231+ for _ , className in ipairs (classes ) do
1232+ if string.find (Normalize (className ), normalizedQuery , 1 , true ) ~= nil then
1233+ local duplicate = false
1234+ for _ , existing in ipairs (suggestions ) do
1235+ if existing == className then
1236+ duplicate = true
1237+ break
1238+ end
1239+ end
1240+ if not duplicate then
1241+ table.insert (suggestions , className )
1242+ if # suggestions >= limit then
1243+ return suggestions
1244+ end
1245+ end
1246+ end
1247+ end
1248+ return suggestions
1249+ end
1250+
1251+ local function ResolveClassName (input )
1252+ local normalizedInput = Normalize (input )
1253+ if normalizedInput == " " then
1254+ return nil
1255+ end
1256+ for _ , className in ipairs (GetAllClassNames ()) do
1257+ if Normalize (className ) == normalizedInput then
1258+ return className
1259+ end
1260+ end
1261+ local suggestions = FindClassSuggestions (input , 1 )
1262+ return suggestions [1 ] or Trim (input )
1263+ end
1264+
1265+ local function RefreshBannedClassRows ()
1266+ if bannedClassLabel ~= nil then
1267+ bannedClassLabel :SetText (string.format (" Banned classes: %d" , # state .settings .bannedClasses ))
1268+ end
1269+ for index = 1 , # bannedClassRows do
1270+ local rowEntry = bannedClassRows [index ]
1271+ local className = state .settings .bannedClasses [index ]
1272+ if rowEntry ~= nil and rowEntry .label ~= nil and className ~= nil then
1273+ local row = rowEntry .label
1274+ row .entryIndex = index
1275+ row :SetText (className )
1276+ row :Show (true )
1277+ if rowEntry .removeButton ~= nil then
1278+ rowEntry .removeButton .entryIndex = index
1279+ rowEntry .removeButton :Show (true )
1280+ end
1281+ if state .selectedBannedClassIndex == index then
1282+ row .style :SetColor (0.04 , 0.50 , 0.08 , 1 )
1283+ elseif row .style .SetColorByKey ~= nil then
1284+ row .style :SetColorByKey (" default" )
1285+ else
1286+ row .style :SetColor (1 , 1 , 1 , 1 )
1287+ end
1288+ elseif rowEntry ~= nil and rowEntry .label ~= nil then
1289+ local row = rowEntry .label
1290+ row .entryIndex = nil
1291+ row :SetText (" " )
1292+ row :Show (false )
1293+ if rowEntry .removeButton ~= nil then
1294+ rowEntry .removeButton .entryIndex = nil
1295+ rowEntry .removeButton :Show (false )
1296+ end
1297+ end
1298+ end
1299+ if bannedClassRemoveButton ~= nil then
1300+ bannedClassRemoveButton :Show (true )
1301+ end
1302+ end
1303+
11861304local function RefreshClassRows ()
11871305 for index = 1 , VISIBLE_ROWS do
11881306 local row = classRows [index ]
@@ -1238,8 +1356,8 @@ local function CheckClasses()
12381356end
12391357
12401358local function AddBannedClass ()
1241- local className = Trim (bannedClassInput :GetText ())
1242- if className == " " then
1359+ local className = ResolveClassName (bannedClassInput :GetText ())
1360+ if className == nil or className == " " then
12431361 SetStatus (" Enter a class name." )
12441362 return
12451363 end
@@ -1251,12 +1369,47 @@ local function AddBannedClass()
12511369 table.sort (state .settings .bannedClasses )
12521370 SaveSettings ()
12531371 bannedClassInput :Clear ()
1254- if bannedClassLabel ~= nil then
1255- bannedClassLabel :SetText (" Banned: " .. table.concat (state .settings .bannedClasses , " , " ))
1372+ state .selectedBannedClassIndex = nil
1373+ if bannedClassDropdown ~= nil then
1374+ bannedClassDropdown :HidePreview ()
12561375 end
1376+ RefreshBannedClassRows ()
12571377 SetStatus (" Added banned class: " .. className )
12581378end
12591379
1380+ local function RemoveBannedClassAt (index )
1381+ if index == nil or state .settings .bannedClasses [index ] == nil then
1382+ return false
1383+ end
1384+ local removed = state .settings .bannedClasses [index ]
1385+ table.remove (state .settings .bannedClasses , index )
1386+ state .selectedBannedClassIndex = nil
1387+ SaveSettings ()
1388+ bannedClassInput :Clear ()
1389+ RefreshBannedClassRows ()
1390+ SetStatus (" Removed banned class: " .. tostring (removed ))
1391+ return true
1392+ end
1393+
1394+ local function RemoveBannedClass ()
1395+ local index = state .selectedBannedClassIndex
1396+ if index == nil then
1397+ local typedClassName = ResolveClassName (bannedClassInput :GetText ())
1398+ local normalizedTyped = Normalize (typedClassName )
1399+ if normalizedTyped ~= " " then
1400+ for classIndex , className in ipairs (state .settings .bannedClasses ) do
1401+ if Normalize (className ) == normalizedTyped then
1402+ index = classIndex
1403+ break
1404+ end
1405+ end
1406+ end
1407+ end
1408+ if not RemoveBannedClassAt (index ) then
1409+ SetStatus (" Select or type a banned class to remove." )
1410+ end
1411+ end
1412+
12601413local function KickBannedClasses ()
12611414 if # state .bannedPlayers == 0 then
12621415 CheckClasses ()
@@ -1374,6 +1527,86 @@ local function CreateInput(parent, name, x, y, width, guideText)
13741527 return edit
13751528end
13761529
1530+ local function CreateClassDropdown (parent , edit , width )
1531+ local dropdown = parent :CreateChildWidget (" emptywidget" , " raidManagerClassDropdown" , 0 , true )
1532+ dropdown :SetExtent (width , 74 )
1533+ dropdown :AddAnchor (" TOPLEFT" , edit , " BOTTOMLEFT" , 0 , 1 )
1534+ dropdown :Show (false )
1535+
1536+ local bg = dropdown :CreateDrawable (" ui/common/default.dds" , " editbox_df" , " background" )
1537+ if bg == nil then
1538+ bg = parent :CreateColorDrawable (0.78 , 0.73 , 0.58 , 0.16 , " background" )
1539+ end
1540+ bg :AddAnchor (" TOPLEFT" , dropdown , 0 , 0 )
1541+ bg :AddAnchor (" BOTTOMRIGHT" , dropdown , 0 , 0 )
1542+
1543+ dropdown .rows = {}
1544+ for i = 1 , 3 do
1545+ local row = dropdown :CreateChildWidget (" label" , " raidManagerClassDropdownRow" .. i , i , true )
1546+ row :SetExtent (width - 10 , 22 )
1547+ row :AddAnchor (" TOPLEFT" , dropdown , 5 , 3 + ((i - 1 ) * 23 ))
1548+ StyleLabel (row , 12 , ALIGN_LEFT )
1549+
1550+ local rowBg = row :CreateDrawable (" ui/common/default.dds" , " editbox_df" , " background" )
1551+ if rowBg == nil then
1552+ rowBg = row :CreateColorDrawable (0.78 , 0.73 , 0.58 , 0.16 , " background" )
1553+ end
1554+ rowBg :AddAnchor (" TOPLEFT" , row , 0 , 0 )
1555+ rowBg :AddAnchor (" BOTTOMRIGHT" , row , 0 , 0 )
1556+ rowBg :SetVisible (false )
1557+ row .rowBg = rowBg
1558+
1559+ row :SetHandler (" OnClick" , function (self )
1560+ if self .className == nil then
1561+ return
1562+ end
1563+ bannedClassInput :SetText (self .className )
1564+ dropdown :HidePreview ()
1565+ end )
1566+ row :SetHandler (" OnEnter" , function (self )
1567+ self .rowBg :SetVisible (true )
1568+ end )
1569+ row :SetHandler (" OnLeave" , function (self )
1570+ self .rowBg :SetVisible (false )
1571+ end )
1572+
1573+ dropdown .rows [i ] = row
1574+ end
1575+
1576+ function dropdown :HidePreview ()
1577+ self :Show (false )
1578+ for _ , row in ipairs (self .rows ) do
1579+ row .className = nil
1580+ row :SetText (" " )
1581+ row :Show (false )
1582+ end
1583+ end
1584+
1585+ function dropdown :Update (query )
1586+ local suggestions = FindClassSuggestions (query , 3 )
1587+ for i = 1 , 3 do
1588+ local row = self .rows [i ]
1589+ local className = suggestions [i ]
1590+ if className ~= nil then
1591+ row .className = className
1592+ row :SetText (className )
1593+ row :Show (true )
1594+ else
1595+ row .className = nil
1596+ row :SetText (" " )
1597+ row :Show (false )
1598+ end
1599+ end
1600+ if # suggestions > 0 and self .Raise ~= nil then
1601+ self :Raise ()
1602+ end
1603+ self :Show (# suggestions > 0 )
1604+ end
1605+
1606+ dropdown :HidePreview ()
1607+ return dropdown
1608+ end
1609+
13771610local function ShowSection (section )
13781611 state .activeSection = section
13791612 for id , widget in pairs (sectionWidgets ) do
@@ -1390,6 +1623,7 @@ local function ShowSection(section)
13901623 sectionTitle :SetText (section )
13911624 end
13921625 if section == " classes" then
1626+ RefreshBannedClassRows ()
13931627 RefreshClassRows ()
13941628 end
13951629end
@@ -1615,21 +1849,57 @@ local function CreateClassesSection(parent)
16151849 CreateFlatButton (panel , " raidManagerClassesCheck" , " Check Classes" , 18 , 18 , 112 , CheckClasses )
16161850 CreateFlatButton (panel , " raidManagerClassesKick" , " Kick Banned Classes" , 140 , 18 , 150 , KickBannedClasses )
16171851 bannedClassInput = CreateInput (panel , " raidManagerBannedClassInput" , 18 , 58 , 180 , " Class name" )
1852+ bannedClassDropdown = CreateClassDropdown (panel , bannedClassInput , 180 )
1853+ bannedClassInput :SetHandler (" OnTextChanged" , function ()
1854+ if bannedClassDropdown ~= nil then
1855+ bannedClassDropdown :Update (bannedClassInput :GetText ())
1856+ end
1857+ end )
16181858 CreateFlatButton (panel , " raidManagerBannedClassAdd" , " Ban Class" , 208 , 58 , 84 , AddBannedClass )
1859+ bannedClassRemoveButton =
1860+ CreateFlatButton (panel , " raidManagerBannedClassRemove" , " Remove Class" , 302 , 58 , 104 , RemoveBannedClass )
16191861
16201862 bannedClassLabel = panel :CreateChildWidget (" label" , " raidManagerBannedClassesLabel" , 0 , true )
1621- bannedClassLabel :SetExtent (450 , 40 )
1863+ bannedClassLabel :SetExtent (180 , 20 )
16221864 bannedClassLabel :AddAnchor (" TOPLEFT" , panel , 18 , 92 )
1623- bannedClassLabel :SetText (" Banned: " .. table.concat (state .settings .bannedClasses , " , " ))
16241865 StyleLabel (bannedClassLabel , 12 , ALIGN_LEFT )
16251866
1867+ for rowIndex = 1 , 5 do
1868+ local rowNumber = rowIndex
1869+ local row = panel :CreateChildWidget (" label" , " raidManagerBannedClassRow" .. rowIndex , rowIndex , true )
1870+ row :SetExtent (180 , ROW_HEIGHT )
1871+ row :AddAnchor (" TOPLEFT" , panel , 18 , 116 + ((rowIndex - 1 ) * ROW_HEIGHT ))
1872+ StyleLabel (row , 12 , ALIGN_LEFT )
1873+ row :SetHandler (" OnClick" , function (self )
1874+ state .selectedBannedClassIndex = self .entryIndex
1875+ RefreshBannedClassRows ()
1876+ end )
1877+ local removeButton = CreateFlatButton (
1878+ panel ,
1879+ " raidManagerBannedClassMinus" .. rowIndex ,
1880+ " -" ,
1881+ 208 ,
1882+ 115 + ((rowIndex - 1 ) * ROW_HEIGHT ),
1883+ 24 ,
1884+ function ()
1885+ RemoveBannedClassAt (rowNumber )
1886+ end
1887+ )
1888+ removeButton :Show (false )
1889+ bannedClassRows [rowIndex ] = {
1890+ label = row ,
1891+ removeButton = removeButton ,
1892+ }
1893+ end
1894+
16261895 for rowIndex = 1 , VISIBLE_ROWS do
16271896 local row = panel :CreateChildWidget (" label" , " raidManagerClassRow" .. rowIndex , rowIndex , true )
16281897 row :SetExtent (420 , ROW_HEIGHT )
1629- row :AddAnchor (" TOPLEFT" , panel , 18 , 138 + ((rowIndex - 1 ) * ROW_HEIGHT ))
1898+ row :AddAnchor (" TOPLEFT" , panel , 18 , 236 + ((rowIndex - 1 ) * ROW_HEIGHT ))
16301899 StyleLabel (row , 12 , ALIGN_LEFT )
16311900 classRows [rowIndex ] = row
16321901 end
1902+ RefreshBannedClassRows ()
16331903 RefreshClassRows ()
16341904end
16351905
0 commit comments