/branches
SGI_Locale = {} |
local function defaultFunc(L,key) |
return key |
end |
local English = setmetatable({}, {__index=defaultFunc}) |
English["English Locale loaded"] = "English Locale loaded" |
English["Enable whispers"] = "Enable whispers" |
English["Level limits"] = nil |
English["Invite Mode"] = nil |
English["Whisper only"] = nil |
English["Invite and whisper"] = nil |
English["Invite only"] = nil |
English["Mute SGI"] = nil |
English["Filter 55-58 Death Knights"] = nil |
English["Do a more thorough search"] = nil |
English["Customize whisper"] = nil |
English["SuperScan"] = nil |
English["Invite: %d"] = nil |
English["Choose Invites"] = nil |
English["Exceptions"] = nil |
English["Help"] = nil |
English["The level you wish to start dividing the search by race"] = nil |
English["Racefilter Start:"] = nil |
English["The level you wish to divide the search by class"] = nil |
English["Classfilter Start:"] = nil |
English["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = nil |
English["Interval:"] = nil |
English["SuperGuildInvite Custom Whisper"] = nil |
English["WhisperInstructions"] = "Create a customized whisper to send people you invite! If you enter the words (must be caps) |cff00ff00NAME|r, |cff0000ffLEVEL|r or |cffff0000PLAYER|r these will be replaced by your Guildname, Guildlevel and the recieving players name" |
English["Enter your whisper"] = nil |
English["Save"] = nil |
English["Cancel"] = nil |
English["less than 1 second"] = nil |
English[" hours "] = nil |
English[" minutes "] = nil |
English[" seconds"] = nil |
English[" remaining"] = nil |
English["Purge Queue"] = nil |
English["Click to toggle SuperScan"] = nil |
English["Click on the players you wish to invite"] = nil |
English["Scan Completed"] = nil |
English["Who sent: "] = nil |
English["SuperScan was started"] = nil |
English["SuperScan was stopped"] = nil |
English["PlayersScanned"] = "Players Scanned: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)" |
English["PlayersGuildLess"] = "Guildless Players: |cff44FF44%d|r (|cff44FF44%d%%|r)" |
English["InvitesQueued"] = "Invites Queued: |cff44FF44%d|r" |
English["ExceptionsInstructions"] = "You can add exception phrases that when found in a name will cause the player to be ignore by SuperGuildInvite. You can add several exceptions at once, seperated by a comma (,)." |
English["SGI Exceptions"] = nil |
English["Enter exceptions"] = nil |
English["Go to Options and select your Invite Mode"] = nil |
English["You need to specify the mode in which you wish to invite"] = nil |
English["Unable to invite %s. They are already in a guild."] = nil |
English["Unable to invite %s. They will not be blacklisted."] = nil |
--Trouble shooter-- |
English["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r" |
English["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r" |
English["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r" |
English["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r" |
English["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r" |
English["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r" |
English["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r" |
English["Enabled whispers"] = nil |
English['Changed invite mode to "Invite and Whisper"'] = nil |
English["Mute has been turned off"] = nil |
English['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = nil |
English["Shaman"] = nil |
English["Death Knight"] = nil |
English["Mage"] = nil |
English["Priest"] = nil |
English["Rogue"] = nil |
English["Paladin"] = nil |
English["Warlock"] = nil |
English["Druid"] = nil |
English["Warrior"] = nil |
English["Hunter"] = nil |
English["Monk"] = nil |
English["Human"] = nil |
English["Gnome"] = nil |
English["Dwarf"] = nil |
English["NightElf"] = nil |
English["Draenei"] = nil |
English["Worgen"] = nil |
English["Pandaren"] = nil |
English["Undead"] = nil |
English["Orc"] = nil |
English["Troll"] = nil |
English["Tauren"] = nil |
English["BloodElf"] = nil |
English["Goblin"] = nil |
English["Author"] = "|cff00A2FF Written by Janniie - Stormreaver EU.|r" |
German = setmetatable({}, {__index=defaultFunc}) |
German["English Locale loaded"] = "German Locale loaded" |
German["Enable whispers"] = "aktivieren Sie flüstert" |
German["Level limits"] = "Levelbeschränkungen" |
German["Invite Mode"] = "Einladungsart" |
German["Whisper only"] = "Nur anflüstern" |
German["Invite and whisper"] = "Einladen und anflüstern" |
German["Invite only"] = "Nur einladen" |
German["Mute SGI"] = "SGI stummschalten" |
German["Filter 55-58 Death Knights"] = "Level 55-58 Todesritter filtern" |
German["Do a more thorough search"] = "Gründlichere Suche ausführen" |
German["Customize whisper"] = "Flüsternachricht anpassen" |
German["SuperScan"] = "SuperScan" |
German["Invite: %d"] = "Einladen: %d" |
German["Choose Invites"] = "einladungen auswählen" |
German["Exceptions"] = "Ausnahmen" |
German["Help"] = "Hilfe" |
German["SuperGuildInvite Custom Whisper"] = "SuperGuildInvite eigene Flüsternachricht" |
German["WhisperInstructions"] = "Erstelle eine eigene Flüsternachricht, die an die Leute gesendet wird, die du einlädst! Wenn du die worte |cff00ff00NAME|r, |cff0000ffLEVEL|r oder |cffff0000PLAYER|r (in GroÃbuchstaben) benutzt werden diese durch Gildenname, Gildenlevel und den Namen des Empfängers ersetzt." |
German["Enter your whisper"] = "Flüsternachricht eingeben" |
German["Save"] = "Speichern" |
German["Cancel"] = "Abbrechen" |
German["less than 1 second"] = "weniger als 1 Sekunden verbleibend" |
German[" hours "] = " Stunden " |
German[" minutes "] = " minute " |
German[" seconds"] = " Sekunden" |
German[" remaining"] = " verbleibend" |
German["Purge Queue"] = "Warteschlange leeren" |
German["Click to toggle SuperScan"] = "Klicken um SuperScan zu beenden" |
German["Click on the players you wish to invite"] = "Klicke die Spieler an, die du einladen willst" |
German["Scan Completed"] = "Suchlauf beendet" |
German["Who sent: "] = "Wer-Abfrage gesendet: " |
German["SuperScan was started"] = "SuperScan wurde gestartet" |
German["SuperScan was stopped"] = "SuperScan wurde gestoppt" |
German["PlayersScanned"] = "Spieler durchsucht: |cff44FF44%d|r (Insgesamt: |cff44FF44%d|r)" |
German["PlayersGuildLess"] = "gildenlose Spieler: |cff44FF44%d|r" |
German["InvitesQueued"] = "Einladungen in Warteschlange: |cff44FF44%d|r" |
German["ExceptionsInstructions"] = "Hier kannst du Ausnahmen eingeben, die, wenn sie in einem Namen gefunden werden, dazu führen daà SGI diesen Spieler ignoriert. Du kannst mehrere Ausnahmen durch ein Komma (,) getrennt eingeben." |
German["SGI Exceptions"] = "SGI Ausnahmen" |
German["Go to Options and select your Invite Mode"] = "Gehen Sie auf Optionen und wählen Sie Einladungsart" |
German["You need to specify the mode in which you wish to invite"] = "Sie müssen den Modus, in dem Sie einladen möchten festlegen" |
German["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = "Anzahl der Level nach denen etwa alle 7 Sekunden gesucht wird (höhere Zahlen erhöhen das Risiko, daà nicht alle Suchergebnisse bearbeitet werden)." |
German["The level you wish to divide the search by class"] = "Level ab dem nach Klasse gesucht wird." |
German["The level you wish to divide the search by race"] = "Level ab dem nach Rasse gesucht wird." |
German["not sending"] = "|cffff8800Warum verschicke ich keine Flüsternachrichten?|r |cff00A2FFMöglicherweise hast du das Kästchen nicht angekreuzt.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r" |
German["to specify"] = "|cffff8800Ich bekomme eine Nachricht, daà ich die Einladungsart auswählen soll wenn ich jemanden einladen möchte.|r|cff00A2FF Das passiert wenn du nicht das Auswahlmenü in den Optionen benutzt hast um auszuwählen wie du Leute einlädst.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r" |
German["I checked the box"] = "|cffff8800Ich verschicke keine Flüsternachrichten beim Einladen, obwohl ich das Kästchen angekreuzt habe.|r|cff00A2FF Das passiert wenn du nur einladen im Auswahlmenü ausgewählt hast.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r" |
German["whisper to everyone"] = "|cffff8800Ich verschicke Flüsternachrichten an jeden den ich einlade ODER ich möchte nur Flüsternachrichten senden aber das AddOn macht beides!|r|cff00A2FF Das passiert weil du einladen und anflüstern im Auswahlmenü ausgewählt hast.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r" |
German["can't get SGI to invite"] = "|cffff8800SGI lädt keine Leute ein und schickt ausschlieÃlich Flüsternachrichten.|r|cff00A2FF DU hast nur diese Option im Auswahlmenü ausgewählt.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r" |
German["can't see any messages"] = "|cffff8800Ich sehe keinerlei Ausgabe von SGI.|r|cff00A2FF Du hast SGI in den Optionen stummgeschaltet.|r|cff00ff00 Klicke auf diese Nachricht um das Problem zu beheben.|r" |
German["None of the above"] = "|cffff8800Keine der obenstehenden Lösungen löst mein Problem!|r|cff00A2FF Es könnte ein Problem mit der Lokalisation (Sprache) geben, die du benutzt. Du kannst versuchen mit /sgi locale:deDE die deutschen Sprachoptionen zu laden (frFR für Französisch). Bitte schick mir eine Nachricht an:|r|cff00ff00 SuperGuildInvite@gmail.com|r" |
German["Enabled whispers"] = "Flüsternachrichten eingeschaltet" |
German['Changed invite mode to "Invite and Whisper"'] = "Einladungsart auf einladen und anflüstern geändert" |
German["Mute has been turned off"] = "Stummschaltung wurde ausgeschaltet" |
German['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = "Einladungsmodus auf nur einladen geändert. Wenn du nur anflüstern wolltest, gehe in die Optionen und ändere es dort." |
German["Enter exceptions"] = "Ausnahmen eingeben" |
German["Highest and lowest level to search for"] = "Höchster und niedrigster Level nach dem gesucht wird" |
German["Shaman"] = "Schamane" |
German["Death Knight"] = "Todesritter" |
German["Mage"] = "Magier" |
German["Priest"] = "Priester" |
German["Rogue"] = "Schurke" |
German["Paladin"] = "Paladin" |
German["Warlock"] = "Hexenmeister" |
German["Druid"] = "Druide" |
German["Warrior"] = "Krieger" |
German["Hunter"] = "Jäger" |
German["Monk"] = "Mönch" |
German["Human"] = "Mensch" |
German["Gnome"] = "Gnom" |
German["Dwarf"] = "Zwerg" |
German["NightElf"] = "Nachtelf" |
German["Draenei"] = "Draenei" |
German["Worgen"] = "Worgen" |
German["Pandaren"] = "Pandaren" |
German["Undead"] = "Untoter" |
German["Orc"] = "Ork" |
German["Troll"] = "Troll" |
German["Tauren"] = "Taure" |
German["BloodElf"] = "Blutelf" |
German["Goblin"] = "Goblin" |
German["Author"] = "|cff00A2FF Translated by Nephthis - Durotan (EU).|r" |
local French = setmetatable({}, {__index=defaultFunc}) |
French["English Locale loaded"] = "French Locale loaded" |
French["Enable whispers"] = "Activer les chuchotements" |
French["Level limits"] = "Limites de niveau" |
French["Invite Mode"] = "Mode d'invitation" |
French["Whisper only"] = "Message seulement" |
French["Invite and whisper"] = "Invitation et message" |
French["Invite only"] = "Invitation seulement" |
French["Mute SGI"] = "Mute SGI" |
French["Filter 55-58 Death Knights"] = "Filtrer les Chevaliers de la mort 55-58" |
French["Do a more thorough search"] = "Faire une recherche plus minutieuse" |
French["Customize whisper"] = "Personnaliser le message" |
French["SuperScan"] = "SuperScan" |
French["Invite: %d"] = "Inviter: %d" |
French["Choose Invites"] = "Choisir les invitations" |
French["Exceptions"] = "Exceptions" |
French["Help"] = "Aide" |
French["SuperGuildInvite Custom Whisper"] = "SuperGuildInvite message personnalisé" |
French["WhisperInstructions"] = "Créé un message personnalisé à envoyer aux personne que vous invitez ! Si vous entrez les mots (doivent être en majuscule) |cff00ff00NAME|r, |cff0000ffLEVEL|r ou |cffff0000PLAYER|r ils seront remplacés par le NomDeLaGuilde, NiveauDeLaGuilde et NomDuJoueurInvité." |
French["Enter your whisper"] = "Entrez votre message" |
French["Save"] = "Sauvegarder" |
French["Cancel"] = "Annuler" |
French["less than 1 second"] = "moins d'1 seconde" |
French[" hours "] = " heures " |
French[" minutes "] = " minutes " |
French[" seconds"] = " secondes " |
French[" remaining"] = " restante(s)" |
French["Purge Queue"] = "Vider la liste" |
French["Click to toggle SuperScan"] = "Cliquez pour afficher SuperScan" |
French["Click on the players you wish to invite"] = "Cliquez sur les joueurs que vous souhaitez inviter" |
French["Scan Completed"] = "Scan terminé" |
French["Who sent: "] = "Qui envoyé: " |
French["SuperScan was started"] = "SuperScan démarré" |
French["SuperScan was stopped"] = "SuperScan arrêté" |
French["PlayersScanned"] = "Joueurs scannés: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)" |
French["PlayersGuildLess"] = "Joueurs sans guilde: |cff44FF44%d|r (|cff44FF44%d%%|r)" |
French["InvitesQueued"] = "Invitations listées: |cff44FF44%d|r" |
French["ExceptionsInstructions"] = "Vous pouvez ajouter des exceptions, si le nom d'un joueur correspond à l'une d'elles, SuperGuildInvite l'ignorera. Vous pouvez ajouter plusieurs exceptions à la fois, pour cela séparez les par une virgule (,)." |
French["SGI Exceptions"] = "SGI Exceptions" |
French["Author"] = "|cff00A2FF Translated by Anonymous, you know who you are and thank you :)|r" |
French["Go to Options and select your Invite Mode"] = "Allez dans Options et sélectionnez votre Mode d'invitation." |
French["You need to specify the mode in which you wish to invite"] = "Vous devez spécifier le mode dans lequel vous souhaitez inviter." |
French["not sending"] = "|cffff8800Pourquoi je n'envoie aucun message ?|r |cff00A2FFPeut-être parce que vous n'avez pas coché l'option.|r|cff00ff00 Cliquez sur ce message pour corriger.|r" |
French["to specify"] = "|cffff8800J'ai un message m'indiquant que je dois spécifier le mode d'invitation quand j'essaye d'inviter !|r|cff00A2FF Ceci arrive quand vous n'avez pas utilisé le menu déroulant dans les options pour choisir votre mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r" |
French["I checked the box"] = "|cffff8800Je n'envoie aucun message lorsque j'invite alors que j'ai coché la case !|r|cff00A2FF C'est parce que vous avez choisi \"Invitation seulement\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r" |
French["whisper to everyone"] = "|cffff8800Je continue d'envoyer des invitations, or je veux seulement envoyer un message et ne pas inviter !|r|cff00A2FF C'est parce que vous avez choisi \"Invitation et message\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r" |
French["can't get SGI to invite"] = "|cffff8800SGI n'invite personne, il envoie seulement des message.|r|cff00A2FF C'est parce que vous avez choisi \"Message seulement\" comme mode d'invitation.|r|cff00ff00 Cliquez pour corriger.|r" |
French["can't see any messages"] = "|cffff8800Je ne vois plus aucun message de SGI !|r|cff00A2FF C'est parce que vous avez muté SGI dans les options.|r|cff00ff00 Cliquez pour corriger.|r" |
French["None of the above"] = "|cffff8800Aucune des solutions n'a corrigé mon problème !|r|cff00A2FF Il peut y avoir une erreur avec le langage que vous utilisez. Vous pouvez essayer de charger votre langue manuellement : /sgi locale:frFR charge la langue française (deDE pour allemande). Merci de me contacter à :|r|cff00ff00 SuperGuildInvite@gmail.com|r" |
French["Enabled whispers"] = "Cuchotements activés." |
French['Changed invite mode to "Invite and Whisper"'] = 'Mode d\'invitation changé en "Invitation et message".' |
French["Mute has been turned off"] = 'Mute désactivé.' |
French['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = 'Mode d\'invitation changé en "Inviter seulement". Si vous voulez envoyer un "Message seulement" choisissez-le dans les options.' |
French["Enter exceptions"] = 'Entrez les exceptions' |
French["Shaman"] = "Chaman" |
French["Death Knight"] = "Chevalier de la mort" |
French["Mage"] = "Mage" |
French["Priest"] = "Prêtre" |
French["Rogue"] = "Voleur" |
French["Paladin"] = "Paladin" |
French["Warlock"] = "Démoniste" |
French["Druid"] = "Druide" |
French["Warrior"] = "Guerrier" |
French["Hunter"] = "Chasseur" |
French["Monk"] = "Moine" |
French["Human"] = "Humain" |
French["Gnome"] = "Gnome" |
French["Dwarf"] = "Nain" |
French["NightElf"] = "Elfe de la nuit" |
French["Draenei"] = "Draeneï" |
French["Worgen"] = "Worgen" |
French["Pandaren"] = "Pandaren" |
French["Undead"] = "Mort-vivant" |
French["Orc"] = "Orc" |
French["Troll"] = "Troll" |
French["Tauren"] = "Tauren" |
French["BloodElf"] = "Elfe de sang" |
French["Goblin"] = "Gobelin" |
local Spanish = setmetatable({}, {__index=defaultFunc}) |
Spanish["English Locale loaded"] = "Spanish Locale loaded" |
Spanish["Enable whispers"] = nil |
Spanish["Level limits"] = nil |
Spanish["Invite Mode"] = nil |
Spanish["Whisper only"] = nil |
Spanish["Invite and whisper"] = nil |
Spanish["Invite only"] = nil |
Spanish["Mute SGI"] = nil |
Spanish["Filter 55-58 Death Knights"] = nil |
Spanish["Do a more thorough search"] = nil |
Spanish["Customize whisper"] = nil |
Spanish["SuperScan"] = nil |
Spanish["Invite: %d"] = nil |
Spanish["Choose Invites"] = nil |
Spanish["Exceptions"] = nil |
Spanish["Help"] = nil |
Spanish["SuperGuildInvite Custom Whisper"] = nil |
Spanish["WhisperInstructions"] = nil |
Spanish["Enter your whisper"] = nil |
Spanish["Save"] = nil |
Spanish["Cancel"] = nil |
Spanish["less than 1 second"] = nil |
Spanish[" hours "] = nil |
Spanish[" minutes "] = nil |
Spanish[" seconds"] = nil |
Spanish[" remaining"] = nil |
Spanish["Purge Queue"] = nil |
Spanish["Click to toggle SuperScan"] = nil |
Spanish["Click on the players you wish to invite"] = nil |
Spanish["Scan Completed"] = nil |
Spanish["Who sent: "] = nil |
Spanish["SuperScan was started"] = nil |
Spanish["SuperScan was stopped"] = nil |
Spanish["PlayersScanned"] = nil |
Spanish["PlayersGuildLess"] = nil |
Spanish["InvitesQueued"] = nil |
Spanish["ExceptionsInstructions"] = nil |
Spanish["SGI Exceptions"] = nil |
Spanish["Author"] = nil |
Spanish["Go to Options and select your Invite Mode"] = nil |
Spanish["You need to specify the mode in which you wish to invite"] = nil |
Spanish["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r" |
Spanish["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r" |
Spanish["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r" |
Spanish["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r" |
Spanish["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r" |
Spanish["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r" |
Spanish["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r" |
Spanish["Enabled whispers"] = nil |
Spanish['Changed invite mode to "Invite and Whisper"'] = nil |
Spanish["Mute has been turned off"] = nil |
Spanish['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = nil |
Spanish["Enter exceptions"] = nil |
Spanish["Shaman"] = nil |
Spanish["Death Knight"] = nil |
Spanish["Mage"] = nil |
Spanish["Priest"] = nil |
Spanish["Rogue"] = nil |
Spanish["Paladin"] = nil |
Spanish["Warlock"] = nil |
Spanish["Druid"] = nil |
Spanish["Warrior"] = nil |
Spanish["Hunter"] = nil |
Spanish["Monk"] = nil |
Spanish["Human"] = nil |
Spanish["Gnome"] = nil |
Spanish["Dwarf"] = nil |
Spanish["NightElf"] = nil |
Spanish["Draenei"] = nil |
Spanish["Worgen"] = nil |
Spanish["Pandaren"] = nil |
Spanish["Undead"] = nil |
Spanish["Orc"] = nil |
Spanish["Troll"] = nil |
Spanish["Tauren"] = nil |
Spanish["BloodElf"] = nil |
Spanish["Goblin"] = nil |
local Russian = setmetatable({}, {__index=defaultFunc}) |
Russian["Russian Locale loaded"] = "Russian Locale loaded" |
Russian["Enable whispers"] = "РазÑеÑиÑÑ ÑообÑениÑ" |
Russian["Level limits"] = "ÐÐ¸Ð¼Ð¸Ñ ÑÑовней" |
Russian["Invite Mode"] = "Режим пÑиглаÑениÑ" |
Russian["Whisper only"] = "ТолÑко ÑообÑение" |
Russian["Invite and whisper"] = "ÐÑиглаÑение и ÑообÑение" |
Russian["Invite only"] = "ТолÑко пÑиглаÑение" |
Russian["Mute SGI"] = "ÐÑÑ SGI" |
Russian["Filter 55-58 Death Knights"] = "ФилÑÑÑоваÑÑ Ð ÑÑаÑей СмеÑÑи 55-58 ÑÑовнÑ" |
Russian["Do a more thorough search"] = "ÐлÑбокий поиÑк" |
Russian["Customize whisper"] = "ÐаÑÑÑоиÑÑ Ð¡Ð¾Ð¾Ð±Ñение" |
Russian["SuperScan"] = "СÑпеÑСканиÑование" |
Russian["Invite: %d"] = "ÐÑиглаÑиÑÑ: %d" |
Russian["Choose Invites"] = "ÐÑбÑаÑÑ ÐÑиглаÑениÑ" |
Russian["Exceptions"] = "ÐÑклÑÑениÑ" |
Russian["Help"] = "ÐомоÑÑ" |
Russian["The level you wish to start dividing the search by race"] = "УÑовенÑ, Ñ ÐºÐ¾ÑоÑого вклÑÑаеÑÑÑ ÑаÑÑовÑй ÑилÑÑÑ" |
Russian["Racefilter Start:"] = "РаÑÑовÑй ФилÑÑÑ" |
Russian["The level you wish to divide the search by class"] = "УÑовенÑ, Ñ ÐºÐ¾ÑоÑого вклÑÑаеÑÑÑ ÐºÐ»Ð°ÑÑовÑй ÑилÑÑÑ" |
Russian["Classfilter Start:"] = "ÐлаÑÑовÑй ФилÑÑÑ" |
Russian["Amount of levels to search every ~7 seconds (higher numbers increase the risk of capping the search results)"] = "ÐнÑеÑвал ÑÑовней Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка каждÑе ~7 ÑекÑнд (болÑÑий инÑеÑвал пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ðº ÑиÑÐºÑ Ð´Ð¾ÑÑигнÑÑÑ Ð»Ð¸Ð¼Ð¸Ñа поиÑка в 49 Ñеловек)" |
Russian["Interval:"] = "ÐнÑеÑвал" |
Russian["SuperGuildInvite Custom Whisper"] = "ÑообÑение по ÑмолÑÐ°Ð½Ð¸Ñ SGI" |
Russian["WhisperInstructions"] = "Create a customized whisper to send people you invite! If you enter the words (must be caps) |cff00ff00NAME|r, |cff0000ffLEVEL|r or |cffff0000PLAYER|r these will be replaced by your Guildname, Guildlevel and the recieving players name" |
Russian["Enter your whisper"] = "ÐведиÑе Ñвое ÑообÑение" |
Russian["Save"] = "Ð¡Ð¾Ñ ÑаниÑÑ" |
Russian["Cancel"] = "ÐÑмена" |
Russian["less than 1 second"] = "Ðенее 1 ÑекÑндÑ" |
Russian[" hours "] = " ЧаÑов " |
Russian[" minutes "] = " ÐинÑÑ " |
Russian[" seconds"] = " СекÑнд " |
Russian[" remaining"] = "оÑÑалоÑÑ" |
Russian["Purge Queue"] = "ÐÑиÑÑиÑÑ ÐÑеÑедÑ" |
Russian["Click to toggle SuperScan"] = "ÐажмиÑе ÑÑÐ¾Ð±Ñ Ð¿ÐµÑеклÑÑиÑÑ Ð¡ÑпеÑСкан" |
Russian["Click on the players you wish to invite"] = "ÐажмиÑе на игÑоков коÑоÑÑÑ Ñ Ð¾ÑиÑе пÑиглаÑиÑÑ" |
Russian["Scan Completed"] = "СканиÑование завеÑÑено" |
Russian["Who sent: "] = "ÐÑо оÑпÑавлено: " |
Russian["SuperScan was started"] = "СÑпеÑСканиÑование наÑалоÑÑ" |
Russian["SuperScan was stopped"] = "СÑпеÑÑканиÑование оÑÑановлено" |
Russian["PlayersScanned"] = "Players Scanned: |cff44FF44%d|r |cffffff00(Total: |r|cff44FF44%d|r)" |
Russian["PlayersGuildLess"] = "Guildless Players: |cff44FF44%d|r (|cff44FF44%d%%|r)" |
Russian["InvitesQueued"] = "Invites Queued: |cff44FF44%d|r" |
Russian["ExceptionsInstructions"] = "You can add exception phrases that when found in a name will cause the player to be ignore by SuperGuildInvite. You can add several exceptions at once, seperated by a comma (,)." |
Russian["SGI Exceptions"] = "ÐÑклÑÑÐµÐ½Ð¸Ñ SGI" |
Russian["Enter exceptions"] = "ÐвеÑÑи иÑклÑÑениÑ" |
Russian["Go to Options and select your Invite Mode"] = "ÐÑкÑойÑе наÑÑÑойки и вÑбеÑиÑе Ñежим пÑиглаÑениÑ" |
Russian["You need to specify the mode in which you wish to invite"] = "ÐÑ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²ÑбÑаÑÑ Ñежим пÑиглаÑениÑ" |
Russian["Unable to invite %s. They are already in a guild."] = "Ðевозможно пÑиÑлаÑиÑÑ %s. Ðн Ñже в гилÑдии" |
Russian["Unable to invite %s. They will not be blacklisted."] = "Ðевозможно пÑиÑлаÑиÑÑ %s. Ðн не бÑÐ´ÐµÑ Ð·Ð°Ð½ÐµÑен в ÑеÑнÑй ÑпиÑок" |
--Trouble shooter-- |
Russian["not sending"] = "|cffff8800Why am I not sending any whispers?|r |cff00A2FFPossibly because you have not checked the checkbox.|r|cff00ff00 Click on this message to fix.|r" |
Russian["to specify"] = "|cffff8800I am getting a message telling me to specify my invite mode when I try to invite!|r|cff00A2FF This happens when you have not used the dropdown menu in the options to pick how to invite people.|r|cff00ff00 Click to fix.|r" |
Russian["I checked the box"] = "|cffff8800I am not sending any whispers when I invite and I checked the box!|r|cff00A2FF This is because you have selected only to invite with the dropdown menu in the options.|r|cff00ff00 Click to fix|r" |
Russian["whisper to everyone"] = "|cffff8800I keep sending a whisper to everyone I invite, OR I just want to send whispers and not invite, but your AddOn does both!|r|cff00A2FF This is because you specified to both invite and whisper on the dropdown menu in options.|r|cff00ff00 Click to fix|r" |
Russian["can't get SGI to invite"] = "|cffff8800I can't get SGI to invite people, all it does is sending whispers.|r|cff00A2FF This is because you picked that option in the dropdown menu.|r|cff00ff00 Click to fix|r" |
Russian["can't see any messages"] = "|cffff8800I can't see any messages from SGI at all!|r|cff00A2FF This is because you have muted SGI in the options.|r|cff00ff00 Click to fix|r" |
Russian["None of the above"] = "|cffff8800None of the above solved my problem!|r|cff00A2FF There might be an issue with the localization (language) you are using. You can try to load your locale manually: /sgi locale:deDE loads German (frFR for french). Please contact me at:|r|cff00ff00 SuperGuildInvite@gmail.com|r" |
Russian["Enabled whispers"] = "РазÑеÑиÑÑ ÑообÑениÑ" |
Russian['Changed invite mode to "Invite and Whisper"'] = "Режим пÑиглаÑÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½ на 'пÑиглаÑение и ÑообÑение'" |
Russian["Mute has been turned off"] = "ÐÑÑ Ð±Ñл вÑклÑÑен" |
Russian['Changed invite mode to "Only Invite". If you wanted "Only Whisper" go to Options and change.'] = "Режим пÑиглаÑÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½ на 'ÑолÑко' пÑиглаÑиÑÑ. ÐÑли Ð²Ñ Ñ Ð¾ÑиÑе пÑиглаÑаÑÑ Ð»Ñдей, ÑмениÑе Ñежим" |
Russian["Shaman"] = "Шаман" |
Russian["Death Knight"] = "Ð ÑÑаÑÑ Ð¡Ð¼ÐµÑÑи" |
Russian["Mage"] = "Ðаг" |
Russian["Priest"] = "ÐÑеÑ" |
Russian["Rogue"] = "Разбойник" |
Russian["Paladin"] = "Ðаладин" |
Russian["Warlock"] = "ЧеÑнокнижник" |
Russian["Druid"] = "ÐÑÑид" |
Russian["Warrior"] = "Ðоин" |
Russian["Hunter"] = "ÐÑ Ð¾Ñник" |
Russian["Monk"] = "ÐÐ¾Ð½Ð°Ñ " |
Russian["Human"] = "Человек" |
Russian["Gnome"] = "Ðном" |
Russian["Dwarf"] = "ÐвоÑÑ" |
Russian["NightElf"] = "ÐоÑной ÐлÑÑ" |
Russian["Draenei"] = "ÐÑеней" |
Russian["Worgen"] = "ÐоÑген" |
Russian["Pandaren"] = "ÐандаÑен" |
Russian["Undead"] = "ÐежиÑÑ" |
Russian["Orc"] = "ÐÑк" |
Russian["Troll"] = "ТÑоллÑ" |
Russian["Tauren"] = "ТаÑÑен" |
Russian["BloodElf"] = "ÐлÑÑ ÐÑови" |
Russian["Goblin"] = "Ðоблин" |
Russian["Author"] = "|cff00A2FF ÐеÑеведено игÑоком ÐовоÑкин - ÐоÑдÑнни.|r" |
SGI_Locale["enGB"] = English |
SGI_Locale["enUS"] = English |
SGI_Locale["deDE"] = German |
SGI_Locale["frFR"] = French |
--SGI_Locale["ruRU"] = Russian Can't be added because of client issues. |
--SGI_Locale["esES"] = Spanish |
--SGI_Locale["esMX"] = Spanish |
## Interface: 70300 |
## Author: Janniie - Stormreaver EU |
## Updated by: Arimang - Zul'jin US |
## Title: Super Guild Invite 2 |
## Notes: Version 7.5.7 |
## Version: 7.5.7 |
## SavedVariables: SGI_DATA |
## SavedVariablesPerCharacter: SGI_BACKUP |
libs\GuildShield\GuildShield.lua |
libs\ChatIntercept\ChatIntercept.lua |
libs\Alerts\Alerts.lua |
libs\LibWho-2.0\libs\LibStub\LibStub.lua |
libs\LibWho-2.0\libs\CallbackHandler-1.0\CallbackHandler-1.0.lua |
libs\LibWho-2.0\LibWho-2.0\LibWho-2.0.lua |
locale\localization.lua |
core\SGI_Constants.lua |
core\SGI_Core.lua |
core\SGI_Blacklist.lua |
core\SGI_AddOn_Message.lua |
core\SGI_Filter.lua |
core\SuperScan.lua |
core\SGI_System_Message.lua |
core\SGI_Events.lua |
core\SGI_GUI.lua |
SGI = {}; |
-- General |
SGI.LOGO = "|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r "; |
SLASH_SUPERGUILDINVITE1 = "/sgi"; |
SLASH_SUPERGUILDINVITE2 = "/superguildinvite"; |
SGI_DATA_INDEX = UnitName("player").." - "..GetRealmName() or "?"; |
SGI.VERSION_ALERT_COOLDOWN = false; |
SGI_MAX_LEVEL_SUPER_SCAN = 110; |
SGI_BREAK_POINT_SUPER_SCAN = 90; |
SGI_MIN_LEVEL_SUPER_SCAN = 1; |
-- Version realted |
SGI.VERSION_MAJOR = "7.5"; |
SGI.VERSION_MINOR = ".7"; |
SGI.versionChanges = { |
version = "Version |cff55EE55"..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.."|r", |
items = { |
"Updated for 7.3, please let me know what doesn't work..", |
}, |
} |
SGI.CommonIssues = { |
"Please post bug reports on WoWInterface and I'll fix them.", |
"Test2", |
"Test3", |
} |
local function defaultFunc(L,key) |
return "857C7C" |
end |
SGI_CLASS_COLORS = { |
["DEATHKNIGHT"] = "C41F3B", |
["DEMONHUNTER"] = "A330C9", |
["DRUID"] = "FF7D0A", |
["HUNTER"] = "ABD473", |
["MAGE"] = "69CCF0", |
["MONK"] = "00FF96", |
["PALADIN"] = "F58CBA", |
["PRIEST"] = "FFFFFF", |
["ROGUE"] = "FFF569", |
["SHAMAN"] = "0070DE", |
["WARLOCK"] = "9482C9", |
["WARRIOR"] = "C79C6E", |
} |
SGI_CLASS_COLORS = setmetatable(SGI_CLASS_COLORS, {__index=defaultFunc}) |
local debugMode = false; |
local old = print |
function SGI:print(...) |
if (SGI_DATA_INDEX == "?" or type(SGI_DATA) ~= "table") then return end |
if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"]) then |
old("|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r|cffffff00",...,"|r") |
end |
end |
function SGI:debug(...) |
if (debugMode) then |
old("|cffffff00<|r|cff16ABB5SGI|r|cffffff00>|r|cffff3300",...,"|r") |
end |
end |
function SGI:DebugState(state) |
debugMode = state; |
end |
SGI:debug("Loading SGI files:"); |
SGI:debug(">> Constants.lua"); |
function SGI:FormatTime(T) |
local R,S,M,H = "" |
T = floor(T) |
H = floor(T/3600) |
M = floor((T-3600*H)/60) |
S = T-(3600*H + 60*M) |
if T <= 0 then |
return L["less than 1 second"] |
end |
if H ~= 0 then |
R = R..H..L[" hours "] |
end |
if M ~= 0 then |
R = R..M..L[" minutes "] |
end |
if S ~= 0 then |
R = R..S..L[" seconds"] |
end |
return R |
end |
function SGI:CountTable(T) |
local i = 0 |
if type(T) ~= "table" then |
return i |
end |
for k,_ in pairs(T) do |
i = i + 1 |
end |
return i |
end |
--[[ |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
function SGI. |
]] |
SGI.superScan = {}; |
SGI.libWho = {}; |
CreateFrame("Frame", "SGI_SUPER_SCAN"); |
CreateFrame("Frame", "SGI_ANTI_SPAM_FRAME"); |
CreateFrame("Frame", "SGI_WHISPER_QUEUE_FRAME"); |
LibStub:GetLibrary("LibWho-2.0"):Embed(SGI.libWho); |
local start-- = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit; |
local stop-- = SGI_DATA[SGI_DATA_INDEX].settings.highLimit; |
local race-- = SGI_DATA[SGI_DATA_INDEX].settings.raceStart; |
local class-- = SGI_DATA[SGI_DATA_INDEX].settings.classStart; |
local interval-- = SGI_DATA[SGI_DATA_INDEX].settings.interval; |
-- Fix for WhoLib bug |
local oldFlags; |
local superScanIntervalTime = 8; |
local superScanLast = 0; |
local superScanProgress = 1; |
local whoQueryList; |
local whoSent = false; |
local whoMaster = false; |
local scanInProgress = false; |
local shouldHideFriendsFrame = false; |
local SGI_QUEUE = {}; |
local SGI_ANTI_SPAM = {}; |
local SGI_TEMP_BAN = {}; |
local whisperWaiting = {}; |
local whisperQueue = {}; |
local sessionTotal = 0; |
local amountScanned = 0; |
local amountGuildless = 0; |
local amountQueued = 0; |
local superScanLap = 1; |
local raceClassCombos = { |
["Alliance"] = { |
["Human"] = { |
"Paladin", |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Warrior", |
"Warlock", |
"Death Knight", |
"Monk", |
}, |
["Draenei"] = { |
"Hunter", |
"Mage", |
"Paladin", |
"Priest", |
"Shaman", |
"Death Knight", |
"Warrior", |
"Monk", |
}, |
["Gnome"] = { |
"Mage", |
"Priest", |
"Rogue", |
"Warlock", |
"Warrior", |
"Death Knight", |
"Monk", |
}, |
["Dwarf"] = { |
"Hunter", |
"Mage", |
"Paladin", |
"Priest", |
"Rogue", |
"Shaman", |
"Warlock", |
"Warrior", |
"Death Knight", |
"Monk", |
}, |
["Night Elf"] = { |
"Druid", |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Warrior", |
"Death Knight", |
"Demon Hunter", |
"Monk", |
}, |
["Worgen"] = { |
"Druid", |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Warlock", |
"Warrior", |
"Death Knight", |
}, |
["Pandaren"] = { |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Shaman", |
"Warrior", |
"Monk", |
}, |
}, |
["Horde"] = { |
["Blood Elf"] = { |
"Paladin", |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Warlock", |
"Warrior", |
"Death Knight", |
"Demon Hunter", |
"Monk", |
}, |
["Orc"] = { |
"Hunter", |
"Mage", |
"Rogue", |
"Shaman", |
"Warlock", |
"Warrior", |
"Death Knight", |
"Monk", |
}, |
["Goblin"] = { |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Shaman", |
"Warlock", |
"Warrior", |
"Death Knight", |
}, |
["Tauren"] = { |
"Druid", |
"Hunter", |
"Paladin", |
"Priest", |
"Shaman", |
"Warrior", |
"Death Knight", |
"Monk", |
}, |
["Troll"] = { |
"Druid", |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Shaman", |
"Warlock", |
"Warrior", |
"Death Knight", |
"Monk", |
}, |
["Undead"] = { |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Warlock", |
"Warrior", |
"Death Knight", |
"Monk", |
}, |
["Pandaren"] = { |
"Hunter", |
"Mage", |
"Priest", |
"Rogue", |
"Shaman", |
"Warrior", |
"Monk", |
}, |
}, |
} |
local GetTime = GetTime; |
local strfind = strfind; |
local strsub = strsub; |
local tonumber = tonumber; |
local L = SGI.L; |
function SGI:PickRandomWhisper() |
local i = 0 |
local tbl = {} |
for k,_ in pairs(SGI_DATA[SGI_DATA_INDEX].settings.whispers) do |
i = i + 1 |
tbl[i] = SGI_DATA[SGI_DATA_INDEX].settings.whispers[k] |
end |
if #tbl == 0 then |
return SGI_DATA[SGI_DATA_INDEX].settings.whisper |
end |
return tbl[random(#tbl)] |
end |
function SGI:FormatWhisper(msg, name) |
local whisper = msg |
if not msg then SGI:print("You have not set your whispers!") msg = "<NO WHISPER SET>" whisper = "<NO WHISPER SET>" end |
if not name then name = "ExampleName" end |
local guildName,guildLevel = GetGuildInfo(UnitName("Player"))--,GetGuildLevel() |
if not guildName then guildName = "<InvalidName>" end |
if not guildLevel then guildLevel = "<InvalidLevel>" end |
if strfind(msg,"PLAYER") then |
whisper = strsub(msg,1,strfind(msg,"PLAYER")-1)..name..strsub(msg,strfind(msg,"PLAYER")+6) |
end |
if strfind(whisper,"NAME") then |
whisper = strsub(whisper,1,strfind(whisper,"NAME")-1)..guildName..strsub(whisper,strfind(whisper,"NAME")+4) |
end |
if strfind(whisper,"LEVEL") then |
whisper = strsub(whisper,1,strfind(whisper,"LEVEL")-1)..guildLevel..strsub(whisper,strfind(whisper,"LEVEL")+5) |
end |
return whisper |
end |
local function QueueInvite(name,level,classFile,race,class,found) |
SGI_QUEUE[name] = { |
level = level, |
class = class, |
classFile = classFile, |
race = race, |
found = found, |
} |
GuildShield:IsShielded(name) |
end |
local function PutOnHold(name,level,classFile,race,class,found) |
SGI_ANTI_SPAM[name] = { |
level = level, |
class = class, |
classFile = classFile, |
race = race, |
found = found, |
} |
GuildShield:IsShielded(name) |
end |
SGI_ANTI_SPAM_FRAME.t = 0; |
SGI_ANTI_SPAM_FRAME:SetScript("OnUpdate", function() |
if (SGI_ANTI_SPAM_FRAME.t < GetTime()) then |
for k,_ in pairs(SGI_ANTI_SPAM) do |
if (SGI_ANTI_SPAM[k].found + 4 < GetTime()) then |
SGI_QUEUE[k] = SGI_ANTI_SPAM[k]; |
SGI_ANTI_SPAM[k] = nil; |
amountQueued = amountQueued + 1; |
end |
end |
SGI_ANTI_SPAM_FRAME.t = GetTime() + 0.5; |
end |
end) |
SGI_WHISPER_QUEUE_FRAME.t = 0; |
SGI_WHISPER_QUEUE_FRAME:SetScript("OnUpdate", function() |
if (SGI_WHISPER_QUEUE_FRAME.t < GetTime()) then |
for k,_ in pairs(whisperQueue) do |
if (whisperQueue[k].t < GetTime()) then |
ChatIntercept:InterceptNextWhisper(); |
SendChatMessage(whisperQueue[k].msg, "WHISPER", nil, k); |
whisperQueue[k] = nil; |
end |
end |
SGI_WHISPER_QUEUE_FRAME.t = GetTime() + 0.5; |
end |
end) |
local function ValidateName(player) |
--Check: |
-- Lock |
-- filter |
-- guild list |
if (SGI_DATA.lock[player.name]) then |
return false; |
end |
if (SGI_DATA.guildList[GetRealmName()][player.name]) then |
return false; |
end |
if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ENABLE_FILTERS"] and not SGI:FilterPlayer(player)) then |
return false; |
end |
return true; |
end |
local function TrimRealmName(name) |
if (type(name) ~= "string") then SGI:debug("TrimRealmName: No name!") return end |
local myRealm = GetRealmName(); |
if (type(myRealm) ~= "string") then SGI:debug("TrimRealmName: No realmName!") return end |
if (strfind(name, myRealm)) then |
if (strfind(name, "-")) then |
local n = strsub(name,1,strfind(name,"-")-1); |
return n; |
end |
end |
return name; |
end |
local function WhoResultCallback(query, results, complete) |
if (whoSent) then |
whoSent = false; |
SGI:debug("...got reply"); |
flags = oldFlags; |
superScanProgress = superScanProgress + 1; |
local ETR = (#whoQueryList - superScanProgress + 1) * superScanIntervalTime; |
if (SuperScanFrame) then |
SuperScanFrame.ETR = ETR; |
SuperScanFrame.lastETR = GetTime(); |
end |
local numResults = 0; |
for _, result in pairs(results) do |
amountScanned = amountScanned + 1; |
numResults = numResults + 1; |
result.Name = TrimRealmName(result.Name); |
SGI:BroadcastVersion(result.Name) |
if (result.Guild == "") then |
local player = { |
name = result.Name, |
level = result.Level, |
race = result.Race, |
class = result.NoLocaleClass, |
} |
amountGuildless = amountGuildless + 1; |
if (ValidateName(player)) then |
PutOnHold(result.Name, result.Level, result.NoLocaleClass, result.Race, result.Class, GetTime()); |
end |
end |
end |
SGI:debug("Scan result: "..numResults); |
end |
end |
local function SuperScan() |
if (GetTime() > superScanLast + superScanIntervalTime) then |
if (superScanProgress == (#whoQueryList + 1)) then |
superScanProgress = 1; |
superScanLast = GetTime(); |
amountGuildless = 0; |
sessionTotal = sessionTotal + amountScanned; |
amountScanned = 0; |
else |
oldFlags = flags; |
flags = nil; |
--SendWho(tostring(whoQueryList[superScanProgress])) |
SGI.libWho:Who(tostring(whoQueryList[superScanProgress]),{queue = SGI.libWho.WHOLIB_QUERY_QUIET, callback = WhoResultCallback}); |
whoSent = true; |
superScanLast = GetTime(); |
SGI:debug("Sent query: "..whoQueryList[superScanProgress].."..."); |
end |
end |
end |
local function CreateSuperScanQuery(start, stop, interval, class, race) |
if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then |
interval = 5; |
class = 999; |
race = 999; |
end |
local SGI_BREAK_POINT_SUPER_SCAN = 90; |
whoQueryList = {}; |
local current = start; |
local Classes = { |
SGI.L["Death Knight"], |
SGI.L["Demon Hunter"], |
SGI.L["Druid"], |
SGI.L["Hunter"], |
SGI.L["Mage"], |
SGI.L["Monk"], |
SGI.L["Paladin"], |
SGI.L["Priest"], |
SGI.L["Rogue"], |
SGI.L["Shaman"], |
SGI.L["Warlock"], |
SGI.L["Warrior"], |
} |
local Races = {} |
if UnitFactionGroup("player") == "Horde" then |
Races = { |
SGI.L["Orc"], |
SGI.L["Blood Elf"], |
SGI.L["Undead"], |
SGI.L["Troll"], |
SGI.L["Goblin"], |
SGI.L["Tauren"], |
SGI.L["Pandaren"], |
} |
else |
Races = { |
SGI.L["Human"], |
SGI.L["Dwarf"], |
SGI.L["Worgen"], |
SGI.L["Draenei"], |
SGI.L["Night Elf"], |
SGI.L["Gnome"], |
SGI.L["Pandaren"], |
} |
end |
if (start < SGI_BREAK_POINT_SUPER_SCAN) then |
while (current + interval < ( (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN)) do |
if (current + interval >= race and current + interval >= class) then |
for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do |
for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do |
tinsert(whoQueryList, current.."- -"..(current + interval - 1).." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]); |
end |
end |
elseif (current + interval >= race) then |
for k, _ in pairs(Races) do |
tinsert(whoQueryList, current.."- -"..(current + interval - 1).." r-"..Races[k]); |
end |
elseif (current + interval >= class) then |
for k, _ in pairs(Classes) do |
tinsert(whoQueryList, current.."- -"..(current + interval - 1).." c-"..Classes[k]); |
end |
else |
tinsert(whoQueryList, current.."- -"..(current + interval - 1)); |
end |
current = current + interval; |
end |
if ( current < ( (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN ) ) then |
local t_stop = (SGI_BREAK_POINT_SUPER_SCAN > stop) and stop or SGI_BREAK_POINT_SUPER_SCAN; |
if (t_stop >= race and t_stop >= class) then |
for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do |
for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do |
tinsert(whoQueryList, current.."- -"..(t_stop).." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]); |
end |
end |
elseif (t_stop >= race) then |
for k, _ in pairs(Races) do |
tinsert(whoQueryList, current.."- -"..(t_stop).." r-"..Races[k]); |
end |
elseif (t_stop >= class) then |
for k, _ in pairs(Classes) do |
tinsert(whoQueryList, current.."- -"..(t_stop).." c-"..Classes[k]); |
end |
else |
tinsert(whoQueryList, current.."- -"..(t_stop)); |
end |
current = t_stop + 1; |
end |
end |
if (stop < current) then return end; |
while (current <= stop) do |
if (current >= race and current >= class) then |
for k,_ in pairs(raceClassCombos[UnitFactionGroup("player")]) do |
for j,_ in pairs(raceClassCombos[UnitFactionGroup("player")][k]) do |
tinsert(whoQueryList, current.." r-"..SGI.L[k].." c-"..SGI.L[raceClassCombos[UnitFactionGroup("player")][k][j]]); |
end |
end |
elseif (current >= race) then |
for k,_ in pairs(Races) do |
tinsert(whoQueryList, current.." r-"..Races[k]); |
end |
elseif (current >= class) then |
for k,_ in pairs(Classes) do |
tinsert(whoQueryList, current.." c-"..Classes[k]); |
end |
else |
tinsert(whoQueryList, current); |
end |
current = current + 1; |
end |
end |
local function CanResume() |
local s = SGI_DATA[SGI_DATA_INDEX].settings; |
return (start == s.lowLimit and stop == s.highLimit and race == s.raceStart and class == s.classStart and interval == s.interval); |
end |
local function ResetSuperScan() |
start = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit; |
stop = SGI_DATA[SGI_DATA_INDEX].settings.highLimit; |
race = SGI_DATA[SGI_DATA_INDEX].settings.raceStart; |
class = SGI_DATA[SGI_DATA_INDEX].settings.classStart; |
interval = SGI_DATA[SGI_DATA_INDEX].settings.interval; |
amountGuildless = 0; |
sessionTotal = sessionTotal + amountScanned; |
amountScanned = 0; |
superScanProgress = 1; |
CreateSuperScanQuery(start, stop, interval, class, race); |
end |
function SGI:StartSuperScan() |
if (not CanResume()) then |
ResetSuperScan(); |
end |
if (SuperScanFrame) then |
SuperScanFrame.lastETR = GetTime(); |
end |
scanInProgress = true; |
SGI_SUPER_SCAN:SetScript("OnUpdate", SuperScan); |
end |
function SGI:StopSuperScan() |
scanInProgress = false; |
SGI_SUPER_SCAN:SetScript("OnUpdate", nil); |
SGI:debug(FriendsFrame:IsShown()); |
--FriendsMicroButton:Click(); |
--FriendsFrameCloseButton:Click(); |
end |
function SGI:RemoveQueued(name) |
SGI:LockPlayer(name); |
SGI_QUEUE[name] = nil; |
SGI_ANTI_SPAM[name] = nil; |
local nameTrim = TrimRealmName(name); |
SGI_ANTI_SPAM[nameTrim] = nil |
SGI_QUEUE[nameTrim] = nil; |
SGI:debug("RemoveQueued(name) removed "..nameTrim); |
end |
function SGI:UnregisterForWhisper(name) |
whisperWaiting[name] = nil; |
whisperQueue[name] = nil; |
end |
function SGI:SendWhisper(message, name, delay) |
whisperQueue[name] = {msg = message, t = delay + GetTime()}; |
whisperWaiting[name] = nil; |
end |
function SGI:RegisterForWhisper(name) |
whisperWaiting[name] = true; |
end |
function SGI:IsRegisteredForWhisper(name) |
return whisperWaiting[name]; |
end |
function SGI:SendGuildInvite(button) |
local name = self.player |
if not name then name = next(SGI_QUEUE) button = "LeftButton" end |
if not name then return end |
if (SGI:IsLocked(name)) then |
SGI:RemoveQueued(name); |
return; |
end |
if (UnitIsInMyGuild(name)) then |
SGI:LockPlayer(name); |
SGI:RemoveQueued(name); |
return; |
end |
if (button == "LeftButton") then |
if (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 1) then |
GuildInvite(name); |
SGI:LockPlayer(name); |
--SGI:print("Only Invite: "..name); |
elseif (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 2) then |
GuildInvite(name); |
SGI:RegisterForWhisper(name); |
SGI:LockPlayer(name); |
--SGI:print("Invite, then whisper: "..name); |
elseif (SGI_DATA[SGI_DATA_INDEX].settings.dropDown["DROPDOWN_INVITE_MODE"] == 3) then |
SGI:SendWhisper(SGI:FormatWhisper(SGI:PickRandomWhisper(), name), name, 4); |
SGI:LockPlayer(name); |
--SGI:print("Only whisper: "..name); |
else |
SGI:print(SGI.L["You need to specify the mode in which you wish to invite"]) |
SGI:print(SGI.L["Go to Options and select your Invite Mode"]) |
end |
GuildShield:IsShielded(name); |
SGI:LiveSync(name) |
end |
SGI:RemoveQueued(name); |
end |
function SGI:RemoveShielded(player) |
SGI:debug(player); |
if (not player) then SGI:debug("Error: No player name provided!") return end |
local playerTrim = TrimRealmName(player); |
SGI_ANTI_SPAM[playerTrim] = nil |
SGI_QUEUE[playerTrim] = nil; |
SGI:LockPlayer(playerTrim); |
SGI_ANTI_SPAM[player] = nil |
SGI_QUEUE[player] = nil; |
SGI:LockPlayer(player); |
SGI:print("|cffffff00Removed |r|cff00A2FF"..player.."|r|cffffff00 because they are shielded.|r") |
end |
function SGI:GetNumQueued() |
return SGI:CountTable(SGI_QUEUE); |
end |
function SGI:PurgeQueue() |
SGI_QUEUE = {}; |
SGI_ANTI_SPAM = {}; |
end |
function SGI:GetSuperScanETR() |
if (whoQueryList) then |
return SGI:FormatTime((#whoQueryList - superScanProgress + 1) * superScanIntervalTime); |
else |
return 0; |
end |
end |
function SGI:GetSuperScanProgress() |
return floor((superScanProgress - 1) / #whoQueryList); |
end |
function SGI:GetTotalScanTime() |
return ((#whoQueryList - 1) * superScanIntervalTime); |
end |
function SGI:IsScanning() |
return scanInProgress; |
end |
function SGI:GetInviteQueue() |
return SGI_QUEUE; |
end |
function SGI:GetSuperScanStats() |
return amountScanned, amountGuildless, amountQueued, sessionTotal; |
end |
SGI:debug(">> SuperScan.lua"); |
CreateFrame("Frame","SGI_EVENT_HANDLER"); |
SGI_EVENTS = {}; |
function SGI_EVENTS:PLAYER_LOGIN() |
-- Index used to separate settings for different characters. |
SGI_DATA_INDEX = UnitName("player").." - "..GetRealmName(); |
-- Make sure the saved variables are correct. |
--General settings: |
if (type(SGI_DATA) ~= "table") then |
SGI_DATA = {}; |
end |
-- Fix transition from 6.x to 7.x |
SGI:ResetFix() |
if (type(SGI_DATA.lock) ~= "table") then |
SGI_DATA.lock = {}; |
end |
if (type(SGI_DATA.guildList) ~= "table") then |
SGI_DATA.guildList = {} |
end |
if (type(SGI_DATA.guildList[GetRealmName()]) ~= "table") then |
SGI_DATA.guildList[GetRealmName()] = {}; |
end |
--Character based settings. |
if type(SGI_DATA[SGI_DATA_INDEX]) ~= "table" then |
SGI_DATA[SGI_DATA_INDEX] = {} |
end |
if type(SGI_DATA[SGI_DATA_INDEX].settings) ~= "table" then |
SGI_DATA[SGI_DATA_INDEX].settings = { |
inviteMode = 1, |
lowLimit = SGI_MIN_LEVEL_SUPER_SCAN, |
highLimit = SGI_MAX_LEVEL_SUPER_SCAN, |
raceStart = SGI_MAX_LEVEL_SUPER_SCAN, |
classStart = SGI_MAX_LEVEL_SUPER_SCAN, |
interval = 5, |
checkBox = {}, |
dropDown = {}, |
frames = {}, |
filters = {}, |
} |
end |
if type(SGI_DATA[SGI_DATA_INDEX].settings.whispers) ~= "table" then |
SGI_DATA[SGI_DATA_INDEX].settings.whispers = {} |
end |
if type(SGI_BACKUP) ~= "table" then |
SGI_BACKUP = SGI_DATA.lock |
end |
-- If there is a saved keybind, activate it. |
if (SGI_DATA[SGI_DATA_INDEX].keyBind) then |
SetBindingClick(SGI_DATA[SGI_DATA_INDEX].keyBind,"SGI_INVITE_BUTTON"); |
end |
-- Anti spam. Users of the AddOn GuildShield are ignored. |
GuildShield:Initiate(SGI.RemoveShielded); |
-- Load locale |
SGI:LoadLocale(); |
-- Load the minimap button |
if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_MINIMAP"]) then |
SGI:ShowMinimapButton(); |
end |
-- Activate the keybind, if any. |
if (SGI_DATA[SGI_DATA_INDEX].keyBind) then |
SetBindingClick(SGI_DATA[SGI_DATA_INDEX].keyBind, "SGI_INVITE_BUTTON2"); |
end |
--Debugging, used for development |
SGI:DebugState(SGI_DATA[SGI_DATA_INDEX].debug); |
--Tell guildies what version you're running |
SGI:BroadcastVersion("GUILD"); |
--Request lock sync from guildies |
SGI:RequestSync(); |
--Remove locks that are > 2 months old |
SGI:RemoveOutdatedLocks(); |
--Chat Intercept |
ChatIntercept:StateSystem(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_SYSTEM"]); |
ChatIntercept:StateWhisper(SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_WHISPER"]); |
ChatIntercept:StateRealm(true); |
--Show changes, if needed |
--SGI:debug((SGI_DATA[SGI_DATA_INDEX].settings.checkBox["SGI_CHANGES"] and "true" or "nil").." "..(SGI_DATA.showChanges and "true" or "nil")); |
if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["SGI_CHANGES"] and SGI_DATA.showChanges ~= SGI.VERSION_MAJOR) then |
SGI:ShowChanges(); |
SGI_DATA.showChanges = SGI.VERSION_MAJOR; |
SGI:debug("Show changes"); |
end |
--Need to load the SuperScan frame for certain functions |
SGI:CreateSmallSuperScanFrame(); |
SuperScanFrame:Hide(); |
end |
function SGI_EVENTS:UPDATE_MOUSEOVER_UNIT() |
-- Create a list of players and their guild (if any). |
-- Used to prevent false positives. |
if (UnitIsPlayer("mouseover")) then |
local name = UnitName("mouseover"); |
local guild = GetGuildInfo("mouseover"); |
local realm = GetRealmName(); |
if (not guild or guild == "") then return end |
if (type(SGI_DATA.guildList[realm][guild]) ~= "table") then |
SGI_DATA.guildList[realm][guild] = {}; |
end |
for k,v in pairs(SGI_DATA.guildList[realm][guild]) do |
if (v == name) then |
return; |
end |
end |
tinsert(SGI_DATA.guildList[realm][guild], name); |
--SGI_DATA.guildList[realm][name] = guild; |
end |
end |
function SGI_EVENTS:PLAYER_LOGOUT() |
SendAddonMessage("SGI_STOP", "", "GUILD"); |
end |
function SGI_EVENTS:CHAT_MSG_ADDON(event, ...) |
SGI:AddonMessage(event, ...); |
end |
function SGI_EVENTS:CHAT_MSG_SYSTEM(event, ...) |
SGI:SystemMessage(event,message,...) |
end |
for event,_ in pairs(SGI_EVENTS) do |
SGI_EVENT_HANDLER:RegisterEvent(event); |
end |
SGI_EVENT_HANDLER:SetScript("OnEvent", function(self,event,...) |
SGI_EVENTS[event](self, event, ...); |
end) |
SGI:debug(">> Events.lua"); |
local function onClickTester(self) |
if self then |
SGI:print("Click on "..self:GetName()); |
end |
end |
local function CreateButton(name, parent, width, height, label, anchor, onClick) |
local f = CreateFrame("Button", name, parent, "UIPanelButtonTemplate"); |
f:SetWidth(width); |
f:SetHeight(height); |
f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall"); |
f.label:SetText(label); |
f.label:SetPoint("CENTER"); |
f:SetWidth(width - 10); |
if (type(anchor) == "table") then |
f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs); |
end |
f:SetScript("OnClick", onClick); |
return f; |
end |
local function CreateCheckbox(name, parent, label, anchor) |
local f = CreateFrame("CheckButton", name, parent, "OptionsBaseCheckButtonTemplate"); |
f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
f.label:SetText(label); |
f.label:SetPoint("LEFT", f, "RIGHT", 5, 1); |
if (type(anchor) == "table") then |
f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs); |
end |
f:HookScript("OnClick", function(self) |
SGI_DATA[SGI_DATA_INDEX].settings.checkBox[name] = self:GetChecked() |
end) |
if SGI_DATA[SGI_DATA_INDEX].settings.checkBox[name] then |
f:SetChecked() |
end |
return f; |
end |
local function CreateDropDown(name, parent, label, items, anchor) |
local f = CreateFrame("Button", name, parent, "UIDropDownMenuTemplate"); |
f:ClearAllPoints(); |
f:SetPoint(anchor.point,parent,anchor.relativePoint,anchor.xOfs,anchor.yOfs) |
f:Show() |
f.label = f:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
f.label:SetPoint("BOTTOMLEFT", f, "TOPLEFT", 20, 5); |
f.label:SetText(label); |
local function OnClick(self) |
UIDropDownMenu_SetSelectedID(f, self:GetID()); |
SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] = self:GetID(); |
end |
local function initialize(self, level) |
local info = UIDropDownMenu_CreateInfo(); |
for k,v in pairs(items) do |
info = UIDropDownMenu_CreateInfo(); |
info.text = v; |
info.value = v; |
info.func = OnClick; |
UIDropDownMenu_AddButton(info, level); |
end |
end |
UIDropDownMenu_Initialize(f, initialize) |
UIDropDownMenu_SetWidth(f, 100); |
UIDropDownMenu_SetButtonWidth(f, 124) |
SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] = SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] or 1 |
UIDropDownMenu_SetSelectedID(f, SGI_DATA[SGI_DATA_INDEX].settings.dropDown[name] or 1) |
UIDropDownMenu_JustifyText(f, "LEFT") |
return f |
end |
local function SetFramePosition(frame) |
if (type(SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()]) ~= "table") then |
if (frame:GetName() == "SGI_MiniMapButton") then |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = "CENTER", relativePoint = "CENTER", xOfs = -71, yOfs = -31}; |
else |
frame:SetPoint("CENTER"); |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = "CENTER", relativePoint = "CENTER", xOfs = 0, yOfs = 0}; |
return; |
end |
end |
if (frame:GetName() == "SGI_MiniMapButton") then |
frame:SetPoint( |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].point, |
Minimap, |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].relativePoint, |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].xOfs, |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].yOfs |
); |
else |
frame:SetPoint( |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].point, |
UIParent, |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].relativePoint, |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].xOfs, |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()].yOfs |
); |
end |
end |
local function SaveFramePosition(frame) |
if (type(SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()]) ~= "table") then |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {}; |
end |
local point, parent, relativePoint, xOfs, yOfs = frame:GetPoint(); |
SGI_DATA[SGI_DATA_INDEX].settings.frames[frame:GetName()] = {point = point, relativePoint = relativePoint, xOfs = xOfs, yOfs = yOfs}; |
end |
local function CreateInviteListFrame() |
CreateFrame("Frame","SGI_Invites") |
local SGI_QUEUE = SGI:GetInviteQueue(); |
SGI_Invites:SetWidth(370) |
SGI_Invites:SetHeight(20*SGI:CountTable(SGI_QUEUE) + 40) |
SGI_Invites:SetMovable(true) |
SetFramePosition(SGI_Invites) |
SGI_Invites:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SGI_Invites:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(SGI_Invites) |
end) |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SGI_Invites:SetBackdrop(backdrop) |
SGI_Invites.text = SGI_Invites:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Invites.text:SetPoint("TOP",SGI_Invites,"TOP",-15,-15) |
SGI_Invites.text:SetText(SGI.L["Click on the players you wish to invite"]) |
SGI_Invites.tooltip = CreateFrame("Frame","InviteTime",SGI_Invites,"GameTooltipTemplate") |
SGI_Invites.tooltip.text = SGI_Invites.tooltip:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Invites.tooltip:SetPoint("TOP",SGI_Invites,"BOTTOM",0,-2) |
SGI_Invites.tooltip.text:SetText("Unknown") |
SGI_Invites.tooltip.text:SetPoint("CENTER") |
local close = CreateFrame("Button",nil,SGI_Invites,"UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",SGI_Invites,"TOPRIGHT",-4,-4) |
SGI_Invites.items = {} |
local update = 0 |
local toolUpdate = 0 |
SGI_Invites:SetScript("OnUpdate",function() |
if (not SGI_Invites:IsShown() or GetTime() < update) then return end |
SGI_QUEUE = SGI:GetInviteQueue(); |
for k,_ in pairs(SGI_Invites.items) do |
SGI_Invites.items[k]:Hide() |
end |
local i = 0 |
local x,y = 10,-30 |
for i = 1,30 do |
if not SGI_Invites.items[i] then |
SGI_Invites.items[i] = CreateFrame("Button","InviteBar"..i,SGI_Invites) |
SGI_Invites.items[i]:SetWidth(350) |
SGI_Invites.items[i]:SetHeight(20) |
SGI_Invites.items[i]:EnableMouse(true) |
SGI_Invites.items[i]:SetPoint("TOP",SGI_Invites,"TOP",0,y) |
SGI_Invites.items[i].text = SGI_Invites.items[i]:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Invites.items[i].text:SetPoint("LEFT",SGI_Invites.items[i],"LEFT",3,0) |
SGI_Invites.items[i].text:SetJustifyH("LEFT") |
SGI_Invites.items[i].text:SetWidth(SGI_Invites.items[i]:GetWidth()-10); |
SGI_Invites.items[i].player = "unknown" |
SGI_Invites.items[i]:RegisterForClicks("LeftButtonDown","RightButtonDown") |
SGI_Invites.items[i]:SetScript("OnClick",SGI.SendGuildInvite) |
SGI_Invites.items[i].highlight = SGI_Invites.items[i]:CreateTexture() |
SGI_Invites.items[i].highlight:SetAllPoints() |
SGI_Invites.items[i].highlight:SetTexture(1,1,0,0.2) |
SGI_Invites.items[i].highlight:Hide() |
SGI_Invites.items[i]:SetScript("OnEnter",function() |
SGI_Invites.items[i].highlight:Show() |
SGI_Invites.tooltip:Show() |
SGI_Invites.items[i]:SetScript("OnUpdate",function() |
if GetTime() > toolUpdate and SGI_QUEUE[SGI_Invites.items[i].player] then |
SGI_Invites.tooltip.text:SetText("Found |cff"..SGI:GetClassColor(SGI_QUEUE[SGI_Invites.items[i].player].classFile)..SGI_Invites.items[i].player.."|r "..SGI:FormatTime(floor(GetTime()-SGI_QUEUE[SGI_Invites.items[i].player].found)).." ago") |
local h,w = SGI_Invites.tooltip.text:GetHeight(),SGI_Invites.tooltip.text:GetWidth() |
SGI_Invites.tooltip:SetWidth(w+20) |
SGI_Invites.tooltip:SetHeight(h+20) |
toolUpdate = GetTime() + 0.1 |
end |
end) |
end) |
SGI_Invites.items[i]:SetScript("OnLeave",function() |
SGI_Invites.items[i].highlight:Hide() |
SGI_Invites.tooltip:Hide() |
SGI_Invites.items[i]:SetScript("OnUpdate",nil) |
end) |
end |
y = y - 20 |
end |
i = 0 |
for k,_ in pairs(SGI_QUEUE) do |
i = i + 1 |
local level,classFile,race,class,found = SGI_QUEUE[k].level, SGI_QUEUE[k].classFile, SGI_QUEUE[k].race, SGI_QUEUE[k].class, SGI_QUEUE[k].found |
local Text = i..". |cff"..SGI:GetClassColor(classFile)..k.."|r Lvl "..level.." "..race.." |cff"..SGI:GetClassColor(classFile)..class.."|r" |
SGI_Invites.items[i].text:SetText(Text) |
SGI_Invites.items[i].player = k |
SGI_Invites.items[i]:Show() |
if i >= 30 then break end |
end |
SGI_Invites:SetHeight(i * 20 + 40) |
update = GetTime() + 0.5 |
end) |
end |
function SGI:ShowInviteList() |
if (not SGI_Invites) then |
CreateInviteListFrame(); |
end |
SGI_Invites:Show(); |
end |
function SGI:HideInviteList() |
if (SGI_Invites) then |
SGI_Invites:Hide(); |
end |
end |
local function SSBtn3_OnClick(self) |
if (SGI:IsScanning()) then |
SGI:StopSuperScan(); |
self:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up"); |
else |
SGI:StartSuperScan(); |
self:SetNormalTexture("Interface\\TimeManager\\PauseButton"); |
end |
end |
function SGI:CreateSmallSuperScanFrame() |
CreateFrame("Frame", "SuperScanFrame"); |
SuperScanFrame:SetWidth(130); |
SuperScanFrame:SetHeight(30); |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SetFramePosition(SuperScanFrame) |
SuperScanFrame:SetMovable(true) |
SuperScanFrame:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SuperScanFrame:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(self) |
end) |
SuperScanFrame:SetBackdrop(backdrop) |
local close = CreateFrame("Button",nil,SuperScanFrame,"UIPanelCloseButton") |
close:SetPoint("LEFT",SuperScanFrame,"RIGHT",-5,0) |
SuperScanFrame.time = SuperScanFrame:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SuperScanFrame.time:SetPoint("CENTER") |
SuperScanFrame.time:SetText(format("|cff00ff00%d%%|r|cffffff00 %s|r",0,SGI:GetSuperScanETR())) |
SuperScanFrame.progressTexture = SuperScanFrame:CreateTexture(); |
SuperScanFrame.progressTexture:SetPoint("LEFT", 5, 0); |
SuperScanFrame.progressTexture:SetHeight(18); |
SuperScanFrame.progressTexture:SetWidth(120); |
SuperScanFrame.progressTexture:SetTexture(1,0.5,0,0.4); |
local anchor = { |
point = "TOPLEFT", |
relativePoint = "BOTTOMLEFT", |
xOfs = 0, |
yOfs = 0, |
} |
SuperScanFrame.button1 = CreateButton("SGI_INVITE_BUTTON2", SuperScanFrame, 70, 30, format("Invite: %d",SGI:GetNumQueued()), anchor, SGI.SendGuildInvite) |
anchor.xOfs = 85; |
SuperScanFrame.button2 = CreateButton("SGI_PURGE_QUEUE", SuperScanFrame, 55, 30, "Purge", anchor, SGI.PurgeQueue); |
anchor.xOfs = 57; |
SuperScanFrame.button2 = CreateButton("SGI_SUPERSCAN_PLAYPAUSE", SuperScanFrame, 40,30,"",anchor,SSBtn3_OnClick); |
SGI_SUPERSCAN_PLAYPAUSE:SetNormalTexture("Interface\\TimeManager\\PauseButton"); |
SuperScanFrame.nextUpdate = 0; |
SuperScanFrame:SetScript("OnUpdate", function() |
if (SuperScanFrame.nextUpdate < GetTime()) then |
SuperScanFrame.button1.label:SetText(format("Invite: %d",SGI:GetNumQueued())); |
if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then |
local remainingTime = SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR); |
local totalScanTime = SGI:GetTotalScanTime(); |
local percentageDone = (totalScanTime - remainingTime) / totalScanTime; |
SuperScanFrame.time:SetText(format("|cff00ff00%d%%|r|cffffff00 %s|r",100*(percentageDone > 1 and 1 or percentageDone),SGI:FormatTime(remainingTime))) |
SuperScanFrame.progressTexture:SetWidth(120 * (percentageDone > 1 and 1 or percentageDone)); |
end |
SuperScanFrame.nextUpdate = GetTime() + 0.2; |
end |
end) |
SuperScanFrame:Hide(); |
-- Interface\Buttons\UI-SpellbookIcon-NextPage-Up |
-- Interface\TimeManager\PauseButton |
end |
function SGI:GetPercentageDone() |
if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then |
local remainingTime = SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR); |
local totalScanTime = SGI:GetTotalScanTime(); |
local percentageDone = (totalScanTime - remainingTime) / totalScanTime; |
return percentageDone * 100; |
end |
return 0; |
end |
function SGI:GetSuperScanTimeLeft() |
if (SGI:IsScanning() and SuperScanFrame.ETR and SuperScanFrame.lastETR) then |
return SGI:FormatTime(SuperScanFrame.ETR - (GetTime() - SuperScanFrame.lastETR)); |
end |
return 0; |
end |
function SGI:ShowSuperScanFrame() |
if (SuperScanFrame and not (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"])) then |
SuperScanFrame:Show(); |
else |
if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"]) then |
SGI:CreateSmallSuperScanFrame(); |
SuperScanFrame:Hide(); |
return; |
else |
SGI:CreateSmallSuperScanFrame(); |
SuperScanFrame:Show(); |
end |
end |
end |
function SGI:HideSuperScanFrame() |
if (SuperScanFrame) then |
SuperScanFrame:Hide(); |
end |
end |
local function CreateWhisperDefineFrame() |
end |
local KeyHarvestFrame = CreateFrame("Frame", "SGI_KeyHarvestFrame"); |
KeyHarvestFrame:SetPoint("CENTER",0,200); |
KeyHarvestFrame:SetWidth(10); |
KeyHarvestFrame:SetHeight(10); |
KeyHarvestFrame.text = KeyHarvestFrame:CreateFontString(nil, "OVERLAY", "MovieSubtitleFont"); |
KeyHarvestFrame.text:SetPoint("CENTER"); |
KeyHarvestFrame.text:SetText("|cff00ff00Press the KEY you wish to bind now!|r"); |
KeyHarvestFrame:Hide(); |
function KeyHarvestFrame:GetNewKeybindKey() |
KeyHarvestFrame:Show(); |
self:SetScript("OnKeyDown", function(self, key) |
if (SetBindingClick(key, "SGI_INVITE_BUTTON2")) then |
Alerter:SendAlert("|cff00ff00Successfully bound "..key.." to InviteButton!|r",1.5); |
SGI:print("Successfully bound "..key.." to InviteButton!"); |
SGI_DATA[SGI_DATA_INDEX].keyBind = key; |
BUTTON_KEYBIND.label:SetText("Set Keybind ("..key..")"); |
else |
Alerter:SendAlert("|cffff0000Error binding "..key.." to InviteButton!|r",1.5); |
SGI:print("Error binding "..key.." to InviteButton!"); |
end |
self:EnableKeyboard(false); |
KeyHarvestFrame:Hide(); |
end) |
self:EnableKeyboard(true); |
end |
local function CreateWhisperDefineFrame() |
CreateFrame("Frame","SGI_Whisper") |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SGI_Whisper:SetWidth(500) |
SGI_Whisper:SetHeight(365) |
SGI_Whisper:SetBackdrop(backdrop) |
SetFramePosition(SGI_Whisper) |
SGI_Whisper:SetMovable(true) |
SGI_Whisper:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SGI_Whisper:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(SGI_Whisper) |
end) |
local close = CreateFrame("Button",nil,SGI_Whisper,"UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",SGI_Whisper,"TOPRIGHT",-4,-4) |
SGI_Whisper.title = SGI_Whisper:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Whisper.title:SetText(SGI.L["SuperGuildInvite Custom Whisper"]) |
SGI_Whisper.title:SetPoint("TOP",SGI_Whisper,"TOP",0,-20) |
SGI_Whisper.info = SGI_Whisper:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Whisper.info:SetPoint("TOPLEFT",SGI_Whisper,"TOPLEFT",33,-55) |
SGI_Whisper.info:SetText(SGI.L["WhisperInstructions"]) |
SGI_Whisper.info:SetWidth(450) |
SGI_Whisper.info:SetJustifyH("LEFT") |
SGI_Whisper.edit = CreateFrame("EditBox",nil,SGI_Whisper) |
SGI_Whisper.edit:SetWidth(450) |
SGI_Whisper.edit:SetHeight(65) |
SGI_Whisper.edit:SetMultiLine(true) |
SGI_Whisper.edit:SetPoint("TOPLEFT",SGI_Whisper,"TOPLEFT",35,-110) |
SGI_Whisper.edit:SetFontObject("GameFontNormal") |
SGI_Whisper.edit:SetTextInsets(10,10,10,10) |
SGI_Whisper.edit:SetMaxLetters(256) |
SGI_Whisper.edit:SetBackdrop(backdrop) |
SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "") |
SGI_Whisper.edit:SetScript("OnHide",function() |
SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "") |
end) |
SGI_Whisper.edit.text = SGI_Whisper.edit:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Whisper.edit.text:SetPoint("TOPLEFT",SGI_Whisper.edit,"TOPLEFT",10,13) |
SGI_Whisper.edit.text:SetText(SGI.L["Enter your whisper"]) |
local yOfs = -20 |
SGI_Whisper.status = {} |
for i = 1,6 do |
SGI_Whisper.status[i] = {} |
SGI_Whisper.status[i].box = CreateFrame("Frame",nil,SGI_Whisper) |
SGI_Whisper.status[i].box:SetWidth(170) |
SGI_Whisper.status[i].box:SetHeight(18) |
SGI_Whisper.status[i].box:SetFrameStrata("HIGH") |
SGI_Whisper.status[i].box.index = i |
SGI_Whisper.status[i].box:SetPoint("LEFT",SGI_Whisper,"CENTER",50,yOfs) |
SGI_Whisper.status[i].box:SetScript("OnEnter",function(self) |
if SGI_DATA[SGI_DATA_INDEX].settings.whispers[self.index] then |
GameTooltip:SetOwner(self,"ANCHOR_CURSOR") |
GameTooltip:SetText(SGI:FormatWhisper(SGI_DATA[SGI_DATA_INDEX].settings.whispers[self.index],UnitName("Player"))) |
end |
end) |
SGI_Whisper.status[i].box:SetScript("OnLeave",function(self) |
GameTooltip:Hide() |
end) |
SGI_Whisper.status[i].text = SGI_Whisper:CreateFontString(nil,nil,"GameFontNormal") |
SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: ") |
SGI_Whisper.status[i].text:SetWidth(200) |
SGI_Whisper.status[i].text:SetJustifyH("LEFT") |
SGI_Whisper.status[i].text:SetPoint("LEFT",SGI_Whisper,"CENTER",50,yOfs) |
yOfs = yOfs - 18 |
end |
local whispers = { |
"Whisper #1", |
"Whisper #2", |
"Whisper #3", |
"Whisper #4", |
"Whisper #5", |
"Whisper #6", |
} |
anchor = {} |
anchor.point = "BOTTOMLEFT" |
anchor.relativePoint = "BOTTOMLEFT" |
anchor.xOfs = 50 |
anchor.yOfs = 120 |
--CreateDropDown(name, parent, label, items, anchor) |
SGI_Whisper.drop = CreateDropDown("SGI_WHISPER_DROP",SGI_Whisper,SGI.L["Select whisper"],whispers,anchor) |
anchor.xOfs = 100 |
anchor.yOfs = 20 |
--CreateButton(name, parent, width, height, label, anchor, onClick) |
CreateButton("SGI_SAVEWHISPER",SGI_Whisper,120,30,SGI.L["Save"],anchor,function() |
local text = SGI_Whisper.edit:GetText() |
local ID = SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] |
SGI_DATA[SGI_DATA_INDEX].settings.whispers[ID] = text |
SGI_Whisper.edit:SetText("") |
end) |
anchor.xOfs = 280 |
CreateButton("SGI_CANCELWHISPER",SGI_Whisper,120,30,SGI.L["Cancel"],anchor,function() |
SGI_Whisper:Hide() |
end) |
SGI_Whisper.update = 0 |
SGI_Whisper.changed = false |
SGI_Whisper:SetScript("OnUpdate",function() |
if GetTime() > SGI_Whisper.update then |
for i = 1,6 do |
if type(SGI_DATA[SGI_DATA_INDEX].settings.whispers[i]) == "string" then |
SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: |cff00ff00Good|r") |
else |
SGI_Whisper.status[i].text:SetText("Whisper #"..i.." status: |cffff0000Undefined|r") |
end |
end |
local ID = SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] |
SGI_Whisper.status[ID].text:SetText("Whisper #"..ID.." status: |cffff8800Editing...|r") |
if ID ~= SGI_Whisper.changed then |
SGI_Whisper.changed = ID |
SGI_Whisper.edit:SetText(SGI_DATA[SGI_DATA_INDEX].settings.whispers[SGI_DATA[SGI_DATA_INDEX].settings.dropDown["SGI_WHISPER_DROP"] or 1] or "") |
end |
SGI_Whisper.update = GetTime() + 0.5 |
end |
end) |
SGI_Whisper:HookScript("OnHide", function() if (SGI_Options.showAgain) then SGI:ShowOptions() SGI_Options.showAgain = false end end) |
end |
local function ShowWhisperFrame() |
if SGI_Whisper then |
SGI_Whisper:Show() |
else |
CreateWhisperDefineFrame() |
SGI_Whisper:Show() |
end |
end |
local function HideWhisperFrame() |
if SGI_Whisper then |
SGI_Whisper:Hide() |
end |
end |
local function CreateFilterFrame() |
CreateFrame("Frame","SGI_Filters") |
SGI_Filters:SetWidth(550) |
SGI_Filters:SetHeight(380) |
SetFramePosition(SGI_Filters) |
SGI_Filters:SetMovable(true) |
SGI_Filters:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SGI_Filters:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(SGI_Filters) |
end) |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SGI_Filters:SetBackdrop(backdrop) |
local close = CreateFrame("Button",nil,SGI_Filters,"UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",SGI_Filters,"TOPRIGHT",-4,-4) |
SGI_Filters.title = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge"); |
SGI_Filters.title:SetPoint("TOP", SGI_Filters, "TOP", 0, -15); |
SGI_Filters.title:SetText("Edit filters"); |
SGI_Filters.underTitle = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.underTitle:SetPoint("TOP", SGI_Filters, "TOP", 0, -38); |
SGI_Filters.underTitle:SetText("|cffff3300Any textbox left empty, except \"Filter name\" will be excluded from the filter|r"); |
SGI_Filters.underTitle:SetWidth(400); |
SGI_Filters.bottomText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFOntNormal"); |
SGI_Filters.bottomText:SetPoint("BOTTOM", SGI_Filters, "BOTTOM", 0, 60); |
SGI_Filters.bottomText:SetText("|cff00ff00In order to be filtered, a player has to match |r|cffFF3300ALL|r |cff00ff00criterias|r"); |
SGI_Filters.tooltip = CreateFrame("Frame", "FilterTooltip", SGI_Filters.tooltip, "GameTooltipTemplate"); |
SGI_Filters.tooltip:SetWidth(150); |
SGI_Filters.tooltip.text = SGI_Filters.tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.tooltip.text:SetPoint("CENTER", SGI_Filters.tooltip, "CENTER", 0, 0); |
SGI_Filters.tooltip.text:SetJustifyH("LEFT"); |
SGI_Filters.editBoxName = CreateFrame("EditBox", "SGI_EditBoxName", SGI_Filters); |
SGI_Filters.editBoxName:SetWidth(150); |
SGI_Filters.editBoxName:SetHeight(30); |
SGI_Filters.editBoxName:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -90); |
SGI_Filters.editBoxName:SetFontObject("GameFontNormal"); |
SGI_Filters.editBoxName:SetMaxLetters(65); |
SGI_Filters.editBoxName:SetBackdrop(backdrop); |
SGI_Filters.editBoxName:SetText(""); |
SGI_Filters.editBoxName:SetTextInsets(10,10,10,10); |
SGI_Filters.editBoxName:SetScript("OnHide",function(self) |
self:SetText(""); |
end) |
SGI_Filters.editBoxName.title = SGI_Filters.editBoxName:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.editBoxName.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxName,"TOPLEFT", 0, 5); |
SGI_Filters.editBoxName.title:SetText("Filter name"); |
SGI_Filters.editBoxNameFilter = CreateFrame("EditBox", "SGI_EditBoxNameFilter", SGI_Filters); |
SGI_Filters.editBoxNameFilter:SetWidth(150); |
SGI_Filters.editBoxNameFilter:SetHeight(30); |
SGI_Filters.editBoxNameFilter:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -150); |
SGI_Filters.editBoxNameFilter:SetFontObject("GameFontNormal"); |
SGI_Filters.editBoxNameFilter:SetMaxLetters(65); |
SGI_Filters.editBoxNameFilter:SetBackdrop(backdrop); |
SGI_Filters.editBoxNameFilter:SetText(""); |
SGI_Filters.editBoxNameFilter:SetTextInsets(10,10,10,10); |
SGI_Filters.editBoxNameFilter:SetScript("OnHide",function(self) |
self:SetText(""); |
end) |
SGI_Filters.editBoxNameFilter:SetScript("OnEnter", function(self) |
SGI_Filters.tooltip.text:SetText(SGI.L["Enter a phrase which you wish to include in the filter. If a player's name contains the phrase, they will not be queued"]); |
SGI_Filters.tooltip.text:SetWidth(135); |
SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12); |
SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5); |
SGI_Filters.tooltip:Show(); |
end) |
SGI_Filters.editBoxNameFilter:SetScript("OnLeave", function() |
SGI_Filters.tooltip:Hide() |
end) |
SGI_Filters.editBoxNameFilter.title = SGI_Filters.editBoxNameFilter:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.editBoxNameFilter.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxNameFilter,"TOPLEFT", 0, 5); |
SGI_Filters.editBoxNameFilter.title:SetText("Name exceptions"); |
SGI_Filters.editBoxLvl = CreateFrame("EditBox", "SGI_EditBoxLvl", SGI_Filters); |
SGI_Filters.editBoxLvl:SetWidth(150); |
SGI_Filters.editBoxLvl:SetHeight(30); |
SGI_Filters.editBoxLvl:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -210); |
SGI_Filters.editBoxLvl:SetFontObject("GameFontNormal"); |
SGI_Filters.editBoxLvl:SetMaxLetters(65); |
SGI_Filters.editBoxLvl:SetBackdrop(backdrop); |
SGI_Filters.editBoxLvl:SetText(""); |
SGI_Filters.editBoxLvl:SetTextInsets(10,10,10,10); |
SGI_Filters.editBoxLvl:SetScript("OnHide",function(self) |
self:SetText(""); |
end) |
SGI_Filters.editBoxLvl:SetScript("OnEnter", function(self) |
SGI_Filters.tooltip.text:SetText(SGI.L["Enter the level range for the filter. \n\nExample: |cff00ff0055|r:|cff00A2FF58|r \n\nThis would result in only matching players that range from level |cff00ff0055|r to |cff00A2FF58|r (inclusive)"]); |
SGI_Filters.tooltip.text:SetWidth(135); |
SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12); |
SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5); |
SGI_Filters.tooltip:Show(); |
end) |
SGI_Filters.editBoxLvl:SetScript("OnLeave", function() |
SGI_Filters.tooltip:Hide() |
end) |
SGI_Filters.editBoxLvl.title = SGI_Filters.editBoxLvl:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.editBoxLvl.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxLvl,"TOPLEFT", 0, 5); |
SGI_Filters.editBoxLvl.title:SetText("Level range (Min:Max)"); |
SGI_Filters.editBoxVC = CreateFrame("EditBox", "SGI_EditBoxVC", SGI_Filters); |
SGI_Filters.editBoxVC:SetWidth(150); |
SGI_Filters.editBoxVC:SetHeight(30); |
SGI_Filters.editBoxVC:SetPoint("TOPRIGHT", SGI_Filters, "TOPRIGHT", -40, -270); |
SGI_Filters.editBoxVC:SetFontObject("GameFontNormal"); |
SGI_Filters.editBoxVC:SetMaxLetters(65); |
SGI_Filters.editBoxVC:SetBackdrop(backdrop); |
SGI_Filters.editBoxVC:SetText(""); |
SGI_Filters.editBoxVC:SetTextInsets(10,10,10,10); |
SGI_Filters.editBoxVC:SetScript("OnHide",function(self) |
self:SetText(""); |
end) |
SGI_Filters.editBoxVC:SetScript("OnEnter", function(self) |
SGI_Filters.tooltip.text:SetText(SGI.L["Enter the maximum amount of consecutive vowels and consonants a player's name can contain.\n\nExample: |cff00ff003|r:|cff00A2FF5|r\n\nThis would cause players with more than |cff00ff003|r vowels in a row or more than |cff00A2FF5|r consonants in a row not to be queued."]); |
SGI_Filters.tooltip.text:SetWidth(135); |
SGI_Filters.tooltip:SetHeight(SGI_Filters.tooltip.text:GetHeight() + 12); |
SGI_Filters.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -5); |
SGI_Filters.tooltip:Show(); |
end) |
SGI_Filters.editBoxVC:SetScript("OnLeave", function() |
SGI_Filters.tooltip:Hide() |
end) |
SGI_Filters.editBoxVC.title = SGI_Filters.editBoxVC:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.editBoxVC.title:SetPoint("BOTTOMLEFT", SGI_Filters.editBoxVC,"TOPLEFT", 0, 5); |
SGI_Filters.editBoxVC.title:SetText("Max Vowels/Cons (V:C)"); |
SGI_EditBoxName:SetScript("OnEnterPressed", function() |
SGI_EditBoxNameFilter:SetFocus(); |
end); |
SGI_EditBoxNameFilter:SetScript("OnEnterPressed", function() |
SGI_EditBoxLvl:SetFocus(); |
end); |
SGI_EditBoxLvl:SetScript("OnEnterPressed", function() |
SGI_EditBoxVC:SetFocus(); |
end); |
SGI_EditBoxVC:SetScript("OnEnterPressed", function() |
SGI_EditBoxName:SetFocus(); |
end); |
SGI_EditBoxName:SetScript("OnTabPressed", function() |
SGI_EditBoxNameFilter:SetFocus(); |
end); |
SGI_EditBoxNameFilter:SetScript("OnTabPressed", function() |
SGI_EditBoxLvl:SetFocus(); |
end); |
SGI_EditBoxLvl:SetScript("OnTabPressed", function() |
SGI_EditBoxVC:SetFocus(); |
end); |
SGI_EditBoxVC:SetScript("OnTabPressed", function() |
SGI_EditBoxName:SetFocus(); |
end); |
local CLASS = { |
[SGI.L["Death Knight"]] = "DEATHKNIGHT", |
[SGI.L["Demon Hunter"]] = "DEMONHUNTER", |
[SGI.L["Druid"]] = "DRUID", |
[SGI.L["Hunter"]] = "HUNTER", |
[SGI.L["Mage"]] = "MAGE", |
[SGI.L["Monk"]] = "MONK", |
[SGI.L["Paladin"]] = "PALADIN", |
[SGI.L["Priest"]] = "PRIEST", |
[SGI.L["Rogue"]] = "ROGUE", |
[SGI.L["Shaman"]] = "SHAMAN", |
[SGI.L["Warlock"]] = "WARLOCK", |
[SGI.L["Warrior"]] = "WARRIOR" |
} |
local Classes = { |
SGI.L["Ignore"], |
SGI.L["Death Knight"], |
SGI.L["Demon Hunter"], |
SGI.L["Druid"], |
SGI.L["Hunter"], |
SGI.L["Mage"], |
SGI.L["Monk"], |
SGI.L["Paladin"], |
SGI.L["Priest"], |
SGI.L["Rogue"], |
SGI.L["Shaman"], |
SGI.L["Warlock"], |
SGI.L["Warrior"], |
} |
local Races = {} |
if UnitFactionGroup("player") == "Horde" then |
Races = { |
SGI.L["Ignore"], |
SGI.L["Orc"], |
SGI.L["Blood Elf"], |
SGI.L["Undead"], |
SGI.L["Troll"], |
SGI.L["Goblin"], |
SGI.L["Tauren"], |
SGI.L["Pandaren"], |
} |
else |
Races = { |
SGI.L["Ignore"], |
SGI.L["Human"], |
SGI.L["Dwarf"], |
SGI.L["Worgen"], |
SGI.L["Draenei"], |
SGI.L["Night Elf"], |
SGI.L["Gnome"], |
SGI.L["Pandaren"], |
} |
end |
SGI_Filters.classText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.raceText = SGI_Filters:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_Filters.classCheckBoxes = {}; |
local anchor = { |
point = "TOPLEFT", |
relativePoint = "TOPLEFT", |
xOfs = 40, |
yOfs = -90, |
} |
for k,_ in pairs(Classes) do |
SGI_Filters.classCheckBoxes[k] = CreateCheckbox("CHECKBOX_FILTERS_CLASS_"..Classes[k], SGI_Filters, Classes[k], anchor) |
anchor.yOfs = anchor.yOfs - 18; |
end |
SGI_Filters.classText:SetPoint("BOTTOM", SGI_Filters.classCheckBoxes[1], "TOP", -5, 3); |
SGI_Filters.classText:SetText(SGI.L["Classes:"]); |
if (SGI_Filters.classCheckBoxes[1]:GetChecked()) then |
for i = 2,12 do |
SGI_Filters.classCheckBoxes[i]:Hide(); |
end |
else |
for i = 2,12 do |
SGI_Filters.classCheckBoxes[i]:Show(); |
end |
end |
SGI_Filters.classCheckBoxes[1]:HookScript("PostClick", function() |
if (SGI_Filters.classCheckBoxes[1]:GetChecked()) then |
for i = 2,12 do |
SGI_Filters.classCheckBoxes[i]:Hide(); |
end |
else |
for i = 2,12 do |
SGI_Filters.classCheckBoxes[i]:Show(); |
end |
end |
end) |
SGI_Filters.raceCheckBoxes = {}; |
anchor = { |
point = "TOPLEFT", |
relativePoint = "TOPLEFT", |
xOfs = 160, |
yOfs = -90, |
} |
for k,_ in pairs(Races) do |
SGI_Filters.raceCheckBoxes[k] = CreateCheckbox("CHECKBOX_FILTERS_RACE_"..Races[k], SGI_Filters, Races[k], anchor) |
anchor.yOfs = anchor.yOfs - 18; |
end |
SGI_Filters.raceText:SetPoint("BOTTOM", SGI_Filters.raceCheckBoxes[1], "TOP", -5, 3); |
SGI_Filters.raceText:SetText(SGI.L["Races:"]); |
if (SGI_Filters.raceCheckBoxes[1]:GetChecked()) then |
for i = 2,8 do |
SGI_Filters.raceCheckBoxes[i]:Hide(); |
end |
else |
for i = 2,8 do |
SGI_Filters.raceCheckBoxes[i]:Show(); |
end |
end |
SGI_Filters.raceCheckBoxes[1]:HookScript("PostClick", function() |
if (SGI_Filters.raceCheckBoxes[1]:GetChecked()) then |
for i = 2,8 do |
SGI_Filters.raceCheckBoxes[i]:Hide(); |
end |
else |
for i = 2,8 do |
SGI_Filters.raceCheckBoxes[i]:Show(); |
end |
end |
end) |
local function GetFilterData() |
local FilterName = SGI_EditBoxName:GetText(); |
SGI_EditBoxName:SetText(""); |
if (not FilterName or strlen(FilterName) < 1) then |
return; |
end |
SGI:debug("Filter name: "..FilterName); |
local V,C = SGI_EditBoxVC:GetText(); |
if (V and strlen(V) > 1) then |
V,C = strsplit(":", V); |
V = tonumber(V); |
C = tonumber(C); |
if (V == "") then V = nil end |
if (C == "") then C = nil end |
SGI:debug("Max Vowels: "..(V or "N/A")..", Max Consonants: "..(C or "N/A")); |
end |
SGI_EditBoxVC:SetText(""); |
local Min,Max = SGI_EditBoxLvl:GetText(); |
if (Min and strlen(Min) > 1) then |
Min, Max = strsplit(":",Min); |
Min = tonumber(Min); |
Max = tonumber(Max); |
SGI:debug("Level range: "..Min.." - "..Max); |
end |
SGI_EditBoxLvl:SetText(""); |
local ExceptionName = SGI_EditBoxNameFilter:GetText() |
if (ExceptionName == "") then |
ExceptionName = nil; |
end |
SGI_EditBoxNameFilter:SetText(""); |
local classes = {}; |
if (not SGI_Filters.classCheckBoxes[1]:GetChecked()) then |
for k,_ in pairs(SGI_Filters.classCheckBoxes) do |
if (SGI_Filters.classCheckBoxes[k]:GetChecked()) then |
classes[CLASS[SGI_Filters.classCheckBoxes[k].label:GetText()]] = true; |
SGI:debug(CLASS[SGI_Filters.classCheckBoxes[k].label:GetText()]); |
SGI_Filters.classCheckBoxes[k]:SetChecked(false); |
end |
end |
end |
local races = {} |
if (not SGI_Filters.raceCheckBoxes[1]:GetChecked()) then |
for k,_ in pairs(SGI_Filters.raceCheckBoxes) do |
if (SGI_Filters.raceCheckBoxes[k]:GetChecked()) then |
races[SGI_Filters.raceCheckBoxes[k].label:GetText()] = true; |
SGI:debug(SGI_Filters.raceCheckBoxes[k].label:GetText()); |
SGI_Filters.raceCheckBoxes[k]:SetChecked(false); |
end |
end |
end |
SGI:CreateFilter(FilterName,classes,ExceptionName,Min,Max,races,V,C); |
SGI_FilterHandle.needRedraw = true; |
return true; |
end |
anchor = { |
point = "BOTTOM", |
relativePoint = "BOTTOM", |
xOfs = -60, |
yOfs = 20, |
} |
SGI_Filters.button1 = CreateButton("BUTTON_SAVE_FILTER", SGI_Filters, 120, 30, SGI.L["Save"], anchor, GetFilterData); |
anchor.xOfs = 60; |
SGI_Filters.button2 = CreateButton("BUTTON_CANCEL_FILTER", SGI_Filters, 120, 30, SGI.L["Back"], anchor, function() SGI_Filters:Hide() end); |
SGI_Filters:HookScript("OnHide", function() SGI:ShowFilterHandle() SGI_FilterHandle.showOpt = true end); |
end |
local function ShowFilterFrame() |
if (not SGI_Filters) then |
CreateFilterFrame(); |
end |
SGI_Filters:Show(); |
end |
local function CreateFilterHandleFrame() |
CreateFrame("Frame","SGI_FilterHandle") |
SGI_FilterHandle:SetWidth(450) |
SGI_FilterHandle:SetHeight(350) |
SetFramePosition(SGI_FilterHandle) |
SGI_FilterHandle:SetMovable(true) |
SGI_FilterHandle:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SGI_FilterHandle:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(SGI_FilterHandle) |
end) |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SGI_FilterHandle:SetBackdrop(backdrop) |
local close = CreateFrame("Button",nil,SGI_FilterHandle,"UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",SGI_FilterHandle,"TOPRIGHT",-4,-4) |
SGI_FilterHandle.title = SGI_FilterHandle:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_FilterHandle.title:SetText("Filters") |
SGI_FilterHandle.title:SetPoint("TOP",SGI_FilterHandle,"TOP",0,-15) |
SGI_FilterHandle.underTitle = SGI_FilterHandle:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_FilterHandle.underTitle:SetText("Click to toggle"); |
SGI_FilterHandle.underTitle:SetPoint("TOP", SGI_FilterHandle, "TOP", 0, -35); |
local anchor = {} |
anchor.point = "BOTTOM" |
anchor.relativePoint = "BOTTOM" |
anchor.xOfs = -60 |
anchor.yOfs = 30 |
SGI_FilterHandle.button1 = CreateButton("BUTTON_EDIT_FILTERS", SGI_FilterHandle, 120, 30, SGI.L["Add filters"], anchor, function() ShowFilterFrame() SGI_FilterHandle.showOpt = false SGI_FilterHandle.showSelf = true SGI_FilterHandle:Hide() end); |
anchor.xOfs = 60 |
SGI_FilterHandle.button2 = CreateButton("BUTTON_EDIT_FILTERS", SGI_FilterHandle, 120, 30, SGI.L["Back"], anchor, function() close:Click() end); |
SGI_FilterHandle.tooltip = CreateFrame("Frame", "SGI_HandleTooltip", SGI_FilterHandle, "GameTooltipTemplate"); |
SGI_FilterHandle.tooltip:SetWidth(150); |
SGI_FilterHandle.tooltip.text = SGI_FilterHandle.tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_FilterHandle.tooltip.text:SetPoint("CENTER", SGI_FilterHandle.tooltip, "CENTER", 0, 0); |
SGI_FilterHandle.tooltip.text:SetJustifyH("LEFT"); |
local function FormatTooltipFilterText(filter) |
local text = "Filter name: "..filter.nameOfFilter.."\n"; |
if (filter.active) then |
text = text.."|cff00ff00[ACTIVE]|r\n"; |
else |
text = text.."|cffff0000[INACTIVE]|r\n"; |
end |
if (filter.class) then |
for k,v in pairs(filter.class) do |
text = text.."|cff"..(SGI:GetClassColor(k)..k).."|r\n"; |
end |
end |
if (filter.race) then |
for k,v in pairs(filter.race) do |
text = text.."|cff16ABB5"..k.."|r\n"; |
end |
end |
if (filter.minLvl and filter.minLvl ~= "") then |
text = text.."|cff00ff00"..filter.minLvl.."|r - "; |
if (filter.maxLvl) then |
text = text.."|cffff0000"..filter.maxLvl.."|r\n"; |
else |
text = text.."\n"; |
end |
end |
if (filter.maxVowels and filter.maxVowels ~= "") then |
text = text.."Vowels: |cff16ABB5"..filter.maxVowels.."|r\n"; |
end |
if (filter.maxConsonants and filter.maxVowels ~= "") then |
text = text.."Consonants: |cff16ABB5"..filter.maxConsonants.."|r\n"; |
end |
if (filter.name and filter.name ~= "") then |
text = text.."Name exception: |cff16ABB5"..filter.name.."|r"; |
end |
return text; |
end |
SGI_FilterHandle.filterFrames = {} |
SGI_FilterHandle.update = 0; |
SGI_FilterHandle.needRedraw = false; |
SGI_FilterHandle:SetScript("OnUpdate", function(self) |
if (SGI_FilterHandle.update < GetTime()) then |
local anchor = {} |
anchor.xOfs = -175 |
anchor.yOfs = 110 |
local F = SGI_DATA[SGI_DATA_INDEX].settings.filters; |
if (SGI_FilterHandle.needRedraw) then |
for k,_ in pairs(SGI_FilterHandle.filterFrames) do |
SGI_FilterHandle.filterFrames[k]:Hide(); |
end |
SGI_FilterHandle.filterFrames = {}; |
SGI_FilterHandle.needRedraw = false; |
end |
for k,_ in pairs(F) do |
if (not SGI_FilterHandle.filterFrames[k]) then |
SGI_FilterHandle.filterFrames[k] = CreateFrame("Button", "FilterFrame"..k, SGI_FilterHandle); |
SGI_FilterHandle.filterFrames[k]:SetWidth(80) |
SGI_FilterHandle.filterFrames[k]:SetHeight(25); |
SGI_FilterHandle.filterFrames[k]:EnableMouse(true); |
SGI_FilterHandle.filterFrames[k]:SetPoint("CENTER", SGI_FilterHandle, "CENTER", anchor.xOfs, anchor.yOfs); |
if mod(k,5) == 0 then |
anchor.xOfs = -175 |
anchor.yOfs = anchor.yOfs - 30 |
else |
anchor.xOfs = anchor.xOfs + 85 |
end |
SGI_FilterHandle.filterFrames[k].text = SGI_FilterHandle.filterFrames[k]:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
SGI_FilterHandle.filterFrames[k].text:SetPoint("LEFT", SGI_FilterHandle.filterFrames[k], "LEFT", 3, 0); |
SGI_FilterHandle.filterFrames[k].text:SetJustifyH("LEFT"); |
SGI_FilterHandle.filterFrames[k].text:SetWidth(75); |
SGI_FilterHandle.filterFrames[k]:EnableMouse(true); |
SGI_FilterHandle.filterFrames[k]:RegisterForClicks("LeftButtonDown","RightButtonDown"); |
SGI_FilterHandle.filterFrames[k].highlight = SGI_FilterHandle.filterFrames[k]:CreateTexture(); |
SGI_FilterHandle.filterFrames[k].highlight:SetAllPoints(); |
if (SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active) then |
SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2); |
else |
SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2); |
end |
SGI_FilterHandle.filterFrames[k]:SetScript("OnEnter", function(self) |
self.highlight:SetTexture(1,1,0,0.2); |
SGI:debug("Enter: YELLOW"); |
SGI_FilterHandle.tooltip.text:SetText(FormatTooltipFilterText(F[k])); |
SGI_FilterHandle.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -3); |
SGI_FilterHandle.tooltip:SetHeight(SGI_FilterHandle.tooltip.text:GetHeight() + 12); |
SGI_FilterHandle.tooltip:SetWidth(SGI_FilterHandle.tooltip.text:GetWidth() + 10); |
SGI_FilterHandle.tooltip:Show(); |
end) |
SGI_FilterHandle.filterFrames[k]:SetScript("OnLeave", function(self) |
if (F[k] and F[k].active) then--SGI_FilterHandle.filterFrames[k].state) then |
SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2); |
SGI:debug("Leave: GREEN"); |
else |
SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2); |
SGI:debug("Leave: RED"); |
end |
SGI_FilterHandle.tooltip:Hide(); |
end) |
end |
SGI_FilterHandle.filterFrames[k].filter = F[k]; |
SGI_FilterHandle.filterFrames[k].text:SetText(F[k].nameOfFilter); |
SGI_FilterHandle.filterFrames[k]:Show(); |
SGI_FilterHandle.filterFrames[k]:SetScript("OnClick", function(self, button) |
SGI:debug(button); |
if (button == "LeftButton") then |
if (SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active) then |
SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active = nil; |
SGI_FilterHandle.filterFrames[k].highlight:SetTexture(1,0,0,0.2); |
SGI:debug("Click: RED"); |
else |
SGI_DATA[SGI_DATA_INDEX].settings.filters[k].active = true; |
SGI_FilterHandle.filterFrames[k].highlight:SetTexture(0,1,0,0.2); |
SGI:debug("Click: GREEN"); |
end |
SGI_FilterHandle.tooltip.text:SetText(FormatTooltipFilterText(F[k])); |
SGI_FilterHandle.tooltip:SetPoint("TOP", self, "BOTTOM", 0, -3); |
SGI_FilterHandle.tooltip:SetHeight(SGI_FilterHandle.tooltip.text:GetHeight() + 12); |
SGI_FilterHandle.tooltip:SetWidth(SGI_FilterHandle.tooltip.text:GetWidth() + 10); |
SGI_FilterHandle.tooltip:Show(); |
else |
SGI_DATA[SGI_DATA_INDEX].settings.filters[k] = nil; |
SGI_FilterHandle.needRedraw = true; |
end |
end) |
end |
SGI_FilterHandle.update = GetTime() + 1; |
end |
end) |
SGI_FilterHandle.showOpt = true; |
SGI_FilterHandle:HookScript("OnHide", function() if SGI_FilterHandle.showOpt then SGI:ShowOptions() end end) |
end |
function SGI:ShowFilterHandle() |
if (not SGI_FilterHandle) then |
CreateFilterHandleFrame(); |
end |
SGI_FilterHandle:Show() |
end |
local function ChangeLog() |
CreateFrame("Frame","SGI_ChangeLog") |
SGI_ChangeLog:SetWidth(550) |
SGI_ChangeLog:SetHeight(350) |
SGI_ChangeLog:SetBackdrop( |
{ |
bgFile = "Interface/ACHIEVEMENTFRAME/UI-Achievement-Parchment-Horizontal", |
edgeFile = "Interface/Tooltips/UI-Tooltip-Border", |
tile = false, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
) |
SetFramePosition(SGI_ChangeLog) |
local anchor = {} |
anchor.point = "BOTTOMRIGHT" |
anchor.relativePoint = "BOTTOMRIGHT" |
anchor.xOfs = -210 |
anchor.yOfs = 10 |
SGI_ChangeLog.check1 = CreateCheckbox("SGI_CHANGES",SGI_ChangeLog,SGI.L["Don't show this after new updates"],anchor) |
anchor.xOfs = -300 |
SGI_ChangeLog.button1 = CreateButton("SGI_CLOSE_CHANGES",SGI_ChangeLog,120,30,SGI.L["Close"],anchor,function() SGI_ChangeLog:Hide() SGI_DATA.showChanges = SGI.VERSION_MAJOR end) |
SGI_ChangeLog.title = SGI_ChangeLog:CreateFontString() |
SGI_ChangeLog.title:SetFont("Fonts\\FRIZQT__.TTF",22,"OUTLINE") |
SGI_ChangeLog.title:SetText("|cffffff00<|r|cff16ABB5SuperGuildInvite|r|cff00ff00 Recent Changes|r|cffffff00>|r|cffffff00") |
SGI_ChangeLog.title:SetPoint("TOP",SGI_ChangeLog,"TOP",0,-12) |
SGI_ChangeLog.version = SGI_ChangeLog:CreateFontString() |
SGI_ChangeLog.version:SetFont("Fonts\\FRIZQT__.TTF",16,"OUTLINE") |
SGI_ChangeLog.version:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",15,-40) |
SGI_ChangeLog.version:SetText("") |
SGI_ChangeLog.items = {} |
local y = -65 |
for i = 1,10 do |
SGI_ChangeLog.items[i] = SGI_ChangeLog:CreateFontString() |
SGI_ChangeLog.items[i]:SetFont("Fonts\\FRIZQT__.TTF",14,"OUTLINE") |
SGI_ChangeLog.items[i]:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",30,y) |
SGI_ChangeLog.items[i]:SetText("") |
SGI_ChangeLog.items[i]:SetJustifyH("LEFT") |
SGI_ChangeLog.items[i]:SetSpacing(3) |
y = y - 17 |
end |
SGI_ChangeLog.SetChange = function(changes) |
local Y = -65 |
SGI_ChangeLog.version:SetText("|cff16ABB5"..changes.version.."|r") |
for k,_ in pairs(changes.items) do |
SGI_ChangeLog.items[k]:SetText("|cffffff00"..changes.items[k].."|r") |
SGI_ChangeLog.items[k]:SetWidth(490) |
SGI_ChangeLog.items[k]:SetPoint("TOPLEFT",SGI_ChangeLog,"TOPLEFT",30,Y) |
Y = Y - SGI_ChangeLog.items[k]:GetHeight() - 5 |
end |
end |
end |
function SGI:ShowChanges() |
if ( SGI_ChangeLog ) then |
SGI_ChangeLog:Show() |
else |
ChangeLog() |
SGI_ChangeLog:Show() |
end |
SGI_ChangeLog.SetChange(SGI.versionChanges); |
end |
local function CreateTroubleShooter() |
CreateFrame("Frame","SGI_TroubleShooter") |
SGI_TroubleShooter:SetWidth(300) |
SGI_TroubleShooter:SetHeight(100) |
SetFramePosition(SGI_TroubleShooter) |
SGI_TroubleShooter:SetMovable(true) |
SGI_TroubleShooter:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SGI_TroubleShooter:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(SGI_TroubleShooter) |
end) |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SGI_TroubleShooter:SetBackdrop(backdrop) |
local close = CreateFrame("Button",nil,SGI_TroubleShooter,"UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",SGI_TroubleShooter,"TOPRIGHT",-4,-4) |
SGI_TroubleShooter.title = SGI_TroubleShooter:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_TroubleShooter.title:SetPoint("TOP",SGI_TroubleShooter,"TOP",0,-10) |
SGI_TroubleShooter.title:SetText("Common issues") |
local update = 0; |
SGI_TroubleShooter.items = {}; |
SGI_TroubleShooter:SetScript("OnUpdate", function() |
if (update < GetTime()) then |
update = GetTime() + 0.5; |
end |
end) |
SGI_TroubleShooter:HookScript("OnHide", function() if (SGI_Options.showAgain) then SGI_Options:Show() SGI_Options.showAgain = false end end); |
end |
function SGI:ShowTroubleShooter() |
if (not SGI_TroubleShooter) then |
CreateTroubleShooter(); |
end |
SGI_TroubleShooter:Show(); |
end |
local function OptBtn2_OnClick() |
SGI:ShowSuperScanFrame(); |
SSBtn3_OnClick(SGI_SUPERSCAN_PLAYPAUSE2); |
end |
local function CreateOptions() |
CreateFrame("Frame","SGI_Options") |
SGI_Options:SetWidth(550) |
SGI_Options:SetHeight(350) |
SetFramePosition(SGI_Options) |
SGI_Options:SetMovable(true) |
SGI_Options:SetScript("OnMouseDown",function(self) |
self:StartMoving() |
end) |
SGI_Options:SetScript("OnMouseUp",function(self) |
self:StopMovingOrSizing() |
SaveFramePosition(SGI_Options) |
end) |
local backdrop = |
{ |
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background", |
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border", |
tile = true, |
tileSize = 16, |
edgeSize = 16, |
insets = { left = 4, right = 4, top = 4, bottom = 4 } |
} |
SGI_Options:SetBackdrop(backdrop) |
local close = CreateFrame("Button",nil,SGI_Options,"UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",SGI_Options,"TOPRIGHT",-4,-4) |
SGI_Options.title = SGI_Options:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.title:SetText("SuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options") |
SGI_Options.title:SetPoint("TOP",SGI_Options,"TOP",0,-15) |
SGI_Options.bottom = SGI_Options:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.bottom:SetText("Written by Janniie - Stormreaver EU") |
SGI_Options.bottom:SetPoint("BOTTOM",SGI_Options,"BOTTOM",0,1) |
SGI_Options.optionHelpText = SGI_Options:CreateFontString(nil, "OVERLAY","GameFontNormal"); |
SGI_Options.optionHelpText:SetText("|cff00D2FFScroll to change levels|r"); |
SGI_Options.optionHelpText:SetPoint("TOP",SGI_Options,"TOP",100,-40); |
local anchor = {} |
anchor.point = "TOPLEFT" |
anchor.relativePoint = "TOPLEFT" |
anchor.xOfs = 7 |
anchor.yOfs = -50 |
local WhisperMode = { |
SGI.L["Invite only"], |
SGI.L["Invite, then whisper"], |
SGI.L["Whisper only"], |
} |
local spacing = 25; |
SGI_Options.dropDown1 = CreateDropDown("DROPDOWN_INVITE_MODE", SGI_Options, SGI.L["Invite Mode"], WhisperMode, anchor); |
anchor.yOfs = anchor.yOfs - spacing - 7; |
anchor.xOfs = anchor.xOfs + 13; |
SGI_Options.checkBox1 = CreateCheckbox("CHECKBOX_SGI_MUTE", SGI_Options, SGI.L["Mute SGI"], anchor); |
anchor.yOfs = anchor.yOfs - spacing; |
SGI_Options.checkBox2 = CreateCheckbox("CHECKBOX_ADV_SCAN", SGI_Options, SGI.L["Advanced scan options"], anchor); |
anchor.yOfs = anchor.yOfs - spacing; |
SGI_Options.checkBox3 = CreateCheckbox("CHECKBOX_HIDE_SYSTEM", SGI_Options, SGI.L["Hide system messages"], anchor); |
anchor.yOfs = anchor.yOfs - spacing; |
SGI_Options.checkBox7 = CreateCheckbox("CHECKBOX_HIDE_WHISPER", SGI_Options, SGI.L["Hide outgoing whispers"], anchor); |
anchor.yOfs = anchor.yOfs - spacing; |
SGI_Options.checkBox4 = CreateCheckbox("CHECKBOX_HIDE_MINIMAP", SGI_Options, SGI.L["Hide minimap button"], anchor); |
anchor.yOfs = anchor.yOfs - spacing; |
SGI_Options.checkBox5 = CreateCheckbox("CHECKBOX_BACKGROUND_MODE", SGI_Options, SGI.L["Run SuperScan in the background"], anchor); |
anchor.yOfs = anchor.yOfs - spacing; |
SGI_Options.checkBox6 = CreateCheckbox("CHECKBOX_ENABLE_FILTERS", SGI_Options, SGI.L["Enable filtering"], anchor); |
SGI_Options.checkBox3:HookScript("PostClick", function(self) ChatIntercept:StateSystem(self:GetChecked()) end); |
SGI_Options.checkBox7:HookScript("PostClick", function(self) ChatIntercept:StateWhisper(self:GetChecked()) end); |
anchor.point = "BOTTOMLEFT" |
anchor.relativePoint = "BOTTOMLEFT" |
anchor.xOfs = 20 |
anchor.yOfs = 45 |
--onClickTester |
SGI_Options.button1 = CreateButton("BUTTON_CUSTOM_WHISPER", SGI_Options, 120, 30, SGI.L["Customize whisper"], anchor, function(self) ShowWhisperFrame() SGI_Options:Hide() SGI_Options.showAgain = true end); |
anchor.xOfs = anchor.xOfs + 125; |
SGI_Options.button2 = CreateButton("BUTTON_SUPER_SCAN", SGI_Options, 120, 30, SGI.L["SuperScan"], anchor, OptBtn2_OnClick); |
anchor.xOfs = anchor.xOfs + 125; |
SGI_Options.button3 = CreateButton("BUTTON_INVITE", SGI_Options, 120, 30, format(SGI.L["Invite: %d"],SGI:GetNumQueued()), anchor, SGI.SendGuildInvite); |
anchor.xOfs = anchor.xOfs + 125; |
SGI_Options.button4 = CreateButton("BUTTON_CHOOSE_INVITES", SGI_Options, 120, 30, SGI.L["Choose invites"], anchor, SGI.ShowInviteList); |
anchor.yOfs = 80; |
SGI_Options.button5 = CreateButton("BUTTON_EDIT_FILTERS", SGI_Options, 120, 30, SGI.L["Filters"], anchor, function() SGI:ShowFilterHandle() SGI_Options:Hide() end); |
anchor.xOfs = anchor.xOfs - 125; |
--SGI_Options.button6 = CreateButton("BUTTON_HELP", SGI_Options, 120, 30, SGI.L["Help"],anchor, function() SGI:ShowTroubleShooter() SGI_Options:Hide() SGI_Options.showAgain = true end); |
--anchor.xOfs = anchor.xOfs - 125; |
SGI_Options.button7 = CreateButton("BUTTON_KEYBIND", SGI_Options, 120, 30, SGI.L["Set Keybind ("..(SGI_DATA[SGI_DATA_INDEX].keyBind and SGI_DATA[SGI_DATA_INDEX].keyBind or "NONE")..")"], anchor, KeyHarvestFrame.GetNewKeybindKey); |
anchor.xOfs = anchor.xOfs - 125; |
--SGI_Options.button8 = CreateButton("BUTTON_FILTER", SGI_Options, 120, 30, SGI.L["Filters"], anchor, onClickTester); |
SGI_Options.limitLow = CreateFrame("Frame","SGI_LowLimit",SGI_Options) |
SGI_Options.limitLow:SetWidth(40) |
SGI_Options.limitLow:SetHeight(40) |
SGI_Options.limitLow:SetPoint("CENTER",SGI_Options,"CENTER",20,80) |
SGI_Options.limitLow.text = SGI_Options.limitLow:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.limitLow.text:SetPoint("CENTER") |
SGI_Options.limitLow.texture = SGI_Options.limitLow:CreateTexture() |
SGI_Options.limitLow.texture:SetAllPoints() |
SGI_Options.limitLow.texture:SetTexture(1,1,0,0.2) |
SGI_Options.limitLow.texture:Hide() |
SGI_Options.limitTooltip = CreateFrame("Frame","LimitTool",SGI_Options.limitLow,"GameTooltipTemplate") |
SGI_Options.limitTooltip:SetPoint("TOP",SGI_Options.limitLow,"BOTTOM") |
SGI_Options.limitTooltip.text = SGI_Options.limitTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.limitTooltip.text:SetPoint("LEFT",SGI_Options.limitTooltip,"LEFT",12,0) |
SGI_Options.limitTooltip.text:SetJustifyH("LEFT") |
SGI_Options.limitTooltip.text:SetText(SGI.L["Highest and lowest level to search for"]) |
SGI_Options.limitTooltip.text:SetWidth(115) |
SGI_Options.limitTooltip:SetWidth(130) |
SGI_Options.limitTooltip:SetHeight(SGI_Options.limitTooltip.text:GetHeight() + 12) |
SGI_Options.limitLow:SetScript("OnEnter",function() |
SGI_Options.limitLow.texture:Show() |
SGI_Options.limitTooltip:Show() |
end) |
SGI_Options.limitLow:SetScript("OnLeave",function() |
SGI_Options.limitLow.texture:Hide() |
SGI_Options.limitTooltip:Hide() |
end) |
SGI_Options.limitHigh = CreateFrame("Frame","SGI_HighLimit",SGI_Options) |
SGI_Options.limitHigh:SetWidth(40) |
SGI_Options.limitHigh:SetHeight(40) |
SGI_Options.limitHigh:SetPoint("CENTER",SGI_Options,"CENTER",60,80) |
SGI_Options.limitHigh.text = SGI_Options.limitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.limitHigh.text:SetPoint("CENTER") |
SGI_Options.limitHigh.texture = SGI_Options.limitHigh:CreateTexture() |
SGI_Options.limitHigh.texture:SetAllPoints() |
SGI_Options.limitHigh.texture:SetTexture(1,1,0,0.2) |
SGI_Options.limitHigh.texture:Hide() |
SGI_Options.limitHigh:SetScript("OnEnter",function() |
SGI_Options.limitHigh.texture:Show() |
SGI_Options.limitTooltip:Show() |
end) |
SGI_Options.limitHigh:SetScript("OnLeave",function() |
SGI_Options.limitHigh.texture:Hide() |
SGI_Options.limitTooltip:Hide() |
end) |
SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ") |
SGI_Options.limitLow:SetScript("OnMouseWheel",function(self,delta) |
if delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.lowLimit + 1 <= SGI_DATA[SGI_DATA_INDEX].settings.highLimit then |
SGI_DATA[SGI_DATA_INDEX].settings.lowLimit = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit + 1 |
SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ") |
elseif delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.lowLimit - 1 >= SGI_MIN_LEVEL_SUPER_SCAN then |
SGI_DATA[SGI_DATA_INDEX].settings.lowLimit = SGI_DATA[SGI_DATA_INDEX].settings.lowLimit - 1 |
SGI_Options.limitLow.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.lowLimit.." - ") |
end |
end) |
SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit) |
SGI_Options.limitHigh:SetScript("OnMouseWheel",function(self,delta) |
if delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.highLimit + 1 <= SGI_MAX_LEVEL_SUPER_SCAN then |
SGI_DATA[SGI_DATA_INDEX].settings.highLimit = SGI_DATA[SGI_DATA_INDEX].settings.highLimit + 1 |
SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit) |
elseif delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.highLimit > SGI_DATA[SGI_DATA_INDEX].settings.lowLimit then |
SGI_DATA[SGI_DATA_INDEX].settings.highLimit = SGI_DATA[SGI_DATA_INDEX].settings.highLimit - 1 |
SGI_Options.limitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.highLimit) |
end |
end) |
SGI_Options.limitText = SGI_Options.limitLow:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.limitText:SetPoint("BOTTOM",SGI_Options.limitLow,"TOP",16,3) |
SGI_Options.limitText:SetText(SGI.L["Level limits"]) |
SGI_Options.raceLimitHigh = CreateFrame("Frame","SGI_RaceLimitHigh",SGI_Options) |
SGI_Options.raceLimitHigh:SetWidth(40) |
SGI_Options.raceLimitHigh:SetHeight(40) |
SGI_Options.raceLimitHigh:SetPoint("CENTER",SGI_Options,"CENTER",150,80) |
SGI_Options.raceLimitHigh.text = SGI_Options.raceLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.raceLimitHigh.text:SetPoint("CENTER") |
SGI_Options.raceLimitHigh.texture = SGI_Options.raceLimitHigh:CreateTexture() |
SGI_Options.raceLimitHigh.texture:SetAllPoints() |
SGI_Options.raceLimitHigh.texture:SetTexture(1,1,0,0.2) |
SGI_Options.raceLimitHigh.texture:Hide() |
SGI_Options.raceTooltip = CreateFrame("Frame","LimitTool",SGI_Options.raceLimitHigh,"GameTooltipTemplate") |
SGI_Options.raceTooltip:SetPoint("TOP",SGI_Options.raceLimitHigh,"BOTTOM") |
SGI_Options.raceTooltip.text = SGI_Options.raceTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.raceTooltip.text:SetPoint("LEFT",SGI_Options.raceTooltip,"LEFT",12,0) |
SGI_Options.raceTooltip.text:SetJustifyH("LEFT") |
SGI_Options.raceTooltip.text:SetText(SGI.L["The level you wish to start dividing the search by race"]) |
SGI_Options.raceTooltip.text:SetWidth(110) |
SGI_Options.raceTooltip:SetWidth(125) |
SGI_Options.raceTooltip:SetHeight(SGI_Options.raceTooltip.text:GetHeight() + 12) |
SGI_Options.raceLimitText = SGI_Options.raceLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.raceLimitText:SetPoint("BOTTOM",SGI_Options.raceLimitHigh,"TOP",0,3) |
SGI_Options.raceLimitText:SetText(SGI.L["Racefilter Start:"]) |
SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart) |
SGI_Options.raceLimitHigh:SetScript("OnMouseWheel",function(self,delta) |
if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.raceStart > 1 then |
SGI_DATA[SGI_DATA_INDEX].settings.raceStart = SGI_DATA[SGI_DATA_INDEX].settings.raceStart - 1 |
SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart) |
elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.raceStart < SGI_MAX_LEVEL_SUPER_SCAN + 1 then |
SGI_DATA[SGI_DATA_INDEX].settings.raceStart = SGI_DATA[SGI_DATA_INDEX].settings.raceStart + 1 |
SGI_Options.raceLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.raceStart) |
if SGI_DATA[SGI_DATA_INDEX].settings.raceStart > SGI_MAX_LEVEL_SUPER_SCAN then |
SGI_Options.raceLimitHigh.text:SetText(SGI.L["OFF"]) |
end |
end |
end) |
SGI_Options.raceLimitHigh:SetScript("OnEnter",function() |
SGI_Options.raceLimitHigh.texture:Show() |
SGI_Options.raceTooltip:Show() |
end) |
SGI_Options.raceLimitHigh:SetScript("OnLeave",function() |
SGI_Options.raceLimitHigh.texture:Hide() |
SGI_Options.raceTooltip:Hide() |
end) |
SGI_Options.classLimitHigh = CreateFrame("Frame","SGI_ClassLimitHigh",SGI_Options) |
SGI_Options.classLimitHigh:SetWidth(40) |
SGI_Options.classLimitHigh:SetHeight(40) |
SGI_Options.classLimitHigh:SetPoint("CENTER",SGI_Options,"CENTER",150,10) |
SGI_Options.classLimitHigh.text = SGI_Options.classLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.classLimitHigh.text:SetPoint("CENTER") |
SGI_Options.classLimitHigh.texture = SGI_Options.classLimitHigh:CreateTexture() |
SGI_Options.classLimitHigh.texture:SetAllPoints() |
SGI_Options.classLimitHigh.texture:SetTexture(1,1,0,0.2) |
SGI_Options.classLimitHigh.texture:Hide() |
SGI_Options.classTooltip = CreateFrame("Frame","LimitTool",SGI_Options.classLimitHigh,"GameTooltipTemplate") |
SGI_Options.classTooltip:SetPoint("TOP",SGI_Options.classLimitHigh,"BOTTOM") |
SGI_Options.classTooltip.text = SGI_Options.classTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.classTooltip.text:SetPoint("LEFT",SGI_Options.classTooltip,"LEFT",12,0) |
SGI_Options.classTooltip.text:SetJustifyH("LEFT") |
SGI_Options.classTooltip.text:SetText(SGI.L["The level you wish to divide the search by class"]) |
SGI_Options.classTooltip.text:SetWidth(110) |
SGI_Options.classTooltip:SetWidth(125) |
SGI_Options.classTooltip:SetHeight(SGI_Options.classTooltip.text:GetHeight() + 12) |
SGI_Options.classLimitText = SGI_Options.classLimitHigh:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.classLimitText:SetPoint("BOTTOM",SGI_Options.classLimitHigh,"TOP",0,3) |
SGI_Options.classLimitText:SetText(SGI.L["Classfilter Start:"]) |
SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart) |
SGI_Options.classLimitHigh:SetScript("OnMouseWheel",function(self,delta) |
if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.classStart > 1 then |
SGI_DATA[SGI_DATA_INDEX].settings.classStart = SGI_DATA[SGI_DATA_INDEX].settings.classStart - 1 |
SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart) |
elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.classStart < SGI_MAX_LEVEL_SUPER_SCAN + 1 then |
SGI_DATA[SGI_DATA_INDEX].settings.classStart = SGI_DATA[SGI_DATA_INDEX].settings.classStart + 1 |
SGI_Options.classLimitHigh.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.classStart) |
if SGI_DATA[SGI_DATA_INDEX].settings.classStart > SGI_MAX_LEVEL_SUPER_SCAN then |
SGI_Options.classLimitHigh.text:SetText(SGI.L["OFF"]) |
end |
end |
end) |
SGI_Options.classLimitHigh:SetScript("OnEnter",function() |
SGI_Options.classLimitHigh.texture:Show() |
SGI_Options.classTooltip:Show() |
end) |
SGI_Options.classLimitHigh:SetScript("OnLeave",function() |
SGI_Options.classLimitHigh.texture:Hide() |
SGI_Options.classTooltip:Hide() |
end) |
SGI_Options.Interval = CreateFrame("Frame","SGI_Interval",SGI_Options) |
SGI_Options.Interval:SetWidth(40) |
SGI_Options.Interval:SetHeight(40) |
SGI_Options.Interval:SetPoint("CENTER",SGI_Options,"CENTER",40,10) |
SGI_Options.Interval.text = SGI_Options.Interval:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") |
SGI_Options.Interval.text:SetPoint("CENTER") |
SGI_Options.Interval.texture = SGI_Options.Interval:CreateTexture() |
SGI_Options.Interval.texture:SetAllPoints() |
SGI_Options.Interval.texture:SetTexture(1,1,0,0.2) |
SGI_Options.Interval.texture:Hide() |
SGI_Options.intervalTooltip = CreateFrame("Frame","LimitTool",SGI_Options.Interval,"GameTooltipTemplate") |
SGI_Options.intervalTooltip:SetPoint("TOP",SGI_Options.Interval,"BOTTOM") |
SGI_Options.intervalTooltip.text = SGI_Options.intervalTooltip:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.intervalTooltip.text:SetPoint("LEFT",SGI_Options.intervalTooltip,"LEFT",12,0) |
SGI_Options.intervalTooltip.text:SetJustifyH("LEFT") |
SGI_Options.intervalTooltip.text:SetText(SGI.L["Amount of levels to search every 7 seconds (higher numbers increase the risk of capping the search results)"]) |
SGI_Options.intervalTooltip.text:SetWidth(130) |
SGI_Options.intervalTooltip:SetHeight(120) |
SGI_Options.intervalTooltip:SetWidth(135) |
SGI_Options.intervalTooltip:SetHeight(SGI_Options.intervalTooltip.text:GetHeight() + 12) |
SGI_Options.intervalText = SGI_Options.Interval:CreateFontString(nil,"OVERLAY","GameFontNormal") |
SGI_Options.intervalText:SetPoint("BOTTOM",SGI_Options.Interval,"TOP",0,3) |
SGI_Options.intervalText:SetText(SGI.L["Interval:"]) |
SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval) |
SGI_Options.Interval:SetScript("OnMouseWheel",function(self,delta) |
if delta == -1 and SGI_DATA[SGI_DATA_INDEX].settings.interval > 1 then |
SGI_DATA[SGI_DATA_INDEX].settings.interval = SGI_DATA[SGI_DATA_INDEX].settings.interval - 1 |
SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval) |
elseif delta == 1 and SGI_DATA[SGI_DATA_INDEX].settings.interval < 30 then |
SGI_DATA[SGI_DATA_INDEX].settings.interval = SGI_DATA[SGI_DATA_INDEX].settings.interval + 1 |
SGI_Options.Interval.text:SetText(SGI_DATA[SGI_DATA_INDEX].settings.interval) |
end |
end) |
SGI_Options.Interval:SetScript("OnEnter",function() |
SGI_Options.Interval.texture:Show() |
SGI_Options.intervalTooltip:Show() |
end) |
SGI_Options.Interval:SetScript("OnLeave",function() |
SGI_Options.Interval.texture:Hide() |
SGI_Options.intervalTooltip:Hide() |
end) |
anchor = { |
point = "BOTTOMLEFT", |
relativePoint = "BOTTOMLEFT", |
xOfs = 4, |
yOfs = 4, |
} |
SGI_Options.superScanText = SGI_Options:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge"); |
SGI_Options.superScanText:SetPoint("BOTTOMLEFT", SGI_Options, "BOTTOMLEFT", 35, 10); |
SGI_Options.superScanText:SetText("SuperScan"); |
SGI_Options.buttonPlayPause = CreateButton("SGI_SUPERSCAN_PLAYPAUSE2", SGI_Options, 40,30,"",anchor,SSBtn3_OnClick); |
SGI_SUPERSCAN_PLAYPAUSE2:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up"); |
SGI_SUPERSCAN_PLAYPAUSE2:Hide(); |
SGI_Options.superScanText:Hide(); |
SGI_Options.nextUpdate = 0; |
SGI_Options:SetScript("OnUpdate", function() |
if (SGI_Options.nextUpdate < GetTime()) then |
if SGI_DATA[SGI_DATA_INDEX].settings.classStart > SGI_MAX_LEVEL_SUPER_SCAN then |
SGI_Options.classLimitHigh.text:SetText(SGI.L["OFF"]) |
end |
if SGI_DATA[SGI_DATA_INDEX].settings.raceStart > SGI_MAX_LEVEL_SUPER_SCAN then |
SGI_Options.raceLimitHigh.text:SetText(SGI.L["OFF"]) |
end |
if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_BACKGROUND_MODE"]) then |
SGI_SUPERSCAN_PLAYPAUSE2:Show(); |
SGI_Options.superScanText:Show(); |
if SuperScanFrame then SuperScanFrame:Hide() end; |
else |
SGI_SUPERSCAN_PLAYPAUSE2:Hide(); |
SGI_Options.superScanText:Hide(); |
if (SGI:IsScanning()) then |
SGI:ShowSuperScanFrame(); |
end |
end |
if (SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_ADV_SCAN"]) then |
if (not SGI_Options.Interval:IsShown()) then |
SGI_Options.Interval:Show(); |
end |
if (not SGI_Options.classLimitHigh:IsShown()) then |
SGI_Options.classLimitHigh:Show(); |
end |
if (not SGI_Options.raceLimitHigh:IsShown()) then |
SGI_Options.raceLimitHigh:Show(); |
end |
else |
SGI_Options.Interval:Hide(); |
SGI_Options.classLimitHigh:Hide(); |
SGI_Options.raceLimitHigh:Hide(); |
end |
BUTTON_INVITE.label:SetText(format(SGI.L["Invite: %d"],SGI:GetNumQueued())); |
BUTTON_KEYBIND.label:SetText(SGI.L["Set Keybind ("..(SGI_DATA[SGI_DATA_INDEX].keyBind and SGI_DATA[SGI_DATA_INDEX].keyBind or "NONE")..")"]); |
if (SGI_DATA[SGI_DATA_INDEX].debug) then |
SGI_Options.title:SetText("|cffff3300(DEBUG MODE) |rSuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options") |
else |
SGI_Options.title:SetText("SuperGuildInvite "..SGI.VERSION_MAJOR..SGI.VERSION_MINOR.." Options") |
end |
if (not SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_HIDE_MINIMAP"]) then |
SGI:ShowMinimapButton(); |
else |
SGI:HideMinimapButton(); |
end |
SGI_Options.nextUpdate = GetTime() + 1; |
end |
end) |
end |
function SGI:ShowOptions() |
if (not SGI_Options) then |
CreateOptions(); |
end |
SGI_Options:Show(); |
end |
function SGI:HideOptions() |
if (SGI_Options) then |
SGI_Options:Hide(); |
end |
end |
local function CreateMinimapButton() |
local f = CreateFrame("Button","SGI_MiniMapButton",Minimap) |
f:SetWidth(32) |
f:SetHeight(32) |
f:SetFrameStrata("MEDIUM") |
f:SetMovable(true) |
SetFramePosition(f) |
f:SetNormalTexture("Interface\\AddOns\\SuperGuildInvite2\\media\\SGI_MiniMapButton") |
f:SetPushedTexture("Interface\\AddOns\\SuperGuildInvite2\\media\\SGI_MiniMapButtonPushed") |
f:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") |
local tooltip = CreateFrame("Frame","SGI_TooltTipMini",f,"GameTooltipTemplate") |
tooltip:SetPoint("BOTTOMRIGHT",f,"TOPLEFT",0,-3) |
local toolstring = tooltip:CreateFontString(nil,"OVERLAY","GameFontNormal") |
toolstring:SetPoint("TOPLEFT",tooltip,"TOPLEFT",5,-7) |
local toolstring2 = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
local toolstring3 = tooltip:CreateFontString(nil, "OVERLAY", "GameFontNormal"); |
toolstring2:SetPoint("TOPLEFT",tooltip,"TOPLEFT",7,-33); |
toolstring3:SetPoint("TOPLEFT", tooltip, "TOPLEFT", 7, -46); |
toolstring2:SetText(format("ETR: %s",SGI:GetSuperScanTimeLeft())); |
toolstring3:SetText(format("%d%% done",floor(SGI:GetPercentageDone()))); |
local tUpdate = 0; |
local function UpdateTooltip() |
if (tUpdate < GetTime()) then |
toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: %d|r",SGI:GetNumQueued())) |
toolstring2:SetText(format("ETR: %s",SGI:GetSuperScanTimeLeft())); |
toolstring3:SetText(format("%d%% done",floor(SGI:GetPercentageDone()))); |
--SGI:debug(format("ETR: %s",SGI:GetSuperScanETR())); |
--SGI:debug(format("%d%% done",floor(SGI:GetPercentageDone()))); |
tUpdate = GetTime() + 0.2; |
end |
end |
toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: |r|cffffff00%d|r",SGI:GetNumQueued())) |
toolstring:SetJustifyH("LEFT"); |
tooltip:SetWidth(max(toolstring:GetWidth(),toolstring2:GetWidth(),toolstring3:GetWidth())+ 20) |
tooltip:SetHeight(toolstring:GetHeight() + toolstring2:GetHeight() + toolstring3:GetHeight() + 15) |
tooltip:Hide() |
f:SetScript("OnEnter",function() |
toolstring:SetText(SGI.LOGO..format("|cff88aaffSuperGuildInvite|r\n|cff16ABB5Queue: %d|r",SGI:GetNumQueued())) |
tooltip:Show() |
tooltip:SetScript("OnUpdate",UpdateTooltip); |
end) |
f:SetScript("OnLeave",function() |
tooltip:Hide() |
tooltip:SetScript("OnUpdate", nil); |
end) |
local function moveButton(self) |
local centerX, centerY = Minimap:GetCenter() |
local x, y = GetCursorPosition() |
x, y = x / self:GetEffectiveScale() - centerX, y / self:GetEffectiveScale() - centerY |
centerX, centerY = math.abs(x), math.abs(y) |
centerX, centerY = (centerX / math.sqrt(centerX^2 + centerY^2)) * 85, (centerY / sqrt(centerX^2 + centerY^2)) * 85 |
centerX = x < 0 and -centerX or centerX |
centerY = y < 0 and -centerY or centerY |
self:ClearAllPoints() |
self:SetPoint("CENTER", centerX, centerY) |
end |
f:SetScript("OnMouseDown",function(self,button) |
if button == "RightButton" then |
self:SetScript("OnUpdate",moveButton) |
end |
end) |
f:SetScript("OnMouseUp",function(self,button) |
self:SetScript("OnUpdate",nil) |
SaveFramePosition(self) |
end) |
f:SetScript("OnClick",function(self,button) |
if SGI_Options and SGI_Options:IsShown() then |
SGI:HideOptions() |
else |
SGI:ShowOptions() |
end |
end) |
end |
function SGI:ShowMinimapButton() |
if (not SGI_MiniMapButton) then |
CreateMinimapButton(); |
end |
SGI_MiniMapButton:Show(); |
end |
function SGI:HideMinimapButton() |
if (SGI_MiniMapButton) then |
SGI_MiniMapButton:Hide(); |
end |
end |
SGI:debug(">> GUI.lua"); |
--[[ |
Filter structure: |
= { |
nameFilter = "A", |
exclusiveFilter = true, |
maxLvl = 10, |
minLvL = 1, |
race = { |
["Tauren"] = true, |
}, |
class = { |
["DEATHKNIGHT"] = true, |
}, |
} |
]] |
local function AddFilter(filter) |
tinsert(SGI_DATA[SGI_DATA_INDEX].settings.filters, filter); |
end |
function SGI:CreateFilter(nameOfFilter,class, name, minLvl, maxLvl, race, maxVowels, maxConsonants, active) |
if (not nameOfFilter) then |
return; |
end |
local filter = { |
nameOfFilter = nameOfFilter, |
race = race, |
class = class, |
name = name, |
minLvl = minLvl, |
maxLvl = maxLvl, |
maxVowels = maxVowels, |
maxConsonants = maxConsonants, |
active = active, |
} |
AddFilter(filter); |
end |
function SGI:RemoveFilter(filterName) |
end |
local function GetMaxNumberConsequtiveVowels(word) |
local vowels = { |
["a"] = 1, |
["o"] = 1, |
["u"] = 1, |
["y"] = 1, |
["i"] = 1, |
["e"] = 1, |
} |
local c = 0; |
local max = 0; |
for i = 1, strlen(word) do |
if (vowels[strsub(word, i, i)]) then |
c = c + 1; |
else |
c = 0; |
end |
if (c > max) then |
max = c; |
end |
end |
return max; |
end |
local function GetMaxNumberConsequtiveConsonants(word) |
local vowels = { |
["a"] = 1, |
["o"] = 1, |
["u"] = 1, |
["y"] = 1, |
["i"] = 1, |
["e"] = 1, |
} |
local c = 0; |
local max = 0; |
for i = 1, strlen(word) do |
if (vowels[strsub(word, i, i)]) then |
c = 0; |
else |
c = c + 1; |
end |
if (c > max) then |
max = c; |
end |
end |
return max; |
end |
function SGI:TestCharacters(word) |
local V = GetMaxNumberConsequtiveVowels(word); |
local C = GetMaxNumberConsequtiveConsonants(word); |
SGI:print("Vowels: "..V.." Consonants: "..C); |
end |
local function debugPlayer(player) |
local text = "|cff"..SGI:GetClassColor(player.class)..player.name.."|r ("..player.level..") ("..player.race..")"; |
return text |
end |
local function match(filter, player) |
--Is this filter for the players class/race? |
if (type(filter.race) == "table" and SGI:CountTable(filter.race) ~= 0) then |
if (not filter.race[player.race]) then |
return false; |
end |
end |
if (type(filter.class) == "table" and SGI:CountTable(filter.class) ~= 0) then |
if (not filter.class[player.class]) then |
return false; |
end |
end |
-- Is the player within the level range? |
if (type(filter.minLvl) == "number") then |
if (filter.minLvl > player.level) then |
return false; |
end |
end |
if (type(filter.maxLvl) == "number") then |
if (filter.maxLvl < player.level) then |
return false; |
end |
end |
if (type(filter.name) == "string" and filter.name ~= "") then |
if not (strfind(player.name,filter.name)) then |
return false; |
end |
end |
if (type(filter.maxVowels) == "number") then |
if (filter.maxVowels >= GetMaxNumberConsequtiveVowels(player.name)) then |
return false; |
end |
end |
if (type(filter.maxConsonants) == "number") then |
if (filter.maxConsonants >= GetMaxNumberConsequtiveConsonants(player.name)) then |
return false; |
end |
end |
SGI:debug("Filter: "..filter.nameOfFilter.." "..debugPlayer(player)); |
return true; |
end |
local function GetActiveFilters() |
local filters, activeFilters = SGI_DATA[SGI_DATA_INDEX].settings.filters, {}; |
if (type(filters) ~= "table") then |
return {}; |
end |
for k,_ in pairs(filters) do |
if (filters[k]["active"]) then |
activeFilters[k] = filters[k]; |
end |
end |
return activeFilters; |
end |
function SGI:FilterPlayer(player) |
local filters = GetActiveFilters();--SGI_DATA[SGI_DATA_INDEX].settings.filters; |
if (type(filters) ~= "table" or type(player) ~= "table") then |
--if invalid parameter, return as filtered |
SGI:debug("Error: Filter or player is not a table!"); |
return false; |
end |
for k,_ in pairs(filters) do |
if (match(filters[k], player)) then |
return false; |
end |
end |
return true; |
end |
SGI:debug(">> Filter.lua"); |
local MessageQueue = {}; |
SGI.ForceStop = {}; |
CreateFrame("Frame", "SGI_MESSAGE_TIMER"); |
SGI_MESSAGE_TIMER.update = 0; |
SGI_MESSAGE_TIMER:SetScript("OnUpdate", function() |
if (SGI_MESSAGE_TIMER.update < GetTime()) then |
for i = 1,5 do |
local key, messageToBeSent = next(MessageQueue); |
if (key and messageToBeSent) then |
if (SGI.ForceStop[messageToBeSent.receiver]) then |
MessageQueue[key] = nil; |
SGI.ForceStop[messageToBeSent.receiver] = nil; |
SGI:debug("Forced sendstop!"); |
return; |
end |
SendAddonMessage(ID_MASSLOCK, messageToBeSent.msg, "WHISPER", messageToBeSent.receiver); |
MessageQueue[key] = nil; |
SGI:debug("Send AddonMessage ("..messageToBeSent.msg..") to "..messageToBeSent.receiver); |
end |
end |
SGI_MESSAGE_TIMER.update = GetTime() + 2; |
end |
end) |
local function AddMessage(message, receiver) |
local newMessage = { |
msg = message, |
receiver = receiver, |
}; |
tinsert(MessageQueue, newMessage); |
end |
function SGI:StopMassShare(player) |
SGI.ForceStop[player] = true; |
end |
function SGI:IsSharing(player) |
for key, message in pairs(MessageQueue) do |
if (message.receiver == player) then |
return true; |
end |
end |
end |
local function RemoveLock(name) |
SGI_DATA.lock[name] = nil; |
end |
function SGI:IsLocked(name) |
return SGI_DATA.lock[name]; |
end |
function SGI:LockPlayer(name) |
if (not SGI:IsLocked(name)) then |
SGI_DATA.lock[name] = tonumber(date("%m")); |
end |
end |
function SGI:UnlockPlayer(name) |
RemoveLock(name); |
end |
function SGI:ShareLocks(name) |
local part = ID_MASSLOCK; |
for k,_ in pairs(SGI_DATA.lock) do |
if (strlen(part..":"..k) > 250) then |
AddMessage(part, name); |
part = ID_MASSLOCK; |
end |
part = part..":"..k; |
end |
AddMessage(part, name); |
end |
function SGI:ReceivedNewLocks(rawLocks) |
local locks = SGI:divideString(rawLocks, ":"); |
for k,_ in pairs(locks) do |
SGI:LockPlayer(locks[k]); |
end |
SGI:debug("Received locks!"); |
end |
function SGI:RemoveOutdatedLocks() |
local month = tonumber(date("%m")); |
for k,_ in pairs(SGI_DATA.lock) do |
if (month - 1) > SGI_DATA.lock[k] or (month < SGI_DATA.lock[k] and month > 1) then |
RemoveLock(k); |
end |
end |
end |
SGI:debug(">> Blacklist.lua"); |
local L; |
function SGI:LoadLocale() |
local Locale = GetLocale() |
if SGI_Locale[Locale] then |
SGI.L = SGI_Locale[Locale] |
L = SGI.L; |
SGI:print(L["English Locale loaded"]..L["Author"]) |
return true |
else |
SGI.L = SGI_Locale["enGB"] |
SGI:print("|cffffff00Locale missing! Loaded English.|r") |
return false |
end |
end |
function SGI:FormatTime2(T) |
local R,S,M,H = "" |
T = floor(T) |
H = floor(T/3600) |
M = floor((T-3600*H)/60) |
S = T-(3600*H + 60*M) |
if T <= 0 then |
return L[" < 1 sec"] |
end |
if H ~= 0 then |
R = R..H..L["h "] |
end |
if M ~= 0 then |
R = R..M..L["m "] |
end |
if S ~= 0 then |
R = R..S..L["s"] |
end |
return R |
end |
function SGI:FormatTime(T) |
local R,S,M,H = "" |
T = floor(T); |
H = floor(T/3600) |
M = floor((T-3600*H)/60) |
S = T-(3600*H + 60*M) |
if (T <= 0) then |
return SGI.L[" < 1 sec"]; |
end |
if (H > 0) then |
R = R..H..":"; |
end |
if (M > 9) then |
R = R..M..":"; |
elseif (M > 0) then |
R = R.."0"..M..":"; |
elseif (M == 0) then |
R = R.."00:"; |
end |
if (S > 9) then |
R = R..S; |
elseif (S > 0) then |
R = R.."0"..S; |
elseif (S == 0) then |
R = R.."00"; |
end |
return R; |
end |
function SGI:CountTable(T) |
local i = 0 |
if type(T) ~= "table" then |
return i |
end |
for k,_ in pairs(T) do |
i = i + 1 |
end |
return i |
end |
function SGI:GetClassColor(classFileName) |
return SGI_CLASS_COLORS[classFileName]; |
end |
function SGI:CompareVersions(V1, V2) |
local p11 = tonumber(strsub(V1,1,strfind(V1,".",1,true)-1)); |
local p12 = tonumber(strsub(V1,strfind(V1,".",1,true)+1)); |
local p21 = tonumber(strsub(V2,1,strfind(V2,".",1,true)-1)); |
local p22 = tonumber(strsub(V2,strfind(V2,".",1,true)+1)); |
if (p11 == p21) then |
if (p22 > p12) then |
return V2; |
else |
return V1; |
end |
elseif (p21 > p11) then |
return V2; |
else |
return V1; |
end |
end |
function SGI:ResetFix() |
if (not SGI_DATA.resetFix) then |
SGI_DATA = {}; |
SGI_DATA.resetFix = true; |
end |
end |
function SGI:divideString(str,div) |
local out = {} |
local i = 0 |
while strfind(str,div) do |
i = i + 1 |
out[i] = strsub(str,1,strfind(str,div)-1) |
str = strsub(str,strfind(str,div)+1) |
end |
out[i+1] = str |
return out |
end |
local function FrameReset() |
SGI_DATA[SGI_DATA_INDEX].settings.frames = {} |
ReloadUI(); |
end |
local reloadWarning = true; |
local reloadWarning2 = true; |
function SlashCmdList.SUPERGUILDINVITE(msg) |
msg = strlower(msg); |
if msg == "reset" then |
local lock = SGI_DATA.lock |
SGI_DATA = nil |
SGI_EVENTS["PLAYER_LOGIN"]() |
SGI_DATA.lock = lock |
elseif (msg == "framereset") then |
if (reloadWarning) then |
SGI:print("WARNING: Reseting your frames requires a reload of the User Interface! If you wish to proceed, type \"/sgi framereset\" again!"); |
reloadWarning = false; |
else |
FrameReset(); |
end |
elseif (msg == "opt" or msg == "options" or msp == "config" or msg == "settings" or msg == "show") then |
SGI:ShowOptions(); |
elseif (msg == "debug") then |
SGI_DATA[SGI_DATA_INDEX].debug = not SGI_DATA[SGI_DATA_INDEX].debug; |
if (SGI_DATA[SGI_DATA_INDEX].debug) then |
SGI:print("Activated debugging!"); |
else |
SGI:print("Deactivated debugging!"); |
end |
SGI:DebugState(SGI_DATA[SGI_DATA_INDEX].debug); |
elseif (msg == "changes") then |
SGI:ShowChanges(); |
elseif (msg == "stats") then |
local amountScanned, amountGuildless, amountQueued, sessionTotal = SGI:GetSuperScanStats(); |
SGI:print("Scanned players this scan: |r|cff0062FF"..amountScanned.."|r"); |
SGI:print("Guildless players this scan: |r|cff0062FF"..amountGuildless.."|r"); |
SGI:print("Queued players this scan: |r|cff0062FF"..amountQueued.."|r"); |
SGI:print("Total players scanned this session: |r|cff0062FF"..sessionTotal.."|r"); |
elseif (msg == "unbind" or msg == "removekeybind") then |
SGI:print("Cleared SGI invite keybind"); |
SGI_DATA[SGI_DATA_INDEX].keyBind = nil; |
elseif (strfind(msg, "lock")) then |
local name = strsub(msg, 6); |
if (name) then |
SGI:LockPlayer(name); |
end |
else |
local temp = SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"]; |
SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"] = false; |
SGI:print("|cffffff00Commands: |r|cff00A2FF/sgi or /superguildinvite|r") |
SGI:print("|cff00A2FFreset |r|cffffff00to reset all data except locks|r") |
SGI:print("|cff00A2FFframereset|r|cffffff00 resets the positions of the frames |r") |
SGI:print("|cff00A2FFunbind|r|cffffff00 removes the saved keybind|r"); |
SGI:print("|cff00A2FFoptions|r|cffffff00 shows the options. Same effect as clicking the minimap button|r") |
SGI_DATA[SGI_DATA_INDEX].settings.checkBox["CHECKBOX_SGI_MUTE"] = temp; |
end |
end |
SGI:debug(">> Core.lua"); |
local function ProcessSystemMsg(msg) |
local place = strfind(ERR_GUILD_INVITE_S,"%s",1,true) |
if (place) then |
local n = strsub(msg,place) |
local name = strsub(n,1,(strfind(n,"%s") or 2)-1) |
if format(ERR_GUILD_INVITE_S,name) == msg then |
return "invite",name |
end |
end |
place = strfind(ERR_GUILD_DECLINE_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-1) |
if format(ERR_GUILD_DECLINE_S,name) == msg then |
return "decline",name |
end |
end |
place = strfind(ERR_ALREADY_IN_GUILD_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-1) |
if format(ERR_ALREADY_IN_GUILD_S,name) == msg then |
return "guilded",name |
end |
end |
place = strfind(ERR_ALREADY_INVITED_TO_GUILD_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-1) |
if format(ERR_ALREADY_INVITED_TO_GUILD_S,name) == msg then |
return "already",name |
end |
end |
place = strfind(ERR_GUILD_DECLINE_AUTO_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-1) |
if format(ERR_GUILD_DECLINE_AUTO_S,name) == msg then |
return "auto",name |
end |
end |
place = strfind(ERR_GUILD_JOIN_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-1) |
if format(ERR_GUILD_JOIN_S,name) == msg then |
return "join",name |
end |
end |
place = strfind(ERR_GUILD_PLAYER_NOT_FOUND_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-2) |
if format(ERR_GUILD_PLAYER_NOT_FOUND_S,name) == msg then |
return "miss",name |
end |
end |
place = strfind(ERR_CHAT_PLAYER_NOT_FOUND_S,"%s",1,true) |
if (place) then |
n = strsub(msg,place) |
name = strsub(n,1,(strfind(n,"%s") or 2)-2) |
if format(ERR_CHAT_PLAYER_NOT_FOUND_S,name) == msg then |
return "out",name |
end |
end |
return "unregistered message", "N/A"; |
end |
function SGI:SystemMessage(event,_,message,...) |
local type, name = ProcessSystemMsg(message); |
SGI:debug("Type: "..type.." Name: "..name); |
if (type == "invite") then |
if (SGI:IsRegisteredForWhisper(name)) then |
SGI:SendWhisper(SGI:FormatWhisper(SGI:PickRandomWhisper(), name), name, 1); |
end |
elseif (type == "decline") then |
SGI:UnregisterForWhisper(name); |
elseif (type == "auto") then |
SGI:LockPlayer(name); |
SGI:UnregisterForWhisper(name); |
elseif (type == "guilded") then |
SGI:LockPlayer(name); |
SGI:UnregisterForWhisper(name); |
elseif (type == "already") then |
SGI:LockPlayer(name); |
SGI:UnregisterForWhisper(name); |
elseif (type == "join") then |
if (CanEditOfficerNote()) then |
for i = 1,GetNumGuildMembers() do |
local n = GetGuildRosterInfo(i); |
if (n == name) then |
GuildRosterSetOfficerNote(i, date()); |
end |
end |
elseif (CanEditPublicNote()) then |
for i = 1,GetNumGuildMembers() do |
local n = GetGuildRosterInfo(i); |
if (n == name) then |
GuildRosterSetPublicNote(i, date()); |
end |
end |
end |
elseif (type == "miss") then |
if (SGI:IsSharing(name)) then |
SGI:StopMassShare(name); |
debug("Stopped mass share!"); |
end |
SGI:print(format(SGI.L["Unable to invite %s. They will not be locked."],name)); |
SGI:UnlockPlayer(name); |
SGI:UnregisterForWhisper(name); |
elseif (type == "out") then |
-- hmm... |
if (SGI:IsSharing(name)) then |
SGI:StopMassShare(name); |
debug("Stopped mass share!"); |
end |
SGI:RemoveQueued(name); |
end |
end |
SGI:debug(">> System_Message.lua"); |
local ID_REQUEST = "SGI_REQ"; |
ID_MASSLOCK = "SGI_MASS"; |
local ID_LOCK = "SGI_LOCK"; |
local ID_SHIELD = "I_HAVE_SHIELD"; |
local ID_VERSION = "SGI_VERSION"; |
local ID_LIVE_SYNC = "SGI_LIVE_SYNC"; |
local ID_PING = "SGI_PING"; |
local ID_PONG = "SGI_PONG"; |
local ID_STOP = "SGI_STOP"; |
RegisterAddonMessagePrefix(ID_REQUEST); |
RegisterAddonMessagePrefix(ID_LOCK); |
RegisterAddonMessagePrefix(ID_SHIELD); |
RegisterAddonMessagePrefix(ID_MASSLOCK); |
RegisterAddonMessagePrefix(ID_VERSION); |
RegisterAddonMessagePrefix(ID_LIVE_SYNC); |
RegisterAddonMessagePrefix(ID_PING); |
RegisterAddonMessagePrefix(ID_STOP); |
function SGI:AddonMessage(event,...) |
local ID, msg, channel, sender = ...; |
if (not SGI_DATA[SGI_DATA_INDEX].debug and sender == UnitName("player")) then return end |
if (ID == ID_SHIELD) then |
SGI:LockPlayer(sender); |
SGI:RemoveShielded(sender); |
SGI:debug("SHIELD: "..ID.." "..msg.." "..sender); |
elseif (ID == ID_LOCK) then |
SGI:LockPlayer(sender); |
SGI:debug("LOCKING: "..ID.." "..msg.." "..sender); |
elseif (ID == ID_REQUEST) then |
SGI:ShareLocks(sender); |
SGI:debug("SHARING: "..ID.." "..msg.." "..sender); |
elseif (ID == ID_MASSLOCK) then |
SGI:ReceivedNewLocks(msg); |
SGI:debug("RECEIVING: "..ID.." "..msg.." "..sender); |
elseif (ID == ID_VERSION) then |
SGI:debug("VERSION: "..ID.." "..msg.." "..sender); |
local receivedVersion = msg; |
if (new == SGI:CompareVersions(SGI.VERSION_MAJOR, receivedVersion)) then |
SGI:print("|cffffff00A new version (|r|cff00A2FF"..new.."|r|cffffff00) of |r|cff16ABB5SuperGuildInvite|r|cffffff00 is available at curse.com!"); |
if Alerter and not SGI.VERSION_ALERT_COOLDOWN then |
Alerter:SendAlert("|cffffff00A new version (|r|cff00A2FF"..new.."|r|cffffff00) of |r|cff16ABB5SuperGuildInvite|r|cffffff00 is available at curse.com!",1.5) |
SGI.VERSION_ALERT_COOLDOWN = true; |
end |
end |
elseif (ID == ID_LIVE_SYNC) then |
SGI:debug("LIVESYNC: "..ID.." "..msg.." "..sender); |
SGI:RemoveQueued(msg); |
elseif (ID == ID_STOP) then |
elseif (ID == ID_PING) then |
SGI:PingedByJanniie(sender); |
end |
end |
function SGI:LiveSync(player) |
SendAddonMessage(ID_LIVE_SYNC, player, "GUILD"); |
end |
function SGI:BroadcastVersion(target) |
if (target == "GUILD") then |
SendAddonMessage(ID_VERSION, SGI.VERSION_MAJOR, "GUILD"); |
else |
SendAddonMessage(ID_VERSION, SGI.VERSION_MAJOR, "WHISPER", target); |
end |
end |
function SGI:PingedByJanniie(sender) |
SendAddonMessage("SGI_PONG", SGI.VERSION_MAJOR, "WHISPER", sender); |
end |
function SGI:RequestSync() |
SendAddonMessage(ID_REQUEST, "", "GUILD"); |
end |
SGI:debug(">> AddOn_Message.lua"); |
------------------------------------------------------------------------ |
r146 | mysticalos | 2015-02-24 16:45:37 +0000 (Tue, 24 Feb 2015) | 1 line |
Changed paths: |
A /tags/2.0.146 (from /trunk:145) |
Tagging as 2.0.146 |
------------------------------------------------------------------------ |
r145 | MysticalOS | 2015-02-24 16:43:23 +0000 (Tue, 24 Feb 2015) | 1 line |
Changed paths: |
M /trunk/LibWho-2.0.toc |
ToC |
------------------------------------------------------------------------ |
r143 | sylvanaar | 2015-02-01 17:28:35 +0000 (Sun, 01 Feb 2015) | 1 line |
Changed paths: |
M /trunk/LibWho-2.0/LibWho-2.0.lua |
Fix compatibility error with Swatter. Issue #25 |
------------------------------------------------------------------------ |
r142 | sylvanaar | 2015-02-01 17:26:11 +0000 (Sun, 01 Feb 2015) | 1 line |
Changed paths: |
M /trunk/LibWho-2.0/LibWho-2.0.lua |
Fix 0/1 false/true errors. Issue #24 |
------------------------------------------------------------------------ |
--- |
--- check for an already loaded old WhoLib |
--- |
if WhoLibByALeX or WhoLib then |
-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail! |
error("an other WhoLib is already running - disable them first!\n") |
return |
end -- if |
--- |
--- check version |
--- |
assert(LibStub, "LibWho-2.0 requires LibStub") |
local major_version = 'LibWho-2.0' |
local minor_version = tonumber("145") or 99999 |
local lib = LibStub:NewLibrary(major_version, minor_version) |
if not lib then |
return -- already loaded and no upgrade necessary |
end |
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) |
local callbacks = lib.callbacks |
local am = {} |
local om = getmetatable(lib) |
if om then |
for k, v in pairs(om) do am[k] = v end |
end |
am.__tostring = function() return major_version end |
setmetatable(lib, am) |
local function dbgfunc(...) if lib.Debug then print(...) end end |
local function NOP() return end |
local dbg = NOP |
--- |
--- initalize base |
--- |
if type(lib['hooked']) ~= 'table' then |
lib['hooked'] = {} |
end -- if |
if type(lib['hook']) ~= 'table' then |
lib['hook'] = {} |
end -- if |
if type(lib['events']) ~= 'table' then |
lib['events'] = {} |
end -- if |
if type(lib['embeds']) ~= 'table' then |
lib['embeds'] = {} |
end -- if |
if type(lib['frame']) ~= 'table' then |
lib['frame'] = CreateFrame('Frame', major_version); |
end -- if |
lib['frame']:Hide() |
lib.Queue = {[1]={}, [2]={}, [3]={}} |
lib.WhoInProgress = false |
lib.Result = nil |
lib.Args = nil |
lib.Total = nil |
lib.Quiet = nil |
lib.Debug = false |
lib.Cache = {} |
lib.CacheQueue = {} |
lib.SetWhoToUIState = false |
lib.MinInterval = 2.5 |
lib.MaxInterval = 10 |
--- |
--- locale |
--- |
if (GetLocale() == "ruRU") then |
lib.L = { |
['console_queued'] = 'Ðобавлено в оÑеÑÐµÐ´Ñ "/who %s"', |
['console_query'] = 'РезÑлÑÑÐ°Ñ "/who %s"', |
['gui_wait'] = '- ÐожалÑйÑÑа подождиÑе -', |
} |
else |
-- enUS is the default |
lib.L = { |
['console_queued'] = 'Added "/who %s" to queue', |
['console_query'] = 'Result of "/who %s"', |
['gui_wait'] = '- Please Wait -', |
} |
end -- if |
--- |
--- external functions/constants |
--- |
lib['external'] = { |
'WHOLIB_QUEUE_USER', |
'WHOLIB_QUEUE_QUIET', |
'WHOLIB_QUEUE_SCANNING', |
'WHOLIB_FLAG_ALWAYS_CALLBACK', |
'Who', |
'UserInfo', |
'CachedUserInfo', |
'GetWhoLibDebug', |
'SetWhoLibDebug', |
-- 'RegisterWhoLibEvent', |
} |
-- queues |
lib['WHOLIB_QUEUE_USER'] = 1 |
lib['WHOLIB_QUEUE_QUIET'] = 2 |
lib['WHOLIB_QUEUE_SCANNING'] = 3 |
local queue_all = { |
[1] = 'WHOLIB_QUEUE_USER', |
[2] = 'WHOLIB_QUEUE_QUIET', |
[3] = 'WHOLIB_QUEUE_SCANNING', |
} |
local queue_quiet = { |
[2] = 'WHOLIB_QUEUE_QUIET', |
[3] = 'WHOLIB_QUEUE_SCANNING', |
} |
-- bit masks! |
lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1 |
function lib:Reset() |
self.Queue = {[1]={}, [2]={}, [3]={}} |
self.Cache = {} |
self.CacheQueue = {} |
end |
function lib.Who(defhandler, query, opts) |
local self, args, usage = lib, {}, 'Who(query, [opts])' |
args.query = self:CheckArgument(usage, 'query', 'string', query) |
opts = self:CheckArgument(usage, 'opts', 'table', opts, {}) |
args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING) |
args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0) |
args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler) |
-- now args - copied and verified from opts |
if args.queue == self.WHOLIB_QUEUE_USER then |
if WhoFrame:IsShown() then |
self:GuiWho(args.query) |
else |
self:ConsoleWho(args.query) |
end |
else |
self:AskWho(args) |
end |
end |
local function ignoreRealm(name) |
local _, realm = string.split("-", name) |
local connectedServers = GetAutoCompleteRealms() |
if connectedServers then |
for i = 1, #connectedServers do |
if realm == connectedServers[i] then return false end |
end |
end |
return true |
end |
function lib.UserInfo(defhandler, name, opts) |
local self, args, usage = lib, {}, 'UserInfo(name, [opts])' |
local now = time() |
name = self:CheckArgument(usage, 'name', 'string', name) |
if name:len() == 0 then return end |
--There is no api to tell connected realms from cross realm by name. As such, we check known connections table before excluding who inquiry |
--UnitRealmRelationship and UnitIsSameServer don't work with "name". They require unitID so they are useless here |
if name:find("%-") and ignoreRealm(name) then return end |
args.name = self:CapitalizeInitial(name) |
opts = self:CheckArgument(usage, 'opts', 'table', opts, {}) |
args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING) |
args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0) |
args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5) |
args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler) |
-- now args - copied and verified from opts |
local cachedName = self.Cache[args.name] |
if(cachedName ~= nil)then |
-- user is in cache |
if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then |
-- cache is valid and timeout is in range |
--dbg('Info(' .. args.name ..') returned immedeatly') |
if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then |
self:RaiseCallback(args, cachedName.data) |
return false |
else |
return self:DupAll(self:ReturnUserInfo(args.name)) |
end |
elseif(cachedName.valid == false)then |
-- query is already running (first try) |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
--dbg('Info(' .. args.name ..') returned cause it\'s already searching') |
return nil |
end |
else |
self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now } |
end |
local cachedName = self.Cache[args.name] |
if(cachedName.inqueue)then |
-- query is running! |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
dbg('Info(' .. args.name ..') returned cause it\'s already searching') |
return nil |
end |
if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon |
if args.name and args.name:len() > 0 then |
local query = 'и-"' .. args.name .. '"' |
cachedName.inqueue = true |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
self.CacheQueue[query] = args.name |
dbg('Info(' .. args.name ..') added to queue') |
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) |
end |
else |
if args.name and args.name:len() > 0 then |
local query = 'n-"' .. args.name .. '"' |
cachedName.inqueue = true |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
self.CacheQueue[query] = args.name |
dbg('Info(' .. args.name ..') added to queue') |
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) |
end |
end |
return nil |
end |
function lib.CachedUserInfo(_, name) |
local self, usage = lib, 'CachedUserInfo(name)' |
name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name)) |
if self.Cache[name] == nil then |
return nil |
else |
return self:DupAll(self:ReturnUserInfo(name)) |
end |
end |
function lib.GetWhoLibDebug(_, mode) |
return lib.Debug |
end |
function lib.SetWhoLibDebug(_, mode) |
lib.Debug = mode |
dbg = mode and dbgfunc or NOP |
end |
--function lib.RegisterWhoLibEvent(defhandler, event, callback, handler) |
-- local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])' |
-- |
-- self:CheckPreset(usage, 'event', self.events, event) |
-- local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true) |
-- table.insert(self.events[event], {callback=callback, handler=handler}) |
--end |
-- non-embedded externals |
function lib.Embed(_, handler) |
local self, usage = lib, 'Embed(handler)' |
self:CheckArgument(usage, 'handler', 'table', handler) |
for _,name in pairs(self.external) do |
handler[name] = self[name] |
end -- do |
self['embeds'][handler] = true |
return handler |
end |
function lib.Library(_) |
local self = lib |
return self:Embed({}) |
end |
--- |
--- internal functions |
--- |
function lib:AllQueuesEmpty() |
local queueCount = #self.Queue[1] + #self.Queue[2] + #self.Queue[3] + #self.CacheQueue |
-- Be sure that we have cleared the in-progress status |
if self.WhoInProgress then |
queueCount = queueCount + 1 |
end |
return queueCount == 0 |
end |
local queryInterval = 5 |
function lib:GetQueryInterval() return queryInterval end |
function lib:AskWhoNextIn5sec() |
if self.frame:IsShown() then return end |
dbg("Waiting to send next who") |
self.Timeout_time = queryInterval |
self['frame']:Show() |
end |
function lib:CancelPendingWhoNext() |
lib['frame']:Hide() |
end |
lib['frame']:SetScript("OnUpdate", function(frame, elapsed) |
lib.Timeout_time = lib.Timeout_time - elapsed |
if lib.Timeout_time <= 0 then |
lib['frame']:Hide() |
lib:AskWhoNext() |
end -- if |
end); |
-- queue scheduler |
local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 } |
local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 } |
-- allow for single queries from the user to get processed faster |
local lastInstantQuery = time() |
local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min |
function lib:UpdateWeights() |
local weightsum, sum, count = 0, 0, 0 |
for k,v in pairs(queue_weights) do |
sum = sum + v |
weightsum = weightsum + v * #self.Queue[k] |
end |
if weightsum == 0 then |
for k,v in pairs(queue_weights) do queue_bounds[k] = v end |
return |
end |
local adjust = sum / weightsum |
for k,v in pairs(queue_bounds) do |
queue_bounds[k] = queue_weights[k] * adjust * #self.Queue[k] |
end |
end |
function lib:GetNextFromScheduler() |
self:UpdateWeights() |
-- Since an addon could just fill up the user q for instant processing |
-- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL |
-- and only try instant fulfilment if it will empty the user queue |
if #self.Queue[1] == 1 then |
if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then |
dbg("INSTANT") |
lastInstantQuery = time() |
return 1, self.Queue[1] |
end |
end |
local n,i = math.random(),0 |
repeat |
i=i+1 |
n = n - queue_bounds[i] |
until i>=#self.Queue or n <= 0 |
dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i])) |
if #self.Queue[i] > 0 then |
dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i])) |
return i, self.Queue[i] |
else |
dbg("Queues empty, waiting") |
end |
end |
lib.queue_bounds = queue_bounds |
function lib:AskWhoNext() |
if lib.frame:IsShown() then |
dbg("Already waiting") |
return |
end |
self:CancelPendingWhoNext() |
if self.WhoInProgress then |
-- if we had a who going, it didnt complete |
dbg("TIMEOUT: "..self.Args.query) |
local args = self.Args |
self.Args = nil |
-- if args.info and self.CacheQueue[args.query] ~= nil then |
dbg("Requeing "..args.query) |
tinsert(self.Queue[args.queue], args) |
if args.console_show ~= nil then |
DEFAULT_CHAT_FRAME:AddMessage(("Timeout on result of '%s' - retrying..."):format(args.query),1,1,0) |
args.console_show = true |
end |
-- end |
if queryInterval < lib.MaxInterval then |
queryInterval = queryInterval + 0.5 |
dbg("--Throttling down to 1 who per " .. queryInterval .. "s") |
end |
end |
self.WhoInProgress = false |
local v,k,args = nil |
local kludge = 10 |
repeat |
k,v = self:GetNextFromScheduler() |
if not k then break end |
if(WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET)then |
break |
end |
if(#v > 0)then |
args = tremove(v, 1) |
break |
end |
kludge = kludge - 1 |
until kludge <= 0 |
if args then |
self.WhoInProgress = true |
self.Result = {} |
self.Args = args |
self.Total = -1 |
if(args.console_show == true)then |
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0) |
end |
if args.queue == self.WHOLIB_QUEUE_USER then |
WhoFrameEditBox:SetText(args.query) |
self.Quiet = false |
if args.whotoui then |
self.hooked.SetWhoToUI(args.whotoui) |
else |
self.hooked.SetWhoToUI(args.gui and true or false) |
end |
else |
self.hooked.SetWhoToUI(true) |
self.Quiet = true |
end |
dbg("QUERY: "..args.query) |
self.hooked.SendWho(args.query) |
else |
self.Args = nil |
self.WhoInProgress = false |
end |
-- Keep processing the who queue if there is more work |
if not self:AllQueuesEmpty() then |
self:AskWhoNextIn5sec() |
else |
dbg("*** Done processing requests ***") |
end |
end |
function lib:AskWho(args) |
tinsert(self.Queue[args.queue], args) |
dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3]) |
self:TriggerEvent('WHOLIB_QUERY_ADDED') |
self:AskWhoNext() |
end |
function lib:ReturnWho() |
if not self.Args then |
self.Quiet = nil |
return |
end |
if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then |
self.Quiet = nil |
end |
if queryInterval > self.MinInterval then |
queryInterval = queryInterval - 0.5 |
dbg("--Throttling up to 1 who per " .. queryInterval .. "s") |
end |
self.WhoInProgress = false |
dbg("RESULT: "..self.Args.query) |
dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3]) |
local now = time() |
local complete = (self.Total == #self.Result) and (self.Total < MAX_WHOS_FROM_SERVER) |
for _,v in pairs(self.Result)do |
if(self.Cache[v.Name] == nil)then |
self.Cache[v.Name] = { inqueue = false, callback = {} } |
end |
local cachedName = self.Cache[v.Name] |
cachedName.valid = true -- is now valid |
cachedName.data = v -- update data |
cachedName.data.Online = true -- player is online |
cachedName.last = now -- update timestamp |
if(cachedName.inqueue)then |
if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then |
-- found by the query which was created to -> remove us from query |
self.CacheQueue[self.Args.query] = nil |
else |
-- found by another query |
for k2,v2 in pairs(self.CacheQueue) do |
if(v2 == v.Name)then |
for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do |
for k3,v3 in pairs(self.Queue[i]) do |
if(v3.query == k2 and v3.info)then |
-- remove the query which was generated for this user, cause another query was faster... |
dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'") |
table.remove(self.Queue[i], k3) |
self.CacheQueue[k2] = nil |
end |
end |
end |
end |
end |
end |
dbg('Info(' .. v.Name ..') returned: on') |
for _,v2 in pairs(cachedName.callback) do |
self:RaiseCallback(v2, self:ReturnUserInfo(v.Name)) |
end |
cachedName.callback = {} |
end |
cachedName.inqueue = false -- query is done |
end |
if(self.Args.info and self.CacheQueue[self.Args.query])then |
-- the query did not deliver the result => not online! |
local name = self.CacheQueue[self.Args.query] |
local cachedName = self.Cache[name] |
if (cachedName.inqueue)then |
-- nothing found (yet) |
cachedName.valid = true -- is now valid |
cachedName.inqueue = false -- query is done? |
cachedName.last = now -- update timestamp |
if(complete)then |
cachedName.data.Online = false -- player is offline |
else |
cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed) |
end |
end |
dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn')) |
for _,v in pairs(cachedName.callback) do |
self:RaiseCallback(v, self:ReturnUserInfo(name)) |
end |
cachedName.callback = {} |
self.CacheQueue[self.Args.query] = nil |
end |
self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info) |
self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info) |
if not self:AllQueuesEmpty() then |
self:AskWhoNextIn5sec() |
end |
end |
function lib:GuiWho(msg) |
if(msg == self.L['gui_wait'])then |
return |
end |
for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do |
if(v.gui == true)then |
return |
end |
end |
if(self.WhoInProgress)then |
WhoFrameEditBox:SetText(self.L['gui_wait']) |
end |
self.savedText = msg |
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true}) |
WhoFrameEditBox:ClearFocus(); |
end |
function lib:ConsoleWho(msg) |
--WhoFrameEditBox:SetText(msg) |
local console_show = false |
local q1 = self.Queue[self.WHOLIB_QUEUE_USER] |
local q1count = #q1 |
if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop |
return |
end |
if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown |
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0) |
q1[q1count].console_show = true |
end |
if(q1count > 0 or self.WhoInProgress)then |
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0) |
console_show = true |
end |
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show}) |
end |
function lib:ReturnUserInfo(name) |
if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then |
return self.Cache[name].data, (time() - self.Cache[name].last) / 60 |
end |
end |
function lib:RaiseCallback(args, ...) |
if type(args.callback) == 'function' then |
args.callback(self:DupAll(...)) |
elseif args.callback then -- must be a string |
args.handler[args.callback](args.handler, self:DupAll(...)) |
end -- if |
end |
-- Argument checking |
function lib:CheckArgument(func, name, argtype, arg, defarg) |
if arg == nil and defarg ~= nil then |
return defarg |
elseif type(arg) == argtype then |
return arg |
else |
error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3) |
end -- if |
end |
function lib:CheckPreset(func, name, preset, arg, defarg) |
if arg == nil and defarg ~= nil then |
return defarg |
elseif arg ~= nil and preset[arg] ~= nil then |
return arg |
else |
local p = {} |
for k,v in pairs(preset) do |
if type(v) ~= 'string' then |
table.insert(p, k) |
else |
table.insert(p, v) |
end -- if |
end -- for |
error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3) |
end -- if |
end |
function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil) |
if not nonil and callback == nil then |
-- no callback: ignore handler |
return nil, nil |
elseif type(callback) == 'function' then |
-- simple function |
if handler ~= nil then |
error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3) |
end -- if |
elseif type(callback) == 'string' then |
-- method |
if handler == nil then |
handler = defhandler |
end -- if |
if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then |
error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3) |
end -- if |
else |
error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3) |
end -- if |
return callback, handler |
end |
-- helpers |
function lib:simple_dump(x) |
if type(x) == 'string' then |
return 'string \''..x..'\'' |
elseif type(x) == 'number' then |
return 'number '..x |
else |
return type(x) |
end |
end |
function lib:Dup(from) |
local to = {} |
for k,v in pairs(from) do |
if type(v) == 'table' then |
to[k] = self:Dup(v) |
else |
to[k] = v |
end -- if |
end -- for |
return to |
end |
function lib:DupAll(x, ...) |
if type(x) == 'table' then |
return self:Dup(x), self:DupAll(...) |
elseif x ~= nil then |
return x, self:DupAll(...) |
else |
return nil |
end -- if |
end |
local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)" |
function lib:CapitalizeInitial(name) |
return name:gsub(MULTIBYTE_FIRST_CHAR, string.upper, 1) |
end |
--- |
--- user events (Using CallbackHandler) |
--- |
lib.PossibleEvents = { |
'WHOLIB_QUERY_RESULT', |
'WHOLIB_QUERY_ADDED', |
} |
function lib:TriggerEvent(event, ...) |
callbacks:Fire(event, ...) |
end |
--- |
--- slash commands |
--- |
SlashCmdList['WHO'] = function(msg) |
dbg("console /who: "..msg) |
-- new /who function |
--local self = lib |
if(msg == '')then |
lib:GuiWho(WhoFrame_GetDefaultWhoCommand()) |
elseif(WhoFrame:IsVisible())then |
lib:GuiWho(msg) |
else |
lib:ConsoleWho(msg) |
end |
end |
SlashCmdList['WHOLIB_DEBUG'] = function() |
-- /wholibdebug: toggle debug on/off |
local self = lib |
self:SetWhoLibDebug(not self.Debug) |
end |
SLASH_WHOLIB_DEBUG1 = '/wholibdebug' |
--- |
--- hook activation |
--- |
-- functions to hook |
local hooks = { |
'SendWho', |
'WhoFrameEditBox_OnEnterPressed', |
-- 'FriendsFrame_OnEvent', |
'SetWhoToUI', |
} |
-- hook all functions (which are not yet hooked) |
for _, name in pairs(hooks) do |
if not lib['hooked'][name] then |
lib['hooked'][name] = _G[name] |
_G[name] = function(...) |
lib.hook[name](lib, ...) |
end -- function |
end -- if |
end -- for |
-- fake 'WhoFrame:Hide' as hooked |
table.insert(hooks, 'WhoFrame_Hide') |
-- check for unused hooks -> remove function |
for name, _ in pairs(lib['hook']) do |
if not hooks[name] then |
lib['hook'][name] = function() end |
end -- if |
end -- for |
-- secure hook 'WhoFrame:Hide' |
if not lib['hooked']['WhoFrame_Hide'] then |
lib['hooked']['WhoFrame_Hide'] = true |
hooksecurefunc(WhoFrame, 'Hide', function(...) |
lib['hook']['WhoFrame_Hide'](lib, ...) |
end -- function |
) |
end -- if |
----- Coroutine based implementation (future) |
--function lib:sendWhoResult(val) |
-- coroutine.yield(val) |
--end |
-- |
--function lib:sendWaitState(val) |
-- coroutine.yield(val) |
--end |
-- |
--function lib:producer() |
-- return coroutine.create( |
-- function() |
-- lib:AskWhoNext() |
-- lib:sendWaitState(true) |
-- |
-- -- Resumed look for data |
-- |
-- end) |
--end |
--- |
--- hook replacements |
--- |
function lib.hook.SendWho(self, msg) |
dbg("SendWho: "..msg) |
lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0}) |
end |
function lib.hook.WhoFrameEditBox_OnEnterPressed(self) |
lib:GuiWho(WhoFrameEditBox:GetText()) |
end |
--[[ |
function lib.hook.FriendsFrame_OnEvent(self, ...) |
if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then |
lib.hooked.FriendsFrame_OnEvent(...) |
end |
end |
]] |
hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event) |
if(event == "WHO_LIST_UPDATE") then |
self:UnregisterEvent("WHO_LIST_UPDATE"); |
end |
end); |
function lib.hook.SetWhoToUI(self, state) |
lib.SetWhoToUIState = state |
end |
function lib.hook.WhoFrame_Hide(self) |
if(not lib.WhoInProgress)then |
lib:AskWhoNextIn5sec() |
end |
end |
--- |
--- WoW events |
--- |
local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+') |
function lib:CHAT_MSG_SYSTEM(arg1) |
if arg1 and arg1:find(who_pattern) then |
lib:ProcessWhoResults() |
end |
end |
FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE") |
function lib:WHO_LIST_UPDATE() |
if not lib.Quiet then |
WhoList_Update() |
FriendsFrame_Update() |
end |
lib:ProcessWhoResults() |
end |
function lib:ProcessWhoResults() |
local num |
self.Total, num = GetNumWhoResults() |
for i=1, num do |
local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i) |
self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex } |
end |
self:ReturnWho() |
end |
--- |
--- event activation |
--- |
lib['frame']:UnregisterAllEvents(); |
lib['frame']:SetScript("OnEvent", function(frame, event, ...) |
lib[event](lib, ...) |
end); |
for _,name in pairs({ |
'CHAT_MSG_SYSTEM', |
'WHO_LIST_UPDATE', |
}) do |
lib['frame']:RegisterEvent(name); |
end -- for |
--- |
--- re-embed |
--- |
for target,_ in pairs(lib['embeds']) do |
if type(target) == 'table' then |
lib:Embed(target) |
end -- if |
end -- for |
## Interface: 60100 |
## X-Curse-Packaged-Version: 2.0.146 |
## X-Curse-Project-Name: WhoLib |
## X-Curse-Project-ID: wholib |
## X-Curse-Repository-ID: wow/wholib/mainline |
## Title: Lib: LibWho-2.0 |
## Notes: Queing of /who and SendWho() queries and a much better interface (see docs), with gurantee to be executed & callback. |
## Version: 2.0.145 |
## Author: ALeX Kazik, Sylvanaar, Pazza |
## eMail: wow@kazik.de |
## X-Category: Library |
## OptionalDeps: LibStub, CallbackHandler-1.0 |
## LoadOnDemand: 1 |
#@no-lib-strip@ |
libs\LibStub\LibStub.lua |
libs\CallbackHandler-1.0\CallbackHandler-1.0.lua |
#@end-no-lib-strip@ |
LibWho-2.0\LibWho-2.0.lua |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="CallbackHandler-1.0.lua"/> |
</Ui> |
--[[ $Id: CallbackHandler-1.0.lua 18 2014-10-16 02:52:20Z mikk $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 6 |
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) |
if not CallbackHandler then return end -- No upgrade needed |
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} |
-- Lua APIs |
local tconcat = table.concat |
local assert, error, loadstring = assert, error, loadstring |
local setmetatable, rawset, rawget = setmetatable, rawset, rawget |
local next, select, pairs, type, tostring = next, select, pairs, type, tostring |
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded |
-- List them here for Mikk's FindGlobals script |
-- GLOBALS: geterrorhandler |
local xpcall = xpcall |
local function errorhandler(err) |
return geterrorhandler()(err) |
end |
local function CreateDispatcher(argCount) |
local code = [[ |
local next, xpcall, eh = ... |
local method, ARGS |
local function call() method(ARGS) end |
local function dispatch(handlers, ...) |
local index |
index, method = next(handlers) |
if not method then return end |
local OLD_ARGS = ARGS |
ARGS = ... |
repeat |
xpcall(call, eh) |
index, method = next(handlers, index) |
until not method |
ARGS = OLD_ARGS |
end |
return dispatch |
]] |
local ARGS, OLD_ARGS = {}, {} |
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end |
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", ")) |
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler) |
end |
local Dispatchers = setmetatable({}, {__index=function(self, argCount) |
local dispatcher = CreateDispatcher(argCount) |
rawset(self, argCount, dispatcher) |
return dispatcher |
end}) |
-------------------------------------------------------------------------- |
-- CallbackHandler:New |
-- |
-- target - target object to embed public APIs in |
-- RegisterName - name of the callback registration API, default "RegisterCallback" |
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" |
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. |
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName) |
RegisterName = RegisterName or "RegisterCallback" |
UnregisterName = UnregisterName or "UnregisterCallback" |
if UnregisterAllName==nil then -- false is used to indicate "don't want this method" |
UnregisterAllName = "UnregisterAllCallbacks" |
end |
-- we declare all objects and exported APIs inside this closure to quickly gain access |
-- to e.g. function names, the "target" parameter, etc |
-- Create the registry object |
local events = setmetatable({}, meta) |
local registry = { recurse=0, events=events } |
-- registry:Fire() - fires the given event/message into the registry |
function registry:Fire(eventname, ...) |
if not rawget(events, eventname) or not next(events[eventname]) then return end |
local oldrecurse = registry.recurse |
registry.recurse = oldrecurse + 1 |
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...) |
registry.recurse = oldrecurse |
if registry.insertQueue and oldrecurse==0 then |
-- Something in one of our callbacks wanted to register more callbacks; they got queued |
for eventname,callbacks in pairs(registry.insertQueue) do |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
for self,func in pairs(callbacks) do |
events[eventname][self] = func |
-- fire OnUsed callback? |
if first and registry.OnUsed then |
registry.OnUsed(registry, target, eventname) |
first = nil |
end |
end |
end |
registry.insertQueue = nil |
end |
end |
-- Registration of a callback, handles: |
-- self["method"], leads to self["method"](self, ...) |
-- self with function ref, leads to functionref(...) |
-- "addonId" (instead of self) with function ref, leads to functionref(...) |
-- all with an optional arg, which, if present, gets passed as first argument (after self if present) |
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) |
if type(eventname) ~= "string" then |
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) |
end |
method = method or eventname |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
if type(method) ~= "string" and type(method) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) |
end |
local regfunc |
if type(method) == "string" then |
-- self["method"] calling style |
if type(self) ~= "table" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) |
elseif self==target then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) |
elseif type(self[method]) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) self[method](self,arg,...) end |
else |
regfunc = function(...) self[method](self,...) end |
end |
else |
-- function ref with self=object or self="addonId" or self=thread |
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then |
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) method(arg,...) end |
else |
regfunc = method |
end |
end |
if events[eventname][self] or registry.recurse<1 then |
-- if registry.recurse<1 then |
-- we're overwriting an existing entry, or not currently recursing. just set it. |
events[eventname][self] = regfunc |
-- fire OnUsed callback? |
if registry.OnUsed and first then |
registry.OnUsed(registry, target, eventname) |
end |
else |
-- we're currently processing a callback in this registry, so delay the registration of this new entry! |
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency |
registry.insertQueue = registry.insertQueue or setmetatable({},meta) |
registry.insertQueue[eventname][self] = regfunc |
end |
end |
-- Unregister a callback |
target[UnregisterName] = function(self, eventname) |
if not self or self==target then |
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) |
end |
if type(eventname) ~= "string" then |
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) |
end |
if rawget(events, eventname) and events[eventname][self] then |
events[eventname][self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(events[eventname]) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then |
registry.insertQueue[eventname][self] = nil |
end |
end |
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds |
if UnregisterAllName then |
target[UnregisterAllName] = function(...) |
if select("#",...)<1 then |
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) |
end |
if select("#",...)==1 and ...==target then |
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) |
end |
for i=1,select("#",...) do |
local self = select(i,...) |
if registry.insertQueue then |
for eventname, callbacks in pairs(registry.insertQueue) do |
if callbacks[self] then |
callbacks[self] = nil |
end |
end |
end |
for eventname, callbacks in pairs(events) do |
if callbacks[self] then |
callbacks[self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(callbacks) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
end |
end |
end |
end |
return registry |
end |
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it |
-- try to upgrade old implicit embeds since the system is selfcontained and |
-- relies on closures to work. |
-- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $ |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/addons/libstub/ for more info |
-- LibStub is hereby placed in the Public Domain |
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
-- Check to see is this version of the stub is obsolete |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
-- LibStub:NewLibrary(major, minor) |
-- major (string) - the major version of the library |
-- minor (string or number ) - the minor version of the library |
-- |
-- returns nil if a newer or same version of the lib is already present |
-- returns empty library object or old library object if upgrade is needed |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
-- LibStub:GetLibrary(major, [silent]) |
-- major (string) - the major version of the library |
-- silent (boolean) - if true, library is optional, silently return nil if its not found |
-- |
-- throws an error if the library can not be found (except silent is set) |
-- returns the library object if found |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
-- LibStub:IterateLibraries() |
-- |
-- Returns an iterator for the currently registered libraries |
function LibStub:IterateLibraries() |
return pairs(self.libs) |
end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
## Interface: 60000 |
## Title: Lib: LibStub |
## Notes: Universal Library Stub |
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel |
## X-Website: http://www.wowace.com/addons/libstub/ |
## X-Category: Library |
## X-License: Public Domain |
## X-Curse-Packaged-Version: 1.0.2.60000 |
## X-Curse-Project-Name: LibStub |
## X-Curse-Project-ID: libstub |
## X-Curse-Repository-ID: wow/libstub/mainline |
LibStub.lua |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy |
assert(lib) -- should return the library table |
assert(not oldMinor) -- should not return the old minor, since it didn't exist |
-- the following is to create data and then be able to check if the same data exists after the fact |
function lib:MyMethod() |
end |
local MyMethod = lib.MyMethod |
lib.MyTable = {} |
local MyTable = lib.MyTable |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail |
assert(not newLib) -- should not return since out of date |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail |
assert(not newLib) -- should not return since out of date |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version |
assert(newLib) -- library table |
assert(rawequal(newLib, lib)) -- should be the same reference as the previous |
assert(newOldMinor == 1) -- should return the minor version of the previous version |
assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved |
assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number) |
assert(newLib) -- library table |
assert(newOldMinor == 2) -- previous version was 2 |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number) |
assert(newLib) |
assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string) |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string |
assert(newLib) |
assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string) |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
for major, library in LibStub:IterateLibraries() do |
-- check that MyLib doesn't exist yet, by iterating through all the libraries |
assert(major ~= "MyLib") |
end |
assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking |
assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error. |
local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib |
assert(lib) -- check it exists |
assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference |
assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version |
local count=0 |
for major, library in LibStub:IterateLibraries() do |
-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries |
if major == "MyLib" then -- we found it! |
count = count +1 |
assert(rawequal(library, lib)) -- verify that the references are equal |
end |
end |
assert(count == 1) -- verify that we actually found it, and only once |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
local proxy = newproxy() -- non-string |
assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata |
local success, ret = pcall(LibStub.GetLibrary, proxy, true) |
assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered. |
assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it. |
assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
-- Pretend like loaded libstub is old and doesn't have :IterateLibraries |
assert(LibStub.minor) |
LibStub.minor = LibStub.minor - 0.0001 |
LibStub.IterateLibraries = nil |
loadfile("../LibStub.lua")() |
assert(type(LibStub.IterateLibraries)=="function") |
-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created |
LibStub.IterateLibraries = 123 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created |
LibStub.minor = LibStub.minor + 0.0001 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
-- Again with a huge number |
LibStub.minor = LibStub.minor + 1234567890 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
print("OK") |
--- |
--- check for an already loaded old WhoLib |
--- |
if WhoLibByALeX or WhoLib then |
-- the WhoLib-1.0 (WhoLibByALeX) or WhoLib (by Malex) is loaded -> fail! |
error("an other WhoLib is already running - disable them first!\n") |
return |
end -- if |
--- |
--- check version |
--- |
assert(LibStub, "LibWho-2.0 requires LibStub") |
local major_version = 'LibWho-2.0' |
local minor_version = tonumber("136") or 99999 |
local lib = LibStub:NewLibrary(major_version, minor_version) |
if not lib then |
return -- already loaded and no upgrade necessary |
end |
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) |
local callbacks = lib.callbacks |
local am = {} |
local om = getmetatable(lib) |
if om then |
for k, v in pairs(om) do am[k] = v end |
end |
am.__tostring = function() return major_version end |
setmetatable(lib, am) |
local function dbgfunc(...) if lib.Debug then print(...) end end |
local function NOP() return end |
local dbg = NOP |
--- |
--- initalize base |
--- |
if type(lib['hooked']) ~= 'table' then |
lib['hooked'] = {} |
end -- if |
if type(lib['hook']) ~= 'table' then |
lib['hook'] = {} |
end -- if |
if type(lib['events']) ~= 'table' then |
lib['events'] = {} |
end -- if |
if type(lib['embeds']) ~= 'table' then |
lib['embeds'] = {} |
end -- if |
if type(lib['frame']) ~= 'table' then |
lib['frame'] = CreateFrame('Frame', major_version); |
end -- if |
lib['frame']:Hide() |
lib.Queue = {[1]={}, [2]={}, [3]={}} |
lib.WhoInProgress = false |
lib.Result = nil |
lib.Args = nil |
lib.Total = nil |
lib.Quiet = nil |
lib.Debug = false |
lib.Cache = {} |
lib.CacheQueue = {} |
lib.SetWhoToUIState = 0 |
lib.MinInterval = 2.5 |
lib.MaxInterval = 10 |
--- |
--- locale |
--- |
if (GetLocale() == "ruRU") then |
lib.L = { |
['console_queued'] = 'Ðобавлено в оÑеÑÐµÐ´Ñ "/who %s"', |
['console_query'] = 'РезÑлÑÑÐ°Ñ "/who %s"', |
['gui_wait'] = '- ÐожалÑйÑÑа подождиÑе -', |
} |
else |
-- enUS is the default |
lib.L = { |
['console_queued'] = 'Added "/who %s" to queue', |
['console_query'] = 'Result of "/who %s"', |
['gui_wait'] = '- Please Wait -', |
} |
end -- if |
--- |
--- external functions/constants |
--- |
lib['external'] = { |
'WHOLIB_QUEUE_USER', |
'WHOLIB_QUEUE_QUIET', |
'WHOLIB_QUEUE_SCANNING', |
'WHOLIB_FLAG_ALWAYS_CALLBACK', |
'Who', |
'UserInfo', |
'CachedUserInfo', |
'GetWhoLibDebug', |
'SetWhoLibDebug', |
-- 'RegisterWhoLibEvent', |
} |
-- queues |
lib['WHOLIB_QUEUE_USER'] = 1 |
lib['WHOLIB_QUEUE_QUIET'] = 2 |
lib['WHOLIB_QUEUE_SCANNING'] = 3 |
local queue_all = { |
[1] = 'WHOLIB_QUEUE_USER', |
[2] = 'WHOLIB_QUEUE_QUIET', |
[3] = 'WHOLIB_QUEUE_SCANNING', |
} |
local queue_quiet = { |
[2] = 'WHOLIB_QUEUE_QUIET', |
[3] = 'WHOLIB_QUEUE_SCANNING', |
} |
-- bit masks! |
lib['WHOLIB_FLAG_ALWAYS_CALLBACK'] = 1 |
function lib:Reset() |
self.Queue = {[1]={}, [2]={}, [3]={}} |
self.Cache = {} |
self.CacheQueue = {} |
end |
function lib.Who(defhandler, query, opts) |
local self, args, usage = lib, {}, 'Who(query, [opts])' |
args.query = self:CheckArgument(usage, 'query', 'string', query) |
opts = self:CheckArgument(usage, 'opts', 'table', opts, {}) |
args.queue = self:CheckPreset(usage, 'opts.queue', queue_all, opts.queue, self.WHOLIB_QUEUE_SCANNING) |
args.flags = self:CheckArgument(usage, 'opts.flags', 'number', flags, 0) |
args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler) |
-- now args - copied and verified from opts |
if args.queue == self.WHOLIB_QUEUE_USER then |
if WhoFrame:IsShown() then |
self:GuiWho(args.query) |
else |
self:ConsoleWho(args.query) |
end |
else |
self:AskWho(args) |
end |
end |
local function ignoreRealm(name) |
local _, realm = string.split("-", name) |
local connectedServers = GetAutoCompleteRealms() |
if connectedServers then |
for i = 1, #connectedServers do |
if realm == connectedServers[i] then return false end |
end |
end |
return true |
end |
function lib.UserInfo(defhandler, name, opts) |
local self, args, usage = lib, {}, 'UserInfo(name, [opts])' |
local now = time() |
name = self:CheckArgument(usage, 'name', 'string', name) |
if name:len() == 0 then return end |
--There is no api to tell connected realms from cross realm by name. As such, we check known connections table before excluding who inquiry |
--UnitRealmRelationship and UnitIsSameServer don't work with "name". They require unitID so they are useless here |
if name:find("%-") and ignoreRealm(name) then return end |
args.name = self:CapitalizeInitial(name) |
opts = self:CheckArgument(usage, 'opts', 'table', opts, {}) |
args.queue = self:CheckPreset(usage, 'opts.queue', queue_quiet, opts.queue, self.WHOLIB_QUEUE_SCANNING) |
args.flags = self:CheckArgument(usage, 'opts.flags', 'number', opts.flags, 0) |
args.timeout = self:CheckArgument(usage, 'opts.timeout', 'number', opts.timeout, 5) |
args.callback, args.handler = self:CheckCallback(usage, 'opts.', opts.callback, opts.handler, defhandler) |
-- now args - copied and verified from opts |
local cachedName = self.Cache[args.name] |
if(cachedName ~= nil)then |
-- user is in cache |
if(cachedName.valid == true and (args.timeout < 0 or cachedName.last + args.timeout*60 > now))then |
-- cache is valid and timeout is in range |
--dbg('Info(' .. args.name ..') returned immedeatly') |
if(bit.band(args.flags, self.WHOLIB_FLAG_ALWAYS_CALLBACK) ~= 0)then |
self:RaiseCallback(args, cachedName.data) |
return false |
else |
return self:DupAll(self:ReturnUserInfo(args.name)) |
end |
elseif(cachedName.valid == false)then |
-- query is already running (first try) |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
--dbg('Info(' .. args.name ..') returned cause it\'s already searching') |
return nil |
end |
else |
self.Cache[args.name] = {valid=false, inqueue=false, callback={}, data={Name = args.name}, last=now } |
end |
local cachedName = self.Cache[args.name] |
if(cachedName.inqueue)then |
-- query is running! |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
dbg('Info(' .. args.name ..') returned cause it\'s already searching') |
return nil |
end |
if (GetLocale() == "ruRU") then -- in ruRU with n- not show information about player in WIM addon |
if args.name and args.name:len() > 0 then |
local query = 'и-"' .. args.name .. '"' |
cachedName.inqueue = true |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
self.CacheQueue[query] = args.name |
dbg('Info(' .. args.name ..') added to queue') |
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) |
end |
else |
if args.name and args.name:len() > 0 then |
local query = 'n-"' .. args.name .. '"' |
cachedName.inqueue = true |
if(args.callback ~= nil)then |
tinsert(cachedName.callback, args) |
end |
self.CacheQueue[query] = args.name |
dbg('Info(' .. args.name ..') added to queue') |
self:AskWho( { query = query, queue = args.queue, flags = 0, info = args.name } ) |
end |
end |
return nil |
end |
function lib.CachedUserInfo(_, name) |
local self, usage = lib, 'CachedUserInfo(name)' |
name = self:CapitalizeInitial(self:CheckArgument(usage, 'name', 'string', name)) |
if self.Cache[name] == nil then |
return nil |
else |
return self:DupAll(self:ReturnUserInfo(name)) |
end |
end |
function lib.GetWhoLibDebug(_, mode) |
return lib.Debug |
end |
function lib.SetWhoLibDebug(_, mode) |
lib.Debug = mode |
dbg = mode and dbgfunc or NOP |
end |
--function lib.RegisterWhoLibEvent(defhandler, event, callback, handler) |
-- local self, usage = lib, 'RegisterWhoLibEvent(event, callback, [handler])' |
-- |
-- self:CheckPreset(usage, 'event', self.events, event) |
-- local callback, handler = self:CheckCallback(usage, '', callback, handler, defhandler, true) |
-- table.insert(self.events[event], {callback=callback, handler=handler}) |
--end |
-- non-embedded externals |
function lib.Embed(_, handler) |
local self, usage = lib, 'Embed(handler)' |
self:CheckArgument(usage, 'handler', 'table', handler) |
for _,name in pairs(self.external) do |
handler[name] = self[name] |
end -- do |
self['embeds'][handler] = true |
return handler |
end |
function lib.Library(_) |
local self = lib |
return self:Embed({}) |
end |
--- |
--- internal functions |
--- |
function lib:AllQueuesEmpty() |
local queueCount = #self.Queue[1] + #self.Queue[2] + #self.Queue[3] + #self.CacheQueue |
-- Be sure that we have cleared the in-progress status |
if self.WhoInProgress then |
queueCount = queueCount + 1 |
end |
return queueCount == 0 |
end |
local queryInterval = 5 |
function lib:GetQueryInterval() return queryInterval end |
function lib:AskWhoNextIn5sec() |
if self.frame:IsShown() then return end |
dbg("Waiting to send next who") |
self.Timeout_time = queryInterval |
self['frame']:Show() |
end |
function lib:CancelPendingWhoNext() |
lib['frame']:Hide() |
end |
lib['frame']:SetScript("OnUpdate", function(frame, elapsed) |
lib.Timeout_time = lib.Timeout_time - elapsed |
if lib.Timeout_time <= 0 then |
lib['frame']:Hide() |
lib:AskWhoNext() |
end -- if |
end); |
-- queue scheduler |
local queue_weights = { [1] = 0.6, [2] = 0.2, [3] = 0.2 } |
local queue_bounds = { [1] = 0.6, [2] = 0.2, [3] = 0.2 } |
-- allow for single queries from the user to get processed faster |
local lastInstantQuery = time() |
local INSTANT_QUERY_MIN_INTERVAL = 60 -- only once every 1 min |
function lib:UpdateWeights() |
local weightsum, sum, count = 0, 0, 0 |
for k,v in pairs(queue_weights) do |
sum = sum + v |
weightsum = weightsum + v * #self.Queue[k] |
end |
if weightsum == 0 then |
for k,v in pairs(queue_weights) do queue_bounds[k] = v end |
return |
end |
local adjust = sum / weightsum |
for k,v in pairs(queue_bounds) do |
queue_bounds[k] = queue_weights[k] * adjust * #self.Queue[k] |
end |
end |
function lib:GetNextFromScheduler() |
self:UpdateWeights() |
-- Since an addon could just fill up the user q for instant processing |
-- we have to limit instants to 1 per INSTANT_QUERY_MIN_INTERVAL |
-- and only try instant fulfilment if it will empty the user queue |
if #self.Queue[1] == 1 then |
if time() - lastInstantQuery > INSTANT_QUERY_MIN_INTERVAL then |
dbg("INSTANT") |
lastInstantQuery = time() |
return 1, self.Queue[1] |
end |
end |
local n,i = math.random(),0 |
repeat |
i=i+1 |
n = n - queue_bounds[i] |
until i>=#self.Queue or n <= 0 |
dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i])) |
if #self.Queue[i] > 0 then |
dbg(("Q=%d, bound=%d"):format(i, queue_bounds[i])) |
return i, self.Queue[i] |
else |
dbg("Queues empty, waiting") |
end |
end |
lib.queue_bounds = queue_bounds |
function lib:AskWhoNext() |
if lib.frame:IsShown() then |
dbg("Already waiting") |
return |
end |
self:CancelPendingWhoNext() |
if self.WhoInProgress then |
-- if we had a who going, it didnt complete |
dbg("TIMEOUT: "..self.Args.query) |
local args = self.Args |
self.Args = nil |
-- if args.info and self.CacheQueue[args.query] ~= nil then |
dbg("Requeing "..args.query) |
tinsert(self.Queue[args.queue], args) |
if args.console_show ~= nil then |
DEFAULT_CHAT_FRAME:AddMessage(("Timeout on result of '%s' - retrying..."):format(args.query),1,1,0) |
args.console_show = true |
end |
-- end |
if queryInterval < lib.MaxInterval then |
queryInterval = queryInterval + 0.5 |
dbg("--Throttling down to 1 who per " .. queryInterval .. "s") |
end |
end |
self.WhoInProgress = false |
local v,k,args = nil |
local kludge = 10 |
repeat |
k,v = self:GetNextFromScheduler() |
if not k then break end |
if(WhoFrame:IsShown() and k > self.WHOLIB_QUEUE_QUIET)then |
break |
end |
if(#v > 0)then |
args = tremove(v, 1) |
break |
end |
kludge = kludge - 1 |
until kludge <= 0 |
if args then |
self.WhoInProgress = true |
self.Result = {} |
self.Args = args |
self.Total = -1 |
if(args.console_show == true)then |
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_query'], args.query), 1, 1, 0) |
end |
if args.queue == self.WHOLIB_QUEUE_USER then |
WhoFrameEditBox:SetText(args.query) |
self.Quiet = false |
if args.whotoui then |
self.hooked.SetWhoToUI(args.whotoui) |
else |
self.hooked.SetWhoToUI(args.gui and 1 or 0) |
end |
else |
self.hooked.SetWhoToUI(1) |
self.Quiet = true |
end |
dbg("QUERY: "..args.query) |
self.hooked.SendWho(args.query) |
else |
self.Args = nil |
self.WhoInProgress = false |
end |
-- Keep processing the who queue if there is more work |
if not self:AllQueuesEmpty() then |
self:AskWhoNextIn5sec() |
else |
dbg("*** Done processing requests ***") |
end |
end |
function lib:AskWho(args) |
tinsert(self.Queue[args.queue], args) |
dbg('[' .. args.queue .. '] added "' .. args.query .. '", queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3]) |
self:TriggerEvent('WHOLIB_QUERY_ADDED') |
self:AskWhoNext() |
end |
function lib:ReturnWho() |
if not self.Args then |
self.Quiet = nil |
return |
end |
if(self.Args.queue == self.WHOLIB_QUEUE_QUIET or self.Args.queue == self.WHOLIB_QUEUE_SCANNING)then |
self.Quiet = nil |
end |
if queryInterval > self.MinInterval then |
queryInterval = queryInterval - 0.5 |
dbg("--Throttling up to 1 who per " .. queryInterval .. "s") |
end |
self.WhoInProgress = false |
dbg("RESULT: "..self.Args.query) |
dbg('[' .. self.Args.queue .. '] returned "' .. self.Args.query .. '", total=' .. self.Total ..' , queues=' .. #self.Queue[1] .. '/'.. #self.Queue[2] .. '/'.. #self.Queue[3]) |
local now = time() |
local complete = (self.Total == #self.Result) and (self.Total < MAX_WHOS_FROM_SERVER) |
for _,v in pairs(self.Result)do |
if(self.Cache[v.Name] == nil)then |
self.Cache[v.Name] = { inqueue = false, callback = {} } |
end |
local cachedName = self.Cache[v.Name] |
cachedName.valid = true -- is now valid |
cachedName.data = v -- update data |
cachedName.data.Online = true -- player is online |
cachedName.last = now -- update timestamp |
if(cachedName.inqueue)then |
if(self.Args.info and self.CacheQueue[self.Args.query] == v.Name)then |
-- found by the query which was created to -> remove us from query |
self.CacheQueue[self.Args.query] = nil |
else |
-- found by another query |
for k2,v2 in pairs(self.CacheQueue) do |
if(v2 == v.Name)then |
for i=self.WHOLIB_QUEUE_QUIET, self.WHOLIB_QUEUE_SCANNING do |
for k3,v3 in pairs(self.Queue[i]) do |
if(v3.query == k2 and v3.info)then |
-- remove the query which was generated for this user, cause another query was faster... |
dbg("Found '"..v.Name.."' early via query '"..self.Args.query.."'") |
table.remove(self.Queue[i], k3) |
self.CacheQueue[k2] = nil |
end |
end |
end |
end |
end |
end |
dbg('Info(' .. v.Name ..') returned: on') |
for _,v2 in pairs(cachedName.callback) do |
self:RaiseCallback(v2, self:ReturnUserInfo(v.Name)) |
end |
cachedName.callback = {} |
end |
cachedName.inqueue = false -- query is done |
end |
if(self.Args.info and self.CacheQueue[self.Args.query])then |
-- the query did not deliver the result => not online! |
local name = self.CacheQueue[self.Args.query] |
local cachedName = self.Cache[name] |
if (cachedName.inqueue)then |
-- nothing found (yet) |
cachedName.valid = true -- is now valid |
cachedName.inqueue = false -- query is done? |
cachedName.last = now -- update timestamp |
if(complete)then |
cachedName.data.Online = false -- player is offline |
else |
cachedName.data.Online = nil -- player is unknown (more results from who than can be displayed) |
end |
end |
dbg('Info(' .. name ..') returned: ' .. (cachedName.data.Online == false and 'off' or 'unkn')) |
for _,v in pairs(cachedName.callback) do |
self:RaiseCallback(v, self:ReturnUserInfo(name)) |
end |
cachedName.callback = {} |
self.CacheQueue[self.Args.query] = nil |
end |
self:RaiseCallback(self.Args, self.Args.query, self.Result, complete, self.Args.info) |
self:TriggerEvent('WHOLIB_QUERY_RESULT', self.Args.query, self.Result, complete, self.Args.info) |
if not self:AllQueuesEmpty() then |
self:AskWhoNextIn5sec() |
end |
end |
function lib:GuiWho(msg) |
if(msg == self.L['gui_wait'])then |
return |
end |
for _,v in pairs(self.Queue[self.WHOLIB_QUEUE_USER]) do |
if(v.gui == true)then |
return |
end |
end |
if(self.WhoInProgress)then |
WhoFrameEditBox:SetText(self.L['gui_wait']) |
end |
self.savedText = msg |
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, gui = true}) |
WhoFrameEditBox:ClearFocus(); |
end |
function lib:ConsoleWho(msg) |
--WhoFrameEditBox:SetText(msg) |
local console_show = false |
local q1 = self.Queue[self.WHOLIB_QUEUE_USER] |
local q1count = #q1 |
if(q1count > 0 and q1[q1count].query == msg)then -- last query is itdenical: drop |
return |
end |
if(q1count > 0 and q1[q1count].console_show == false)then -- display 'queued' if console and not yet shown |
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], q1[q1count].query), 1, 1, 0) |
q1[q1count].console_show = true |
end |
if(q1count > 0 or self.WhoInProgress)then |
DEFAULT_CHAT_FRAME:AddMessage(string.format(self.L['console_queued'], msg), 1, 1, 0) |
console_show = true |
end |
self:AskWho({query = msg, queue = self.WHOLIB_QUEUE_USER, flags = 0, console_show = console_show}) |
end |
function lib:ReturnUserInfo(name) |
if(name ~= nil and self ~= nil and self.Cache ~= nil and self.Cache[name] ~= nil) then |
return self.Cache[name].data, (time() - self.Cache[name].last) / 60 |
end |
end |
function lib:RaiseCallback(args, ...) |
if type(args.callback) == 'function' then |
args.callback(self:DupAll(...)) |
elseif args.callback then -- must be a string |
args.handler[args.callback](args.handler, self:DupAll(...)) |
end -- if |
end |
-- Argument checking |
function lib:CheckArgument(func, name, argtype, arg, defarg) |
if arg == nil and defarg ~= nil then |
return defarg |
elseif type(arg) == argtype then |
return arg |
else |
error(string.format("%s: '%s' - %s%s expected got %s", func, name, (defarg ~= nil) and 'nil or ' or '', argtype, type(arg)), 3) |
end -- if |
end |
function lib:CheckPreset(func, name, preset, arg, defarg) |
if arg == nil and defarg ~= nil then |
return defarg |
elseif arg ~= nil and preset[arg] ~= nil then |
return arg |
else |
local p = {} |
for k,v in pairs(preset) do |
if type(v) ~= 'string' then |
table.insert(p, k) |
else |
table.insert(p, v) |
end -- if |
end -- for |
error(string.format("%s: '%s' - one of %s%s expected got %s", func, name, (defarg ~= nil) and 'nil, ' or '', table.concat(p, ', '), self:simple_dump(arg)), 3) |
end -- if |
end |
function lib:CheckCallback(func, prefix, callback, handler, defhandler, nonil) |
if not nonil and callback == nil then |
-- no callback: ignore handler |
return nil, nil |
elseif type(callback) == 'function' then |
-- simple function |
if handler ~= nil then |
error(string.format("%s: '%shandler' - nil expected got %s", func, prefix, type(arg)), 3) |
end -- if |
elseif type(callback) == 'string' then |
-- method |
if handler == nil then |
handler = defhandler |
end -- if |
if type(handler) ~= 'table' or type(handler[callback]) ~= 'function' or handler == self then |
error(string.format("%s: '%shandler' - nil or function expected got %s", func, prefix, type(arg)), 3) |
end -- if |
else |
error(string.format("%s: '%scallback' - %sfunction or string expected got %s", func, prefix, nonil and 'nil or ' or '', type(arg)), 3) |
end -- if |
return callback, handler |
end |
-- helpers |
function lib:simple_dump(x) |
if type(x) == 'string' then |
return 'string \''..x..'\'' |
elseif type(x) == 'number' then |
return 'number '..x |
else |
return type(x) |
end |
end |
function lib:Dup(from) |
local to = {} |
for k,v in pairs(from) do |
if type(v) == 'table' then |
to[k] = self:Dup(v) |
else |
to[k] = v |
end -- if |
end -- for |
return to |
end |
function lib:DupAll(x, ...) |
if type(x) == 'table' then |
return self:Dup(x), self:DupAll(...) |
elseif x ~= nil then |
return x, self:DupAll(...) |
else |
return nil |
end -- if |
end |
local MULTIBYTE_FIRST_CHAR = "^([\192-\255]?%a?[\128-\191]*)" |
function lib:CapitalizeInitial(name) |
return name:gsub(MULTIBYTE_FIRST_CHAR, string.upper, 1) |
end |
--- |
--- user events (Using CallbackHandler) |
--- |
lib.PossibleEvents = { |
'WHOLIB_QUERY_RESULT', |
'WHOLIB_QUERY_ADDED', |
} |
function lib:TriggerEvent(event, ...) |
callbacks:Fire(event, ...) |
end |
--- |
--- slash commands |
--- |
SlashCmdList['WHO'] = function(msg) |
dbg("console /who: "..msg) |
-- new /who function |
--local self = lib |
if(msg == '')then |
lib:GuiWho(WhoFrame_GetDefaultWhoCommand()) |
elseif(WhoFrame:IsVisible())then |
lib:GuiWho(msg) |
else |
lib:ConsoleWho(msg) |
end |
end |
SlashCmdList['WHOLIB_DEBUG'] = function() |
-- /wholibdebug: toggle debug on/off |
local self = lib |
self:SetWhoLibDebug(not self.Debug) |
end |
SLASH_WHOLIB_DEBUG1 = '/wholibdebug' |
--- |
--- hook activation |
--- |
-- functions to hook |
local hooks = { |
'SendWho', |
'WhoFrameEditBox_OnEnterPressed', |
-- 'FriendsFrame_OnEvent', |
'SetWhoToUI', |
} |
-- hook all functions (which are not yet hooked) |
for _, name in pairs(hooks) do |
if not lib['hooked'][name] then |
lib['hooked'][name] = _G[name] |
_G[name] = function(...) |
lib.hook[name](lib, ...) |
end -- function |
end -- if |
end -- for |
-- fake 'WhoFrame:Hide' as hooked |
table.insert(hooks, 'WhoFrame_Hide') |
-- check for unused hooks -> remove function |
for name, _ in pairs(lib['hook']) do |
if not hooks[name] then |
lib['hook'][name] = function() end |
end -- if |
end -- for |
-- secure hook 'WhoFrame:Hide' |
if not lib['hooked']['WhoFrame_Hide'] then |
lib['hooked']['WhoFrame_Hide'] = true |
hooksecurefunc(WhoFrame, 'Hide', function(...) |
lib['hook']['WhoFrame_Hide'](lib, ...) |
end -- function |
) |
end -- if |
----- Coroutine based implementation (future) |
--function lib:sendWhoResult(val) |
-- coroutine.yield(val) |
--end |
-- |
--function lib:sendWaitState(val) |
-- coroutine.yield(val) |
--end |
-- |
--function lib:producer() |
-- return coroutine.create( |
-- function() |
-- lib:AskWhoNext() |
-- lib:sendWaitState(true) |
-- |
-- -- Resumed look for data |
-- |
-- end) |
--end |
--- |
--- hook replacements |
--- |
function lib.hook.SendWho(self, msg) |
dbg("SendWho: "..msg) |
lib.AskWho(self, {query = msg, queue = lib.WHOLIB_QUEUE_USER, whotoui = lib.SetWhoToUIState, flags = 0}) |
end |
function lib.hook.WhoFrameEditBox_OnEnterPressed(self) |
lib:GuiWho(WhoFrameEditBox:GetText()) |
end |
--[[ |
function lib.hook.FriendsFrame_OnEvent(self, ...) |
if event ~= 'WHO_LIST_UPDATE' or not lib.Quiet then |
lib.hooked.FriendsFrame_OnEvent(...) |
end |
end |
]] |
hooksecurefunc(FriendsFrame, 'RegisterEvent', function(self, event) |
if(event == "WHO_LIST_UPDATE") then |
self:UnregisterEvent("WHO_LIST_UPDATE"); |
end |
end); |
function lib.hook.SetWhoToUI(self, state) |
lib.SetWhoToUIState = state |
end |
function lib.hook.WhoFrame_Hide(self) |
if(not lib.WhoInProgress)then |
lib:AskWhoNextIn5sec() |
end |
end |
--- |
--- WoW events |
--- |
local who_pattern = string.gsub(WHO_NUM_RESULTS, '%%d', '%%d%+') |
function lib:CHAT_MSG_SYSTEM(arg1) |
if arg1 and arg1:find(who_pattern) then |
lib:ProcessWhoResults() |
end |
end |
FriendsFrame:UnregisterEvent("WHO_LIST_UPDATE") |
function lib:WHO_LIST_UPDATE() |
if not lib.Quiet then |
WhoList_Update() |
FriendsFrame_Update() |
end |
lib:ProcessWhoResults() |
end |
function lib:ProcessWhoResults() |
local num |
self.Total, num = GetNumWhoResults() |
for i=1, num do |
local charname, guildname, level, race, class, zone, nonlocalclass, sex = GetWhoInfo(i) |
self.Result[i] = {Name=charname, Guild=guildname, Level=level, Race=race, Class=class, Zone=zone, NoLocaleClass=nonlocalclass, Sex=sex } |
end |
self:ReturnWho() |
end |
--- |
--- event activation |
--- |
lib['frame']:UnregisterAllEvents(); |
lib['frame']:SetScript("OnEvent", function(frame, event, ...) |
lib[event](lib, ...) |
end); |
for _,name in pairs({ |
'CHAT_MSG_SYSTEM', |
'WHO_LIST_UPDATE', |
}) do |
lib['frame']:RegisterEvent(name); |
end -- for |
--- |
--- re-embed |
--- |
for target,_ in pairs(lib['embeds']) do |
if type(target) == 'table' then |
lib:Embed(target) |
end -- if |
end -- for |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy |
assert(lib) -- should return the library table |
assert(not oldMinor) -- should not return the old minor, since it didn't exist |
-- the following is to create data and then be able to check if the same data exists after the fact |
function lib:MyMethod() |
end |
local MyMethod = lib.MyMethod |
lib.MyTable = {} |
local MyTable = lib.MyTable |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail |
assert(not newLib) -- should not return since out of date |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail |
assert(not newLib) -- should not return since out of date |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version |
assert(newLib) -- library table |
assert(rawequal(newLib, lib)) -- should be the same reference as the previous |
assert(newOldMinor == 1) -- should return the minor version of the previous version |
assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved |
assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number) |
assert(newLib) -- library table |
assert(newOldMinor == 2) -- previous version was 2 |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number) |
assert(newLib) |
assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string) |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string |
assert(newLib) |
assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string) |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
for major, library in LibStub:IterateLibraries() do |
-- check that MyLib doesn't exist yet, by iterating through all the libraries |
assert(major ~= "MyLib") |
end |
assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking |
assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error. |
local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib |
assert(lib) -- check it exists |
assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference |
assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version |
local count=0 |
for major, library in LibStub:IterateLibraries() do |
-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries |
if major == "MyLib" then -- we found it! |
count = count +1 |
assert(rawequal(library, lib)) -- verify that the references are equal |
end |
end |
assert(count == 1) -- verify that we actually found it, and only once |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
local proxy = newproxy() -- non-string |
assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata |
local success, ret = pcall(LibStub.GetLibrary, proxy, true) |
assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered. |
assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it. |
assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
-- Pretend like loaded libstub is old and doesn't have :IterateLibraries |
assert(LibStub.minor) |
LibStub.minor = LibStub.minor - 0.0001 |
LibStub.IterateLibraries = nil |
loadfile("../LibStub.lua")() |
assert(type(LibStub.IterateLibraries)=="function") |
-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created |
LibStub.IterateLibraries = 123 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created |
LibStub.minor = LibStub.minor + 0.0001 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
-- Again with a huge number |
LibStub.minor = LibStub.minor + 1234567890 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
print("OK") |
-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $ |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain |
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
-- Check to see is this version of the stub is obsolete |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
-- LibStub:NewLibrary(major, minor) |
-- major (string) - the major version of the library |
-- minor (string or number ) - the minor version of the library |
-- |
-- returns nil if a newer or same version of the lib is already present |
-- returns empty library object or old library object if upgrade is needed |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
-- LibStub:GetLibrary(major, [silent]) |
-- major (string) - the major version of the library |
-- silent (boolean) - if true, library is optional, silently return nil if its not found |
-- |
-- throws an error if the library can not be found (except silent is set) |
-- returns the library object if found |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
-- LibStub:IterateLibraries() |
-- |
-- Returns an iterator for the currently registered libraries |
function LibStub:IterateLibraries() |
return pairs(self.libs) |
end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
## Interface: 50001 |
## Title: Lib: LibStub |
## Notes: Universal Library Stub |
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel |
## X-Website: http://www.wowace.com/addons/libstub/ |
## X-Category: Library |
## X-License: Public Domain |
## X-Curse-Packaged-Version: 1.0.3-50001 |
## X-Curse-Project-Name: LibStub |
## X-Curse-Project-ID: libstub |
## X-Curse-Repository-ID: wow/libstub/mainline |
LibStub.lua |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="CallbackHandler-1.0.lua"/> |
</Ui> |
--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 6 |
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) |
if not CallbackHandler then return end -- No upgrade needed |
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} |
-- Lua APIs |
local tconcat = table.concat |
local assert, error, loadstring = assert, error, loadstring |
local setmetatable, rawset, rawget = setmetatable, rawset, rawget |
local next, select, pairs, type, tostring = next, select, pairs, type, tostring |
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded |
-- List them here for Mikk's FindGlobals script |
-- GLOBALS: geterrorhandler |
local xpcall = xpcall |
local function errorhandler(err) |
return geterrorhandler()(err) |
end |
local function CreateDispatcher(argCount) |
local code = [[ |
local next, xpcall, eh = ... |
local method, ARGS |
local function call() method(ARGS) end |
local function dispatch(handlers, ...) |
local index |
index, method = next(handlers) |
if not method then return end |
local OLD_ARGS = ARGS |
ARGS = ... |
repeat |
xpcall(call, eh) |
index, method = next(handlers, index) |
until not method |
ARGS = OLD_ARGS |
end |
return dispatch |
]] |
local ARGS, OLD_ARGS = {}, {} |
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end |
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", ")) |
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler) |
end |
local Dispatchers = setmetatable({}, {__index=function(self, argCount) |
local dispatcher = CreateDispatcher(argCount) |
rawset(self, argCount, dispatcher) |
return dispatcher |
end}) |
-------------------------------------------------------------------------- |
-- CallbackHandler:New |
-- |
-- target - target object to embed public APIs in |
-- RegisterName - name of the callback registration API, default "RegisterCallback" |
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" |
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. |
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused) |
-- TODO: Remove this after beta has gone out |
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused") |
RegisterName = RegisterName or "RegisterCallback" |
UnregisterName = UnregisterName or "UnregisterCallback" |
if UnregisterAllName==nil then -- false is used to indicate "don't want this method" |
UnregisterAllName = "UnregisterAllCallbacks" |
end |
-- we declare all objects and exported APIs inside this closure to quickly gain access |
-- to e.g. function names, the "target" parameter, etc |
-- Create the registry object |
local events = setmetatable({}, meta) |
local registry = { recurse=0, events=events } |
-- registry:Fire() - fires the given event/message into the registry |
function registry:Fire(eventname, ...) |
if not rawget(events, eventname) or not next(events[eventname]) then return end |
local oldrecurse = registry.recurse |
registry.recurse = oldrecurse + 1 |
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...) |
registry.recurse = oldrecurse |
if registry.insertQueue and oldrecurse==0 then |
-- Something in one of our callbacks wanted to register more callbacks; they got queued |
for eventname,callbacks in pairs(registry.insertQueue) do |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
for self,func in pairs(callbacks) do |
events[eventname][self] = func |
-- fire OnUsed callback? |
if first and registry.OnUsed then |
registry.OnUsed(registry, target, eventname) |
first = nil |
end |
end |
end |
registry.insertQueue = nil |
end |
end |
-- Registration of a callback, handles: |
-- self["method"], leads to self["method"](self, ...) |
-- self with function ref, leads to functionref(...) |
-- "addonId" (instead of self) with function ref, leads to functionref(...) |
-- all with an optional arg, which, if present, gets passed as first argument (after self if present) |
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) |
if type(eventname) ~= "string" then |
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) |
end |
method = method or eventname |
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. |
if type(method) ~= "string" and type(method) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) |
end |
local regfunc |
if type(method) == "string" then |
-- self["method"] calling style |
if type(self) ~= "table" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) |
elseif self==target then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) |
elseif type(self[method]) ~= "function" then |
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) self[method](self,arg,...) end |
else |
regfunc = function(...) self[method](self,...) end |
end |
else |
-- function ref with self=object or self="addonId" or self=thread |
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then |
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2) |
end |
if select("#",...)>=1 then -- this is not the same as testing for arg==nil! |
local arg=select(1,...) |
regfunc = function(...) method(arg,...) end |
else |
regfunc = method |
end |
end |
if events[eventname][self] or registry.recurse<1 then |
-- if registry.recurse<1 then |
-- we're overwriting an existing entry, or not currently recursing. just set it. |
events[eventname][self] = regfunc |
-- fire OnUsed callback? |
if registry.OnUsed and first then |
registry.OnUsed(registry, target, eventname) |
end |
else |
-- we're currently processing a callback in this registry, so delay the registration of this new entry! |
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency |
registry.insertQueue = registry.insertQueue or setmetatable({},meta) |
registry.insertQueue[eventname][self] = regfunc |
end |
end |
-- Unregister a callback |
target[UnregisterName] = function(self, eventname) |
if not self or self==target then |
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) |
end |
if type(eventname) ~= "string" then |
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) |
end |
if rawget(events, eventname) and events[eventname][self] then |
events[eventname][self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(events[eventname]) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then |
registry.insertQueue[eventname][self] = nil |
end |
end |
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds |
if UnregisterAllName then |
target[UnregisterAllName] = function(...) |
if select("#",...)<1 then |
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) |
end |
if select("#",...)==1 and ...==target then |
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) |
end |
for i=1,select("#",...) do |
local self = select(i,...) |
if registry.insertQueue then |
for eventname, callbacks in pairs(registry.insertQueue) do |
if callbacks[self] then |
callbacks[self] = nil |
end |
end |
end |
for eventname, callbacks in pairs(events) do |
if callbacks[self] then |
callbacks[self] = nil |
-- Fire OnUnused callback? |
if registry.OnUnused and not next(callbacks) then |
registry.OnUnused(registry, target, eventname) |
end |
end |
end |
end |
end |
end |
return registry |
end |
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it |
-- try to upgrade old implicit embeds since the system is selfcontained and |
-- relies on closures to work. |
Alerter = CreateFrame("Frame") |
Alerter.items = {} |
Alerter.update = 0 |
Alerter.free = { |
[1] = true, |
[2] = true, |
[3] = true, |
[4] = true, |
[5] = true, |
} |
Alerter.wipe = {} |
local Alerts = {} |
do |
yOfs = 250 |
for i = 1,5 do |
Alerter.items[i] = Alerter:CreateFontString() |
Alerter.items[i]:SetFont("Fonts\\FRIZQT__.TTF",40,"OUTLINE") |
Alerter.items[i]:SetPoint("CENTER",ALERT,"CENTER",0,yOfs) |
yOfs = yOfs - 50 |
end |
end |
function Alerter:SendAlert(msg,duration) |
tinsert(Alerts,{m=msg,t=GetTime()+duration}) |
end |
Alerter:SetScript("OnUpdate",function() |
if Alerter.update < GetTime() then |
for k,_ in pairs(Alerter.wipe) do |
if Alerter.wipe[k] < GetTime() then |
Alerter.items[k]:SetText("") |
Alerter.wipe[k] = nil |
Alerter.free[k] = true |
end |
end |
for k,_ in pairs(Alerts) do |
for j,_ in pairs(Alerter.free) do |
if Alerter.free[j] then |
Alerter.items[j]:SetText(Alerts[k].m) |
Alerter.wipe[j] = Alerts[k].t |
Alerter.free[j] = false |
Alerts[k] = nil |
break |
end |
end |
end |
Alerter.update = GetTime() + 0.2 |
end |
end) |
-- Format: ["SYSTEM"] = { pattern1, pattern2, pattern3, ...} |
local messagesToHide = { |
ERR_GUILD_INVITE_S, |
ERR_GUILD_DECLINE_S, |
ERR_ALREADY_IN_GUILD_S, |
ERR_ALREADY_INVITED_TO_GUILD_S, |
ERR_GUILD_DECLINE_AUTO_S, |
ERR_GUILD_PLAYER_NOT_FOUND_S, |
ERR_CHAT_PLAYER_NOT_FOUND_S, |
} |
local RealmCleanup = { |
ERR_CHAT_PLAYER_NOT_FOUND_S, |
} |
local chatFilters = {} |
local OnInt = {} |
local WhisperFilterActive = false; |
local function check(msg) |
local place |
local n |
local name |
for k,_ in pairs(messagesToHide) do |
place = strfind(messagesToHide[k],"%s",1,true) |
if place then |
name = strfind(msg," ",place,true) |
if name then |
n = strsub(msg,place,name-1) |
if format(messagesToHide[k],n) == msg then |
return true |
else |
n = strsub(msg,place,name-2) |
if format(messagesToHide[k],n) == msg then |
return true |
end |
end |
end |
end |
end |
end |
local function check2(msg) |
local place |
local n |
local name |
for k,_ in pairs(RealmCleanup) do |
place = strfind(RealmCleanup[k],"%s",1,true) |
if place then |
name = strfind(msg," ",place,true) |
if name then |
n = strsub(msg,place,name-1) |
if format(RealmCleanup[k],n) == msg then |
return true |
else |
n = strsub(msg,place,name-2) |
if format(RealmCleanup[k],n) == msg then |
return true |
end |
end |
end |
end |
end |
end |
local function HideOutWhispers(self, event, msg, sender) |
if (sender == UnitName("player")) then |
ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers); |
SGI:debug("Blocked outgoing whisper!"); |
return true; |
end |
end |
local function HideSystemMessage(self, event, msg) |
if (check(msg)) then |
SGI:debug("Blocked message: "..msg); |
return true; |
end |
end |
local function HideRealmConflictMessage(self, event, msg) |
if (check2(msg)) then |
SGI:debug("Blocked message: "..msg.." from check2()"); |
return true; |
end |
end |
ChatIntercept = {} |
function ChatIntercept:StateSystem(on) |
if (on) then |
ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HideSystemMessage); |
print("|cffffff00ChatIntercept [|r|cff16ABB5System Messages|r|cffffff00] is now |r|cff00ff00ACTIVE|r"); |
else |
ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM", HideSystemMessage); |
print("|cffffff00ChatIntercept [|r|cff16ABB5System Messages|r|cffffff00] is now |r|cffff0000INACTIVE|r"); |
end |
end |
function ChatIntercept:StateRealm(state) |
if (state) then |
ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HideRealmConflictMessage); |
SGI:debug("Blocking realm conflict messages"); |
else |
ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM",HideRealmConflictMessage); |
SGI:debug("Not blocking realm conflict messages"); |
end |
end |
function ChatIntercept:StateWhisper(on) |
WhisperFilterActive = on; |
if (on) then |
--ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers); |
print("|cffffff00ChatIntercept [|r|cff16ABB5Whispers|r|cffffff00] is now |r|cff00ff00ACTIVE|r"); |
else |
--ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers); |
print("|cffffff00ChatIntercept [|r|cff16ABB5Whispers|r|cffffff00] is now |r|cffff0000INACTIVE|r"); |
end |
end |
function ChatIntercept:InterceptNextWhisper() |
if (WhisperFilterActive) then |
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", HideOutWhispers); |
end |
end |
--[[ |
GuildShield by Janniie - Stormreaver EU |
The purpose of GuildShield is to protect players from being |
contacted by guild invite mods. |
To users: Use this as any other AddOn and you will be protected against some |
guild invite mods. |
To developers: 1. Put GuildShield.lua in you Guild Invite AddOns' folder and load it before your own, ie in the TOC file. |
2. Then run the function GuildShield:Initiate(action) inside your AddOn. |
"action" is the function you wish to call when you find a player with GuildShield |
active. |
In my case it's a function that removes the player from my AddOns' invite queue. |
3. Then call, when fitting, GuildShield:IsShielded(playerName) to check if the player |
has GuildShield installed. If they have, the "action" you specified earlier should be called |
automaically, and in my case remove the player. |
]] |
RegisterAddonMessagePrefix("GUILD_SHIELD") |
RegisterAddonMessagePrefix("I_HAVE_SHIELD") |
local function IsShielded(self,player) |
SendAddonMessage("GUILD_SHIELD","","WHISPER",player) |
end |
local function Initiate(self,action) |
local Shield = CreateFrame("Frame") |
Shield:RegisterEvent("CHAT_MSG_ADDON") |
Shield:SetScript("OnEvent",function(self,event,...) |
local prefix,msg,channel,sender = select(1,...) |
if prefix == "I_HAVE_SHIELD" then |
action(sender) |
end |
end) |
print("|cffff8800Guild|r|cff00A2FFShield|r|cff55EE55 has been initiated|r") |
end |
local f = CreateFrame("Frame") |
f:RegisterEvent("CHAT_MSG_ADDON") |
f:SetScript("OnEvent",function(...) |
local prefix,msg,channel,sender = select(3,...) |
if prefix == "GUILD_SHIELD" and sender ~= UnitName("player") then |
SendAddonMessage("I_HAVE_SHIELD","","WHISPER",sender) |
print("|cffff8800Guild|r|cff00A2FFShield|r|cff55EE55 protected you from an invite (|r|cff00A2FF"..sender.."|r|cff55EE55)|r") |
GuildShield.protects = GuildShield.protects + 1 |
GuildShield.lastSession = GuildShield.lastSession + 1 |
end |
end) |
local login = CreateFrame("Frame") |
login:RegisterEvent("PLAYER_LOGIN") |
login:SetScript("OnEvent",function() |
if type(GuildShield) ~= "table" then |
GuildShield = {} |
end |
GuildShield.protects = GuildShield.protects or 0 |
GuildShield.lastSession = GuildShield.lastSession or 0 |
print("|cffff8800Guild|r|cff00A2FFShield|r|cff55EE55 Protected you from |r|cffEC55EE"..GuildShield.lastSession.."|r|cff55EE55 invites last game session, for a total of |r|cffEC55EE"..GuildShield.protects.."|r|cff55EE55 blocked invites.|r") |
GuildShield.lastSession = 0 |
GuildShield.IsShielded = IsShielded |
GuildShield.Initiate = Initiate |
print("|cffff8800Guild|r|cff00A2FFShield|r|cff55EE55 is active and protecting you|r") |
end) |