7 Commits

5 changed files with 76 additions and 14 deletions
+10
View File
@@ -14,6 +14,16 @@ You play the best class, now you have the best companion for it (and its not you
- MetaHunt is fully compatible with QUIVER <3, and is not a replacement for it.
- The addon purposely disable itself on all Capycraft/Ravencraft Realms, following the DDOS attacks they conducted on other servers.
### Installation (READ THIS!) ⚠️⚠️⚠️
After you download the zip, you have a manual action to do because of Gitea behaviour.
When you unzip, you will find a "metahunt" root folder, you SHOULD rename it as exactly "MetaHunt", and then move that folder in your \Interface\AddOns\ directory. If you dont restore the capital letters in the folder name, the addon will be broken.
This is [a known issue from Gitea/Forgejo](https://codeberg.org/forgejo/forgejo/issues/800) when the system creates zip files, and there's nothing add-on devs can do to overcome it.
## Twow Data
MetaHunt ships with large twow datastores, and notably:
+2 -2
View File
@@ -30,8 +30,8 @@ MTH_FEED_TRACE = false
local function MTH_FEED_Trace(message)
if not MTH_FEED_TRACE then return end
if type(DEFAULT_CHAT_FRAME) == "table" and DEFAULT_CHAT_FRAME.AddMessage then
DEFAULT_CHAT_FRAME:AddMessage("|cff88aaff[MTH-FeedTrack]|r " .. tostring(message))
if MTH_DebugFrame and type(MTH_DebugFrame.AddInfo) == "function" then
MTH_DebugFrame:AddInfo("[MTH-FeedTrack] " .. tostring(message))
end
end
+9
View File
@@ -4,6 +4,7 @@
local MTH_LT_Frame = nil
local MTH_LT_PendingPetCheck = false
local MTH_LT_SuppressUntil = 0
local MTH_LT_HunterLines = {
[1] = "You can now track beasts. Revolutionary: look for the things you intend to shoot.",
@@ -293,6 +294,13 @@ local function MTH_LT_HandlePetState()
store.pet = state
return
end
-- Just after a loading screen the pet's real level/loyalty can arrive a beat
-- late; record them as the baseline silently so we never announce progress
-- that actually happened in an earlier session (e.g. a fresh install).
if type(GetTime) == "function" and MTH_LT_SuppressUntil > 0 and GetTime() < MTH_LT_SuppressUntil then
store.pet = state
return
end
if state.level > (tonumber(pet.level) or 0) then
local line = MTH_LT_NextLine(store, "petLine", MTH_LT_PetLines)
if MTH_LT_MessageEnabled("petLevelUp", true) then MTH:Print(state.name .. " reached level " .. state.level .. ". " .. line) end
@@ -368,6 +376,7 @@ function MTH_LevelTracker_Initialize()
if event == "PLAYER_ENTERING_WORLD" then
local level = type(UnitLevel) == "function" and tonumber(UnitLevel("player")) or nil
if level then MTH_LT_Store().hunterLevel = level end
if type(GetTime) == "function" then MTH_LT_SuppressUntil = GetTime() + 8 end
MTH_LT_RequestPetCheck()
elseif event == "PLAYER_LEVEL_UP" then
MTH_LT_HandleHunterLevel(tonumber(arg1) or tonumber(UnitLevel("player")) or 1)
+42 -9
View File
@@ -2138,16 +2138,45 @@ local function MTH_PETS_SelectPetIdBySnapshot(store, snapshot, previousPetId)
if snapshot.signature and snapshot.signature ~= "" then
local list = store.signatureIndex[snapshot.signature]
if type(list) == "table" then
local count = 0
local candidateId = nil
local liveIds = {}
for _, listedId in pairs(list) do
if listedId and store.activeById[listedId] then
count = count + 1
candidateId = listedId
if listedId and store.activeById[tostring(listedId)] then
table.insert(liveIds, tostring(listedId))
end
end
if count == 1 then
return candidateId
local liveCount = table.getn(liveIds)
if liveCount == 1 then
return liveIds[1]
elseif liveCount > 1 then
-- Several records share this name+family (earlier fragmentation, or two
-- pets with the same name). Reuse the best existing match instead of
-- minting yet another empty shell that only worsens the fragmentation:
-- require a level match, then prefer loyalty match and records that
-- already carry tame/spellbook history, then most recently seen.
local snapLevel = tonumber(snapshot.level)
local snapLoyalty = tonumber(snapshot.loyaltyLevel)
local bestId = nil
local bestScore = -1
local bestSeen = -1
for i = 1, liveCount do
local rowId = liveIds[i]
local row = store.activeById[rowId]
if type(row) == "table" and snapLevel and tonumber(row.level) == snapLevel then
local score = 0
if snapLoyalty and tonumber(row.loyaltyLevel) == snapLoyalty then score = score + 2 end
if MTH_PETS_RowHasAnyTameMetadata(row) then score = score + 1 end
if type(row.petSpellbook) == "table" then score = score + 1 end
local seen = tonumber(row.lastSeen) or tonumber(row.lastUpdated) or 0
if score > bestScore or (score == bestScore and seen > bestSeen) then
bestScore = score
bestSeen = seen
bestId = rowId
end
end
end
if bestId then
return bestId
end
end
end
end
@@ -2364,10 +2393,14 @@ local function MTH_PETS_RecordStableSlot(pets, slot, raw1, raw2, raw3, raw4, raw
local snapshotGuid = snapshot and snapshot.guid or nil
local signatureMatches = (existingSignature and snapshotSignature and existingSignature == snapshotSignature) and true or false
local guidMatches = (existingGuid and snapshotGuid and existingGuid ~= "" and existingGuid == snapshotGuid) and true or false
-- An empty shell must not lock the slot: a richer same-signature record may
-- exist that we should re-adopt instead (self-heals earlier fragmentation).
local existingHasData = MTH_PETS_RowHasAnyTameMetadata(existingRow)
or type(existingRow.petSpellbook) == "table" or existingRow.petNumber ~= nil
if signatureMatches or guidMatches then
if guidMatches or (signatureMatches and existingHasData) then
petId = existingId
else
elseif not signatureMatches then
MTH_PETS_LogConsistency("RecordStableSlot remapping stale slot=" .. tostring(slotNumber)
.. " existingId=" .. tostring(existingId)
.. " existingSignature='" .. tostring(existingSignature or "") .. "'"
+13 -3
View File
@@ -2483,10 +2483,20 @@ function FOM_FlatFoodList()
local isExceptionReject = false;
local isLevelOverrideReject = not FOM_IsItemPetLevelCompatible(itemID, petLevel);
local isQuarantineReject = FOM_IsQuarantined(itemID, petLevel, familyKey);
-- A food whose known level is below the pet's minimum is refused by the
-- server ("not high enough"); skip it up front so FOM never keeps
-- re-feeding a too-low stack just to free a bag slot.
local isLevelRuleReject = false;
if (petLevel > 0 and tonumber(foodLevel) ~= nil and type(MTH_FEED_GetDerivedMinFoodLevel) == "function") then
local minFoodLevel = MTH_FEED_GetDerivedMinFoodLevel(petLevel);
if (minFoodLevel ~= nil and tonumber(foodLevel) < minFoodLevel) then
isLevelRuleReject = true;
end
end
if (isExceptionReject) then
rejectedByException = rejectedByException + 1;
end
if (isLevelOverrideReject) then
if (isLevelOverrideReject or isLevelRuleReject) then
rejectedByLevelOverride = rejectedByLevelOverride + 1;
end
if (isQuarantineReject) then
@@ -2500,7 +2510,7 @@ function FOM_FlatFoodList()
unknownLevelCandidates = unknownLevelCandidates + 1;
end
if (isCompatible and not isExceptionReject and not isLevelOverrideReject and not isQuarantineReject) then
if (isCompatible and not isExceptionReject and not isLevelOverrideReject and not isQuarantineReject and not isLevelRuleReject) then
compatibleCount = compatibleCount + 1;
local foodQuality = tonumber(foodLevel);
if (foodQuality == nil) then
@@ -2511,7 +2521,7 @@ function FOM_FlatFoodList()
end
end
table.insert(foodList, {bag=bagNum, slot=itemNum, link=itemLink, itemId=itemID, count=itemCount, quality=foodQuality, useful=isUseful, temp=FOM_IsTemporaryFood(itemLink), knownLevel=hasKnownLevel});
elseif (isAbovePreferredLevel and not isExceptionReject and not isLevelOverrideReject and not isQuarantineReject) then
elseif (isAbovePreferredLevel and not isExceptionReject and not isLevelOverrideReject and not isQuarantineReject and not isLevelRuleReject) then
overflowCompatibleCount = overflowCompatibleCount + 1;
local overflowQuality = tonumber(foodLevel);
if (overflowQuality == nil) then