-- Event-driven achievement tracking, character scan, and hotkey binding. local frame = CreateFrame("Frame", "RelationshipsAchievementsEventFrame", UIParent) -- Turtle/OctoWoW builds expose slightly different event sets. Registering an -- unknown event can abort an entire Lua file on some 1.12 clients, so optional -- events are protected. The standard Vanilla events remain the primary path. local function SafeRegister(name) pcall(frame.RegisterEvent, frame, name) end local trackedEvents = { "PLAYER_LOGIN", "PLAYER_ENTERING_WORLD", "PLAYER_LEVEL_UP", "PLAYER_DEAD", "QUEST_COMPLETE", "QUEST_TURNED_IN", "ZONE_CHANGED_NEW_AREA", "ZONE_CHANGED", "ZONE_CHANGED_INDOORS", "CHAT_MSG_COMBAT_HONOR_GAIN", "CHAT_MSG_COMBAT_FACTION_CHANGE", "SKILL_LINES_CHANGED", "CHAT_MSG_LOOT", "CHAT_MSG_MONEY", "CHAT_MSG_COMBAT_HOSTILE_DEATH", "CHAT_MSG_COMBAT_XP_GAIN", "CHAT_MSG_SYSTEM", "CHAT_MSG_BG_SYSTEM_NEUTRAL", "CHAT_MSG_BG_SYSTEM_ALLIANCE", "CHAT_MSG_BG_SYSTEM_HORDE", "UPDATE_FACTION", "PARTY_MEMBERS_CHANGED", "FRIENDLIST_UPDATE", "GUILD_ROSTER_UPDATE", "PLAYER_UNGHOST", "PLAYER_ALIVE", "CHAT_MSG_TEXT_EMOTE", "CHAT_MSG_EMOTE", "PLAYER_PVP_RANK_CHANGED", "PLAYER_PVP_KILLS_CHANGED", "PLAYER_PVPKILLS_CHANGED", "HONOR_CURRENCY_UPDATE", "HEARTHSTONE_BOUND", "BANKFRAME_OPENED", "TRAINER_SHOW", "MAIL_SEND_SUCCESS", "PLAYER_EQUIPMENT_CHANGED", "BAG_UPDATE", "CHARACTER_POINTS_CHANGED", "SPELLS_CHANGED", "UNIT_HEALTH", "PLAYER_MONEY" } for i = 1, table.getn(trackedEvents) do SafeRegister(trackedEvents[i]) end -- ============ PvP rank scanning ============ -- Vanilla UnitPVPRank("player") returns 0 (no rank) or 5..19 where the -- lowest ranked player is Private/Scout = 5. Subtract 4 to get 1..14. local function ScanPvPRank() if not UnitPVPRank then return end local raw = UnitPVPRank("player") or 0 -- Lifetime stats preserve the highest rank ever earned, even after weekly -- decay. Use whichever is higher so installing later still grants every -- lower title in the chain. if GetPVPLifetimeStats then local _, _, highest = GetPVPLifetimeStats() if highest and highest > raw then raw = highest end end if raw == 0 then return end local rank = raw if rank >= 5 then rank = rank - 4 end if rank < 1 then return end if rank >= 1 then RelationshipsAchievements:Unlock(2001) end -- Private / Scout if rank >= 3 then RelationshipsAchievements:Unlock(2002) end -- Sergeant / Senior Sergeant if rank >= 6 then RelationshipsAchievements:Unlock(2003) end -- Knight / Stone Guard if rank >= 9 then RelationshipsAchievements:Unlock(2004) end -- Champion / Centurion if rank >= 12 then RelationshipsAchievements:Unlock(2005) end -- Marshal / Legionnaire if rank >= 13 then RelationshipsAchievements:Unlock(2006) end -- Field Marshal / Warlord if rank >= 14 then local _, faction = UnitFactionGroup("player") if faction == "Horde" then RelationshipsAchievements:Unlock(1003) -- High Warlord else RelationshipsAchievements:Unlock(1002) -- Grand Marshal end end end local function ScanPvPKills() if not GetPVPLifetimeStats then return end local honorable = GetPVPLifetimeStats() or 0 RelationshipsAchievements:UpdateStat("honorKills", honorable) if honorable >= 1 then RelationshipsAchievements:Unlock(501) end end local function ScanTalents() if not GetNumTalentTabs or not GetNumTalents or not GetTalentInfo then return end local spent = 0 for tab = 1, GetNumTalentTabs() do for talent = 1, GetNumTalents(tab) do local _, _, _, _, rank = GetTalentInfo(tab, talent) spent = spent + (rank or 0) end end if spent >= 1 then RelationshipsAchievements:Unlock(1111) end if spent >= 51 then RelationshipsAchievements:Unlock(1112) end end local previousTalentSpent local function ScanTalentChange() if not GetNumTalentTabs or not GetNumTalents or not GetTalentInfo then return end local spent = 0 for tab = 1, GetNumTalentTabs() do for talent = 1, GetNumTalents(tab) do local _, _, _, _, rank = GetTalentInfo(tab, talent) spent = spent + (rank or 0) end end if previousTalentSpent and previousTalentSpent > 0 and spent == 0 then RelationshipsAchievements:Unlock(1113) end previousTalentSpent = spent ScanTalents() end local function ScanEquipmentAndBags() if GetInventoryItemLink then if GetInventoryItemLink("player", 4) then RelationshipsAchievements:Unlock(1203) end if GetInventoryItemLink("player", 19) then RelationshipsAchievements:Unlock(109) end local allRare, haveGear, epic = true, false, false for slot = 1, 18 do if slot ~= 4 and slot ~= 18 then local link = GetInventoryItemLink("player", slot) if link then haveGear = true local _, _, quality = GetItemInfo(link) if quality and quality >= 4 then epic = true end if not quality or quality < 3 then allRare = false end local itemName = GetItemInfo(link) if itemName == "Atiesh, Greatstaff of the Guardian" then RelationshipsAchievements:Unlock(1004) end if itemName == "Thunderfury, Blessed Blade of the Windseeker" then RelationshipsAchievements:Unlock(1005) end if itemName == "Sulfuras, Hand of Ragnaros" then RelationshipsAchievements:Unlock(1006) end else allRare = false end end end if haveGear and allRare then RelationshipsAchievements:Unlock(1208) end if epic then RelationshipsAchievements:Unlock(1209) end end if GetContainerNumSlots then local bags, has16 = 0, false for bag = 1, 4 do local slots = GetContainerNumSlots(bag) or 0 if slots > 0 then bags = bags + 1 end if slots >= 16 then has16 = true end end if bags >= 4 then RelationshipsAchievements:Unlock(1202) end if has16 then RelationshipsAchievements:Unlock(1201) end end end local function ScanSpellbook() if not GetSpellName then return end local mounts, pets = 0, 0 local i = 1 while true do local name, rank = GetSpellName(i, BOOKTYPE_SPELL or "spell") if not name then break end local low = string.lower(name) if string.find(low, "summon ") and (string.find(low, "horse") or string.find(low, "ram") or string.find(low, "tiger") or string.find(low, "raptor") or string.find(low, "wolf") or string.find(low, "kodo") or string.find(low, "mechanostrider")) then mounts = mounts + 1 end if string.find(low, "summon ") and not string.find(low, "demon") and not string.find(low, "elemental") then pets = pets + 1 end i = i + 1 end RelationshipsAchievements:UpdateStat("mountCount", mounts) RelationshipsAchievements:UpdateStat("petCount", pets) if mounts >= 1 then RelationshipsAchievements:Unlock(211) end if mounts >= 1 and (UnitLevel("player") or 1) >= 60 then RelationshipsAchievements:Unlock(212) end if pets >= 1 then RelationshipsAchievements:Unlock(1204) end end function RelationshipsAchievements_ScanCharacter() RelationshipsAchievements:Init() local lvl = UnitLevel("player") or 1 if lvl >= 5 then RelationshipsAchievements:Unlock(216) end if lvl >= 10 then RelationshipsAchievements:Unlock(201) end if lvl >= 15 then RelationshipsAchievements:Unlock(218) end if lvl >= 20 then RelationshipsAchievements:Unlock(202) end if lvl >= 25 then RelationshipsAchievements:Unlock(219) end if lvl >= 30 then RelationshipsAchievements:Unlock(203) end if lvl >= 35 then RelationshipsAchievements:Unlock(220) end if lvl >= 40 then RelationshipsAchievements:Unlock(204) end if lvl >= 45 then RelationshipsAchievements:Unlock(221) end if lvl >= 50 then RelationshipsAchievements:Unlock(205) end if lvl >= 55 then RelationshipsAchievements:Unlock(222) end if lvl >= 60 then RelationshipsAchievements:Unlock(206) end -- Custom races and OctoWoW level milestone. local race = UnitRace("player") if race == "High Elf" or race == "HighElf" then RelationshipsAchievements:Unlock(1302) end if race == "Goblin" then RelationshipsAchievements:Unlock(1303) end if lvl >= 60 then RelationshipsAchievements:Unlock(1307) end -- Class-at-60 achievements if lvl >= 60 then local _, class = UnitClass("player") if class == "WARRIOR" then RelationshipsAchievements:Unlock(1101) elseif class == "PALADIN" then RelationshipsAchievements:Unlock(1102) elseif class == "HUNTER" then RelationshipsAchievements:Unlock(1103) elseif class == "ROGUE" then RelationshipsAchievements:Unlock(1104) elseif class == "PRIEST" then RelationshipsAchievements:Unlock(1105) elseif class == "SHAMAN" then RelationshipsAchievements:Unlock(1106) elseif class == "MAGE" then RelationshipsAchievements:Unlock(1107) elseif class == "WARLOCK" then RelationshipsAchievements:Unlock(1108) elseif class == "DRUID" then RelationshipsAchievements:Unlock(1109) end end if GetGuildInfo and GetGuildInfo("player") then RelationshipsAchievements:Unlock(103) if GetNumGuildMembers and GetNumGuildMembers() >= 10 then RelationshipsAchievements:Unlock(1703) end end if GetNumPartyMembers and GetNumPartyMembers() > 0 then RelationshipsAchievements:Unlock(105) end if GetNumFriends and GetNumFriends() > 0 then RelationshipsAchievements:Unlock(102) RelationshipsAchievements:UpdateStat("friendCount", GetNumFriends()) end if GetInventoryItemLink and GetInventoryItemLink("player", 19) then RelationshipsAchievements:Unlock(109) end -- Gold-in-bag achievements (retroactive on scan) if GetMoney then local copper = GetMoney() or 0 if copper >= 100 then RelationshipsAchievements:Unlock(1901) end -- 1 silver if copper >= 10000 then RelationshipsAchievements:Unlock(1902) end -- 1 gold if copper >= 5000000 then RelationshipsAchievements:Unlock(223) end -- 500g if copper >= 10000000 then RelationshipsAchievements:Unlock(1903) end -- 1000g if copper >= 50000000 then RelationshipsAchievements:Unlock(224) end -- 5000g if copper >= 100000000 then RelationshipsAchievements:Unlock(1904) end -- 10000g end local zc = 0 for _ in pairs(RelationshipsAchievementsCharDB.zones) do zc = zc + 1 end RelationshipsAchievements:UpdateStat("zoneCount", zc) if GetNumSkillLines then local highestProf = 0 local highestWeapon = 0 for i = 1, GetNumSkillLines() do local name, isHeader, _, rank = GetSkillLineInfo(i) if not isHeader and rank and rank > 0 then if name == "Swords" or name == "Two-Handed Swords" or name == "Axes" or name == "Two-Handed Axes" or name == "Maces" or name == "Two-Handed Maces" or name == "Daggers" or name == "Fist Weapons" or name == "Polearms" or name == "Staves" or name == "Bows" or name == "Crossbows" or name == "Guns" or name == "Wands" or name == "Thrown" then if rank > highestWeapon then highestWeapon = rank end elseif name == "Cooking" then RelationshipsAchievements:UpdateStat("cookingSkill", rank) elseif name == "Fishing" then RelationshipsAchievements:UpdateStat("fishingSkill", rank) elseif name == "First Aid" then if rank >= 300 then RelationshipsAchievements:Unlock(707) end else if rank > highestProf then highestProf = rank end if rank >= 300 then if name == "Alchemy" then RelationshipsAchievements:Unlock(708) end if name == "Blacksmithing" then RelationshipsAchievements:Unlock(709) end if name == "Enchanting" then RelationshipsAchievements:Unlock(710) end if name == "Engineering" then RelationshipsAchievements:Unlock(711) end if name == "Herbalism" then RelationshipsAchievements:Unlock(712) end if name == "Leatherworking"then RelationshipsAchievements:Unlock(713) end if name == "Mining" then RelationshipsAchievements:Unlock(714) end if name == "Skinning" then RelationshipsAchievements:Unlock(715) end if name == "Tailoring" then RelationshipsAchievements:Unlock(716) end end end end end RelationshipsAchievements:UpdateStat("profSkill", highestProf) RelationshipsAchievements:UpdateStat("weaponSkill", highestWeapon) end if GetNumFactions then local exalted = 0 local hasFriendly, hasHonored, hasRevered, hasExalted = false, false, false, false for i = 1, GetNumFactions() do local name, _, standing = GetFactionInfo(i) if standing then if standing >= 5 then hasFriendly = true end if standing >= 6 then hasHonored = true end if standing >= 7 then hasRevered = true end if standing >= 8 then hasExalted = true exalted = exalted + 1 if name and RelationshipsAchievements_FactionMap[name] then RelationshipsAchievements:Unlock(RelationshipsAchievements_FactionMap[name]) end RelationshipsAchievementsCharDB.factionsExalted[name or "?"] = true end end end if hasFriendly then RelationshipsAchievements:Unlock(801) end if hasHonored then RelationshipsAchievements:Unlock(802) end if hasRevered then RelationshipsAchievements:Unlock(803) end if hasExalted then RelationshipsAchievements:Unlock(804) end RelationshipsAchievements:UpdateStat("exaltedCount", exalted) end ScanPvPRank() ScanPvPKills() ScanTalents() ScanEquipmentAndBags() ScanSpellbook() RelationshipsAchievements_RefreshUI = RelationshipsAchievements_RefreshUI or function() end if RelationshipsAchievementFrame and RelationshipsAchievementFrame:IsVisible() then RelationshipsAchievements_RefreshUI() end end local function BindHotkey() if not SetBinding then return end local existing = GetBindingAction and GetBindingAction("Y") if existing and existing ~= "" and existing ~= "TOGGLERELATIONSHIPSACHIEVEMENT" then return end SetBinding("Y", "TOGGLERELATIONSHIPSACHIEVEMENT") end -- ============ SendChatMessage hook (Chatty achievement) ============ -- Wrapping SendChatMessage is more reliable than reading CHAT_MSG_SAY back, -- because whispers, guild chat, and channels each fire different events and -- some don't echo the sender field consistently on Turtle / Vanilla. local _origSendChatMessage = SendChatMessage if _origSendChatMessage then SendChatMessage = function(msg, chatType, language, target) _origSendChatMessage(msg, chatType, language, target) if msg and msg ~= "" and RelationshipsAchievements and RelationshipsAchievements.AddStat then RelationshipsAchievements:AddStat("chatCount", 1) end end end local _origSendMail = SendMail if _origSendMail then SendMail = function(name, subject, body) _origSendMail(name, subject, body) RelationshipsAchievements:Unlock(110) end end local _origPostAuction = PostAuction if _origPostAuction then PostAuction = function(minBid, buyoutPrice, runTime, stackSize, numStacks) _origPostAuction(minBid, buyoutPrice, runTime, stackSize, numStacks) RelationshipsAchievements:AddStat("auctionsListed", numStacks or 1) end end local _origBuyoutAuction = BuyoutAuction if _origBuyoutAuction then BuyoutAuction = function(index) _origBuyoutAuction(index) RelationshipsAchievements:Unlock(107) RelationshipsAchievements:AddStat("auctionsWon", 1) end end local OnQuestComplete -- Hook ConfirmBinder(): the innkeeper popup's OnAccept calls this API and it -- fires exactly once per successful bind. The HEARTHSTONE_BOUND event does not -- exist in vanilla 1.12, and the CHAT_MSG_SYSTEM string fallback below is -- localised / worded differently on some Turtle/Octo builds, so hooking the -- API is the only reliable trigger for re-binding to a new inn. local _origConfirmBinder = ConfirmBinder if _origConfirmBinder then ConfirmBinder = function() _origConfirmBinder() if RelationshipsAchievements and RelationshipsAchievements.Unlock then RelationshipsAchievements:Unlock(108) end if RelationshipsAchievementsCharDB then RelationshipsAchievementsCharDB.pendingInnBind = nil end end end -- Hook GetQuestReward(): fires exactly once when the player accepts a quest -- reward. Much more reliable than QUEST_COMPLETE (which fires each time the -- reward window opens) for tracking completed-quest counters. local _origGetQuestReward = GetQuestReward if _origGetQuestReward then GetQuestReward = function(choice) OnQuestComplete() return _origGetQuestReward(choice) end end -- ============ DoEmote hook (Say Hello / Dance Off) ============ -- Hooking DoEmote is the cleanest way: the token is stable ("wave", "dance") -- across all locales, unlike the CHAT_MSG_TEXT_EMOTE text which is localized. local _origDoEmote = DoEmote if _origDoEmote then DoEmote = function(token, target) _origDoEmote(token, target) if not token then return end local t = string.lower(token) if t == "wave" then RelationshipsAchievements:Unlock(1701) elseif t == "dance" then RelationshipsAchievements:Unlock(1702) end end end local loginScanDone = false local function OnLogin() RelationshipsAchievements:Init() RelationshipsAchievements:Unlock(101) RelationshipsAchievements:Unlock(1301) BindHotkey() if not loginScanDone then loginScanDone = true local scanner = CreateFrame("Frame") local acc = 0 scanner:SetScript("OnUpdate", function() acc = acc + (arg1 or 0) if acc >= 2 then RelationshipsAchievements_ScanCharacter() if ShowFriends then ShowFriends() end if GuildRoster then GuildRoster() end this:SetScript("OnUpdate", nil) end end) end end local function OnLevelUp() RelationshipsAchievements_ScanCharacter() end OnQuestComplete = function() -- QUEST_COMPLETE is the reliable 1.12 turn-in event. Custom clients that -- also emit QUEST_TURNED_IN are de-duplicated by time stamp below. local now = time() if RelationshipsAchievementsCharDB.lastQuestCredit == now then return end RelationshipsAchievementsCharDB.lastQuestCredit = now RelationshipsAchievements:AddStat("questCount", 1) local title = GetTitleText and GetTitleText() or "" local low = string.lower(title or "") if string.find(low, "attunement to the core") then RelationshipsAchievements:Unlock(683) end if string.find(low, "blackhand's command") then RelationshipsAchievements:Unlock(682) end if string.find(low, "onyxia") or string.find(low, "great masquerade") then RelationshipsAchievements:Unlock(684) end if string.find(low, "head of onyxia") or string.find(low, "victory for the alliance") or string.find(low, "victory for the horde") then RelationshipsAchievements:Unlock(2104) end if string.find(low, "silithyst") then RelationshipsAchievements:AddStat("silithystTurnIns", 1) end if string.find(low, "class") then RelationshipsAchievements:Unlock(312) end end local function OnZoneChanged() local zone = GetRealZoneText() or GetZoneText() if not zone or zone == "" then return end if RelationshipsAchievements_CityMap and RelationshipsAchievements_CityMap[zone] then RelationshipsAchievements:Unlock(RelationshipsAchievements_CityMap[zone]) RelationshipsAchievementsCharDB.cities = RelationshipsAchievementsCharDB.cities or {} if not RelationshipsAchievementsCharDB.cities[zone] then RelationshipsAchievementsCharDB.cities[zone] = true local a, h = 0, 0 for c in pairs(RelationshipsAchievementsCharDB.cities) do if RelationshipsAchievements_AllianceCities[c] then a = a + 1 end if RelationshipsAchievements_HordeCities[c] then h = h + 1 end end RelationshipsAchievements:UpdateStat("allianceCitiesVisited", a) RelationshipsAchievements:UpdateStat("hordeCitiesVisited", h) if a >= 3 then RelationshipsAchievements:Unlock(1807) end if h >= 3 then RelationshipsAchievements:Unlock(1808) end end end local lowZone = string.lower(zone) if string.find(lowZone, "karazhan crypt") then RelationshipsAchievements:Unlock(1305) end if string.find(lowZone, "emerald sanctum") then RelationshipsAchievements:Unlock(1308) end if not RelationshipsAchievementsCharDB.zones[zone] then RelationshipsAchievementsCharDB.zones[zone] = true local id = RelationshipsAchievements_ZoneMap[zone] if id then RelationshipsAchievements:Unlock(id) end local count = 0 for _ in pairs(RelationshipsAchievementsCharDB.zones) do count = count + 1 end RelationshipsAchievements:UpdateStat("zoneCount", count) end end local function OnHonorGain(msg) -- Objective/bonus honor uses this event too, so never increment blindly. -- Lifetime stats give the authoritative HK total and cannot double-count. if GetPVPLifetimeStats then local before = RelationshipsAchievements:GetStat("honorKills") ScanPvPKills() local after = RelationshipsAchievements:GetStat("honorKills") if after > before then RelationshipsAchievements:Unlock(501) RelationshipsAchievements:UpdateStat("pvpKills", after) end elseif msg and string.find(string.lower(msg), "honorable kill") then RelationshipsAchievements:Unlock(501) RelationshipsAchievements:AddStat("honorKills", 1) RelationshipsAchievements:AddStat("pvpKills", 1) end end local function OnFactionChange(msg) if not msg then return end -- Recompute from the faction table. Incrementing from chat inflated the -- count when duplicate messages fired and could award 5/10 Exalted early. RelationshipsAchievements_ScanCharacter() end local function OnSkillLinesChanged() RelationshipsAchievements_ScanCharacter() end local function OnLootMessage(msg) if not msg then return end local clean = string.gsub(msg, ",", "") local _, _, g = string.find(clean, "(%d+) Gold") if g then RelationshipsAchievements:AddStat("goldLooted", tonumber(g)) end local low = string.lower(msg) if string.find(low, "fish") or string.find(low, "snapper") or string.find(low, "trout") or string.find(low, "salmon") or string.find(low, "catfish") or string.find(low, "eel") then RelationshipsAchievements:Unlock(1401) RelationshipsAchievements:AddStat("fishCount", 1) end if string.find(low, "you create") and (string.find(low, "food") or string.find(low, "meal") or string.find(low, "roast") or string.find(low, "stew")) then RelationshipsAchievements:Unlock(1501) end end local function OnEnemyDeath(msg) if not msg then return end if string.find(msg, "You have slain") or string.find(msg, "slain by you") then RelationshipsAchievements:AddStat("killCount", 1) end local bossMap = RelationshipsAchievements_BossMap or {} for boss, info in pairs(bossMap) do if string.find(msg, boss, 1, true) then RelationshipsAchievements:Unlock(info.id) local seen = info.raid and RelationshipsAchievementsCharDB.raidBosses or RelationshipsAchievementsCharDB.dungeonBosses if not seen[boss] then seen[boss] = true RelationshipsAchievements:AddStat(info.raid and "raidsCleared" or "dungeonsCleared", 1) end end end end local function OnSystemMessage(msg) if not msg then return end local _, _, winner = string.find(msg, "^(.-) has defeated ") if winner and winner == UnitName("player") then RelationshipsAchievements:AddStat("duelWins", 1) end if string.find(msg, "home is now") or string.find(msg, "bound to") then RelationshipsAchievements:Unlock(108) RelationshipsAchievementsCharDB.pendingInnBind = nil end local low = string.lower(msg) if string.find(low, "learned a new") or string.find(low, "you have learned") then RelationshipsAchievements:Unlock(1110) end if string.find(low, "darkmoon faire") then RelationshipsAchievements:Unlock(911) end if string.find(low, "trick or treat") then RelationshipsAchievements:Unlock(903) end if string.find(low, "lunar festival") then RelationshipsAchievements:Unlock(909) end if string.find(low, "winter veil") then RelationshipsAchievements:Unlock(901) end -- Battleground victories. On 1.12 the win message reads "The Alliance wins!" -- or "The Horde wins!" via CHAT_MSG_BG_SYSTEM_NEUTRAL and does NOT include -- the map name, so we look up the current BG from GetRealZoneText() and -- credit the player's faction only. Guard with pendingBgWin so duplicate -- messages (both faction and neutral system chat) don't double-count. if string.find(msg, "wins!") or string.find(msg, "[Vv]ictory") then local zone = (GetRealZoneText and GetRealZoneText()) or "" local _, myFaction = UnitFactionGroup("player") local winner if string.find(msg, "Alliance") then winner = "Alliance" elseif string.find(msg, "Horde") then winner = "Horde" end local key = zone .. "|" .. (winner or "?") if RelationshipsAchievementsCharDB and RelationshipsAchievementsCharDB.lastBgWinKey ~= key then RelationshipsAchievementsCharDB.lastBgWinKey = key if not winner or winner == myFaction then if string.find(zone, "Warsong Gulch") then RelationshipsAchievements:Unlock(505) RelationshipsAchievements:AddStat("wsgWins", 1) RelationshipsAchievements:AddStat("bgWins", 1) elseif string.find(zone, "Alterac Valley") then RelationshipsAchievements:Unlock(506) RelationshipsAchievements:AddStat("avWins", 1) RelationshipsAchievements:AddStat("bgWins", 1) elseif string.find(zone, "Arathi Basin") then RelationshipsAchievements:Unlock(507) RelationshipsAchievements:AddStat("abWins", 1) RelationshipsAchievements:AddStat("bgWins", 1) end end end end end -- Emote handler: catch /wave and /dance in every locale by matching the -- token via DoEmote hook AND as a fallback matching the English text here. local function OnTextEmote(msg, sender) if not msg then return end local me = UnitName("player") -- vanilla emote text always begins with "You " when it's the local player, -- or the player's name otherwise. local mine = (sender and sender == me) or string.find(msg, "^You ") if not mine then return end if string.find(string.lower(msg), "wave") then RelationshipsAchievements:Unlock(1701) end if string.find(string.lower(msg), "dance") then RelationshipsAchievements:Unlock(1702) end end frame:SetScript("OnEvent", function() if event == "PLAYER_LOGIN" then OnLogin() elseif event == "PLAYER_ENTERING_WORLD" then RelationshipsAchievements:Init() BindHotkey() OnZoneChanged() ScanPvPRank() elseif event == "PLAYER_LEVEL_UP" then OnLevelUp() elseif event == "PLAYER_DEAD" or event == "PLAYER_UNGHOST" or event == "PLAYER_ALIVE" then if event == "PLAYER_DEAD" then RelationshipsAchievements:Unlock(207) RelationshipsAchievements:AddStat("deaths", 1) end elseif event == "QUEST_COMPLETE" or event == "QUEST_TURNED_IN" then OnQuestComplete() elseif event == "ZONE_CHANGED_NEW_AREA" or event == "ZONE_CHANGED" or event == "ZONE_CHANGED_INDOORS" then OnZoneChanged() elseif event == "CHAT_MSG_COMBAT_HONOR_GAIN" then OnHonorGain(arg1) elseif event == "CHAT_MSG_COMBAT_FACTION_CHANGE" then OnFactionChange(arg1) elseif event == "SKILL_LINES_CHANGED" then OnSkillLinesChanged() elseif event == "CHAT_MSG_LOOT" or event == "CHAT_MSG_MONEY" then OnLootMessage(arg1) elseif event == "CHAT_MSG_COMBAT_HOSTILE_DEATH" or event == "CHAT_MSG_COMBAT_XP_GAIN" then OnEnemyDeath(arg1) elseif event == "CHAT_MSG_SYSTEM" or event == "CHAT_MSG_BG_SYSTEM_NEUTRAL" or event == "CHAT_MSG_BG_SYSTEM_ALLIANCE" or event == "CHAT_MSG_BG_SYSTEM_HORDE" then OnSystemMessage(arg1) elseif event == "CHAT_MSG_TEXT_EMOTE" or event == "CHAT_MSG_EMOTE" then OnTextEmote(arg1, arg2) elseif event == "PLAYER_PVP_RANK_CHANGED" or event == "HONOR_CURRENCY_UPDATE" or event == "PLAYER_PVPKILLS_CHANGED" or event == "PLAYER_PVP_KILLS_CHANGED" then ScanPvPRank() ScanPvPKills() elseif event == "HEARTHSTONE_BOUND" then RelationshipsAchievements:Unlock(108) RelationshipsAchievementsCharDB.pendingInnBind = nil elseif event == "BANKFRAME_OPENED" then RelationshipsAchievements:Unlock(106) elseif event == "TRAINER_SHOW" then RelationshipsAchievements:Unlock(111) elseif event == "MAIL_SEND_SUCCESS" then RelationshipsAchievements:Unlock(110) elseif event == "PLAYER_EQUIPMENT_CHANGED" or event == "BAG_UPDATE" then ScanEquipmentAndBags() elseif event == "CHARACTER_POINTS_CHANGED" then ScanTalentChange() elseif event == "SPELLS_CHANGED" then ScanSpellbook() elseif event == "PLAYER_MONEY" then if GetMoney then local copper = GetMoney() or 0 if copper >= 100 then RelationshipsAchievements:Unlock(1901) end if copper >= 10000 then RelationshipsAchievements:Unlock(1902) end if copper >= 5000000 then RelationshipsAchievements:Unlock(223) end if copper >= 10000000 then RelationshipsAchievements:Unlock(1903) end if copper >= 50000000 then RelationshipsAchievements:Unlock(224) end if copper >= 100000000 then RelationshipsAchievements:Unlock(1904) end end elseif event == "UNIT_HEALTH" and arg1 == "player" then local maxHealth = UnitHealthMax("player") or 0 if maxHealth > 0 and UnitHealth("player") > 0 and UnitHealth("player") * 10 < maxHealth then RelationshipsAchievements:Unlock(1605) end elseif event == "UPDATE_FACTION" then RelationshipsAchievements_ScanCharacter() elseif event == "PARTY_MEMBERS_CHANGED" then if GetNumPartyMembers and GetNumPartyMembers() > 0 then RelationshipsAchievements:Unlock(105) end elseif event == "FRIENDLIST_UPDATE" then if GetNumFriends and GetNumFriends() > 0 then RelationshipsAchievements:Unlock(102) RelationshipsAchievements:UpdateStat("friendCount", GetNumFriends()) end elseif event == "GUILD_ROSTER_UPDATE" then if GetGuildInfo and GetGuildInfo("player") then RelationshipsAchievements:Unlock(103) if GetNumGuildMembers and GetNumGuildMembers() >= 10 then RelationshipsAchievements:Unlock(1703) end end end end)