Mercurial > wow > worldplan
comparison QuestPOI.lua @ 93:98b5e08b75ed v1.4.9
- Fixed quest completion checking and handling
- Changed animation method to hopefully stop weird flickering.
- Pins are now visible before full reward data is loaded
- Filter bar redesigned:
- aligned horizontally along the top of the map display
- filter buttons display a '+' when there are matches in both current and other zones, and '*' when there only matches in other zones
- button tooltips separate local and global quests
- button categories are highlighted and labeled when the cursor is over them
- Fixed invalid POI targets appearing when the spell targeting cursor is active
| author | Nenue |
|---|---|
| date | Sat, 15 Apr 2017 11:04:54 -0400 |
| parents | 77013bd72adb |
| children | b29b35cb8539 |
comparison
equal
deleted
inserted
replaced
| 92:df725cba1a6a | 93:98b5e08b75ed |
|---|---|
| 24 local SpellCanTargetQuest, GetCVarBool = SpellCanTargetQuest, GetCVarBool | 24 local SpellCanTargetQuest, GetCVarBool = SpellCanTargetQuest, GetCVarBool |
| 25 local SetSuperTrackedQuestID = SetSuperTrackedQuestID | 25 local SetSuperTrackedQuestID = SetSuperTrackedQuestID |
| 26 local HaveQuestRewardData = HaveQuestRewardData | 26 local HaveQuestRewardData = HaveQuestRewardData |
| 27 | 27 |
| 28 | 28 |
| 29 local pairs, ipairs, tinsert, unpack, select = pairs, ipairs, tinsert, unpack, select | 29 local pairs, ipairs, tinsert, tremove, unpack, select = pairs, ipairs, tinsert, tremove, unpack, select |
| 30 local floor, mod, tostring, tonumber, GetSuperTrackedQuestID = floor, mod, tostring, tonumber, GetSuperTrackedQuestID | 30 local floor, mod, tostring, tonumber, GetSuperTrackedQuestID = floor, mod, tostring, tonumber, GetSuperTrackedQuestID |
| 31 local GameTooltip = GameTooltip | 31 local GameTooltip = GameTooltip |
| 32 local GetItemIcon = GetItemIcon | 32 local GetItemIcon = GetItemIcon |
| 33 | 33 |
| 34 local print = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or nop | 34 local print = DEVIAN_WORKSPACE and function(...) _G.print('POI', ...) end or nop |
| 38 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or nop | 38 local iprint = DEVIAN_WORKSPACE and function(...) _G.print('ItemScan', ...) end or nop |
| 39 local rprint = DEVIAN_WORKSPACE and function(...) _G.print('WQRefresh', ...) end or nop | 39 local rprint = DEVIAN_WORKSPACE and function(...) _G.print('WQRefresh', ...) end or nop |
| 40 local dprint = DEVIAN_WORKSPACE and function(...) _G.print('WQData', ...) end or nop | 40 local dprint = DEVIAN_WORKSPACE and function(...) _G.print('WQData', ...) end or nop |
| 41 local QuestPOI = WorldPlanPOIMixin | 41 local QuestPOI = WorldPlanPOIMixin |
| 42 | 42 |
| 43 local pinBaseIndex = 1500 | 43 local pinBaseIndex = 1320 |
| 44 local overlayBaseIndex = 1580 | 44 local overlayBaseIndex = 1380 |
| 45 local previousHighlight | 45 local previousHighlight |
| 46 | 46 |
| 47 local DATA_DEBUG = false | 47 local DATA_DEBUG = false |
| 48 local PIN_REFRESH_DELAY = 1 | 48 local PIN_REFRESH_DELAY = 1 |
| 49 local PIN_REQUEST_DELAY = .2 | 49 local PIN_REQUEST_DELAY = .2 |
| 250 end | 250 end |
| 251 end | 251 end |
| 252 | 252 |
| 253 end | 253 end |
| 254 | 254 |
| 255 function QuestPOI:OnLoad() | |
| 256 --qprint('|cFF00FF88'..self:GetName()..':OnLoad()|r',db.Config) | |
| 257 self.debugTimer = 4 | |
| 258 self.title = '|cFF0088FF' .. RETRIEVING_DATA..'|r' | |
| 259 self.count = self.Overlay.count | |
| 260 self.timeLabel = self.Overlay.timeLabel | |
| 261 self.Description = self.Overlay.Description | |
| 262 self.updateRate = PIN_REQUEST_DELAY | |
| 263 self.itemName = '|cFF0088FF' .. RETRIEVING_DATA..'|r' | |
| 264 | |
| 265 | |
| 266 self.IconBackdrop:SetVertexColor(0,0,0,1) | |
| 267 self.Overlay:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 4) | |
| 268 self.Overlay:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, -4) | |
| 269 end | |
| 270 | |
| 271 function QuestPOI:OnShow () | |
| 272 if self.isStale then | |
| 273 --print('|cFF00FF00refresh on show') | |
| 274 self:Refresh('POI_ONSHOW_STALE') | |
| 275 end | |
| 276 self:RegisterEvent('QUEST_TURNED_IN') | |
| 277 self:RegisterEvent('QUEST_LOG_UPDATE') | |
| 278 self:HideOrShowFrames(true) | |
| 279 end | |
| 280 | |
| 281 function QuestPOI:OnEvent(event, questID) | |
| 282 if (self.questID == questID) and IsQuestComplete(self.questID) then | |
| 283 db.log(self.questID .. " Marked completed.") | |
| 284 self:Release() | |
| 285 end | |
| 286 end | |
| 287 | |
| 288 function QuestPOI:OnHide() | |
| 289 --DEFAULT_CHAT_FRAME:AddMessage('|cFFFFFF00'..self:GetName()..'|r:OnHide()') | |
| 290 self:HideOrShowFrames(false) | |
| 291 -- reset flags | |
| 292 self:SetAlpha(db.PinAlpha) | |
| 293 self.isAnimating = nil | |
| 294 if db.Config.DebugEnabled then | |
| 295 db.log(tostring(self.questID) .. ' ' .. tostring(self.title) .. "\n" .. tostring(REWARD_TYPE_NAMES[self.rewardType]) .. ' ' .. tostring(self.itemName) .. ' ' .. tostring(self.itemNumber) .. "\n|cFFFF4400" .. (self.hideReason or 'NO_MESSAGE') .. "|r\n|cFF00FFFF" .. debugstack(2,3,0) .. '|r') | |
| 296 end | |
| 297 self.hideReason = nil | |
| 298 end | |
| 255 | 299 |
| 256 function QuestPOI:OnEnter() | 300 function QuestPOI:OnEnter() |
| 257 if self.filtered and (self.questID ~= GetSuperTrackedQuestID()) then | 301 if self.filtered and (self.questID ~= GetSuperTrackedQuestID()) then |
| 258 return | 302 return |
| 259 end | 303 end |
| 326 WorldMapTooltip:Show() | 370 WorldMapTooltip:Show() |
| 327 --WorldMapTooltip.recalculatePadding = true; | 371 --WorldMapTooltip.recalculatePadding = true; |
| 328 --print(WorldMapTooltip:GetParent()) | 372 --print(WorldMapTooltip:GetParent()) |
| 329 --print(WorldMapTooltip:IsVisible()) | 373 --print(WorldMapTooltip:IsVisible()) |
| 330 end | 374 end |
| 375 | |
| 376 function QuestPOI:OnMouseDown(button) | |
| 377 if button == 'RightButton' then | |
| 378 SetSuperTrackedQuestID(nil) | |
| 379 else | |
| 380 TaskPOI_OnClick(self, button) | |
| 381 end | |
| 382 end | |
| 383 | |
| 331 function QuestPOI:OnLeave() | 384 function QuestPOI:OnLeave() |
| 332 if self.filtered and (self.questID ~= GetSuperTrackedQuestID()) then | 385 if self.filtered and (self.questID ~= GetSuperTrackedQuestID()) then |
| 333 return | 386 return |
| 334 end | 387 end |
| 335 WorldMap_RestoreTooltip() | 388 WorldMap_RestoreTooltip() |
| 336 WorldMapTooltip:Hide(); | 389 WorldMapTooltip:Hide(); |
| 390 end | |
| 391 | |
| 392 local updateTime, markTime | |
| 393 function QuestPOI:OnUpdate (sinceLast) | |
| 394 -- control update check intervals | |
| 395 | |
| 396 if self.animating then | |
| 397 local alpha = self.icon:GetAlpha() + sinceLast*3 | |
| 398 | |
| 399 self.animateTime = (self.animateTime or 0) + sinceLast | |
| 400 if alpha >= 1 then | |
| 401 alpha = 1 | |
| 402 print('fade over', self.animateTime) | |
| 403 self.animating = nil | |
| 404 self.animateTime = nil | |
| 405 | |
| 406 end | |
| 407 | |
| 408 self.icon:SetAlpha(alpha) | |
| 409 self.RewardBorder:SetAlpha(alpha) | |
| 410 end | |
| 411 | |
| 412 self.throttle = (self.throttle or self.updateRate) + sinceLast | |
| 413 if self.throttle >= self.updateRate then | |
| 414 -- factor overtime into the throttle timer | |
| 415 self.throttle = self.throttle - self.updateRate | |
| 416 else | |
| 417 return | |
| 418 end | |
| 419 --@debug@ | |
| 420 if DATA_DEBUG then | |
| 421 self.debugTimer = self.debugTimer - sinceLast | |
| 422 if self.debugTimer >= 0 then | |
| 423 print(self.debugTimer) | |
| 424 return | |
| 425 end | |
| 426 end | |
| 427 --@end-debug@ | |
| 428 | |
| 429 -- query for reward data if it wasn't found in the original scan | |
| 430 | |
| 431 if not self.dataLoaded then | |
| 432 local dataLoaded = self:GetData() | |
| 433 if dataLoaded and not tContains(db.UpdatedPins, self) then | |
| 434 -- self.PendingFade:Stop() | |
| 435 -- scale info from the parent module is needed, so deal with it there | |
| 436 print('|cFF00FF88 queueing for update') | |
| 437 self.isNew = true | |
| 438 tinsert(db.UpdatedPins, self) | |
| 439 else | |
| 440 | |
| 441 --print('|cFFFF4400OnUpdate(|r'..self:GetID()..'|cFFFF4400)|r poll failed') | |
| 442 end | |
| 443 return | |
| 444 end | |
| 445 | |
| 446 if self.maxAlertLevel then | |
| 447 self:UpdateStatus() | |
| 448 end | |
| 449 end | |
| 450 | |
| 451 | |
| 452 function QuestPOI:StartFading() | |
| 453 if not self.animating then | |
| 454 self.animating = true | |
| 455 self.icon:SetAlpha(0) | |
| 456 self.RewardBorder:SetAlpha(0) | |
| 457 end | |
| 337 end | 458 end |
| 338 | 459 |
| 339 -- attempt to pull pin data | 460 -- attempt to pull pin data |
| 340 function QuestPOI:GetData () | 461 function QuestPOI:GetData () |
| 341 --dprint('|cFF00FF88'..self:GetID()..':GetData()|r') | 462 --dprint('|cFF00FF88'..self:GetID()..':GetData()|r') |
| 350 if not questTitle then | 471 if not questTitle then |
| 351 --dprint('|cFFBB8844dataLoaded|r = false|cFF00FFFF', self.questId) | 472 --dprint('|cFFBB8844dataLoaded|r = false|cFF00FFFF', self.questId) |
| 352 return false | 473 return false |
| 353 else | 474 else |
| 354 self.title, self.factionID, self.capped = questTitle, factionID, capped | 475 self.title, self.factionID, self.capped = questTitle, factionID, capped |
| 355 print(questTitle, factionID, capped) | 476 --print(questTitle, factionID, capped) |
| 356 -- set tag details | 477 -- set tag details |
| 357 local worldQuestType | 478 local worldQuestType |
| 358 self.tagID, self.tagName, worldQuestType, self.rarity, self.isElite, self.tradeskillLineIndex = GetQuestTagInfo(questID); | 479 self.tagID, self.tagName, worldQuestType, self.rarity, self.isElite, self.tradeskillLineIndex = GetQuestTagInfo(questID); |
| 359 local tagAtlas | 480 local tagAtlas |
| 360 if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then | 481 if worldQuestType == LE_QUEST_TAG_TYPE_PET_BATTLE then |
| 395 end | 516 end |
| 396 | 517 |
| 397 local ID_RESOURCES = 1220 | 518 local ID_RESOURCES = 1220 |
| 398 local ID_LEGIONFALL = 1342 | 519 local ID_LEGIONFALL = 1342 |
| 399 | 520 |
| 400 function QuestPOI:Reset() | |
| 401 self.isActive = nil | |
| 402 self.complete = nil | |
| 403 self.used = nil | |
| 404 self.dataLoaded = nil | |
| 405 self.rewardType = nil | |
| 406 self.itemTexture = nil | |
| 407 self.itemName = nil | |
| 408 self.itemNumber = nil | |
| 409 self:SetShown(false) | |
| 410 end | |
| 411 | |
| 412 --- Returns true if data has changed (either from loading in or qualifications changed) | 521 --- Returns true if data has changed (either from loading in or qualifications changed) |
| 413 function QuestPOI:UpdateRewards() | 522 function QuestPOI:UpdateRewards() |
| 414 local questID = self.questID | 523 local questID = self.questID |
| 415 if not HaveQuestRewardData(questID) then | 524 if not HaveQuestRewardData(questID) then |
| 416 C_TaskQuest.RequestPreloadRewardData(questID); | 525 C_TaskQuest.RequestPreloadRewardData(questID); |
| 482 for i = 1, numQuestRewards do | 591 for i = 1, numQuestRewards do |
| 483 local name, texture, numItems, quality, isUsable, itemID = GetQuestLogRewardInfo(i, questID) | 592 local name, texture, numItems, quality, isUsable, itemID = GetQuestLogRewardInfo(i, questID) |
| 484 | 593 |
| 485 if itemID then | 594 if itemID then |
| 486 local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, sellPrice, classID, subclassID = GetItemInfo(itemID); | 595 local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, sellPrice, classID, subclassID = GetItemInfo(itemID); |
| 487 | |
| 488 | |
| 489 if ( classID == LE_ITEM_CLASS_WEAPON or classID == LE_ITEM_CLASS_ARMOR or (classID == LE_ITEM_CLASS_GEM and subclassID == LE_ITEM_GEM_ARTIFACTRELIC) ) then | 596 if ( classID == LE_ITEM_CLASS_WEAPON or classID == LE_ITEM_CLASS_ARMOR or (classID == LE_ITEM_CLASS_GEM and subclassID == LE_ITEM_GEM_ARTIFACTRELIC) ) then |
| 490 rewardType = REWARD_GEAR | 597 rewardType = REWARD_GEAR |
| 491 rewardIcon = texture | 598 rewardIcon = texture |
| 492 rewardName = name | 599 rewardName = name |
| 493 rewardCount = numItems | 600 rewardCount = numItems |
| 494 foundPrimary = true | 601 foundPrimary = true |
| 495 elseif IsArtifactPowerItem(itemID) then | 602 elseif IsArtifactPowerItem(itemID) then |
| 496 rewardType = REWARD_ARTIFACT_POWER | 603 rewardType = REWARD_ARTIFACT_POWER |
| 497 rewardIcon = texture | 604 rewardIcon = texture |
| 498 rewardName = name | 605 rewardName = name |
| 499 rewardCount = 1 | 606 rewardCount = self:UpdateArtifactPower(itemLink) |
| 500 foundPrimary = true | 607 foundPrimary = true |
| 501 | |
| 502 WorldPlanTooltip:SetOwner(self, 'ANCHOR_NONE') | |
| 503 WorldPlanTooltip:SetHyperlink(itemLink) | |
| 504 for i = 1, WorldPlanTooltip:NumLines() do | |
| 505 local line = _G['WorldPlanTooltipTextLeft' .. i] | |
| 506 local text = line and line:GetText() | |
| 507 local ap = text and text:gsub(',', ''):gsub(' million', '000000'):match('(%d+) '..ARTIFACT_POWER) | |
| 508 if ap then | |
| 509 rewardCount = tonumber(ap) | |
| 510 --dprint(ap) | |
| 511 end | |
| 512 | |
| 513 end | |
| 514 | |
| 515 if WorldPlanTooltipTextLeft2 then | |
| 516 local text = WorldPlanTooltipTextLeft2:GetText() | |
| 517 end | |
| 518 | |
| 519 --dprint('is an AP token') | 608 --dprint('is an AP token') |
| 520 elseif classID == LE_ITEM_CLASS_TRADEGOODS then | 609 elseif classID == LE_ITEM_CLASS_TRADEGOODS then |
| 521 rewardType = REWARD_REAGENT | 610 rewardType = REWARD_REAGENT |
| 522 rewardIcon = texture | 611 rewardIcon = texture |
| 523 rewardName = name | 612 rewardName = name |
| 524 rewardCount = numItems | 613 rewardCount = numItems |
| 525 foundPrimary = true | 614 foundPrimary = true |
| 526 end | 615 end |
| 527 | |
| 528 | |
| 529 --dprint(' reward', i, name, " |T"..tostring(texture)..":12:12|t", quality, isUsable, itemID) | 616 --dprint(' reward', i, name, " |T"..tostring(texture)..":12:12|t", quality, isUsable, itemID) |
| 530 tinsert(rewardItems, { | 617 tinsert(rewardItems, { |
| 531 name = name, | 618 name = name, |
| 532 texture = texture, | 619 texture = texture, |
| 533 numItems = numItems, | 620 numItems = numItems, |
| 580 --]] | 667 --]] |
| 581 | 668 |
| 582 end | 669 end |
| 583 end | 670 end |
| 584 | 671 |
| 585 -- run from OnShow if .isNew is set | 672 |
| 586 | 673 function QuestPOI:UpdateArtifactPower(rewardLink) |
| 587 function QuestPOI:OnAnimStart() | 674 if not (rewardLink or self.rewardLink) then |
| 588 --qprint('|cFFFFFF00OnAnimStart(|r'..self:GetID()..'|cFFFFFF00)|r', self.fadeEvent) | |
| 589 self:Refresh('FADE_IN_START') | |
| 590 self.isNew = nil | |
| 591 end | |
| 592 | |
| 593 function QuestPOI:TryToFade(event) | |
| 594 if self.FadeIn:IsPlaying() then | |
| 595 --qprint('|cFFFF4400TryToFade('..self:GetID()..'|cFFFF4400)|r stopping because already in progress') | |
| 596 return | 675 return |
| 597 end | 676 end |
| 598 | 677 |
| 599 self.fadeEvent = event | 678 self.rewardLink = rewardLink or self.rewardLink |
| 600 if self.dataLoaded then | 679 |
| 601 --qprint('|cFFFFFF00TryToFade('..self:GetID()..'|cFFFFFF00)|r', event) | 680 local rewardCount |
| 602 self:SetAlpha(0) | 681 WorldPlanTooltip:SetOwner(self, 'ANCHOR_NONE') |
| 603 self.FadeIn.FadeIn:SetToAlpha(db.PinAlpha) | 682 WorldPlanTooltip:SetHyperlink(rewardLink or self.rewardLink) |
| 604 self.FadeIn:Play() | 683 for i = 1, WorldPlanTooltip:NumLines() do |
| 605 else | 684 local line = _G['WorldPlanTooltipTextLeft' .. i] |
| 606 | 685 local text = line and line:GetText() |
| 607 --qprint('|cFFFF4400TryToFade('..self:GetID()..'|cFFFF4400)|r stopping because not loaded') | 686 local ap = text and text:gsub(',', ''):gsub(' million', '000000'):match('([%d%.]+) '..ARTIFACT_POWER) |
| 608 end | 687 if ap then |
| 609 end | 688 rewardCount = tonumber(ap) |
| 610 | 689 end |
| 611 function QuestPOI:OnAnimStop() | 690 end |
| 612 self:SetAlpha(db.PinAlpha) | 691 return rewardCount |
| 613 end | |
| 614 | |
| 615 function QuestPOI:OnShow () | |
| 616 | |
| 617 if self.isNew then | |
| 618 self:TryToFade('POI_ONSHOW_NEW') | |
| 619 elseif not self.FadeIn:IsPlaying() then | |
| 620 print('|cFF00FF00Alpha correction') | |
| 621 self:SetAlpha(db.PinAlpha) -- fix stuck alpha | |
| 622 if self.isStale then | |
| 623 --print('|cFF00FF00refresh on show') | |
| 624 self:Refresh('POI_ONSHOW_STALE') | |
| 625 end | |
| 626 end | |
| 627 self:RegisterEvent('QUEST_LOG_UPDATE') | |
| 628 self:ShowFrames() | |
| 629 end | |
| 630 | |
| 631 function QuestPOI:OnEvent(event) | |
| 632 if not TQ_IsActive(self.questID) then | |
| 633 self:UnregisterEvent('QUEST_LOG_UPDATE') | |
| 634 self.hideReason = 'Hiding self because quest is inactive.' | |
| 635 self:SetShown(false) | |
| 636 end | |
| 637 end | |
| 638 | |
| 639 function QuestPOI:OnHide() | |
| 640 --DEFAULT_CHAT_FRAME:AddMessage('|cFFFFFF00'..self:GetName()..'|r:OnHide()') | |
| 641 self:HideFrames() | |
| 642 -- reset flags | |
| 643 self:SetAlpha(db.PinAlpha) | |
| 644 self.isAnimating = nil | |
| 645 if db.Config.DebugEnabled then | |
| 646 db.log(tostring(self.questID) .. ' ' .. tostring(self.title) .. "\n" .. tostring(REWARD_TYPE_NAMES[self.rewardType]) .. ' ' .. tostring(self.itemName) .. ' ' .. tostring(self.itemNumber) .. "\n|cFFFF4400" .. (self.hideReason or 'NO_MESSAGE') .. "|r\n|cFF00FFFF" .. debugstack(2,3,0) .. '|r') | |
| 647 end | |
| 648 self.hideReason = nil | |
| 649 end | 692 end |
| 650 | 693 |
| 651 -- Applies position and sizing parameters to the pin data | 694 -- Applies position and sizing parameters to the pin data |
| 652 function QuestPOI:SetAnchor(owner, dX, dY, mapWidth, mapHeight, scaleFactor) | 695 function QuestPOI:SetAnchor(owner, dX, dY, mapWidth, mapHeight, scaleFactor) |
| 653 --dprint(self:GetName()..':SetAnchor()', owner, dX, dY, scaleFactor, self.filtered, self.used) | 696 --dprint(self:GetName()..':SetAnchor()', owner, dX, dY, scaleFactor, self.filtered, self.used) |
| 654 if not self.used then | 697 if not self.used then |
| 655 self.hideReason = 'SetAnchor() on an unused frame.' | 698 self.hideReason = 'SetAnchor() on an unused frame.' |
| 656 self:HideFrames() | 699 self:HideOrShowFrames(false) |
| 657 return | 700 return |
| 658 end | 701 end |
| 659 | 702 |
| 660 | 703 |
| 661 if owner then | 704 if owner then |
| 694 self:SetPoint('CENTER', owner, 'TOPLEFT', pX, pY) | 737 self:SetPoint('CENTER', owner, 'TOPLEFT', pX, pY) |
| 695 end | 738 end |
| 696 | 739 |
| 697 end | 740 end |
| 698 | 741 |
| 699 -- Show/Hide the text overlays associated with the quest pin; they aren't hierarchically linked | |
| 700 function QuestPOI:ShowFrames() | |
| 701 if not self:IsShown() then | |
| 702 -- print('|cFFFFFF00' ..self:GetName()..':ShowFrames()') | |
| 703 -- do not SetShown() here | |
| 704 end | |
| 705 self.Overlay:SetShown(true) | |
| 706 self.count:SetShown(true) | |
| 707 self.timeLabel:SetShown(true) | |
| 708 end | |
| 709 | |
| 710 function QuestPOI:HideFrames() | |
| 711 if self:IsShown() then | |
| 712 if not self.hideReason then | |
| 713 self.hideReason = "HideFrames() called" | |
| 714 end | |
| 715 end | |
| 716 self.Overlay:SetShown(false) | |
| 717 self.count:SetShown(false) | |
| 718 self.timeLabel:SetShown(false) | |
| 719 end | |
| 720 | |
| 721 function QuestPOI:OnLoad() | |
| 722 --qprint('|cFF00FF88'..self:GetName()..':OnLoad()|r',db.Config) | |
| 723 self.debugTimer = 4 | |
| 724 self.title = '|cFF0088FF' .. RETRIEVING_DATA..'|r' | |
| 725 self.isPending = true | |
| 726 self.count = self.Overlay.count | |
| 727 self.timeLabel = self.Overlay.timeLabel | |
| 728 self.Description = self.Overlay.Description | |
| 729 self.updateRate = PIN_REQUEST_DELAY | |
| 730 self.itemName = '|cFF0088FF' .. RETRIEVING_DATA..'|r' | |
| 731 | |
| 732 self.Overlay:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 4) | |
| 733 self.Overlay:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, -4) | |
| 734 end | |
| 735 | |
| 736 function QuestPOI:OnMouseDown(button) | |
| 737 if button == 'RightButton' then | |
| 738 SetSuperTrackedQuestID(nil) | |
| 739 else | |
| 740 TaskPOI_OnClick(self, button) | |
| 741 end | |
| 742 end | |
| 743 | |
| 744 local updateTime, markTime | |
| 745 function QuestPOI:OnUpdate (sinceLast) | |
| 746 -- control update check intervals | |
| 747 | |
| 748 | |
| 749 self.throttle = (self.throttle or self.updateRate) + sinceLast | |
| 750 if self.throttle >= self.updateRate then | |
| 751 -- factor overtime into the throttle timer | |
| 752 self.throttle = self.throttle - self.updateRate | |
| 753 else | |
| 754 return | |
| 755 end | |
| 756 --@debug@ | |
| 757 if DATA_DEBUG then | |
| 758 self.debugTimer = self.debugTimer - sinceLast | |
| 759 if self.debugTimer >= 0 then | |
| 760 print(self.debugTimer) | |
| 761 return | |
| 762 end | |
| 763 end | |
| 764 --@end-debug@ | |
| 765 | |
| 766 -- query for reward data if it wasn't found in the original scan | |
| 767 | |
| 768 if not self.dataLoaded then | |
| 769 | |
| 770 local dataLoaded = self:GetData() | |
| 771 if dataLoaded and not tContains(db.UpdatedPins, self) then | |
| 772 -- self.PendingFade:Stop() | |
| 773 -- scale info from the parent module is needed, so deal with it there | |
| 774 --print('|cFF00FF88 queueing for update') | |
| 775 tinsert(db.UpdatedPins, self) | |
| 776 else | |
| 777 | |
| 778 --print('|cFFFF4400OnUpdate(|r'..self:GetID()..'|cFFFF4400)|r poll failed') | |
| 779 end | |
| 780 return | |
| 781 end | |
| 782 | |
| 783 if self.maxAlertLevel then | |
| 784 self:UpdateStatus() | |
| 785 end | |
| 786 | |
| 787 end | |
| 788 | |
| 789 -- Non-hieriarchical display states, checked separately from used/filtered states | 742 -- Non-hieriarchical display states, checked separately from used/filtered states |
| 790 function QuestPOI:GetCriteriaState() | 743 function QuestPOI:GetCriteriaState() |
| 791 local isCriteria, isBounty, isSpellTarget | 744 local isCriteria, isBounty, isSpellTarget |
| 792 if self.factionID then | 745 |
| 793 for index, bounty in pairs(db.Bounties) do | 746 |
| 794 if IsQuestCriteriaForBounty(self.questID, bounty.questID) then | 747 |
| 795 isCriteria = true | 748 for index, bounty in pairs(db.Bounties) do |
| 796 if db.selectedBounty == bounty then | 749 if (not IsQuestComplete(bounty.questID)) and IsQuestCriteriaForBounty(self.questID, bounty.questID) then |
| 797 isBounty = true | 750 isCriteria = true |
| 798 end | 751 if db.selectedBounty == bounty then |
| 799 --dprint('|cFF00FF88Criteria:|r', self.questID, bounty.questID, isCriteria, isBounty) | 752 isBounty = true |
| 800 end | 753 end |
| 754 --dprint('|cFF00FF88Criteria:|r', self.questID, bounty.questID, isCriteria, isBounty) | |
| 801 end | 755 end |
| 802 end | 756 end |
| 803 isSpellTarget = IsQuestIDValidSpellTarget(self.questID) | 757 isSpellTarget = IsQuestIDValidSpellTarget(self.questID) |
| 804 | 758 |
| 805 if (self.isBounty ~= isBounty) or (self.isCriteria ~= isCriteria) or (self.isSpellTarget ~= isSpellTarget) then | 759 if (self.isBounty ~= isBounty) or (self.isCriteria ~= isCriteria) or (self.isSpellTarget ~= isSpellTarget) then |
| 810 self.isStale = true | 764 self.isStale = true |
| 811 return true | 765 return true |
| 812 end | 766 end |
| 813 end | 767 end |
| 814 | 768 |
| 815 -- Called at static intervals and with Refresh | 769 local cvar_check = { |
| 816 function QuestPOI:UpdateStatus() | 770 [REWARD_CASH] = 'worldQuestFilterGold', |
| 817 -- update time elements | 771 [REWARD_ARTIFACT_POWER] = 'worldQuestFilterArtifactPower', |
| 818 self.isActive = TQ_IsActive(self.questID) | 772 [REWARD_CURRENCY] = 'worldQuestFilterOrderResources', |
| 819 | 773 [REWARD_REAGENT]= 'worldQuestFilterProfessionMaterials', |
| 820 if self.isActive then | 774 [REWARD_GEAR] = 'worldQuestFilterEquipment', |
| 821 local tl = self.alertLevel | 775 } |
| 822 local timeLeft = TQ_GetQuestTimeLeftMinutes(self.questID) | 776 |
| 823 if timeLeft > 0 then | 777 |
| 824 | 778 function QuestPOI:CheckFilterRules () |
| 825 local text, timeState = WorldPlan:GetTimeInfo(timeLeft, self.maxAlertLevel) | 779 local print = qprint |
| 826 if tl ~= timeState then | 780 local qType = self.worldQuestType |
| 827 tl = timeState | 781 if not TQ_IsActive(self.questID) then |
| 828 self.timeLabel:SetText(text) | 782 self.hideReason = 'Filter check ended because quest is inactive.' |
| 829 end | 783 self.used = nil |
| 830 end | 784 self:SetShown(false) |
| 831 | 785 return |
| 832 local border = (self.isBounty or self.isCriteria) and self.RewardBorder or self.HighlightBorder | 786 end |
| 833 | 787 |
| 834 if tl and (timeLeft < 120) then | 788 if qType == LE_QUEST_TAG_TYPE_PROFESSION then |
| 835 border:SetVertexColor(1,0,0,0.7) | 789 if not(self.isKnownProfession or db.Config.ShowAllProfessionQuests) then |
| 836 else | 790 self.hideReason = 'Failed profession check.' |
| 837 border:SetVertexColor(0,0,0,0.7) | 791 self.used = nil |
| 838 end | 792 self:SetShown(false) |
| 839 self.alertLevel = tl | 793 return |
| 840 self.timeLabel:SetShown(self.worldQuest and (self.maxAlertLevel >= 1)) | 794 end |
| 841 else | 795 end |
| 842 self.hideReason = "No longer active." | 796 |
| 843 self:HideFrames() | 797 local filtered |
| 844 | 798 for filterKey, value in pairs(db.UsedFilters) do |
| 845 end | 799 if self[filterKey] ~= value then |
| 846 end | 800 if not self.filtered then |
| 847 | 801 print('|cFFFF4400filtering', filterKey, value, '~=', self[filterKey], self.title) |
| 802 end | |
| 803 filtered = true | |
| 804 end | |
| 805 end | |
| 806 if self.rewardType and cvar_check[self.rewardType] then | |
| 807 if not GetCVarBool(cvar_check[self.rewardType]) then | |
| 808 filtered = true | |
| 809 end | |
| 810 end | |
| 811 | |
| 812 print(' '..self.questID..':|cFFFFFF00CheckFilterRules()|r', filtered, self.title) | |
| 813 if self.filtered ~= filtered then | |
| 814 wqprint('|cFF00FF00filter changed') | |
| 815 self.isStale = true | |
| 816 end | |
| 817 | |
| 818 self.filtered = filtered | |
| 819 self.used = true | |
| 820 self:SetShown(true) | |
| 821 end | |
| 848 | 822 |
| 849 function QuestPOI:Refresh (event) | 823 function QuestPOI:Refresh (event) |
| 850 | |
| 851 print('|cFF00FF88Refresh(|r'..self:GetID()..'|cFF00FF88)|r', event, self.title) | 824 print('|cFF00FF88Refresh(|r'..self:GetID()..'|cFF00FF88)|r', event, self.title) |
| 852 | 825 |
| 826 | |
| 853 local style = DEFAULT_STYLE | 827 local style = DEFAULT_STYLE |
| 854 if self.dataLoaded and not self.filtered then | 828 if self.filtered then |
| 829 print('choose minimized') | |
| 830 style = MINIMIZED_STYLE | |
| 831 elseif self.dataLoaded then | |
| 832 print('choose reward type') | |
| 855 style = REWARD_TYPE_STYLES[self.rewardType] | 833 style = REWARD_TYPE_STYLES[self.rewardType] |
| 856 else | 834 else |
| 857 style = MINIMIZED_STYLE | 835 print('choose default') |
| 858 end | 836 end |
| 859 | 837 |
| 860 local currentWidth = style.iconWidth or DEFAULT_STYLE.iconWidth | 838 local currentWidth = style.iconWidth or DEFAULT_STYLE.iconWidth |
| 861 | 839 |
| 862 | 840 |
| 872 local trackingBorder = self.HighlightBorder | 850 local trackingBorder = self.HighlightBorder |
| 873 local icon = self.icon | 851 local icon = self.icon |
| 874 local count = self.count | 852 local count = self.count |
| 875 local hideNumbers = style.hideNumber or DEFAULT_STYLE.hideNumber | 853 local hideNumbers = style.hideNumber or DEFAULT_STYLE.hideNumber |
| 876 | 854 |
| 855 | |
| 877 local tagIcon = self.tagIcon | 856 local tagIcon = self.tagIcon |
| 878 self.maxAlertLevel = style.maxAlertLevel or DEFAULT_STYLE.maxAlertLevel | 857 self.maxAlertLevel = style.maxAlertLevel or DEFAULT_STYLE.maxAlertLevel |
| 879 | 858 |
| 859 if self.dataLoaded then | |
| 860 print('new pin, has data, cue fade') | |
| 861 if self.isNew then | |
| 862 self:StartFading() | |
| 863 self.isNew = nil | |
| 864 end | |
| 865 else | |
| 866 if not self.animating then | |
| 867 print('new pin, but no data, hide icon') | |
| 868 self.icon:SetAlpha(0) | |
| 869 self.RewardBorder:SetAlpha(0) | |
| 870 end | |
| 871 end | |
| 880 | 872 |
| 881 if self.itemName then | 873 if self.itemName then |
| 882 if self.itemNumber and (self.itemNumber > 1) and (not hideNumbers) then | 874 if self.itemNumber and (self.itemNumber > 1) and (not hideNumbers) then |
| 883 local numberString = self.itemNumber | 875 local numberString = self.itemNumber |
| 884 if self.itemNumber >= 1000000 then | 876 if self.itemNumber >= 1000000 then |
| 925 icon:SetDesaturated(false) | 917 icon:SetDesaturated(false) |
| 926 icon:SetVertexColor(1, 1, 1) | 918 icon:SetVertexColor(1, 1, 1) |
| 927 end | 919 end |
| 928 else | 920 else |
| 929 -- | 921 -- |
| 930 icon:SetTexture(PENDING_ICON) | 922 --icon:SetTexture(PENDING_ICON) |
| 931 icon:SetDesaturated(true) | 923 --icon:SetDesaturated(true) |
| 932 icon:SetVertexColor(unpack(borderColor)) | 924 --icon:SetVertexColor(unpack(borderColor)) |
| 933 end | 925 end |
| 934 local borderMask = style.borderMask or DEFAULT_STYLE.borderMask | 926 local borderMask = style.borderMask or DEFAULT_STYLE.borderMask |
| 935 local borderSize = currentWidth + (borderWidth * 2) + (self.isCriteria and 2 or 0) | 927 local borderSize = currentWidth + (borderWidth * 2) + (self.isCriteria and 2 or 0) |
| 936 | 928 |
| 937 | 929 |
| 938 iconBorder:SetSize(borderSize, borderSize) | 930 iconBorder:SetSize(borderSize, borderSize) |
| 931 | |
| 939 iconBorder:SetMask(borderMask) | 932 iconBorder:SetMask(borderMask) |
| 940 iconBorder:SetTexture(PENDING_BORDER) | 933 iconBorder:SetTexture(PENDING_BORDER) |
| 941 | 934 |
| 942 iconBorder:SetDesaturated(true) | 935 iconBorder:SetDesaturated(true) |
| 943 | 936 |
| 945 trackingBorder:SetSize(highlightSize, highlightSize) | 938 trackingBorder:SetSize(highlightSize, highlightSize) |
| 946 trackingBorder:SetMask(borderMask) | 939 trackingBorder:SetMask(borderMask) |
| 947 trackingBorder:SetTexture(PENDING_BORDER) | 940 trackingBorder:SetTexture(PENDING_BORDER) |
| 948 | 941 |
| 949 self:SetSize(borderSize, borderSize) | 942 self:SetSize(borderSize, borderSize) |
| 943 self.IconBackdrop:SetSize(currentWidth, currentWidth) | |
| 950 | 944 |
| 951 | 945 |
| 952 | 946 |
| 953 iconBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) | 947 iconBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) |
| 954 trackingBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) | 948 trackingBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) |
| 955 | 949 |
| 956 self.tagIcon:SetShown((not self.filtered) and true or false) | 950 self.tagIcon:SetShown((not self.filtered) and true or false) |
| 957 self.tagIcon:SetAtlas(self.tagAtlas) | 951 self.tagIcon:SetAtlas(self.tagAtlas) |
| 958 self.EliteBorder:SetShown(self.isElite and not self.filtered) | 952 self.EliteBorder:SetShown(self.isElite and not self.filtered) |
| 959 | 953 |
| 960 self:UpdateSize() | |
| 961 self:UpdateStatus() | 954 self:UpdateStatus() |
| 962 self.isStale = nil | |
| 963 | 955 |
| 964 if self.isBounty then | 956 if self.isBounty then |
| 965 --print('is bounty') | 957 --print('is bounty') |
| 966 iconBorder:SetVertexColor(trackingBorder:GetVertexColor()) | 958 iconBorder:SetVertexColor(trackingBorder:GetVertexColor()) |
| 967 trackingBorder:SetVertexColor(unpack(BORDER_SELECTED_BOUNTY)) | 959 trackingBorder:SetVertexColor(unpack(BORDER_SELECTED_BOUNTY)) |
| 970 iconBorder:SetVertexColor(trackingBorder:GetVertexColor()) | 962 iconBorder:SetVertexColor(trackingBorder:GetVertexColor()) |
| 971 trackingBorder:SetVertexColor(unpack(BORDER_CRITERIA)) | 963 trackingBorder:SetVertexColor(unpack(BORDER_CRITERIA)) |
| 972 else | 964 else |
| 973 | 965 |
| 974 iconBorder:SetVertexColor(unpack(borderColor)) | 966 iconBorder:SetVertexColor(unpack(borderColor)) |
| 975 trackingBorder:SetVertexColor(1,1,1,1) | 967 trackingBorder:SetVertexColor(0,0,0,.5) |
| 976 end | 968 end |
| 977 | 969 |
| 978 if SpellCanTargetQuest() then | 970 if SpellCanTargetQuest() then |
| 979 if IsQuestIDValidSpellTarget(self.questID) then | 971 if IsQuestIDValidSpellTarget(self.questID) then |
| 980 icon:SetVertexColor(1,1,1) | 972 icon:SetVertexColor(1,1,1) |
| 983 end | 975 end |
| 984 self:EnableMouse(false) | 976 self:EnableMouse(false) |
| 985 else | 977 else |
| 986 self:EnableMouse(true) | 978 self:EnableMouse(true) |
| 987 end | 979 end |
| 980 self.isStale = nil | |
| 988 | 981 |
| 989 -- signal filter info update | 982 -- signal filter info update |
| 990 WorldPlanSummary.isStale = true | 983 WorldPlanSummary.isStale = true |
| 991 end | 984 end |
| 992 | 985 |
| 993 local cvar_check = { | 986 -- Called at static intervals and with Refresh |
| 994 [REWARD_CASH] = 'worldQuestFilterGold', | 987 function QuestPOI:UpdateStatus() |
| 995 [REWARD_ARTIFACT_POWER] = 'worldQuestFilterArtifactPower', | 988 -- update time elements |
| 996 [REWARD_CURRENCY] = 'worldQuestFilterOrderResources', | 989 self.isActive = TQ_IsActive(self.questID) |
| 997 [REWARD_REAGENT]= 'worldQuestFilterProfessionMaterials', | 990 |
| 998 [REWARD_GEAR] = 'worldQuestFilterEquipment', | 991 if self.isActive then |
| 999 } | 992 local tl = self.alertLevel |
| 1000 | 993 local timeLeft = TQ_GetQuestTimeLeftMinutes(self.questID) |
| 1001 | 994 if timeLeft > 0 then |
| 1002 function QuestPOI:CheckFilterRules () | 995 |
| 1003 local print = qprint | 996 local text, timeState = WorldPlan:GetTimeInfo(timeLeft, self.maxAlertLevel) |
| 1004 local qType = self.worldQuestType | 997 if tl ~= timeState then |
| 1005 if not TQ_IsActive(self.questID) then | 998 tl = timeState |
| 1006 self.hideReason = 'Filter check ended because quest is inactive.' | 999 self.timeLabel:SetText(text) |
| 1007 self.used = nil | 1000 end |
| 1008 self:SetShown(false) | 1001 end |
| 1009 return | 1002 |
| 1010 end | 1003 local border = (self.isBounty or self.isCriteria) and self.RewardBorder or self.HighlightBorder |
| 1011 | 1004 |
| 1012 if qType == LE_QUEST_TAG_TYPE_PROFESSION then | 1005 if tl and (timeLeft < 120) then |
| 1013 if not(self.isKnownProfession or db.Config.ShowAllProfessionQuests) then | 1006 border:SetVertexColor(1,0,0,0.7) |
| 1014 self.hideReason = 'Failed profession check.' | |
| 1015 self.used = nil | |
| 1016 self:SetShown(false) | |
| 1017 return | |
| 1018 end | |
| 1019 end | |
| 1020 | |
| 1021 local filtered | |
| 1022 for filterKey, value in pairs(db.UsedFilters) do | |
| 1023 if self[filterKey] ~= value then | |
| 1024 if not self.filtered then | |
| 1025 print('|cFFFF4400filtering', filterKey, value, '~=', self[filterKey], self.title) | |
| 1026 end | |
| 1027 filtered = true | |
| 1028 end | |
| 1029 end | |
| 1030 if self.rewardType and cvar_check[self.rewardType] then | |
| 1031 if not GetCVarBool(cvar_check[self.rewardType]) then | |
| 1032 filtered = true | |
| 1033 end | |
| 1034 end | |
| 1035 | |
| 1036 print(' '..self.questID..':|cFFFFFF00CheckFilterRules()|r', filtered, self.title) | |
| 1037 if self.filtered ~= filtered then | |
| 1038 wqprint('|cFF00FF00filter changed') | |
| 1039 self.isStale = true | |
| 1040 end | |
| 1041 | |
| 1042 self.filtered = filtered | |
| 1043 self.used = true | |
| 1044 self:SetShown(true) | |
| 1045 end | |
| 1046 | |
| 1047 --- Fixes icons upon size update | |
| 1048 function QuestPOI:UpdateSize () | |
| 1049 | |
| 1050 --qprint('|cFF00BB88'..self:GetID()..'|r:UpdateSize()', self.style, self.subStyle) | |
| 1051 return | |
| 1052 --[[ | |
| 1053 local style = self.style | |
| 1054 local subStyle = self.subStyle | |
| 1055 local icon = self.icon | |
| 1056 local iconBorder = self.RewardBorder | |
| 1057 local trackingBorder = self.HighlightBorder | |
| 1058 local tag = self.tagIcon | |
| 1059 | |
| 1060 local iconWidth = subStyle.iconWidth | |
| 1061 local borderWidth = iconWidth + (subStyle.borderWidth * 2) | |
| 1062 local highlightWidth = borderWidth + (subStyle.highlightWidth * 2) | |
| 1063 local iconTexture = self.itemTexture | |
| 1064 | |
| 1065 | |
| 1066 self:SetSize(highlightWidth, highlightWidth) | |
| 1067 if self.questID == GetSuperTrackedQuestID() then | |
| 1068 highlightWidth = highlightWidth + 2 | |
| 1069 if self.filtered then | |
| 1070 self:SetAlpha(db.PinAlpha * 0.5) | |
| 1071 else | 1007 else |
| 1072 self:SetAlpha(db.PinAlpha) | 1008 border:SetVertexColor(0,0,0,0.7) |
| 1073 end | 1009 end |
| 1074 | 1010 self.alertLevel = tl |
| 1075 end | 1011 self.timeLabel:SetShown(self.worldQuest and (self.maxAlertLevel >= 1)) |
| 1076 | 1012 else |
| 1077 if self.rarity and WORLD_QUEST_QUALITY_COLORS[self.rarity] then | 1013 self.hideReason = "No longer active." |
| 1078 highlightWidth = highlightWidth + self.rarity | 1014 self:HideOrShowFrames(false) |
| 1079 end | 1015 |
| 1080 self.tagIcon:SetSize(self.tagSize, self.tagSize) | 1016 end |
| 1081 icon:SetSize(iconWidth, iconWidth) | 1017 end |
| 1082 iconBorder:SetSize(borderWidth, borderWidth) | 1018 |
| 1083 trackingBorder:SetSize(highlightWidth, highlightWidth) | 1019 -- Show/Hide the text overlays associated with the quest pin; they aren't hierarchically linked |
| 1084 | 1020 function QuestPOI:HideOrShowFrames(isShown) |
| 1085 | 1021 if not isShown then |
| 1086 iconBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) | 1022 -- print('|cFFFFFF00' ..self:GetName()..':HideOrShowFrames()') |
| 1087 trackingBorder:SetPoint('CENTER', (style.x or 0), (style.y or 0)) | 1023 -- do not SetShown() here |
| 1088 | 1024 if not self.hideReason then |
| 1089 | 1025 self.hideReason = "HideOrShowFrames() called" |
| 1090 if (subStyle.showNumber and self.itemNumber) and style.hasNumeric then | 1026 end |
| 1091 self.count:SetTextColor(unpack(style.numberRGB)) | 1027 end |
| 1092 if subStyle.numberFontObject then | 1028 self.Overlay:SetShown(isShown) |
| 1093 --wqprint('change font', _G[subStyle.numberFontObject]:GetName()) | 1029 self.count:SetShown(isShown) |
| 1094 self.count:SetFontObject(_G[subStyle.numberFontObject]) | 1030 self.timeLabel:SetShown(isShown) |
| 1095 end | 1031 end |
| 1096 else | 1032 |
| 1097 self.count:SetText(nil) | 1033 function QuestPOI:Release() |
| 1098 end | 1034 |
| 1099 --]] | 1035 self.hideReason = 'Released by script.' |
| 1100 end | 1036 self:SetShown(false) |
| 1037 if self.questID then | |
| 1038 db.QuestsByID[self.questID] = nil | |
| 1039 for _, map in pairs(db.QuestsByZone) do | |
| 1040 map[self.questID] = nil | |
| 1041 end | |
| 1042 self.questID = nil | |
| 1043 end | |
| 1044 self.isActive = nil | |
| 1045 self.complete = nil | |
| 1046 self.used = nil | |
| 1047 self.dataLoaded = nil | |
| 1048 self.rewardType = nil | |
| 1049 self.itemTexture = nil | |
| 1050 self.itemName = nil | |
| 1051 self.itemNumber = nil | |
| 1052 self:SetShown(false) | |
| 1053 self.animating = nil | |
| 1054 self.icon:SetAlpha(0) | |
| 1055 self.RewardBorder:SetAlpha(0) | |
| 1056 self:UnregisterEvent('QUEST_TURNED_IN') | |
| 1057 self:UnregisterEvent('QUEST_LOG_UPDATE') | |
| 1058 | |
| 1059 for i, pin in ipairs(db.UsedPins) do | |
| 1060 if pin == self then | |
| 1061 tremove(db.UsedPins, i) | |
| 1062 break | |
| 1063 end | |
| 1064 | |
| 1065 end | |
| 1066 | |
| 1067 tinsert(db.FreePins, self) | |
| 1068 WorldPlan.dataFlush = true | |
| 1069 end |
