master
Brett O'Donnell 2012-12-01 23:30:31 +10:30
parent b570f6ffb5
commit d3efdf98de
444 changed files with 147636 additions and 0 deletions

15
ACP/ACP.iml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="LUA_MODULE" version="4">
<component name="DBNavigator.Module.ConnectionManager">
<connections />
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="Lua 5.1.4" jdkType="Lua SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

2122
ACP/ACP.lua Normal file

File diff suppressed because it is too large Load Diff

32
ACP/ACP.toc Normal file
View File

@ -0,0 +1,32 @@
## Interface: 40000
## X-Compatible-With: 40000
## X-Since-Interface: 30300
## X-Curse-Packaged-Version: 3.3.9
## X-Curse-Project-Name: Addon Control Panel
## X-Curse-Project-ID: acp
## X-Curse-Repository-ID: wow/acp/mainline
## Title: Addon Control Panel
## Author: sylvanaar, Rophy, Saien
## Notes: Adds an addon manager in game via the 'Addons' menu. Special support for multi-part addons. Based on rMCP by Rophy.
## Notes-ruRU: Добавляет менеджер модификаций а игру посредством пункта меню 'Модификации'. Специальная поддержка модификаций состоящих из нескольких частей. Основан на rMCP от Rophy.
## Notes-zhTW: 在系統選單按「插件管理」按鈕管理插件。ACP 以 rMCP (MCP由Rophy修改) 為基礎。
## Notes-esES: A?ade un panel de Accesorios en el juego mediante el men? 'Accesorios'. Soporte especial para accesorios multi-parte. Basado en rMCP de Rophy.
## Notes-zhCN: 在系统选项按「插件管理」按钮管理插件。ACP 以 rMCPMCP由 Rophy 修改)为基础。
## Version: 3.3.9
## SavedVariables: ACP_Data
## X-Credits: ACP based now on rMCP, which is MCP modified by Rophy, originally by Saien.
## X-Category: Interface Enhancements
ACP.lua
localization-enUS.lua
localization-zhTW.lua
localization-koKR.lua
localization-deDE.lua
localization-zhCN.lua
localization-frFR.lua
localization-esES.lua
localization-ruRU.lua
ACP.xml

690
ACP/ACP.xml Normal file
View File

@ -0,0 +1,690 @@
<!-- edited with XMLSpy v2007 (http://www.altova.com) by jon (n/a) -->
<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/ W:\WORLDO~1\BLIZZA~1\FrameXML\UI.xsd">
<Button name="ACP_AddonListEntryTemplate" virtual="true">
<Size>
<AbsDimension x="520" y="16"/>
</Size>
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentTitle" inherits="GameFontNormal" justifyH="LEFT">
<Size>
<AbsDimension x="200" y="12"/>
</Size>
<Anchors>
<Anchor point="LEFT">
<Offset>
<AbsDimension x="42" y="0"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
<FontString name="$parentStatus" inherits="GameFontNormalSmall" justifyH="LEFT">
<Size>
<AbsDimension x="160" y="12"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentTitle" relativePoint="RIGHT">
<Offset>
<AbsDimension x="30" y="0"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
<FontString name="$parentHeader" inherits="GameFontHighlight">
<Anchors>
<Anchor point="LEFT">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<Button name="$parentCollapse" hidden="true">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="RIGHT" relativePoint="LEFT">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ACP:Collapse_OnClick(self:GetParent())
</OnClick>
</Scripts>
<NormalTexture name="$parentIcon"/>
<HighlightTexture alphaMode="ADD" file="Interface\Minimap\UI-Minimap-ZoomButton-Highlight"/>
</Button>
<Button name="$parentSecurity">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="RIGHT" relativePoint="LEFT">
<Offset>
<AbsDimension x="2" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ACP:Security_OnClick(self:GetParent().addon)
</OnClick>
<OnEnter>
ACP:ShowSecurityTooltip(self)
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
<NormalTexture name="$parentIcon" file="Interface\Glues\CharacterSelect\Glues-AddOn-Icons"/>
</Button>
<Button name="$parentLoadNow" inherits="UIPanelButtonTemplate" text="Load">
<Size>
<AbsDimension x="80" y="16"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentStatus" relativePoint="RIGHT">
<Offset>
<AbsDimension x="2" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ACP:AddonList_LoadNow(self:GetParent().addon);
</OnClick>
</Scripts>
</Button>
<CheckButton name="$parentEnabled">
<Size>
<AbsDimension x="32" y="32"/>
</Size>
<Anchors>
<Anchor point="LEFT">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnEnter>
ACP:ShowHintTooltip(self, self.addon)
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
<OnClick>
ACP:AddonList_Enable(self:GetParent().addon, self:GetChecked(),
IsShiftKeyDown(), IsControlKeyDown(), self:GetParent().category);
</OnClick>
</Scripts>
<NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/>
<PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/>
<HighlightTexture file="Interface\Buttons\UI-CheckBox-Highlight" alphaMode="ADD"/>
<CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/>
<DisabledCheckedTexture file="Interface\Buttons\UI-CheckBox-Check-Disabled"/>
</CheckButton>
</Frames>
<Scripts>
<OnEnter>
ACP:ShowTooltip(self, self.addon)
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
<Button name="GameMenuButtonAddOns" inherits="GameMenuButtonTemplate" text="AddOns" parent="GameMenuFrame">
<Anchors>
<Anchor point="TOP" relativeTo="GameMenuButtonMacros" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-1"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<!--<OnLoad>
GameMenuButtonLogout:SetPoint("TOP",self:GetName(),"BOTTOM",0,-1);
GameMenuFrame:SetHeight(GameMenuFrame:GetHeight()+25);
</OnLoad>-->
<OnShow>
GameMenuFrame:SetHeight(GameMenuFrame:GetHeight()+25);
local point, relativeTo, relativePoint, x, y= GameMenuButtonMacros:GetPoint(1);
if (relativeTo and relativeTo ~= self ) then
self:SetPoint( point, relativeTo, relativePoint, x, y)
end
GameMenuButtonMacros:ClearAllPoints()
GameMenuButtonMacros:SetPoint("TOP",self,"BOTTOM",0,-1);
</OnShow>
<OnHide>
GameMenuFrame:SetHeight(GameMenuFrame:GetHeight()-25);
</OnHide>
<OnClick>
PlaySound("igMainMenuOption");
HideUIPanel(GameMenuFrame);
ShowUIPanel(ACP_AddonList);
</OnClick>
</Scripts>
</Button>
<Frame name="ACP_AddonList" hidden="true" toplevel="true" enableMouse="true" enableKeyboard="false">
<Size>
<AbsDimension x="640" y="512"/>
</Size>
<Anchors>
<Anchor point="CENTER"/>
</Anchors>
<HitRectInsets>
<AbsInset left="0" right="44" top="0" bottom="13"/>
</HitRectInsets>
<Frames>
<Button name="$parentCloseButton" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT">
<Offset>
<AbsDimension x="-42" y="-3"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentSortDropDown" inherits="UIDropDownMenuTemplate">
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="280" y="-22"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnShow>
ACP:SortDropDown_OnShow(self)
</OnShow>
</Scripts>
</Button>
<Button name="$parentDisableAll" inherits="UIPanelButtonTemplate" text="Disable All">
<Size>
<AbsDimension x="80" y="24"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT">
<Offset>
<AbsDimension x="90" y="20"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ACP:DisableAll_OnClick(self)
</OnClick>
</Scripts>
</Button>
<Button name="$parentEnableAll" inherits="UIPanelButtonTemplate" text="Enable All">
<Size>
<AbsDimension x="80" y="24"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT">
<Offset>
<AbsDimension x="175" y="20"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
EnableAllAddOns()
ACP:AddonList_OnShow(self)
</OnClick>
</Scripts>
</Button>
<Button name="$parentCollapseAll">
<Size>
<AbsDimension x="16" y="16"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT" relativePoint="TOPLEFT">
<Offset>
<AbsDimension x="20" y="-35"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ACP:CollapseAll_OnClick(self)
</OnClick>
</Scripts>
<NormalTexture name="$parentIcon" file="Interface\Minimap\UI-Minimap-ZoomOutButton-Up"/>
<HighlightTexture alphaMode="ADD" file="Interface\Minimap\UI-Minimap-ZoomButton-Highlight"/>
</Button>
<Button name="$parentSetButton" inherits="UIPanelButtonTemplate" text="Sets">
<Size>
<AbsDimension x="40" y="24"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT">
<Offset>
<AbsDimension x="20" y="20"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ACP:SetButton_OnClick(self);
</OnClick>
</Scripts>
</Button>
<CheckButton name="$parent_NoRecurse">
<Size>
<AbsDimension x="32" y="32"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentEnableAll" relativePoint="RIGHT">
<Offset>
<AbsDimension x="5" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentText" inherits="GameFontHighlightSmall" text="Recurse">
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT">
<Offset>
<AbsDimension x="2" y="0"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnClick>
ACP:ToggleRecursion(self:GetChecked());
</OnClick>
</Scripts>
<NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/>
<PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/>
<HighlightTexture file="Interface\Buttons\UI-CheckBox-Highlight" alphaMode="ADD"/>
<CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/>
<DisabledCheckedTexture file="Interface\Buttons\UI-CheckBox-Check-Disabled"/>
</CheckButton>
<Button name="$parent_ReloadUI" inherits="UIPanelButtonTemplate" text="ReloadUI">
<Size>
<AbsDimension x="80" y="25"/>
</Size>
<Anchors>
<Anchor point="BOTTOMRIGHT">
<Offset>
<AbsDimension x="-160" y="20"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
ReloadUI();
</OnClick>
</Scripts>
</Button>
<Button name="$parentBottomClose" inherits="UIPanelButtonTemplate" text="Close">
<Size>
<AbsDimension x="80" y="24"/>
</Size>
<Anchors>
<Anchor point="BOTTOMRIGHT">
<Offset>
<AbsDimension x="-50" y="20"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
HideUIPanel(ACP_AddonList);
</OnClick>
</Scripts>
</Button>
<Button name="$parentEntry1" inherits="ACP_AddonListEntryTemplate" id="1">
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="37" y="-62"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry2" inherits="ACP_AddonListEntryTemplate" id="2">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry1" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry3" inherits="ACP_AddonListEntryTemplate" id="3">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry2" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry4" inherits="ACP_AddonListEntryTemplate" id="4">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry3" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry5" inherits="ACP_AddonListEntryTemplate" id="5">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry4" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry6" inherits="ACP_AddonListEntryTemplate" id="6">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry5" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry7" inherits="ACP_AddonListEntryTemplate" id="7">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry6" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry8" inherits="ACP_AddonListEntryTemplate" id="8">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry7" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry9" inherits="ACP_AddonListEntryTemplate" id="9">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry8" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry10" inherits="ACP_AddonListEntryTemplate" id="10">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry9" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry11" inherits="ACP_AddonListEntryTemplate" id="11">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry10" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry12" inherits="ACP_AddonListEntryTemplate" id="12">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry11" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry13" inherits="ACP_AddonListEntryTemplate" id="13">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry12" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry14" inherits="ACP_AddonListEntryTemplate" id="14">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry13" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry15" inherits="ACP_AddonListEntryTemplate" id="15">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry14" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry16" inherits="ACP_AddonListEntryTemplate" id="16">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry15" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry17" inherits="ACP_AddonListEntryTemplate" id="17">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry16" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry18" inherits="ACP_AddonListEntryTemplate" id="18">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry17" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry19" inherits="ACP_AddonListEntryTemplate" id="19">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry18" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<Button name="$parentEntry20" inherits="ACP_AddonListEntryTemplate" id="20">
<Anchors>
<Anchor point="TOP" relativeTo="$parentEntry19" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="0" y="-4"/>
</Offset>
</Anchor>
</Anchors>
</Button>
<ScrollFrame name="$parent_ScrollFrame" inherits="FauxScrollFrameTemplate">
<Size>
<AbsDimension x="510" y="410"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="49" y="-53"/>
</Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentTop" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
<Size>
<AbsDimension x="31" y="256"/>
</Size>
<Anchors>
<!-- <AbsDimension x="-2" y="-4"/> -->
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT">
<Offset>
<AbsDimension x="-2" y="5"/>
</Offset>
</Anchor>
</Anchors>
<TexCoords left="0" right="0.484375" top="0" bottom="1.0"/>
</Texture>
<Texture name="$parentBottom" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
<Size>
<AbsDimension x="31" y="106"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT">
<Offset>
<AbsDimension x="-2" y="-2"/>
</Offset>
</Anchor>
</Anchors>
<TexCoords left="0.515625" right="1.0" top="0" bottom="0.4140625"/>
</Texture>
<Texture name="$parentMiddle" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
<Size>
<AbsDimension x="31" y="60"/>
</Size>
<Anchors>
<Anchor point="TOP" relativeTo="$parentTop" relativePoint="BOTTOM"/>
<Anchor point="BOTTOM" relativeTo="$parentBottom" relativePoint="TOP"/>
</Anchors>
<TexCoords left="0" right="0.484375" top=".75" bottom="1.0"/>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnVerticalScroll>
FauxScrollFrame_OnVerticalScroll(self, offset, ACP_LINEHEIGHT, function() ACP:AddonList_OnShow() end);
</OnVerticalScroll>
</Scripts>
</ScrollFrame>
</Frames>
<Layers>
<Layer level="BACKGROUND">
<Texture file="Interface\HelpFrame\HelpFrame-TopLeft">
<Size>
<AbsDimension x="256" y="256"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT"/>
</Anchors>
</Texture>
<Texture file="Interface\HelpFrame\HelpFrame-Top">
<Size>
<AbsDimension x="256" y="256"/>
</Size>
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="256" y="0"/>
</Offset>
</Anchor>
</Anchors>
</Texture>
<Texture file="Interface\HelpFrame\HelpFrame-TopRight">
<Size>
<AbsDimension x="128" y="256"/>
</Size>
<Anchors>
<Anchor point="TOPRIGHT"/>
</Anchors>
</Texture>
<Texture file="Interface\HelpFrame\HelpFrame-BotLeft">
<Size>
<AbsDimension x="256" y="256"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT"/>
</Anchors>
</Texture>
<Texture file="Interface\HelpFrame\HelpFrame-Bottom">
<Size>
<AbsDimension x="256" y="256"/>
</Size>
<Anchors>
<Anchor point="BOTTOMLEFT">
<Offset>
<AbsDimension x="256" y="0"/>
</Offset>
</Anchor>
</Anchors>
</Texture>
<Texture file="Interface\HelpFrame\HelpFrame-BotRight">
<Size>
<AbsDimension x="128" y="256"/>
</Size>
<Anchors>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
</Texture>
</Layer>
<Layer level="ARTWORK">
<Texture name="$parentHeader" file="Interface\DialogFrame\UI-DialogBox-Header">
<Size>
<AbsDimension x="536" y="64"/>
</Size>
<Anchors>
<Anchor point="TOP">
<Offset>
<AbsDimension x="-12" y="12"/>
</Offset>
</Anchor>
</Anchors>
</Texture>
<FontString name="$parentHeaderTitle" inherits="GameFontNormal" text="ADDON_LIST">
<Anchors>
<Anchor point="TOP" relativeTo="$parentHeader">
<Offset>
<AbsDimension x="0" y="-14"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnLoad>
ACP:OnLoad(self)
</OnLoad>
<OnEvent>
ACP:OnEvent(self, event, ...)
</OnEvent>
<OnShow>
ACP:AddonList_OnShow(self)
</OnShow>
<!--<OnKeyDown>-->
<!--ACP:OnKeyDown(self, key);-->
<!--</OnKeyDown>-->
</Scripts>
</Frame>
</Ui>

View File

@ -0,0 +1,8 @@
2010-10-19 sylvanaar <sylvanaar@7213456c-7c21-484b-8324-69955f39d2f8>
[558e8517963d] [3.3.9]
* ACP.lua:
set the number of addon sets to 25

81
ACP/localization-deDE.lua Normal file
View File

@ -0,0 +1,81 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "deDE") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** Aktiviere <%s> %s deiner UI ***",
["*** Unknown Addon <%s> Required ***"] = "*** Unbekanntes Addon <%s> benötigt ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: Einige geschützte Addons sind nicht geladen. Jetzt neu laden?",
["Active Embeds"] = "Aktive Embeds",
["Add to current selection"] = "Zur aktuellen Auswahl hinzufügen",
AddOns = "AddOns",
["Addon <%s> not valid"] = "Addon <%s> ungültig",
["Addons [%s] Loaded."] = "Addons [%s] geladen.",
["Addons [%s] Saved."] = "Addons [%s] gespeichert.",
["Addons [%s] Unloaded."] = "Addons [%s] entladen.",
["Addons [%s] renamed to [%s]."] = "Addons [%s] umbenannt zu [%s].",
Author = "Autor",
Blizzard_AchievementUI = "Blizzard: Achievement",
Blizzard_AuctionUI = "Blizzard: Auction",
Blizzard_BarbershopUI = "Blizzard: Barbershop",
Blizzard_BattlefieldMinimap = "Blizzard: Battlefield Minimap",
Blizzard_BindingUI = "Blizzard: Binding",
Blizzard_Calendar = "Blizzard: Calendar",
Blizzard_CombatLog = "Blizzard: Combat Log",
Blizzard_CombatText = "Blizzard: Combat Text",
Blizzard_FeedbackUI = "Blizzard: Feedback",
Blizzard_GMSurveyUI = "Blizzard: GM Survey",
Blizzard_GlyphUI = "Blizzard: Glyph",
Blizzard_GuildBankUI = "Blizzard: GuildBank",
Blizzard_InspectUI = "Blizzard: Inspect",
Blizzard_ItemSocketingUI = "Blizzard: Item Socketing",
Blizzard_MacroUI = "Blizzard: Macro",
Blizzard_RaidUI = "Blizzard: Raid",
Blizzard_TalentUI = "Blizzard: Talent",
Blizzard_TimeManager = "Blizzard: TimeManager",
Blizzard_TokenUI = "Blizzard: Token",
Blizzard_TradeSkillUI = "Blizzard: Trade Skill",
Blizzard_TrainerUI = "Blizzard: Trainer",
Blizzard_VehicleUI = "Blizzard: Vehicle",
["Click to enable protect mode. Protected addons will not be disabled"] = "Klicken um geschützten Modus zu aktivieren. Geschützte Addons werden nicht deaktiviert",
Close = "Schließen",
Default = "Standard",
Dependencies = "Abhängigkeiten",
["Disable All"] = "Alle Aus",
["Disabled on reloadUI"] = "Deaktiviert nach reloadUI",
Embeds = "Embeds",
["Enable All"] = "Alle An",
["Enter the new name for [%s]:"] = "Gib den neuen Namen für [%s] ein:",
["LoD Child Enable is now %s"] = "LoD Nachfolger Aktivierung ist nun %s .",
Load = "Laden",
["Loadable OnDemand"] = "Wird bei Bedarf geladen",
Loaded = "Geladen",
["Loaded on demand."] = "Geladen bei Bedarf.",
["Memory Usage"] = "Speichernutzung",
["No information available."] = "Keine Information verfügbar.",
Recursive = "Rekursiv",
["Recursive Enable is now %s"] = "Rekursives Aktivieren ist nun %s",
Reload = "Neuladen",
["Reload your User Interface?"] = "Interface neu laden?",
ReloadUI = "ReloadUI",
["Remove from current selection"] = "Aus der aktuellen Auswahl entfernen",
Rename = "Umbenennen",
Save = "Speichern",
["Save the current addon list to [%s]?"] = "Die aktuelle Addonliste als [%s] speichern?",
["Set "] = "Setzen",
Sets = "Sets",
Status = "Status",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "Benutze SHIFT um die momentane Einstellung des Abhängigkeitsverhaltens zu überschreiben",
Version = "Version",
["when performing a reloadui."] = "wenn ein Reloadui ausgeführt wird.",
}
)
end
--@end-non-debug@

153
ACP/localization-enUS.lua Normal file
View File

@ -0,0 +1,153 @@
if not ACP then return end
--@debug@
ACP:UpdateLocale( {
["Reload your User Interface?"] = true,
["Save the current addon list to [%s]?"] = true,
["Enter the new name for [%s]:"] = true,
["Addons [%s] Saved."] = true,
["Addons [%s] Unloaded."] = true,
["Addons [%s] Loaded."] = true,
["Addons [%s] renamed to [%s]."] = true,
["Loaded on demand."] = true,
["AddOns"] = true,
["Load"] = true,
["Disable All"] = true,
["Enable All"] = true,
["ReloadUI"] = true,
["Sets"] = true,
["No information available."] = true,
["Loaded"] = true,
["Recursive"] = true,
["Loadable OnDemand"] = true,
["Disabled on reloadUI"] = true,
["Default"] = true;
["Set "] = true;
["Save"] = true;
["Load"] = true;
["Add to current selection"] = true;
["Remove from current selection"] = true;
["Rename"] = true;
["Use SHIFT to override the current enabling of dependancies behaviour."] = true,
["Click to enable protect mode. Protected addons will not be disabled"] = true,
["when performing a reloadui."]=true,
["ACP: Some protected addons aren't loaded. Reload now?"]=true,
["Active Embeds"] = true,
["Memory Usage"] = true,
["Close"] = true,
["Blizzard_AchievementUI"] = "Blizzard: Achievement",
["Blizzard_AuctionUI"] = "Blizzard: Auction",
["Blizzard_BarbershopUI"] = "Blizzard: Barbershop",
["Blizzard_BattlefieldMinimap"] = "Blizzard: Battlefield Minimap",
["Blizzard_BindingUI"] = "Blizzard: Binding",
["Blizzard_Calendar"] = "Blizzard: Calendar",
["Blizzard_CombatLog"] = "Blizzard: Combat Log",
["Blizzard_CombatText"] = "Blizzard: Combat Text",
["Blizzard_FeedbackUI"] = "Blizzard: Feedback",
["Blizzard_GlyphUI"] = "Blizzard: Glyph",
["Blizzard_GMSurveyUI"] = "Blizzard: GM Survey",
["Blizzard_GuildBankUI"] = "Blizzard: GuildBank",
["Blizzard_InspectUI"] = "Blizzard: Inspect",
["Blizzard_ItemSocketingUI"] = "Blizzard: Item Socketing",
["Blizzard_MacroUI"] = "Blizzard: Macro",
["Blizzard_RaidUI"] = "Blizzard: Raid",
["Blizzard_TalentUI"] = "Blizzard: Talent",
["Blizzard_TimeManager"] = "Blizzard: TimeManager",
["Blizzard_TokenUI"] = "Blizzard: Token",
["Blizzard_TradeSkillUI"] = "Blizzard: Trade Skill",
["Blizzard_TrainerUI"] = "Blizzard: Trainer",
["Blizzard_VehicleUI"] = "Blizzard: Vehicle",
["*** Enabling <%s> %s your UI ***"] = true;
["*** Unknown Addon <%s> Required ***"] = true;
["LoD Child Enable is now %s"] = true;
["Recursive Enable is now %s"] = true;
["Addon <%s> not valid"] = true,
["Reload"] = true;
["Author"] = true;
["Version"] = true;
["Status"] = true;
["Dependencies"] = true;
["Embeds"] = true;
} )
--@enddebug@
--@non-debug@
if (GetLocale() == "enUS") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** Enabling <%s> %s your UI ***",
["*** Unknown Addon <%s> Required ***"] = "*** Unknown Addon <%s> Required ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: Some protected addons aren't loaded. Reload now?",
["Active Embeds"] = "Active Embeds",
["Add to current selection"] = "Add to current selection",
AddOns = "AddOns",
["Addon <%s> not valid"] = "Addon <%s> not valid",
["Addons [%s] Loaded."] = "Addons [%s] Loaded.",
["Addons [%s] Saved."] = "Addons [%s] Saved.",
["Addons [%s] Unloaded."] = "Addons [%s] Unloaded.",
["Addons [%s] renamed to [%s]."] = "Addons [%s] renamed to [%s].",
Author = "Author",
Blizzard_AchievementUI = "Blizzard: Achievement",
Blizzard_AuctionUI = "Blizzard: Auction",
Blizzard_BarbershopUI = "Blizzard: Barbershop",
Blizzard_BattlefieldMinimap = "Blizzard: Battlefield Minimap",
Blizzard_BindingUI = "Blizzard: Binding",
Blizzard_Calendar = "Blizzard: Calendar",
Blizzard_CombatLog = "Blizzard: Combat Log",
Blizzard_CombatText = "Blizzard: Combat Text",
Blizzard_FeedbackUI = "Blizzard: Feedback",
Blizzard_GMSurveyUI = "Blizzard: GM Survey",
Blizzard_GlyphUI = "Blizzard: Glyph",
Blizzard_GuildBankUI = "Blizzard: GuildBank",
Blizzard_InspectUI = "Blizzard: Inspect",
Blizzard_ItemSocketingUI = "Blizzard: Item Socketing",
Blizzard_MacroUI = "Blizzard: Macro",
Blizzard_RaidUI = "Blizzard: Raid",
Blizzard_TalentUI = "Blizzard: Talent",
Blizzard_TimeManager = "Blizzard: TimeManager",
Blizzard_TokenUI = "Blizzard: Token",
Blizzard_TradeSkillUI = "Blizzard: Trade Skill",
Blizzard_TrainerUI = "Blizzard: Trainer",
Blizzard_VehicleUI = "Blizzard: Vehicle",
["Click to enable protect mode. Protected addons will not be disabled"] = "Click to enable protect mode. Protected addons will not be disabled",
Close = "Close",
Default = "Default",
Dependencies = "Dependencies",
["Disable All"] = "Disable All",
["Disabled on reloadUI"] = "Disabled on reloadUI",
Embeds = "Embeds",
["Enable All"] = "Enable All",
["Enter the new name for [%s]:"] = "Enter the new name for [%s]:",
["LoD Child Enable is now %s"] = "LoD Child Enable is now %s",
Load = "Load",
["Loadable OnDemand"] = "Loadable OnDemand",
Loaded = "Loaded",
["Loaded on demand."] = "Loaded on demand.",
["Memory Usage"] = "Memory Usage",
["No information available."] = "No information available.",
Recursive = "Recursive",
["Recursive Enable is now %s"] = "Recursive Enable is now %s",
Reload = "Reload",
["Reload your User Interface?"] = "Reload your User Interface?",
ReloadUI = "ReloadUI",
["Remove from current selection"] = "Remove from current selection",
Rename = "Rename",
Save = "Save",
["Save the current addon list to [%s]?"] = "Save the current addon list to [%s]?",
["Set "] = "Set ",
Sets = "Sets",
Status = "Status",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "Use SHIFT to override the current enabling of dependancies behaviour.",
Version = "Version",
["when performing a reloadui."] = "when performing a reloadui.",
}
)
end
--@end-non-debug@

79
ACP/localization-esES.lua Normal file
View File

@ -0,0 +1,79 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "esES") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** Activando <%s> %s su IU ***",
["*** Unknown Addon <%s> Required ***"] = "*** Accesorio desconocido <%s> requerido ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: Algunos accesorios protegidos no se encuentran cargados. ?Recargar ahora?",
-- ["Active Embeds"] = "",
["Add to current selection"] = "A?adir a la selección actual",
AddOns = "Accesorios",
["Addon <%s> not valid"] = "Accesorio <%s> incorrecto",
["Addons [%s] Loaded."] = "Accesorios [%s] cargados.",
["Addons [%s] Saved."] = "Accesorios [%s] grabados.",
["Addons [%s] Unloaded."] = "Accesorios [%s] descargados.",
["Addons [%s] renamed to [%s]."] = "Accesorios [%s] renombrados a [%s].",
Author = "Autor",
Blizzard_AchievementUI = "Blizzard: Achievement",
Blizzard_AuctionUI = "Blizzard: Subasta",
Blizzard_BarbershopUI = "Blizzard: Barbershop",
Blizzard_BattlefieldMinimap = "Blizzard: Minimapa del Campo de Batalla",
Blizzard_BindingUI = "Blizzard: Asignación",
Blizzard_Calendar = "Blizzard: Calendar",
Blizzard_CombatLog = "Blizzard: Combat Log",
Blizzard_CombatText = "Blizzard: Texto de Combate",
Blizzard_FeedbackUI = "Blizzard: Feedback",
Blizzard_GMSurveyUI = "Blizzard: Ayuda GM",
Blizzard_GlyphUI = "Blizzard: Glyph",
Blizzard_GuildBankUI = "Blizzard: GuildBank",
Blizzard_InspectUI = "Blizzard: Inspeción",
Blizzard_ItemSocketingUI = "Blizzard: Colocación de objetos",
Blizzard_MacroUI = "Blizzard: Macro",
Blizzard_RaidUI = "Blizzard: Raid",
Blizzard_TalentUI = "Blizzard: Talento",
Blizzard_TimeManager = "Blizzard: TimeManager",
Blizzard_TokenUI = "Blizzard: Token",
Blizzard_TradeSkillUI = "Blizzard: Profesión",
Blizzard_TrainerUI = "Blizzard: Profesor",
Blizzard_VehicleUI = "Blizzard: Vehicle",
["Click to enable protect mode. Protected addons will not be disabled"] = "Clic para activar el modo protegido. Los accesorios protegidos no seran deshabilitados",
-- Close = "",
Default = "Por defecto",
Dependencies = "Dependencias",
["Disable All"] = "---",
["Disabled on reloadUI"] = "Desactivar al RecargarIU",
Embeds = "Inclusiones",
["Enable All"] = "+++",
["Enter the new name for [%s]:"] = "Escriba el nuevo nombre para [%s]:",
["LoD Child Enable is now %s"] = "La Activación de los Hijos CaD es ahora %s",
Load = "Cargar ",
["Loadable OnDemand"] = "Cargable a demanda",
Loaded = "Cargado",
["Loaded on demand."] = "Cargar a demanda.",
-- ["Memory Usage"] = "",
["No information available."] = "No hay información disponible.",
Recursive = "Recursivo",
["Recursive Enable is now %s"] = "La Activación Recursiva es ahora %s",
Reload = "Recargar",
["Reload your User Interface?"] = "?Recargar la Interfaz de Usuario?",
ReloadUI = "RecargarIU",
["Remove from current selection"] = "Eliminar de la selección actual",
Rename = "Renombrar ",
Save = "Grabar ",
["Save the current addon list to [%s]?"] = "?Grabar la lista actual de accesorios en [%s]?",
["Set "] = "Perfil ",
Sets = "Perfiles",
Status = "Estado",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "Utilice MAY para reemplazar el comportamiento de activaci?n de dependencias actual.",
Version = "Versión",
["when performing a reloadui."] = "cuando realice RecargarIU.",
}
)
end
--@end-non-debug@

80
ACP/localization-frFR.lua Normal file
View File

@ -0,0 +1,80 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "frFR") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** Activation <%s> %s votre UI ***",
["*** Unknown Addon <%s> Required ***"] = "*** Addon inconnu <%s> requis ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: Certains addons ne sont pas chargés. Recharger maintenant?",
-- ["Active Embeds"] = "",
["Add to current selection"] = "Ajouter à la sélection courante",
AddOns = "Addons",
["Addon <%s> not valid"] = "Addon <%s> invalide",
["Addons [%s] Loaded."] = "Addons [%s] chargés.",
["Addons [%s] Saved."] = "Addons [%s] sauvés.",
["Addons [%s] Unloaded."] = "Addons [%s] déchargés.",
["Addons [%s] renamed to [%s]."] = "Addons [%s] renommé en [%s].",
Author = "Auteur",
Blizzard_AchievementUI = "Blizzard: Hauts faits",
Blizzard_AuctionUI = "Blizzard: Hôtel des ventes",
Blizzard_BarbershopUI = "Blizzard: Barbier",
Blizzard_BattlefieldMinimap = "Blizzard: Minimap Champ de Bataille",
Blizzard_BindingUI = "Blizzard: Raccourcis",
Blizzard_Calendar = "Blizzard: Calendrier",
Blizzard_CombatLog = "Blizzard: Log de combat",
Blizzard_CombatText = "Blizzard: Texte de combat",
Blizzard_FeedbackUI = "Blizzard: Commentaire",
Blizzard_GMSurveyUI = "Blizzard: Aide MJ",
Blizzard_GlyphUI = "Blizzard: Glyphe",
Blizzard_GuildBankUI = "Blizzard: Banque de guilde",
Blizzard_InspectUI = "Blizzard: Inspection",
Blizzard_ItemSocketingUI = "Blizzard: Mise en place de gemmes",
Blizzard_MacroUI = "Blizzard: Macro",
Blizzard_RaidUI = "Blizzard: Raid",
Blizzard_TalentUI = "Blizzard: Talent",
Blizzard_TimeManager = "Blizzard: Gestion du temps",
Blizzard_TokenUI = "Blizzard: Jeton",
Blizzard_TradeSkillUI = "Blizzard: Profession",
Blizzard_TrainerUI = "Blizzard: Maîtres",
Blizzard_VehicleUI = "Blizzard: Vehicule",
["Click to enable protect mode. Protected addons will not be disabled"] = "Cliquez pour activer le mode protégé. Les addons protégés ne seront pas désactivés",
Close = "Fermer",
Default = "Défaut",
Dependencies = "Dépendances",
["Disable All"] = "---",
["Disabled on reloadUI"] = "Désactivé au rechargement d'interface",
Embeds = "Intégrés",
["Enable All"] = "+++",
["Enter the new name for [%s]:"] = "Entrez le nouveau nom pour [%s]:",
["LoD Child Enable is now %s"] = "L'activation des enfants LoD est maintenant %s",
Load = "Charger ",
["Loadable OnDemand"] = "Chargement à la demande",
Loaded = "Chargé",
["Loaded on demand."] = "Chargé à la demande.",
["Memory Usage"] = "Utilisation de la mémoire",
["No information available."] = "Pas d'information disponible.",
Recursive = "Récursif",
["Recursive Enable is now %s"] = "L'activation récursive est maintenant %s",
Reload = "Rechargement",
["Reload your User Interface?"] = "Recharger l'interface utilisateur?",
ReloadUI = "Recharger",
["Remove from current selection"] = "Enlever de la sélection courante",
Rename = "Renommer ",
Save = "Sauver ",
["Save the current addon list to [%s]?"] = "Sauver la liste actuelle dans [%s]?",
["Set "] = "Set ",
Sets = "Sets",
Status = "Statut",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "Utilisez SHIFT pour passer outre la résolution des dépendances actuellement activée.",
Version = "Version",
["when performing a reloadui."] = "lors d'un rechargement de l'interface.",
}
)
end
--@end-non-debug@

80
ACP/localization-koKR.lua Normal file
View File

@ -0,0 +1,80 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "koKR") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** 애드온 <%s> %s 사용 ***",
["*** Unknown Addon <%s> Required ***"] = "*** 알 수 없는 <%s> 애드온 요구 ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: 몇몇 보호된 애드온이 로드되지 않습니다. 지금 재로드할까요?",
["Active Embeds"] = "임베드 활성화",
["Add to current selection"] = "현재 선택 추가",
AddOns = "애드온",
["Addon <%s> not valid"] = "<%s> 애드온이 정확하지 않습니다.",
["Addons [%s] Loaded."] = "애드온 [%s]를 불려옵니다.",
["Addons [%s] Saved."] = "애드온 [%s]를 저장합니다.",
["Addons [%s] Unloaded."] = "애드온 [%s]를 삭제합니다.",
["Addons [%s] renamed to [%s]."] = "애드온 [%s]를 [%s]로 이름을 변경합니다.",
Author = "제작자",
Blizzard_AchievementUI = "Blizzard: 업적",
Blizzard_AuctionUI = "Blizzard: 경매장",
Blizzard_BarbershopUI = "Blizzard: 이발소",
Blizzard_BattlefieldMinimap = "Blizzard: 전장 미니맵",
Blizzard_BindingUI = "Blizzard: 단축키",
Blizzard_Calendar = "Blizzard: 달력",
Blizzard_CombatLog = "Blizzard: 전투로그",
Blizzard_CombatText = "Blizzard: 전투메시지",
Blizzard_FeedbackUI = "Blizzard: 피드백",
Blizzard_GMSurveyUI = "Blizzard: GM 요청",
Blizzard_GlyphUI = "Blizzard: 문양",
Blizzard_GuildBankUI = "Blizzard: 길드 은행",
Blizzard_InspectUI = "Blizzard: 살펴보기",
Blizzard_ItemSocketingUI = "Blizzard: 보석세공",
Blizzard_MacroUI = "Blizzard: 매크로",
Blizzard_RaidUI = "Blizzard: 공격대",
Blizzard_TalentUI = "Blizzard: 특성",
Blizzard_TimeManager = "Blizzard: 시계",
Blizzard_TokenUI = "Blizzard: 토큰",
Blizzard_TradeSkillUI = "Blizzard: 전문기술",
Blizzard_TrainerUI = "Blizzard: 기술숙련",
Blizzard_VehicleUI = "Blizzard: 탈 것",
["Click to enable protect mode. Protected addons will not be disabled"] = "클릭하면 보호모드가 실행됩니다. 보호된 애드온은 사용하지 않도록 합니다.",
Close = "닫기",
Default = "기본값",
Dependencies = "요구사항",
["Disable All"] = "모두 미사용",
["Disabled on reloadUI"] = "ReloadUI 해야 사용안함",
Embeds = "임베드",
["Enable All"] = "모두 사용",
["Enter the new name for [%s]:"] = "[%s]의 새로운 이름 입력:",
["LoD Child Enable is now %s"] = "LoD Child Enable is now %s",
Load = "불러오기",
["Loadable OnDemand"] = "불러올때 실행",
Loaded = "실행됨",
["Loaded on demand."] = "사용시 자동 실행",
["Memory Usage"] = "메모리 사용량",
["No information available."] = "알려진 정보가 없습니다.",
Recursive = "반복",
["Recursive Enable is now %s"] = "Recursive Enable is now %s",
Reload = "재실행",
["Reload your User Interface?"] = "당신의 사용자 인터페이스를 재시작 하시겠습니까?",
ReloadUI = "재시작",
["Remove from current selection"] = "현재 선택 삭제",
Rename = "이름바꾸기",
Save = "저장하기",
["Save the current addon list to [%s]?"] = "현재 애드온 목록을 [%s]로 저장 하시겠습니까?",
["Set "] = "세트 ",
Sets = "세트",
Status = "상태",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "SHIFT키를 사용하여 실행하는데 우선권을 가집니다.",
Version = "버전",
["when performing a reloadui."] = "ReloadUI를 했을 때",
}
)
end
--@end-non-debug@

80
ACP/localization-ruRU.lua Normal file
View File

@ -0,0 +1,80 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "ruRU") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** Включаю <%s> %s вашего ПИ ***",
["*** Unknown Addon <%s> Required ***"] = "*** Неизвест. модиф. <%s> требуется ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: Некоторые защищенные модификации не загруженны. Перезагрузить сейчас?",
["Active Embeds"] = "Активные встроенные",
["Add to current selection"] = "Добавить в текущее выделение",
AddOns = "Модификации",
["Addon <%s> not valid"] = "Модификация <%s> неисправна",
["Addons [%s] Loaded."] = "Модификации [%s] загружены.",
["Addons [%s] Saved."] = "Модификации [%s] сохранены.",
["Addons [%s] Unloaded."] = "Модификации [%s] выгружены.",
["Addons [%s] renamed to [%s]."] = "Модификации [%s] переименованны в [%s].",
Author = "Автор",
Blizzard_AchievementUI = "Blizzard: Достижения",
Blizzard_AuctionUI = "Blizzard: Аукцион",
Blizzard_BarbershopUI = "Blizzard: Парикмахерская",
Blizzard_BattlefieldMinimap = "Blizzard: Миникарта поля боя",
Blizzard_BindingUI = "Blizzard: Привязка ПИ",
Blizzard_Calendar = "Blizzard: Календарь",
Blizzard_CombatLog = "Blizzard: Журнал поля боя",
Blizzard_CombatText = "Blizzard: Текст поля боя",
Blizzard_FeedbackUI = "Blizzard: Обратная связь",
Blizzard_GMSurveyUI = "Blizzard: GM опрос",
Blizzard_GlyphUI = "Blizzard: Значки",
Blizzard_GuildBankUI = "Blizzard: Банк гильдии",
Blizzard_InspectUI = "Blizzard: Осмотр",
Blizzard_ItemSocketingUI = "Blizzard: Соединение элементов",
Blizzard_MacroUI = "Blizzard: Макросы",
Blizzard_RaidUI = "Blizzard: Рейд",
Blizzard_TalentUI = "Blizzard: Таланты",
Blizzard_TimeManager = "Blizzard: Управление временем",
Blizzard_TokenUI = "Blizzard: Сивол",
Blizzard_TradeSkillUI = "Blizzard: Торговля",
Blizzard_TrainerUI = "Blizzard: Инструктор",
Blizzard_VehicleUI = "Blizzard: Транспорт",
["Click to enable protect mode. Protected addons will not be disabled"] = "Щелкните чтобы включить защищенный режим. Защищенные модификации не будут отключены",
Close = "Закрыть",
Default = "По умолчанию",
Dependencies = "Зависимости",
["Disable All"] = "Откл. все",
["Disabled on reloadUI"] = "Отключен во время перез. ПИ",
Embeds = "Встроенные",
["Enable All"] = "Вкл. все",
["Enter the new name for [%s]:"] = "Введите новое имя для [%s]:",
["LoD Child Enable is now %s"] = "Дочерний ЗпТ теперь включен %s",
Load = "Загрузить",
["Loadable OnDemand"] = "Загружаемый по требованию",
Loaded = "Загружен",
["Loaded on demand."] = "Загружен по требованию.",
["Memory Usage"] = "Использование памяти",
["No information available."] = "Информация недоступна.",
Recursive = "Рекурсия",
["Recursive Enable is now %s"] = "Рекурсия теперь включена %s",
Reload = "Перезагрузить",
["Reload your User Interface?"] = "Перезагрузить пользовательский интерфейс?",
ReloadUI = "Перез. ПИ",
["Remove from current selection"] = "Убрать из текущего выделения",
Rename = "Переименовать",
Save = "Сохранить",
["Save the current addon list to [%s]?"] = "Сохранить текущий список модификаций в [%s]?",
["Set "] = "Набор ",
Sets = "Наб.",
Status = "Статус",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "Используйте SHIFT чтобы изменить поведение зависимостей.",
Version = "Версия",
["when performing a reloadui."] = "когда производиться перезагрузка ПИ.",
}
)
end
--@end-non-debug@

80
ACP/localization-zhCN.lua Normal file
View File

@ -0,0 +1,80 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "zhCN") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** 启用 <%s>%s 你的插件 ***",
["*** Unknown Addon <%s> Required ***"] = "*** 需要未知插件 <%s> ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP部分受保护插件没有被加载。现在重载插件么",
["Active Embeds"] = "单独使用",
["Add to current selection"] = "添加当前选择",
AddOns = "插件管理",
["Addon <%s> not valid"] = "无效的插件:<%s>",
["Addons [%s] Loaded."] = "插件设置[%s]已加载。",
["Addons [%s] Saved."] = "插件设置[%s]已保存。",
["Addons [%s] Unloaded."] = "插件设置[%s]已卸载。",
["Addons [%s] renamed to [%s]."] = "插件设置[%s]已改名为[%s]。",
Author = "作者",
Blizzard_AchievementUI = "Blizzard: Achievement",
Blizzard_AuctionUI = "Blizzard: Auction",
Blizzard_BarbershopUI = "Blizzard: Barbershop",
Blizzard_BattlefieldMinimap = "Blizzard: Battlefield Minimap",
Blizzard_BindingUI = "Blizzard: Binding",
Blizzard_Calendar = "Blizzard: Calendar",
Blizzard_CombatLog = "Blizzard: Combat Log",
Blizzard_CombatText = "Blizzard: Combat Text",
Blizzard_FeedbackUI = "Blizzard: Feedback",
Blizzard_GMSurveyUI = "Blizzard: GM Survey",
Blizzard_GlyphUI = "Blizzard: Glyph",
Blizzard_GuildBankUI = "Blizzard: GuildBank",
Blizzard_InspectUI = "Blizzard: Inspect",
Blizzard_ItemSocketingUI = "Blizzard: Item Socketing",
Blizzard_MacroUI = "Blizzard: Macro",
Blizzard_RaidUI = "Blizzard: Raid",
Blizzard_TalentUI = "Blizzard: Talent",
Blizzard_TimeManager = "Blizzard: TimeManager",
Blizzard_TokenUI = "Blizzard: Token",
Blizzard_TradeSkillUI = "Blizzard: Trade Skill",
Blizzard_TrainerUI = "Blizzard: Trainer",
Blizzard_VehicleUI = "Blizzard: Vehicle",
["Click to enable protect mode. Protected addons will not be disabled"] = "点击启用保护模式。受保护插件不会被禁用。",
Close = "关闭",
Default = "默认",
Dependencies = "依赖",
["Disable All"] = "全部禁用",
["Disabled on reloadUI"] = "重载插件后禁用",
Embeds = "内置",
["Enable All"] = "全部启用",
["Enter the new name for [%s]:"] = "输入[%s]的新名字:",
["LoD Child Enable is now %s"] = "需要时加载的子插件:%s",
Load = "加载",
["Loadable OnDemand"] = "需要时加载",
Loaded = "已加载",
["Loaded on demand."] = "需要时加载。",
["Memory Usage"] = "内存占用",
["No information available."] = "无可用信息。",
Recursive = "递归",
["Recursive Enable is now %s"] = "递归加载的插件:%s",
Reload = "重载",
["Reload your User Interface?"] = "重载插件?",
ReloadUI = "重载插件",
["Remove from current selection"] = "移除当前选择",
Rename = "重命名",
Save = "保存",
["Save the current addon list to [%s]?"] = "保存当前插件设置为[%s]",
["Set "] = "配置:",
Sets = "配置",
Status = "状态",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "使用 Shift 键无视目前的递归设定。",
Version = "版本",
["when performing a reloadui."] = "重载插件时。",
}
)
end
--@end-non-debug@

80
ACP/localization-zhTW.lua Normal file
View File

@ -0,0 +1,80 @@
if not ACP then return end
--@non-debug@
if (GetLocale() == "zhTW") then
ACP:UpdateLocale(
{
["*** Enabling <%s> %s your UI ***"] = "*** 啟用<%s>%s你的使用者介面 ***",
["*** Unknown Addon <%s> Required ***"] = "*** 需要未知的插件<%s> ***",
["ACP: Some protected addons aren't loaded. Reload now?"] = "ACP: 部分受保護的插件沒有被載入。現在重載介面?",
["Active Embeds"] = "運行中的程式集",
["Add to current selection"] = "新增到現在的選擇",
AddOns = "插件管理",
["Addon <%s> not valid"] = "無效的插件: <%s>",
["Addons [%s] Loaded."] = "插件清單[%s]已載入。",
["Addons [%s] Saved."] = "插件清單[%s]存檔完畢。",
["Addons [%s] Unloaded."] = "插件清單[%s]已卸載。",
["Addons [%s] renamed to [%s]."] = "插件清單[%s]重新命名為[%s]。",
Author = "作者",
Blizzard_AchievementUI = "Blizzard: Achievement",
Blizzard_AuctionUI = "Blizzard: Auction",
Blizzard_BarbershopUI = "Blizzard: Barbershop",
Blizzard_BattlefieldMinimap = "Blizzard: Battlefield Minimap",
Blizzard_BindingUI = "Blizzard: Binding",
Blizzard_Calendar = "Blizzard: Calendar",
Blizzard_CombatLog = "Blizzard: Combat Log",
Blizzard_CombatText = "Blizzard: Combat Text",
Blizzard_FeedbackUI = "Blizzard: Feedback",
Blizzard_GMSurveyUI = "Blizzard: GM Survey",
Blizzard_GlyphUI = "Blizzard: Glyph",
Blizzard_GuildBankUI = "Blizzard: GuildBank",
Blizzard_InspectUI = "Blizzard: Inspect",
Blizzard_ItemSocketingUI = "Blizzard: Item Socketing",
Blizzard_MacroUI = "Blizzard: Macro",
Blizzard_RaidUI = "Blizzard: Raid",
Blizzard_TalentUI = "Blizzard: Talent",
Blizzard_TimeManager = "Blizzard: TimeManager",
Blizzard_TokenUI = "Blizzard: Token",
Blizzard_TradeSkillUI = "Blizzard: Trade Skill",
Blizzard_TrainerUI = "Blizzard: Trainer",
Blizzard_VehicleUI = "Blizzard: Vehicle",
["Click to enable protect mode. Protected addons will not be disabled"] = "點擊啟用保護模式。受保護的插件",
Close = "關閉",
Default = "預設",
Dependencies = "附屬程式",
["Disable All"] = "全部停用",
["Disabled on reloadUI"] = "重載介面後停用",
Embeds = "程式集",
["Enable All"] = "全部啟用",
["Enter the new name for [%s]:"] = "替[%s]重新取名:",
["LoD Child Enable is now %s"] = "隨需求載入子插件: %s",
Load = "載入",
["Loadable OnDemand"] = "可隨需求載入",
Loaded = "已載入",
["Loaded on demand."] = "隨需求載入。",
["Memory Usage"] = "記憶體用量",
["No information available."] = "無可用的資訊。",
Recursive = "遞迴",
["Recursive Enable is now %s"] = "遞迴載入插件: %s",
Reload = "重載",
["Reload your User Interface?"] = "重載你的使用者介面?",
ReloadUI = "重載介面",
["Remove from current selection"] = "從現在的選擇中移除",
Rename = "重新命名",
Save = "存檔",
["Save the current addon list to [%s]?"] = "儲存目前的插件清單為[%s]?",
["Set "] = "設定: ",
Sets = "設定",
Status = "狀態",
["Use SHIFT to override the current enabling of dependancies behaviour."] = "使用Shift鍵無視目前的遞迴設定。",
Version = "版本",
["when performing a reloadui."] = "重載介面後不會被停用。",
}
)
end
--@end-non-debug@

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
## Interface: 30300
## Title: BonusScanner Continued |cff00aa005.3|r
## Version: 5.3
## Notes: Scans your Equipment for cumulative item bonuses and sums them up. Currently maintained and updated by Tristanian. Updated by Mirrikat45 / Arxkanite
## Notes-deDE: Durchsucht die Ausrüstung nach Gegenstandboni und zählt diese zusammen.
## Author: Tristanian (tristanian@live.com)
## SavedVariables: BonusScannerConfig
## OptionalDeps: Ace3, LibTipHooker-1.1
## Dependencies:
## X-WoWI-ID: 7919
BonusScanner.xml

View File

@ -0,0 +1,16 @@
<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="libs\LibStub\LibStub.lua"/>
<Include file="libs\LibTipHooker-1.1\lib.xml"/>
<Include file="libs\AceTimer-3.0\AceTimer-3.0.xml"/>
<Include file="libs\AceLocale-3.0\AceLocale-3.0.xml"/>
<Script file="locale\Localization.lua"/>
<Script file="locale\Localization.FR.lua"/>
<Script file="locale\Localization.DE.lua"/>
<Script file="locale\Localization.CN.lua"/>
<Script file="locale\Localization.TW.lua"/>
<Script file="locale\Localization.ES.lua"/>
<GameTooltip name="BonusScannerTooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate"/>
<Script file="BonusScanner.lua"/>
</Ui>

288
BonusScanner/Changelog.txt Normal file
View File

@ -0,0 +1,288 @@
5.3 Mirrikat45 2010.01.23
- Added Rune of the Narubian Carapace
- Corrected amount of Defense from Run of the Stoneskin Gargoyle.
5.2 Tristanian 2009.08.09
- Updated libraries.
- Updated base ratings for 3.2, in accordance with the following changes:
Dodge Rating: The amount of dodge rating required per percentage of dodge has been increased by 15%.
Parry Rating: The amount of parry rating required per percentage of parry has been reduced by 8%.
Resilience: The amount of resilience needed to reduce critical strike chance, critical strike damage and overall damage has been increased by 15%.
------------------------------------------------
5.1 Tristanian 2009.08.04
- Major update.
- Updated toc for 30200 (WoW 3.2).
- Implemented changes to facilitate a more object oriented design.
- Localized unnecessary and forgotten globals.
- Removed some redundant code.
- Properly merged the global bonus table with the frame object.
- Reduced overall memory usage.
- Totally revamped the GetGemSum method, which now properly relies on tooltip scanning, instead of static table ID matching (localization needed!).
- Updated locale independent enchants.
- Implemented itemlink caching for equipped items, to throttle down unnecessary updates fired because of UNIT_INVENTORY_CHANGED.
- Changed the LDB plugin's profile to a per character basis. Previous settings will all be reverted to defaults.
------------------------------------------------
5.0 (hotfix) Tristanian 2009.06.02
- Fixed an issue with the LDB feed not properly reporting special rating bonuses details, on the button (eg. defense, expertise).
------------------------------------------------
5.0 Tristanian 2009.05.24
- Major update.
- Added support for CUSTOM_CLASS_COLORS.
- Added Titanium Plating bonus.
- Added new pattern for Vitality.
- Added some missings gem ID's (stormjewels etc).
- Added ItemHasEnchant(itemlink) method.
- Added GetEmptySockets(itemlink) method.
- Modified the GetGemSum method to detect up to 4 gemmed sockets.
- Added detection method for engineering enchants.
- Added support for Prismatic Gems. Modified ScanEquipment method. It now returns bonuses, bonuses_details, RedGems, YellowGems, BlueGems, PrismaticGems, AverageiLevel.
- Updated LDB feed to support the latest changes.
------------------------------------------------
4.9 Tristanian 2009.04.24
- Implemented a 1 second delay when scanning a target via the /bscan target slash command to ensure gear is properly parsed and
bonuses are properly counted.
- Updated Korean and Chinese localization.
- Removed ranged slot calculation from average item level.
------------------------------------------------
4.8 Tristanian 2009.04.14
- Updated TOC to 30100 (WoW 3.1)
- Added an obscure spell power pattern found on certain items, on the new emblem rewards.
- Added Spanish localization.
- Removed Resistance to Snare and Root effects as it doesn't seem to be used anymore.
- Added a new option to the button configuration of the LDB feed, enabling the user to hide watched bonuses.
- Added some sanity checks for empty slots, to avoid calculation errors.
- Parry, Defense, Block, Dodge and Resilience Rating: Low-level players will now convert these ratings into their corresponding
defensive stats at the same rate as level 34 players.
- WoW 3.1 Armor Penetration Rating: All classes now receive 25% more benefit from Armor Penetration Rating. Corrected base rating value.
- WoW 3.1 Haste Rating: Shamans, Paladins, Druids and Death knights now receive 30% more melee haste from Haste Rating.
Implemented changes to core addon plus the LDB feed to return different melee and ranged/spell values.
------------------------------------------------
4.7 Tristanian 2009.03.15
- Fixed a bug that would sometimes prevent the bonuses of certain prismatic gems from being properly counted.
- Updated Chinese localization.
- Changed default behavior of the LDB feed to enabled.
------------------------------------------------
4.6b Tristanian 2009.02.23
- Fixed a bug with the library loading order that would prevent the configuration option for the minimap icon from being enabled
- Updated French localization
------------------------------------------------
4.6 Tristanian 2009.02.20
- Configuration initialization moved to ADDON_LOADED instead of VARIABLES_LOADED
- Implemented a load on demand LDB plugin, that provides an overview of the gear bonuses for the current player
- Added /bscan broker slash command to toggle the state of the LDB feed (enabled/disabled)
- Added LibDBIcon support for the LDB feed, for users lacking a proper display addon
------------------------------------------------
4.5 Tristanian 2009.02.09
- Added average item level to bonuses table
- Modified /bscan show and /bscan target commands to display the average item level of the relevant target
------------------------------------------------
4.4 Tristanian 2009.01.20
- Replaced instances of getglobal() with _G for efficiency.
- Added DPS values and categories for weapons
- Re-enabled German localization with a few needed updates for Wotlk (work in progress)
- Added Chinese localizations (zhCN and zhTW)
- Added support for feral AP on weapons (patch 3.0.8)
------------------------------------------------
4.3 Tristanian 2009.01.12
- Fixed "Void Star Talisman" pattern detection
- Scrapped AceLibrary and TipHooker-1.0 in favor of the Libstubbed LibTipHooker-1.1 library
- Merged gem table, implemented proper folder structure for localization
- Minor code improvements (event handling via the main module, level & class specification for scanned targets)
------------------------------------------------
4.2 Tristanian 2009.01.04
- Re-enabled "Ranged critical Rating"
- Added a significant amount of missing patterns (Hodir healing enchants, mp5 metagem effect, vitality, wisdom etc)
------------------------------------------------
4.1 Tristanian 2008.10.14
- Removed "/bs" slash command handler to avoid conflicts with other addons
- Added new rating conversion formula for levels 71-80
- Consolidated Crit/Hit/Haste Ratings and adjusted info for "Hit Rating" according to melee/spells
- Fixed proper detection for Shattered Sun crit metagem
- Fixed slash command for itemlink scanning
- Minor improvements
- Re-enabled "Ranged Hit Rating"
- Disabled auto-hooking of itemlinks. Itembasic and Itemextend commands now depend on tooltips enabled.
- Added French locale
- Added Armor Penetration Rating
- Removed OnUpdate, replaced with AceTimer-3.0 to slightly throttle spammy events
- Added initial batch of Gem Item ID's for coloring purposes
- Added patterns for new metagem bonuses
- Added Icewalker enchant
- Revamped localization, eliminated global strings, AceLocale-3.0 is used instead.
- Redundant code cleanup
------------------------------------------------
3.5 Tristanian 2008.07.25
- Fixed a bug with socket bonuses improperly detecting damage and healing values
- Replaced instances of "this" with "self" to ensure compatibility with future expansion(s)
- Fixed missing gem colors added with patch 2.4.2
- Slight improvements to the line parser for easier detection of patterns
- Tagged code for revision in preparation of "Wrath of the Lich King" expansion
------------------------------------------------
3.4a Tristanian 2008.04.07
- Commited a couple of missing de/DE enchant patterns
- Added gem color support for the new WoW 2.4 gems
------------------------------------------------
3.4 Tristanian 2008.03.31
- Updated TOC to 20400
- Implemented a few more safeguards to avoid errors on invalid itemlinks
- Updated German localization
- Fixed a bug that would make you unable to scan a "custom" target along with a proper range check
- Added a custom pattern for a shoulder enchant for EU/US locale
- Added some more gem ID's to identify coloring for some gem quest rewards due to Blizzard using different ID's
------------------------------------------------
3.3 Tristanian 2008.02.11
- Added support for some countable, secondary effects, derived from meta gems
- BonusScanner will now properly warn you when trying to manually scan an item that hasn't been validated on the server
- Added a missing critical strike rating pattern
- Minor efficiency fixes
- Fixed a bug that was preventing tooltips from being hooked properly while zoning
or switching to different frames
------------------------------------------------
3.2 Tristanian 2007.12.08
- Added Gem color count support
- Updated all relevant slash commands to support the new functionality (show, target, itemlink, slotname, etc)
- Added /bs tooltip gems command to optionally attach gem color count on tooltips
- Holding Ctrl and hovering over an itemlink will also reveal gem color count information
- Added a new option to TitanItemBonuses to display character Gem color count on the ItemBonuses tooltip
- Refined TitanItemBonuses category menu on right-click to display ratings as percentages if selected
------------------------------------------------
3.1a Tristanian 2007.11.27
- Fixed a serious bug that was preventing tooltip attachment for users with no previous savedvariables
------------------------------------------------
3.1 Tristanian 2007.11.25
- Fixed parsing for some color-coded metagems, adjusted text and translations here and there
- Defense, Resilience and Expertise ratings will now also display percentages of decreased crit chance
- You may (optionally) enable additional statistics (ItemID, GemsIDs, EnchantID, Itemlevel etc) on item tooltips
- Implemented code to display hidden spell damage bonuses for healers (work in progress)
------------------------------------------------
3.0a Tristanian 2007.11.16
- Fixed an issue with TitanItemBonuses category submenu disappearing on mouseover
------------------------------------------------
3.0 Tristanian 2007.11.15
- Major update
- Updated TOC to 20300
- Improved addon message output
- Added /bs slash command and revamped slash command help
- Improved /bs <itemlink> and /bs target to take into consideration the validity of checks
- Added Expertise rating, removed weapon ratings
- Added a pattern for healing items that also provide spell damage bonuses
- Revamped line parser to support the new separators for multi bonus enchants/gems
- Revamped passive bonus parser to support custom values for specific patterns
- Adjusted the healing bonus granted from spell damage enchants accordingly (work in progress)
- Implemented tooltip hooking support for item bonus summary (requires AceLibrary, TipHooker)
- Renamed GetRatingBonus function to BonusScanner:GetRatingBonus
- Removed dependency from TitanItemBonuses for bonus category display. BonusScanner is now completely independent.
- Implemented local item (session) cache to reduce rapid memory increase when tooltip summary is enabled
- Forced a cache reset and garbage collection every every hour to improve performance
- Removed temporary item buff detection (BonusScanner will be limited to persistent bonuses now)
- Added a few missing patterns for critical hits and spell damage
------------------------------------------------
2.11a Tristanian 2007.9.30
- Fixed Haste Rating conversions to percentages to reflect the latest change in the patch
------------------------------------------------
2.11 Tristanian 2007.9.24
- Updated TOC to 20200
- Implemented conversion of Combat Ratings to percentages/points
- Updated /bscan commands to support the rating conversion where applicable
- Updated TitanItemBonuses to support rating conversions
------------------------------------------------
2.10 Tristanian 2007.9.7
- Implemented German Localization (BonusScanner will now work with German clients again)
- Corrected a bug that was preventing certain passive effects, on multi-bonus patterns from being parsed
- Removed some redundant patterns
- Efficiency improvements here and there
------------------------------------------------
2.9a BETA Tristanian 2007.8.31
- Added German Localization (work in progress)
------------------------------------------------
2.9 Tristanian 2007.8.28
- Added a missing bonus pattern derived from Void Star Talisman
- Added a missing unarmed (fist) bonus pattern
- Removed some redundant patterns and variables
- Improved /bscan and /bscan details commands if TitanItemBonuses is loaded
- Implemented a range check for the /bscan target command
------------------------------------------------
2.8 Tristanian 2007.8.9
- Merged multi pattern separators into a single table (long overdue)
- Modifications made to generic pattern parser for future efficiency (needs testing)
- Added a missing block rating pattern
- The block value of a shield will now properly add to the total amount of block value
------------------------------------------------
2.7a Tristanian 2007.8.1
- Corrected the Demon's Blood pattern
- Added scope crit rating pattern
- Added scope ranged weapon damage pattern
- Scrapped reinforced armor detection (limited to weapons, rings, trinkets and kits) for total armor detection
from gear
------------------------------------------------
2.7 Tristanian 2007.7.25
- Corrected an issue with two-handed swords skill rating
- Corrected typos with Bow, Crossbow and Gun skill ratings that prevented the bonuses from being counted
- Added feral combat rating and two-handed axes skill rating bonus detection
- Added Surefooted pattern
- Added two generic haste enchant patterns (just in case)
------------------------------------------------
2.6b Tristanian 2007.7.14
- Added a new melee bonus called "Armor Penetration" found in T6 (warrior/rogue) item sets and weapons
------------------------------------------------
2.6a Tristanian 2007.7.8
- Added a missing mana regeneration socket bonus
------------------------------------------------
2.6 Tristanian 2007.7.1
- Added Enchant separators to localization.lua for easier reference
- Added missing fist skill rating and pattern
- Added Soulfrost, Sunfire and Savagery patterns
- Added a missing health regeneration pattern
------------------------------------------------
2.5 Tristanian 2007.6.16
- Added missing shield block rating pattern, values are added to regular block rating
- Added "Minor Speed increase and +9 Stamina" pattern, correcting overall stamina values
- Added pattern for Vitality on boots
- Refined the generic parser to support metagems with the "&" separator
- Added a couple of haste rating patterns to support Black Temple item equip bonuses (possibly more out there)
------------------------------------------------
2.4a Tristanian 2007.6.4
- Updated TOC to 20100
- Added missing weapon ratings (eg. daggers)
- Added support for Armor detection on weapons, rings and trinkets
- Added/Fixed several patterns to support BC tooltip equip bonuses
- Added Atiesh patterns
- Fixed the way several special enchants are detected (especially mana regen)
- Fixed detection of bonuses on several green and blue items "of the <type>" (basically reinstated enchantment fix)
- Modified /bscan <itemlink> to show the item link instead of the plain item name in default chat frame
- Added a new command /bscan <itemlink> <player> which will whisper bonuses to the said player
------------------------------------------------
2.3 jmlsteele 2007.02.20
-Added support for multiple bonus lines seperated by " and "
-Added support for "Socket Bonus:" (checks if you have socketed correctly)
-Fixed /bscan <itemlink> command to reflect changes to the itemlink format
-Updated English Localization file
------------------------------------------------
2.2 jmlsteele 2007.01.11
-Updated TOC to 20003
-Removed redundant code
-Re-enabled unused bonus types to fix error with ItemBonuses
-Fixed scanning of multiple, different, values/line
-Fixed scanning for Atiesh staffs
-Added weapon ratings (Axe,Mace,Sword,Bow,XBow,Gun)
-Added Resilience
-Added Weapon Damage
-Added Spell Penetration
-Added ability to scan other people
-New slash command /bscan target
-Removed enchantment fix (fixed properly by patch 2.0.3)
------------------------------------------------
2.1 jmlsteele 2006.12.21
-Fixed +healing enchants not displaying properly
-Re-enabled Feral Attack Power
-Re-enabled Undead Attack power
-Thanks to Tristanian for the above fixes
------------------------------------------------
2.0 jmlsteele 2006.12.17
-Updated codebase for TOC 20000
-Added fix to compensate for enchant colours
-Added fix for itemlink scanning
-Changed %s to ratings (hit, crit, dodge, etc...)
------------------------------------------------
1.2 Crowley 2006.11.02
- Link: http://wow.curse-gaming.com/en/files/details/1732/bonusscanner/

View File

@ -0,0 +1,128 @@
--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
-- @class file
-- @name AceLocale-3.0
-- @release $Id: AceLocale-3.0.lua 766 2009-04-04 08:26:05Z nevcairiel $
local MAJOR,MINOR = "AceLocale-3.0", 2
local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceLocale then return end -- no upgrade needed
local gameLocale = GetLocale()
if gameLocale == "enGB" then
gameLocale = "enUS"
end
AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
-- This metatable is used on all tables returned from GetLocale
local readmeta = {
__index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
rawset(self, key, key) -- only need to see the warning once, really
geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
return key
end
}
-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
local readmetasilent = {
__index = function(self, key) -- requesting totally unknown entries: return key
rawset(self, key, key) -- only need to invoke this function once
return key
end
}
-- Remember the locale table being registered right now (it gets set by :NewLocale())
-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
local registering
-- local assert false function
local assertfalse = function() assert(false) end
-- This metatable proxy is used when registering nondefault locales
local writeproxy = setmetatable({}, {
__newindex = function(self, key, value)
rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
end,
__index = assertfalse
})
-- This metatable proxy is used when registering the default locale.
-- It refuses to overwrite existing values
-- Reason 1: Allows loading locales in any order
-- Reason 2: If 2 modules have the same string, but only the first one to be
-- loaded has a translation for the current locale, the translation
-- doesn't get overwritten.
--
local writedefaultproxy = setmetatable({}, {
__newindex = function(self, key, value)
if not rawget(registering, key) then
rawset(registering, key, value == true and key or value)
end
end,
__index = assertfalse
})
--- Register a new locale (or extend an existing one) for the specified application.
-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
-- game locale.
-- @paramsig application, locale[, isDefault[, silent]]
-- @param application Unique name of addon / module
-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
-- @param silent If true, the locale will not issue warnings for missing keys. Can only be set on the default locale.
-- @usage
-- -- enUS.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
-- L["string1"] = true
--
-- -- deDE.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
-- if not L then return end
-- L["string1"] = "Zeichenkette1"
-- @return Locale Table to add localizations to, or nil if the current locale is not required.
function AceLocale:NewLocale(application, locale, isDefault, silent)
if silent and not isDefault then
error("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' can only be specified for the default locale", 2)
end
-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
-- Ammo: I still think this is a bad idea, for instance an addon that checks for some ingame string will fail, just because some other addon
-- gives the user the illusion that they can run in a different locale? Ditch this whole thing or allow a setting per 'application'. I'm of the
-- opinion to remove this.
local gameLocale = GAME_LOCALE or gameLocale
if locale ~= gameLocale and not isDefault then
return -- nop, we don't need these translations
end
local app = AceLocale.apps[application]
if not app then
app = setmetatable({}, silent and readmetasilent or readmeta)
AceLocale.apps[application] = app
AceLocale.appnames[app] = application
end
registering = app -- remember globally for writeproxy and writedefaultproxy
if isDefault then
return writedefaultproxy
end
return writeproxy
end
--- Returns localizations for the current locale (or default locale if translations are missing).
-- Errors if nothing is registered (spank developer, not just a missing translation)
-- @param application Unique name of addon / module
-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
-- @return The locale table for the current language.
function AceLocale:GetLocale(application, silent)
if not silent and not AceLocale.apps[application] then
error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
end
return AceLocale.apps[application]
end

View File

@ -0,0 +1,4 @@
<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="AceLocale-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,467 @@
--- **AceTimer-3.0** provides a central facility for registering timers.
-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered, rescheduled
-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
-- AceTimer is currently limited to firing timers at a frequency of 0.1s. This constant may change
-- in the future, but for now it seemed like a good compromise in efficiency and accuracy.
--
-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
-- need to cancel or reschedule the timer you just registered.
--
-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceTimer itself.\\
-- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceTimer.
-- @class file
-- @name AceTimer-3.0
-- @release $Id: AceTimer-3.0.lua 769 2009-04-04 11:05:08Z nevcairiel $
--[[
Basic assumptions:
* In a typical system, we do more re-scheduling per second than there are timer pulses per second
* Regardless of timer implementation, we cannot guarantee timely delivery due to FPS restriction (may be as low as 10)
This implementation:
CON: The smallest timer interval is constrained by HZ (currently 1/10s).
PRO: It will still correctly fire any timer slower than HZ over a length of time, e.g. 0.11s interval -> 90 times over 10 seconds
PRO: In lag bursts, the system simly skips missed timer intervals to decrease load
CON: Algorithms depending on a timer firing "N times per minute" will fail
PRO: (Re-)scheduling is O(1) with a VERY small constant. It's a simple linked list insertion in a hash bucket.
CAUTION: The BUCKETS constant constrains how many timers can be efficiently handled. With too many hash collisions, performance will decrease.
Major assumptions upheld:
- ALLOWS scheduling multiple timers with the same funcref/method
- ALLOWS scheduling more timers during OnUpdate processing
- ALLOWS unscheduling ANY timer (including the current running one) at any time, including during OnUpdate processing
]]
local MAJOR, MINOR = "AceTimer-3.0", 5
local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceTimer then return end -- No upgrade needed
AceTimer.hash = AceTimer.hash or {} -- Array of [0..BUCKET-1] = linked list of timers (using .next member)
-- Linked list gets around ACE-88 and ACE-90.
AceTimer.selfs = AceTimer.selfs or {} -- Array of [self]={[handle]=timerobj, [handle2]=timerobj2, ...}
AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame")
local type = type
local next = next
local pairs = pairs
local select = select
local tostring = tostring
local floor = floor
local max = max
-- Simple ONE-SHOT timer cache. Much more efficient than a full compost for our purposes.
local timerCache = nil
--[[
Timers will not be fired more often than HZ-1 times per second.
Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999)
If this is ever LOWERED, all existing timers need to be enforced to have a delay >= 1/HZ on lib upgrade.
If this number is ever changed, all entries need to be rehashed on lib upgrade.
]]
local HZ = 11
--[[
Prime for good distribution
If this number is ever changed, all entries need to be rehashed on lib upgrade.
]]
local BUCKETS = 131
local hash = AceTimer.hash
for i=1,BUCKETS do
hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes
end
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ... -- our arguments are received as unnamed values in "..." since we don't have a proper function declaration
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("ARGS", table.concat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {
__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end
})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
return Dispatchers[select('#', ...)](func, ...)
end
local lastint = floor(GetTime() * HZ)
-- --------------------------------------------------------------------
-- OnUpdate handler
--
-- traverse buckets, always chasing "now", and fire timers that have expired
local function OnUpdate()
local now = GetTime()
local nowint = floor(now * HZ)
-- Have we passed into a new hash bucket?
if nowint == lastint then return end
local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2
-- Pass through each bucket at most once
-- Happens on e.g. instance loads, but COULD happen on high local load situations also
for curint = (max(lastint, nowint - BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteration
local curbucket = (curint % BUCKETS)+1
-- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
local nexttimer = hash[curbucket]
hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
while nexttimer do
local timer = nexttimer
nexttimer = timer.next
local when = timer.when
if when < soon then
-- Call the timer func, either as a method on given object, or a straight function ref
local callback = timer.callback
if type(callback) == "string" then
safecall(timer.object[callback], timer.object, timer.arg)
elseif callback then
safecall(callback, timer.arg)
else
-- probably nilled out by CancelTimer
timer.delay = nil -- don't reschedule it
end
local delay = timer.delay -- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback
if not delay then
-- single-shot timer (or cancelled)
AceTimer.selfs[timer.object][tostring(timer)] = nil
timerCache = timer
else
-- repeating timer
local newtime = when + delay
if newtime < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
newtime = now + delay
end
timer.when = newtime
-- add next timer execution to the correct bucket
local bucket = (floor(newtime * HZ) % BUCKETS) + 1
timer.next = hash[bucket]
hash[bucket] = timer
end
else -- if when>=soon
-- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
timer.next = hash[curbucket]
hash[curbucket] = timer
end -- if when<soon ... else
end -- while nexttimer do
end -- for curint=lastint,nowint
lastint = nowint
end
-- ---------------------------------------------------------------------
-- Reg( callback, delay, arg, repeating )
--
-- callback( function or string ) - direct function ref or method name in our object for the callback
-- delay(int) - delay for the timer
-- arg(variant) - any argument to be passed to the callback function
-- repeating(boolean) - repeating timer, or oneshot
--
-- returns the handle of the timer for later processing (canceling etc)
local function Reg(self, callback, delay, arg, repeating)
if type(callback) ~= "string" and type(callback) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(callback, delay, arg): 'callback' - function or method name expected.", 3)
end
if type(callback) == "string" then
if type(self)~="table" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'self' - must be a table.", 3)
end
if type(self[callback]) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'methodName' - method not found on target object.", 3)
end
end
if delay < (1 / (HZ - 1)) then
delay = 1 / (HZ - 1)
end
-- Create and stuff timer in the correct hash bucket
local now = GetTime()
local timer = timerCache or {} -- Get new timer object (from cache if available)
timerCache = nil
timer.object = self
timer.callback = callback
timer.delay = (repeating and delay)
timer.arg = arg
timer.when = now + delay
local bucket = (floor((now+delay)*HZ) % BUCKETS) + 1
timer.next = hash[bucket]
hash[bucket] = timer
-- Insert timer in our self->handle->timer registry
local handle = tostring(timer)
local selftimers = AceTimer.selfs[self]
if not selftimers then
selftimers = {}
AceTimer.selfs[self] = selftimers
end
selftimers[handle] = timer
selftimers.__ops = (selftimers.__ops or 0) + 1
return handle
end
--- Schedule a new one-shot timer.
-- The timer will fire once in `delay` seconds, unless canceled before.
-- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds.
-- @param arg An optional argument to be passed to the callback function.
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
--
-- function MyAddon:OnEnable()
-- self:ScheduleTimer("TimerFeedback", 5)
-- end
--
-- function MyAddon:TimerFeedback()
-- print("5 seconds passed")
-- end
function AceTimer:ScheduleTimer(callback, delay, arg)
return Reg(self, callback, delay, arg)
end
--- Schedule a repeating timer.
-- The timer will fire every `delay` seconds, until canceled.
-- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds.
-- @param arg An optional argument to be passed to the callback function.
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
--
-- function MyAddon:OnEnable()
-- self.timerCount = 0
-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
-- end
--
-- function MyAddon:TimerFeedback()
-- self.timerCount = self.timerCount + 1
-- print(("%d seconds passed"):format(5 * self.timerCount))
-- -- run 30 seconds in total
-- if self.timerCount == 6 then
-- self:CancelTimer(self.testTimer)
-- end
-- end
function AceTimer:ScheduleRepeatingTimer(callback, delay, arg)
return Reg(self, callback, delay, arg, true)
end
--- Cancels a timer with the given handle, registered by the same addon object as used for `:ScheduleTimer`
-- Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid
-- and the timer has not fired yet or was canceled before.
-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @param silent If true, no error is raised if the timer handle is invalid (expired or already canceled)
-- @return True if the timer was successfully cancelled.
function AceTimer:CancelTimer(handle, silent)
if not handle then return end -- nil handle -> bail out without erroring
if type(handle) ~= "string" then
error(MAJOR..": CancelTimer(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if silent then
if timer then
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
-- The timer object is removed in the OnUpdate loop
end
return not not timer -- might return "true" even if we double-cancel. we'll live.
else
if not timer then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - no such timer registered")
return false
end
if not timer.callback then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - timer already cancelled or expired")
return false
end
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
return true
end
end
--- Cancels all timers registered to the current addon object ('self')
function AceTimer:CancelAllTimers()
if not(type(self) == "string" or type(self) == "table") then
error(MAJOR..": CancelAllTimers(): 'self' - must be a string or a table",2)
end
if self == AceTimer then
error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2)
end
local selftimers = AceTimer.selfs[self]
if selftimers then
for handle,v in pairs(selftimers) do
if type(v) == "table" then -- avoid __ops, etc
AceTimer.CancelTimer(self, handle, true)
end
end
end
end
--- Returns the time left for a timer with the given handle, registered by the current addon object ('self').
-- This function will raise a warning when the handle is invalid, but not stop execution.
-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @return The time left on the timer, or false if the handle is invalid.
function AceTimer:TimeLeft(handle)
if not handle then return end
if type(handle) ~= "string" then
error(MAJOR..": TimeLeft(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if not timer then
geterrorhandler()(MAJOR..": TimeLeft(handle): '"..tostring(handle).."' - no such timer registered")
return false
end
return timer.when - GetTime()
end
-- ---------------------------------------------------------------------
-- PLAYER_REGEN_ENABLED: Run through our .selfs[] array step by step
-- and clean it out - otherwise the table indices can grow indefinitely
-- if an addon starts and stops a lot of timers. AceBucket does this!
--
-- See ACE-94 and tests/AceTimer-3.0-ACE-94.lua
local lastCleaned = nil
local function OnEvent(this, event)
if event~="PLAYER_REGEN_ENABLED" then
return
end
-- Get the next 'self' to process
local selfs = AceTimer.selfs
local self = next(selfs, lastCleaned)
if not self then
self = next(selfs)
end
lastCleaned = self
if not self then -- should only happen if .selfs[] is empty
return
end
-- Time to clean it out?
local list = selfs[self]
if (list.__ops or 0) < 250 then -- 250 slosh indices = ~10KB wasted (max!). For one 'self'.
return
end
-- Create a new table and copy all members over
local newlist = {}
local n=0
for k,v in pairs(list) do
newlist[k] = v
n=n+1
end
newlist.__ops = 0 -- Reset operation count
-- And since we now have a count of the number of live timers, check that it's reasonable. Emit a warning if not.
if n>BUCKETS then
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(self).."' has "..n.." live timers. Surely that's not intended?")
end
selfs[self] = newlist
end
-- ---------------------------------------------------------------------
-- Embed handling
AceTimer.embeds = AceTimer.embeds or {}
local mixins = {
"ScheduleTimer", "ScheduleRepeatingTimer",
"CancelTimer", "CancelAllTimers",
"TimeLeft"
}
function AceTimer:Embed(target)
AceTimer.embeds[target] = true
for _,v in pairs(mixins) do
target[v] = AceTimer[v]
end
return target
end
-- AceTimer:OnEmbedDisable( target )
-- target (object) - target object that AceTimer is embedded in.
--
-- cancel all timers registered for the object
function AceTimer:OnEmbedDisable( target )
target:CancelAllTimers()
end
for addon in pairs(AceTimer.embeds) do
AceTimer:Embed(addon)
end
-- ---------------------------------------------------------------------
-- Debug tools (expose copies of internals to test suites)
AceTimer.debug = AceTimer.debug or {}
AceTimer.debug.HZ = HZ
AceTimer.debug.BUCKETS = BUCKETS
-- ---------------------------------------------------------------------
-- Finishing touchups
AceTimer.frame:SetScript("OnUpdate", OnUpdate)
AceTimer.frame:SetScript("OnEvent", OnEvent)
AceTimer.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
-- In theory, we should hide&show the frame based on there being timers or not.
-- However, this job is fairly expensive, and the chance that there will
-- actually be zero timers running is diminuitive to say the lest.

View File

@ -0,0 +1,4 @@
<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="AceTimer-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,30 @@
-- 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]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
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
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
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

View File

@ -0,0 +1,13 @@
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: @repository-id@
LibStub.lua

View File

@ -0,0 +1,402 @@
--[[
Name: LibTipHooker-1.1.lua
Description: A Library for hooking tooltips.
Revision: $Revision: 7 $
Author: Whitetooth
Email: hotdogee [at] gmail [dot] com
LastUpdate: $Date: 2009-08-09 17:24:10 +0000 (Sun, 09 Aug 2009) $
Website:
Documentation:
SVN: $URL $
License: LGPL v3
]]
--[[ Features
{
1. Why not use the OnTooltipSetItem script hook?
OnTooltipSetItem is bugged that it's called twice on proffesion patterns, once for the pattern and once for the item it makes.
2. Maintains support for most tooltip mods
3. Hooks dynamically created tooltips
}
--]]
--[[ Tips for using TipHooker
{
This library provides tooltip hooks, mainly for use with item tooltip modification, you can easily append or modify text in a tooltip with TipHookerLib.
If you need to not only modify the tooltip but also need to scan the tooltip for information, you should use other libraries with TipHookerLib.
Because TipHookerLib passes the real tooltip frame to your handler function,
which may already be modifided by other addons and may not be suited for scanning.
For simple custom scaning you can use GratuityLib, it creates a custom tooltip and scan that for patterns.
For a complete item scanning solution to stat scanning you can use ItemBonusLib or StatLogicLib.
}
--]]
local MAJOR = "LibTipHooker-1.1"
local MINOR = "$Revision: 7 $"
local TipHooker = LibStub:NewLibrary(MAJOR, MINOR)
if not TipHooker then return end
local VariablesLoaded
-----------
-- Tools --
-----------
local DEBUG = false
-- Localize globals
local _G = getfenv(0)
local type = type
local pairs = pairs
local select = select
local ipairs = ipairs
local strfind = strfind
local tinsert = tinsert
local hooksecurefunc = hooksecurefunc
local EnumerateFrames = EnumerateFrames
local function print(text)
if DEBUG then
DEFAULT_CHAT_FRAME:AddMessage(text)
end
end
-----------------------
-- Hook Tooltip Core --
-----------------------
local TooltipList = {
item = {
"GameTooltip",
"ItemRefTooltip",
"ShoppingTooltip",
"ComparisonTooltip",-- EquipCompare
"EQCompareTooltip",-- EQCompare
"tekKompareTooltip",-- tekKompare
"LinkWrangler",-- LinkWrangler
"LinksTooltip",-- Links
"AtlasLootTooltip",-- AtlasLoot
"ItemMagicTooltip",-- ItemMagic
"SniffTooltip",-- Sniff
"MirrorTooltip",-- Mirror
"TooltipExchange_TooltipShow",-- TooltipExchange
"AtlasQuestTooltip",-- AtlasQuest
},
buff = {
"GameTooltip",
},
spell = {
"GameTooltip",
},
talant = {
"GameTooltip",
},
unit = {
"GameTooltip",
},
action = {
"GameTooltip",
},
}
local MethodList = {
item = {
"SetHyperlink",
"SetBagItem",
"SetInventoryItem",
-- auction
"SetAuctionItem",
"SetAuctionSellItem",
-- loot
"SetLootItem",
"SetLootRollItem",
-- crafting
"SetTradeSkillItem",
"SetTrainerService",
-- mail
"SetInboxItem",
"SetSendMailItem",
-- quest log
"SetQuestItem",
"SetQuestLogItem",
-- trade
"SetTradePlayerItem",
"SetTradeTargetItem",
-- vendor tooltip
"SetMerchantItem",
"SetBuybackItem",
"SetMerchantCostItem",
-- socketing interface
"SetSocketGem",
"SetExistingSocketGem",
-- 2.1.0
"SetHyperlinkCompareItem",
-- 2.3.0
"SetGuildBankItem",
-- 3.0
"SetCurrencyToken",
"SetBackpackToken",
},
buff = {
"SetPlayerBuff",
"SetUnitBuff",
"SetUnitDebuff",
},
spell = {
"SetSpell",
"SetTrackingSpell",
"SetShapeshift",
},
talant = {
"SetTalent",
},
unit = {
"SetUnit",
},
action = {
"SetAction",
"SetPetAction",
},
}
local HandlerList = TipHooker.HandlerList or {}
TipHooker.HandlerList = HandlerList
local Set = {
item = function(tooltip, ...)
if not tooltip.GetItem then return end
local name, link = tooltip:GetItem()
if not name then return end -- Check if tooltip really has an item
for handler in pairs(HandlerList.item) do
handler(tooltip, name, link)
end
end,
buff = function(tooltip, unitId, buffIndex, raidFilter)
if not unitId then
unitId = "player"
end
for handler in pairs(HandlerList.buff) do
handler(tooltip, unitId, buffIndex, raidFilter)
end
end,
spell = function(tooltip, spellId, bookType)
for handler in pairs(HandlerList.spell) do
handler(tooltip, spellId, bookType)
end
end,
talant = function(tooltip, tabIndex, talentIndex)
for handler in pairs(HandlerList.talant) do
handler(tooltip, tabIndex, talentIndex)
end
end,
unit = function(tooltip, unit)
if not tooltip.GetUnit then return end
local name = tooltip:GetUnit()
for handler in pairs(HandlerList.unit) do
handler(tooltip, unit)
end
end,
action = function(tooltip, slot)
for handler in pairs(HandlerList.action) do
handler(tooltip, slot)
end
end,
}
-- This gets called during VARIABLES_LOADED and :Hook()
-- InitializeHook will hook all methods in MethodList[tipType]
-- from tooltips in TooltipList[tipType] to the Set[tipType] function
local Initialized = {}
local function InitializeHook(tipType)
if Initialized[tipType] then return end
-- Walk through all frames
local tooltip = EnumerateFrames()
while tooltip do
if tooltip:GetObjectType() == "GameTooltip" then
local name = tooltip:GetName()
if name then
for _, v in ipairs(TooltipList[tipType]) do
if strfind(name, v) then
--print("InitializeHook("..tipType..") = "..name)
for _, methodName in ipairs(MethodList[tipType]) do
if type(tooltip[methodName]) == "function" then
hooksecurefunc(tooltip, methodName, Set[tipType])
end
end
break
end
end
end
end
tooltip = EnumerateFrames(tooltip)
end
-- Destroy tooltip list so we don't have double hooking accidents
Initialized[tipType] = true
end
local HookedFrames = {}
local function CreateFrameHook(frameType, name, parent, inheritFrame)
if name and frameType == "GameTooltip" then
for tipType in pairs(HandlerList) do
for _, v in ipairs(TooltipList[tipType]) do
-- prevent double hooking by checking HookedFrames table
if strfind(name, v) and not HookedFrames[name] then
HookedFrames[name] = true
--print("CreateFrameHook("..tipType..") = "..name)
local tooltip = _G[name]
for _, methodName in ipairs(MethodList[tipType]) do
if type(tooltip[methodName]) == "function" then
hooksecurefunc(tooltip, methodName, Set[tipType])
end
end
break
end
end
end
end
end
------------------
-- OnEventFrame --
------------------
if TipHooker.OnEventFrame then -- Check for old frame
TipHooker.OnEventFrame:UnregisterAllEvents()
TipHooker.OnEventFrame:SetScript("OnEvent", nil)
end
local OnEventFrame = CreateFrame("Frame")
OnEventFrame:RegisterEvent("VARIABLES_LOADED")
OnEventFrame:SetScript("OnEvent", function(self, event, ...)
--print(event)
VariablesLoaded = true
--print("VariablesLoaded = true")
-- Check for exsiting hooks
for tipType in pairs(HandlerList) do
InitializeHook(tipType)
end
hooksecurefunc("CreateFrame", CreateFrameHook)
end)
TipHooker.OnEventFrame = OnEventFrame
--[[---------------------------------
{ :Hook(handler, ...)
-------------------------------------
-- Description
Hooks tooltip SetX methods with handler
-- Args
handler
func - handler func
...
string - list of tooltips that you want to hook:
"item": Items
"buff": Buff/Debuff
"spell": Spells
"talant": Talants
"unit": Units
"action": Action button
-- Examples
}
-----------------------------------]]
function TipHooker:Hook(handler, ...)
for i = 1, select('#', ...) do
local tipType = select(i, ...)
--print("TipHooker:Hook("..tipType..")")
if VariablesLoaded then
InitializeHook(tipType)
end
if not HandlerList[tipType] then
HandlerList[tipType] = {}
end
HandlerList[tipType][handler] = true
end
end
--[[---------------------------------
{ :Unhook(handler, ...)
-------------------------------------
-- Description
Unhooks handler from tooltip SetX methods
-- Args
handler
func - handler func
...
string - list of tooltips that you want to hook:
"item": Items
"buff": Buff/Debuff
"spell": Spells
"talant": Talants
"unit": Units
"action": Action button
-- Examples
}
-----------------------------------]]
function TipHooker:Unhook(handler, ...)
for i = 1, select('#', ...) do
local tipType = select(i, ...)
if HandlerList[tipType] then
HandlerList[tipType][handler] = nil
end
end
end
--[[---------------------------------
{ :IsHooked(handler, tipType)
-------------------------------------
-- Description
Check if handler is hooker
-- Args
handler
func - handler func
tipType
string - tooltip that you want to hook:
"item": Items
"buff": Buff/Debuff
"spell": Spells
"talant": Talants
"unit": Units
"action": Action button
-- Examples
}
-----------------------------------]]
function TipHooker:IsHooked(handler, tipType)
if HandlerList[tipType] then
return HandlerList[tipType][handler]
end
end
--[[---------------------------------
{ :RegisterCustomTooltip(tipType,frameName)
-------------------------------------
-- Description
Unhooks handler from tooltip SetX methods
-- Args
tipType
string - tooltip that you want to hook:
"item": Items
"buff": Buff/Debuff
"spell": Spells
"talant": Talants
"unit": Units
"action": Action button
frameName
string - name of your tooltip frame you want to be hooked
-- Examples
}
-----------------------------------]]
function TipHooker:RegisterCustomTooltip(tipType, frameName)
local tooltip = _G[frameName]
if(tooltip == nil) then
return
end
--print("InitializeHook("..tipType..") = "..frameName)
for _, methodName in ipairs(MethodList[tipType]) do
if type(tooltip[methodName]) == "function" then
hooksecurefunc(tooltip, methodName, Set[tipType])
end
end
end
--_G.TipHooker = TipHooker

View File

@ -0,0 +1,6 @@
<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="LibTipHooker-1.1.lua"/>
</Ui>

View File

@ -0,0 +1,419 @@
-- Chinese simplified translated by yeachan.
local L = LibStub("AceLocale-3.0"):NewLocale("BonusScanner","zhCN")
if not L then return end
-- bonus names
L["BONUSSCANNER_NAMES"] = {
--Base Stats
STR = "力量",
AGI = "敏捷",
STA = "耐力",
INT = "智力",
SPI = "精神",
ARMOR = "护甲",
--Resistances
ARCANERES = "奥术抗性",
FIRERES = "火焰抗性",
NATURERES = "自然抗性",
FROSTRES = "冰霜抗性",
SHADOWRES = "暗影抗性",
--Skills
FISHING = "钓鱼",
MINING = "采矿",
HERBALISM = "草药学",
SKINNING = "剥皮",
DEFENSE = "防御等级",
EXPERTISE = "精准等级",
--Abilities
BLOCK = "盾牌格挡等级",
BLOCKVALUE = "格挡值",
DODGE = "躲闪等级",
PARRY = "招架等级",
RESILIENCE = "韧性等级",
DMGWPN = "提高近战伤害",
RANGEDDMG = "远程武器伤害",
ARMORPEN = "护甲穿透等级",
-- DPS
DPSMAIN = "主武器 DPS",
DPSRANGED = "远程武器 DPS",
DPSTHROWN = "投掷武器 DPS",
--Attack Power
ATTACKPOWER = "攻击强度",
ATTACKPOWERUNDEAD = "对亡灵攻击强度",
ATTACKPOWERFERAL = "野性形态攻击强度",
RANGEDATTACKPOWER = "远程攻击强度",
--Critical
CRIT = "爆击等级",
RANGEDCRIT = "远程爆击等级",
--HOLYCRIT = "神圣爆击等级", -- Investigation
--Hit
TOHIT = "命中等级",
RANGEDHIT = "远程命中等级",
--Haste
HASTE = "急速等级",
--Spell Damage/healing
DMGUNDEAD = "对亡灵法术强度",
ARCANEDMG = "奥术伤害",
FIREDMG = "火焰伤害",
FROSTDMG = "冰霜伤害",
HOLYDMG = "神圣伤害",
NATUREDMG = "自然伤害",
SHADOWDMG = "暗影伤害",
SPELLPEN = "法术穿透",
SPELLPOW = "法术强度",
--Regen
HEALTHREG = "生命值回复",
MANAREG = "法力回复",
--Health/mana
HEALTH = "生命值",
MANA = "法力值",
--Extra bonuses
THREATREDUCTION = "% 减少威胁",
THREATINCREASE = "% 提高威胁",
INCRCRITDMG = "% 提高爆击伤害",
SPELLREFLECT = "% 法术反射",
STUNRESIST = "% 抵抗昏迷",
PERCINT = "% 提高智力",
PERCBLOCKVALUE = "% 盾牌格挡值",
-- WOTLK Metagems
PERCARMOR = "% 提高由物品获得的护甲值",
PERCMANA ="% 提高法力值",
PERCREDSPELLDMG = "% 降低受到的法术伤害",
PERCSNARE = "% 减少诱捕/缠绕时间",
PERCSILENCE = "% 减少沉默时间",
PERCFEAR = "% 减少恐惧时间",
PERCSTUN = "% 减少昏迷时间",
PERCCRITHEALING = "% 提高治疗爆击",
};
-- equip and set bonus prefixes:
--L["BONUSSCANNER_PREFIX_EQUIP"] = "装备: "; --no longer used but kept in case Blizzard decides to alter its own global string referring to this
L["BONUSSCANNER_PREFIX_SET"] = "套装:";
L["BONUSSCANNER_PREFIX_SOCKET"] = "镶孔奖励:";
L["BONUSSCANNER_WEAPON_SPEED"] = "速度";
-- translation needed !
L["BONUSCANNER_GEM_STRINGS"] = {
-- red
["matches a red socket"] = { red = 1, yellow = 0, blue = 0, prismatic = 0},
-- blue
["matches a blue socket"] = { red = 0, yellow = 0, blue = 1, prismatic = 0},
-- yellow
["matches a yellow socket"] = { red = 0, yellow = 1, blue = 0, prismatic = 0},
-- purple
["matches a red or blue socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
["matches a blue or red socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
-- green
["matches a blue or yellow socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
["matches a yellow or blue socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
-- orange
["matches a red or yellow socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
["matches a yellow or red socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
-- prismatic
["matches any socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1},
["matches a red, yellow or blue socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1}
}
-- Enchant separators
L["BONUSSCANNER_GLOBAL_SEP"] = "+";
L["BONUSSCANNER_SEPARATORS"] = { "/", "", "", "" };
-- passive bonus patterns. checked against lines which start with above prefixes
L["BONUSSCANNER_PATTERNS_PASSIVE"] = {
--Skills
{ pattern = "防御等级提高(%d+)。", effect = "DEFENSE" }, --jmlsteele
{ pattern = "韧性等级提高(%d+)。", effect = "RESILIENCE" },
{ pattern = "使你的精准等级提高(%d+)。", effect = "EXPERTISE" },
{ pattern = "钓鱼技能提高(%d+)点。", effect = "FISHING" }, -- fishing poles
-- Abilities
{ pattern = "使你的格挡等级提高(%d+)。", effect = "BLOCK" },
{ pattern = "使你的盾牌格挡等级提高(%d+)。", effect = "BLOCK" },
{ pattern = "使你的盾牌格挡值提高(%d+)点。", effect = "BLOCKVALUE" },
{ pattern = "使你的躲闪等级提高(%d+)。", effect = "DODGE" },
{ pattern = "使你的招架等级提高(%d+)。", effect = "PARRY" },
{ pattern = "%+(%d+)武器伤害。", effect = "DMGWPN" }, -- Might of Cenarius...
--Crit
{ pattern = "使你的爆击等级提高(%d+)%。", effect = "CRIT" },
{ pattern = "爆击等级提高(%d+)%。", effect = "CRIT" },
{ pattern = "提高近战爆击等级(%d+)%。", effect = "CRIT" },
{ pattern = "使你的远程攻击爆击等级提高(%d+)%。", effect = "RANGEDCRIT" },
--Damage/Heal/Spell Power
{ pattern = "法术强度提高(%d+)%点。", effect = "SPELLPOW" },
{ pattern = "使你的法术强度提高(%d+)%点。", effect = "SPELLPOW" },
{ pattern = "暗影法术强度提高(%d+)点。", effect = "SHADOWDMG" },
{ pattern = "奥术法术强度提高(%d+)点。", effect = "ARCANEDMG" },
{ pattern = "火焰法术强度提高(%d+)点。", effect = "FIREDMG" },
{ pattern = "冰霜法术强度提高(%d+)点。", effect = "FROSTDMG" },
{ pattern = "神圣法术强度提高(%d+)点。", effect = "HOLYDMG" },
{ pattern = "自然法术强度提高(%d+)点。", effect = "NATUREDMG" },
{ pattern = "略微提高法术强度。", effect = "SPELLPOW", value = 6 },
{ pattern = "对亡灵的法术强度提高(%d+)点", effect = "DMGUNDEAD" },
-- Multibonus Equip patterns
{ pattern = "使周围半径%d+码范围内的所有小队成员的法术强度提高(%d+)点。", effect = "SPELLPOW" },
{ pattern = "使你宠物的抗性提高130点并提高你的法术强度(%d+)点。", effect = "SPELLPOW" }, -- Void Star Talisman
--{ pattern = "Increases healing done by up to (%d+) and damage done by up to (%d+) for all magical spells and effects%.", effect = {"HEAL","DMG"} },
--{ pattern = "Increases your spell damage by up to (%d+) and your healing by up to (%d+)%.", effect = {"DMG","HEAL"} },
--{ pattern = "Increases healing done by magical spells and effects of all party members within %d+ yards by up to (%d+)%. ", effect = "HEAL" },
--{ pattern = "Increases damage and healing done by magical spells and effects of all party members within %d+ yards by up to (%d+)%.", effect = {"HEAL", "DMG"} },
{ pattern = "使周围半径%d+码范围内的所有小队成员每5秒恢复(%d+)点法力值。", effect = "MANAREG" },
{ pattern = "使周围半径%d+码范围内的所有小队成员的法术爆击等级提高(%d+)%。", effect = "CRIT" }, --SPELLCRIT
{ pattern = "使防御等级提高(%d+)点,暗影抗性提高(%d+)点和生命力恢复速度提高(%d+)。", effect = {"DEFENSE", "SHADOWRES", "HEALTHREG"} }, --more info needed
--Attack power
{ pattern = "攻击强度提高(%d+)点。", effect = "ATTACKPOWER" },
{ pattern = "使你的近战和远程攻击强度提高(%d+)点。", effect = {"ATTACKPOWER","RANGEDATTACKPOWER"} }, -- Andonisus, Reaper of Souls pattern
{ pattern = "+(%d+)点远程攻击强度。", effect = "RANGEDATTACKPOWER" },
{ pattern = "远程攻击强度提高(%d+)点。", effect = "RANGEDATTACKPOWER" },
{ pattern = "在猎豹、熊、巨熊和枭兽形态下的攻击强度提高(%d+)点。", effect = "ATTACKPOWERFERAL" },
{ pattern = "与亡灵作战时的攻击强度提高(%d+)点。", effect = "ATTACKPOWERUNDEAD" },
{ pattern = "与亡灵作战时的攻击强度提高(%d+)点。", effect = "ATTACKPOWERUNDEAD" },
--Regen
{ pattern = "每5秒恢复(%d+)点生命值。", effect = "HEALTHREG" },
{ pattern = "每5秒恢复(%d+)点生命值。", effect = "HEALTHREG" }, -- both versions ('per' and 'every') seem to be used
{ pattern = "每5秒恢复(%d+)点法力值。", effect = "MANAREG" },
{ pattern = "每5秒恢复(%d+)点法力值。", effect = "MANAREG" },
--Hit
{ pattern = "使你的命中等级提高(%d+)。", effect = "TOHIT" },
{ pattern = "命中等级提高(%d+)。", effect = "TOHIT" },
--Haste
{ pattern = "急速等级提高(%d+)。", effect = "HASTE" },
--Penetration
--{ pattern = "Decreases the magical resistances of your spell targets by (%d+)。", effect = "SPELLPEN" }, --no need
{ pattern = "使你的法术穿透提高(%d+)。", effect = "SPELLPEN" },
{ pattern = "使你的护甲穿透提高(%d+)。", effect = "ARMORPEN" },
{ pattern = "护甲穿透等级提高(%d+)。", effect = "ARMORPEN" }
};
-- generic patterns have the form "+xx bonus" or "bonus +xx" or even "xx bonus" with an optional % sign after the value.
-- first the generic bonus string is looked up in the following table
L["BONUSSCANNER_PATTERNS_GENERIC_LOOKUP"] = {
["所有属性"] = {"STR", "AGI", "STA", "INT", "SPI"},
--["to All Stats"] = {"STR", "AGI", "STA", "INT", "SPI"},
["力量"] = "STR",
["敏捷"] = "AGI",
["耐力"] = "STA",
["智力"] = "INT",
["精神"] = "SPI",
["所有抗性"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- obsidian items id:22195
["所有魔法抗性"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- prismatic gems
["钓鱼"] = "FISHING",
["鱼饵"] = "FISHING",
["使钓鱼技能提高"] = "FISHING", --LibStatLogic-1.1
["点钓鱼技能"] = "FISHING",
["采矿"] = "MINING",
["草药学"] = "HERBALISM",
["剥皮"] = "SKINNING",
["防御"] = "DEFENSE",
["增加防御"] = "DEFENSE", --LibStatLogic-1.1
["攻击强度"] = "ATTACKPOWER",
["与亡灵作战时的攻击强度"] = "ATTACKPOWERUNDEAD",
["与亡灵和恶魔作战时的攻击强度"] = "ATTACKPOWERUNDEAD", --deamon needed
["在猎豹、熊、巨熊和枭兽形态下的攻击强度"] = "ATTACKPOWERFERAL",
["武器伤害"] = "DMGWPN",
-- TBC/Wotlk Patterns Generic/Gems/Sockets
["法术强度"] = "SPELLPOW",
["爆击等级"] = "CRIT",
--["爆击等级"] = "CRIT",
--["爆击等级"] = "CRIT",
--["爆击等级"] = "CRIT",
["远程爆击等级"] = "RANGEDCRIT",
["法术穿透"] = "SPELLPEN",
["护甲穿透等级"] = "ARMORPEN",
["防御等级"] = "DEFENSE",
["急速等级"] = "HASTE",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["每5秒法力"] = "MANAREG",
["躲闪等级"] = "DODGE",
["招架等级"] = "PARRY",
["韧性等级"] = "RESILIENCE",
["近战伤害"] = "DMGWPN",
["精准等级"] = "EXPERTISE",
-- End TBC Patterns
["躲闪"] = "DODGE",
["格挡"] = "BLOCKVALUE",
["格挡值"] = "BLOCKVALUE",
["格挡等级"] = "BLOCK",
["盾牌格挡"] = "BLOCK",
["命中"] = "TOHIT",
["命中等级"] = "TOHIT",
["远程命中等级"] = "RANGEDHIT",
["远程攻击强度"] = "RANGEDATTACKPOWER",
["远程攻击强度"] = "RANGEDATTACKPOWER", -- Experimental for TBC
["每5秒生命值"] = "HEALTHREG",
["每5秒生命值"] = "HEALTHREG",
["治疗"] = "HEAL",
["治疗法术"] = "HEAL", --no need
["提高治疗效果"] = "HEAL", --no need
["每5秒法力"] = "MANAREG",
["法力回复"] = "MANAREG",
["爆击"] = "CRIT",
--["Critical Hit"] = "CRIT",
["生命值"] = "HEALTH",
["生命值"] = "HEALTH",
["法力值"] = "MANA",
["护甲"] = "ARMOR",
["加固"] = "ARMOR",
["韧性"] = "RESILIENCE",
-- Patterns for color coded/special lines
["威胁"] = "THREATREDUCTION", --not sure
["爆击伤害"] = "INCRCRITDMG",
["法术反射"] = "SPELLREFLECT",
["抵抗昏迷"] = "STUNRESIST",
--["Stun Resist"] = "STUNRESIST",
["赌牌格挡值"] = "PERCBLOCKVALUE",
["由物品获得的护甲值提高"] = "PERCARMOR",
["受到的法术伤害降低"] = "PERCREDSPELLDMG",
["沉默时间"] = "PERCSILENCE",
["恐惧时间"] = "PERCFEAR",
["昏迷时间"] = "PERCSTUN",
["诱捕时间"] = "PERCSNARE",
["治疗爆击效果提高"] = "PERCCRITHEALING",
};
-- next we try to match against one pattern of stage 1 and one pattern of stage 2 and concatenate the effect strings
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE1"] = {
{ pattern = "奥术", effect = "ARCANE" },
{ pattern = "火焰", effect = "FIRE" },
{ pattern = "冰霜", effect = "FROST" },
{ pattern = "神圣", effect = "HOLY" },
{ pattern = "暗影", effect = "SHADOW" },
{ pattern = "自然", effect = "NATURE" }
};
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE2"] = {
{ pattern = "抗性", effect = "RES" },
{ pattern = "伤害", effect = "DMG" },
{ pattern = "效果", effect = "DMG" }
};
-- finally if we got no match, we match against some special enchantment patterns.
L["BONUSSCANNER_PATTERNS_OTHER"] = {
-- Infused Amethyst
{ pattern = "%+(%d+) 法术强度,%+(%d+) 耐力", effect = {"SPELLPOW", "STA"} },
-- special patterns that cannot be handled any other way
{ pattern = "%+21 爆击等级,%+2%% 法力值", effect = {"CRIT", "PERCMANA"}, value = {21, 2} }, --no need
{ pattern = "%+12 爆击等级,%-10% 诱捕/缠绕时间", effect = {"CRIT", "PERCSNARE"}, value = {12, 10} },
{ pattern = "%+21 爆击等级,%-15%%诱捕/缠绕时间", effect = {"CRIT", "PERCSNARE"}, value = {21, 15} },
{ pattern = "%+14 法术强度,%+2%% 智力", effect = {"SPELLPOW", "PERCINT"}, value = {14, 2} },
{ pattern = "%+25 法术强度,%+2%% 智力", effect = {"SPELLPOW", "PERCINT"}, value = {25, 2} },
{ pattern = "%+18 耐力,%-15%% 昏迷时间", effect = {"STA", "PERCSTUN"}, value = {18, 15} },
{ pattern = "%+18 法术强度每5秒法力回复%+4", effect = {"SPELLPOW", "MANAREG"}, value = {18, 4} }, -- which gem
{ pattern = "%+24 法术强度每5秒法力回复%+6", effect = {"SPELLPOW", "MANAREG"}, value = {24, 6} },
{ pattern = "%+61 法术强度每5秒法力回复%+6", effect = {"SPELLPOW", "MANAREG"}, value = {61, 6} },
{ pattern = "%+2%% 威胁,%+10 招架等级", effect = {"THREATINCREASE","PARRY"}, value = {2 , 10} },
-- rest of custom patterns
{ pattern = "在猎豹、熊、巨熊和枭兽形态下的攻击强度提高(%d+)点。", effect = "ATTACKPOWERFERAL" },
{ pattern = "每5秒恢复(%d+)点法力值", effect = "MANAREG" },
{ pattern = "%+(%d+)护甲", effect = "ARMOR" },
{ pattern = "%+(%d+)%%威胁", effect = "THREATINCREASE" },
{ pattern = "瞄准镜%%+(%d+) 爆击等级%", effect = "CRIT" },
{ pattern = "瞄准镜%%+(%d+) 伤害%", effect = "RANGEDDMG" },
};
-- localized strings
L["BONUSSCANNER_BONUSSUM_LABEL"] = "装备加成统计";
L["BONUSSCANNER_TOOLTIP_STRING"] = "BonusScanner统计提示信息";
L["BONUSSCANNER_TOOLTIPGEMS_STRING"] = "宝石颜色统计";
L["BONUSSCANNER_BASICLINKID_STRING"] = "基础的物品链接ID";
L["BONUSSCANNER_EXTENDEDLINKID_STRING"] = "扩展的物品链接ID";
L["BONUSSCANNER_TOOLTIP_ENABLED"] = "启用";
L["BONUSSCANNER_TOOLTIP_DISABLED"] = "禁用";
L["BONUSSCANNER_IBONUS_LABEL"] = "物品加成";
L["BONUSSCANNER_NOBONUS_LABEL"] = "没有任何加成.";
L["BONUSSCANNER_CUREQ_LABEL"] = "当前装备属性加成";
L["BONUSSCANNER_CUREQDET_LABEL"] = "当前详细的装备属性加成";
L["BONUSSCANNER_OOR_LABEL"] = "超出距离.";
L["BONUSSCANNER_GEMCOUNT_LABEL"] = "数量";
L["BONUSSCANNER_INVALIDTAR_LABEL"] = "目标无法统计.";
L["BONUSSCANNER_SELTAR_LABEL"] = "请先选一个目标.";
L["BONUSSCANNER_SLOT_LABEL"] = "插槽";
L["BONUSSCANNER_FAILEDPARSE_LABEL"] = "物品未被缓存或者服务器尚未出现.";
L["BONUSSCANNER_CACHESUMMARY_LABEL"] = "BonusScanner物品缓存: ";
L["BONUSSCANNER_CACHECLEAR_LABEL"] = "BonusScanner物品缓存已清除.";
L["BONUSSCANNER_SPECIAL1_LABEL"] = " 爆击率";
L["BONUSSCANNER_SPECIAL2_LABEL"] = " 躲闪/招架";
L["BONUSSCANNER_SPECIAL3_LABEL"] = " 近战";
L["BONUSSCANNER_SPECIAL4_LABEL"] = " 法术";
L["BONUSSCANNER_SPECIAL5_LABEL"] = " 远程/法术";
L["BONUSSCANNER_ITEMID_LABEL"] = "物品 ID: |cffffffff";
L["BONUSSCANNER_ILVL_LABEL"] = "物品等级: |cffffffff";
L["BONUSSCANNER_ENCHANTID_LABEL"] = "附魔 ID: |cffffffff";
L["BONUSSCANNER_GEM1ID_LABEL"] = "宝石1 ID: |cffffffff";
L["BONUSSCANNER_GEM2ID_LABEL"] = "宝石2 ID: |cffffffff";
L["BONUSSCANNER_GEM3ID_LABEL"] = "宝石3 ID: |cffffffff";
L["BONUSSCANNER_GEMRED_LABEL"] = "";
L["BONUSSCANNER_GEMBLUE_LABEL"] = "";
L["BONUSSCANNER_GEMYELLOW_LABEL"] = "";
L["BONUSSCANNER_GEMPRISM_LABEL"] = "Prismatic";
L["BONUSSCANNER_AVERAGE_ILVL_LABEL"] = "平均物品等级";
L["BONUSSCANNER_NEEDS_RELOADUI_LABEL"] = "更改会在插件重载后生效.";
L["BONUSSCANNER_LDB_PLUGIN_LABEL"] = "BonusScanner LDB 模块 ";
--bonus categories
L["BONUSSCANNER_CAT_ATT"] = "属性";
L["BONUSSCANNER_CAT_RES"] = "抗性";
L["BONUSSCANNER_CAT_SKILL"] = "技能";
L["BONUSSCANNER_CAT_BON"] = "近战/远程攻击";
L["BONUSSCANNER_CAT_SBON"] = "法术";
L["BONUSSCANNER_CAT_OBON"] = "生命和法力值";
L["BONUSSCANNER_CAT_EBON"] = "特殊加成";
L["BONUSSCANNER_CAT_GEMS"] = "宝石插槽";
--slash command text
L["BONUSSCANNER_SLASH_STRING1"] = GREEN_FONT_COLOR_CODE.."BonusScanner 物品加成统计";
L["BONUSSCANNER_SLASH_STRING1a"] = "|cffffffff 作者 Crowley, Archarodim, jmsteele, Tristanian";
L["BONUSSCANNER_SLASH_STRING2"] = LIGHTYELLOW_FONT_COLOR_CODE.."用法: |cffffffff/bscan {show | details | tooltip | tooltip gems | itembasic | itemextend | broker | clearcache | target | target <player> | <itemlink> | <itemlink> <player> | <slotname>}";
L["BONUSSCANNER_SLASH_STRING3"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."show: |cffffffff显示当前装备的所有加成统计.";
L["BONUSSCANNER_SLASH_STRING4"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."details: |cffffffff显示详细的各类统计.";
L["BONUSSCANNER_SLASH_STRING5"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip: [";
L["BONUSSCANNER_SLASH_STRING5a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上显示加成.";
L["BONUSSCANNER_SLASH_STRING14"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip gems: [";
L["BONUSSCANNER_SLASH_STRING14a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上显示宝石颜色.";
L["BONUSSCANNER_SLASH_STRING12"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itembasic: [";
L["BONUSSCANNER_SLASH_STRING12a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上显示物品的ID和等级.";
L["BONUSSCANNER_SLASH_STRING13"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itemextend: [";
L["BONUSSCANNER_SLASH_STRING13a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上显示物品的附魔和宝石ID.";
L["BONUSSCANNER_SLASH_STRING15"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."broker: [";
L["BONUSSCANNER_SLASH_STRING15a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff 控制 LDB 插件的状态,其用来显示角色的统计信息.";
L["BONUSSCANNER_SLASH_STRING11"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."clearcache: |cffffffff清除缓存.";
L["BONUSSCANNER_SLASH_STRING6"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target: |cffffffff显示你目标的加成统计(必须在距离内).";
L["BONUSSCANNER_SLASH_STRING7"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target <player>: |cffffffff把你当前目标的加成数据密语给指定人.";
L["BONUSSCANNER_SLASH_STRING8"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink>: |cffffffff显示链接物品的加成(用Shift-Click插入链接).";
L["BONUSSCANNER_SLASH_STRING9"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink> <player>: |cffffffff把你当前链接的加成数据密语给指定人.";
L["BONUSSCANNER_SLASH_STRING10"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<slotname>: |cffffffff显示指定类别的加成统计.";

View File

@ -0,0 +1,405 @@
-- German localization for 3.3 by Tristanian (work in progress)
local L = LibStub("AceLocale-3.0"):NewLocale("BonusScanner","deDE")
if not L then return end
-- bonus names
L["BONUSSCANNER_NAMES"] = {
--Base Stats
STR = "Stärke",
AGI = "Beweglichkeit",
STA = "Ausdauer",
INT = "Intelligenz",
SPI = "Willenskraft",
ARMOR = "Rüstung",
--Resistances
ARCANERES = "Arkanwiderstand",
FIRERES = "Feuerwiderstand",
NATURERES = "Naturwiderstand",
FROSTRES = "Frostwiderstand",
SHADOWRES = "Schattenwiderstand",
--Skills
FISHING = "Angeln",
MINING = "Bergbau",
HERBALISM = "Kräuterkunde",
SKINNING = "Kürschnerei",
DEFENSE = "Verteidigungswertung",
EXPERTISE = "Waffenkundewertung",
--Abilities
BLOCK = "Blockwertung",
BLOCKVALUE = "Blockwert des Schildes",
DODGE = "Ausweichwertung",
PARRY = "Parrierwertung",
RESILIENCE = "Abhärtungswertung",
DMGWPN = "Waffenschaden",
RANGEDDMG = "Distanzschaden",
ARMORPEN = "Rüstungsdurchschlagwertung",
-- DPS
DPSMAIN = "Main Weapon(s) DPS",
DPSRANGED = "Ranged Weapon DPS",
DPSTHROWN = "Thrown Weapon DPS",
--Attack Power
ATTACKPOWER = "Angriffskraft",
ATTACKPOWERUNDEAD = "Angriffskraft gegen Untote",
ATTACKPOWERFERAL = "Angriffskraft in Tierform",
RANGEDATTACKPOWER = "Distanzangriffskraft",
--Critical
CRIT = "Kritische Trefferwertung",
RANGEDCRIT = "Krit. Schuss",
--HOLYCRIT = "Krit. Heiligzauber",
--Hit
TOHIT = "Trefferwertung",
RANGEDHIT = "Distanztrefferwertung",
--Haste
HASTE = "Tempowertung",
--Spell Damage/healing
DMGUNDEAD = "Zauberschaden gegen Untote",
ARCANEDMG = "Arkanschaden",
FIREDMG = "Feuerschaden",
FROSTDMG = "Frostschaden",
HOLYDMG = "Heiligschaden",
NATUREDMG = "Naturschaden",
SHADOWDMG = "Schattenschaden",
SPELLPEN = "Zauberdurchschlagskraft",
SPELLPOW = "Zaubermacht",
--Regen
HEALTHREG = "Lebensregeneration",
MANAREG = "Manaregeneration",
--Health/mana
HEALTH = "Lebenspunkte",
MANA = "Manapunkte",
--Extra bonuses
THREATREDUCTION = "% Verringerte Bedrohung",
THREATINCREASE = "% Erhöhte Bedrohung",
INCRCRITDMG = "% Erhöhter Kritischer Schaden",
SPELLREFLECT = "% Zauberreflexion",
STUNRESIST = "% Betäubungswiderstand",
PERCINT = "% Intelligenz",
PERCBLOCKVALUE = "% Blockwert des Schildes",
--WOTLK Metagems
PERCARMOR = "% Increased Armor Value",
PERCMANA ="% Mana",
PERCREDSPELLDMG = "% Reduced Spell Damage Taken",
PERCSNARE = "% Reduced Snare/Root Duration",
PERCSILENCE = "% Reduced Silence Duration",
PERCFEAR = "% Reduced Fear Duration",
PERCSTUN = "% Reduced Stun Duration",
PERCCRITHEALING = "% Increased Critical Healing",
};
-- equip and set bonus prefixes:
--L["BONUSSCANNER_PREFIX_EQUIP"] = "Anlegen: ";
L["BONUSSCANNER_PREFIX_SET"] = "Set: ";
L["BONUSSCANNER_PREFIX_SOCKET"] = "Sockelbonus: ";
L["BONUSSCANNER_WEAPON_SPEED"] = "Tempo";
-- translation needed !
L["BONUSCANNER_GEM_STRINGS"] = {
-- red
["matches a red socket"] = { red = 1, yellow = 0, blue = 0, prismatic = 0},
-- blue
["matches a blue socket"] = { red = 0, yellow = 0, blue = 1, prismatic = 0},
-- yellow
["matches a yellow socket"] = { red = 0, yellow = 1, blue = 0, prismatic = 0},
-- purple
["matches a red or blue socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
["matches a blue or red socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
-- green
["matches a blue or yellow socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
["matches a yellow or blue socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
-- orange
["matches a red or yellow socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
["matches a yellow or red socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
-- prismatic
["matches any socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1},
["matches a red, yellow or blue socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1}
}
-- Enchant separators
L["BONUSSCANNER_GLOBAL_SEP"] = " +";
L["BONUSSCANNER_SEPARATORS"] = { "/", " & ", " und ", ", " };
-- passive bonus patterns. checked against lines which start with above prefixes
L["BONUSSCANNER_PATTERNS_PASSIVE"] = {
--Skills
{ pattern = "Erhöht Verteidigungswertung um (%d+)%.", effect = "DEFENSE" },
{ pattern = "Erhöht die Verteidigungswertung um (%d+)%.", effect = "DEFENSE" },
{ pattern = "Erhöht Eure Abhärtungswertung um (%d+)%.", effect = "RESILIENCE" },
{ pattern = "Erhöht Eure Waffenkundewertung um (%d+)%.", effect = "EXPERTISE" },
{ pattern = "Angeln %+(%d+)%.", effect = "FISHING" },
-- Abilities
{ pattern = "Erhöht Eure Blockwertung um (%d+)%.", effect = "BLOCK" },
{ pattern = "Erhöht den Blockwert Eures Schildes um (%d+)%.", effect = "BLOCKVALUE" },
{ pattern = "Erhöht Eure Ausweichwertung um (%d+)%.", effect = "DODGE" },
{ pattern = "Erhöht Eure Parrierwertung um (%d+)%.", effect = "PARRY" },
{ pattern = "%+(%d+) Waffenschaden%.", effect = "DMGWPN" },
--Crit
{ pattern = "Erhöht Eure kritische Trefferwertung um (%d+)%.", effect = "CRIT" },
{ pattern = "Erhöht kritische Trefferwertung um (%d+)%.", effect = "CRIT" },
{ pattern = "Erhöht kritische Nahkampftrefferwertung um (%d+)%.", effect = "CRIT" },
{ pattern = "Erhöht Eure kritische Distanztrefferwertung um (%d+)%.", effect = "RANGEDCRIT" },
--Damage/Heal/Spell Power
{ pattern = "Erhöht die Zaubermacht um (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Erhöht Zaubermacht um (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Erhöht durch Arkanzauber und Arkaneffekte zugefügten Schaden um bis zu (%d+)%.", effect = "ARCANEDMG" },
{ pattern = "Erhöht durch Feuerzauber und Feuereffekte zugefügten Schaden um bis zu (%d+)%.", effect = "FIREDMG" },
{ pattern = "Erhöht durch Frostzauber und Frosteffekte zugefügten Schaden um bis zu (%d+)%.", effect = "FROSTDMG" },
{ pattern = "Erhöht durch Heiligzauber und Heiligeffekte zugefügten Schaden um bis zu (%d+)%.", effect = "HOLYDMG" },
{ pattern = "Erhöht durch Naturzauber und Natureffekte zugefügten Schaden um bis zu (%d+)%.", effect = "NATUREDMG" },
{ pattern = "Erhöht durch Schattenzauber und Schatteneffekte zugefügten Schaden um bis zu (%d+)%.", effect = "SHADOWDMG" },
{ pattern = "Erhöht den durch magische Zauber und magische Effekte zugefügten Schaden gegen Untote um bis zu (%d+)%.", effect = "DMGUNDEAD" },
-- Multibonus Equip patterns
{ pattern = "Erhöht durch sämtliche Zauber und magische Effekte verursachte Heilung um bis zu (%d+) und den verursachten Schaden um bis zu (%d+)%.", effect = {"HEAL","DMG"} },
{ pattern = "Erhöht die Widerstände Eures Begleiters um 130 und Euren Zaubermacht um bis zu (%d+)%.", effect = "SPELLPOW" }, -- Void Star Talisman
{ pattern = "Erhöht Euren Zauberschaden um bis zu (%d+) und Eure Heilung um bis zu (%d+)%.", effect = {"DMG","HEAL"} },
{ pattern = "Erhöht durch Zauber und magische Effekte verursachte Heilung aller Gruppenmitglieder, die sich im Umkreis von %d+ Metern befinden, um bis zu (%d+)%.", effect = "HEAL" },
{ pattern = "Erhöht durch Zauber und magische Effekte verursachte Schaden und Heilung aller Gruppenmitglieder, die sich im Umkreis von %d+ Metern befinden, um bis zu (%d+)%.", effect = {"HEAL", "DMG"} },
{ pattern = "Stellt alle 5 Sek. (%d+) Mana bei allen Gruppenmitgliedern, die sich im Umkreis von %d+ Metern befinden, wieder her.", effect = "MANAREG" },
{ pattern = "Erhöht die kritische Trefferwertung aller Gruppenmitglieder innerhalb von %d+ Metern um (%d+)%.", effect = "CRIT" },
{ pattern = "Verbessert Verteidigungswertung um (%d+), Schattenwiderstand um (%d+) sowie Eure normale Gesundheitsregeneration um (%d+)%.", effect = {"DEFENSE", "SHADOWRES", "HEALTHREG"} },
--Attack power
{ pattern = "Erhöht die Angriffskraft um (%d+)%.", effect = "ATTACKPOWER" },
{ pattern = "Erhöht Angriffskraft um (%d+)%.", effect = "ATTACKPOWER" },
{ pattern = "Verbessert Eure Angriffskraft um (%d+)%.", effect = "ATTACKPOWER" },
{ pattern = "Erhöht die Nahkampf- und Distanzangriffskraft um (%d+)%.", effect = {"ATTACKPOWER","RANGEDATTACKPOWER"} }, -- Andonisus, Reaper of Souls pattern
{ pattern = "+(%d+) Distanzangriffskraft.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Erhöht die Distanzangriffskraft um (%d+)%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Erhöht die Angriffskraft in Katzengestalt, Bärengestalt, Terrorbärengestalt oder Mondkingestalt um (%d+)", effect = "ATTACKPOWERFERAL" },
{ pattern = "Erhöht die Angriffskraft im Kampf gegen Untote um (%d+)%.", effect = "ATTACKPOWERUNDEAD" },
{ pattern = "Erhöht die Angriffskraft im Kampf gegen Untote um (%d+)%. Ermöglicht das Einsammeln von Geißelsteinen im Namen der Agentumdämmerung.", effect = "ATTACKPOWERUNDEAD" },
--Regen
{ pattern = "Stellt alle 5 Sek%. (%d+) Gesundheit wieder her%.", effect = "HEALTHREG" },
{ pattern = "Stellt alle 5 Sek%. (%d+) Mana wieder her%.", effect = "MANAREG" },
--Hit
{ pattern = "Erhöht Eure Trefferwertung um (%d+)%.", effect = "TOHIT" },
{ pattern = "Erhöht Trefferwertung um (%d+)%.", effect = "TOHIT" },
--Haste
{ pattern = "Erhöht Tempowertung um (%d+)%.", effect = "HASTE" },
--Penetration
{ pattern = "Reduziert die Magiewiderstände der Ziele Eurer Zauber um (%d+)%.", effect = "SPELLPEN" },
{ pattern = "Erhöht Eure Zauberdurchschlagskraft um (%d+)%.", effect = "SPELLPEN" },
{ pattern = "Eure Angriffe ignorieren (%d+) Rüstung Eures Gegners%.", effect = "ARMORPEN" },
{ pattern = "Erhöht Eure Rüstungsdurchschlagwertung um (%d+)%.", effect = "ARMORPEN" },
};
-- generic patterns have the form "+xx bonus" or "bonus +xx" or even "xx bonus" with an optional % sign after the value.
-- first the generic bonus string is looked up in the following table
L["BONUSSCANNER_PATTERNS_GENERIC_LOOKUP"] = {
["Alle Werte"] = {"STR", "AGI", "STA", "INT", "SPI"},
["Stärke"] = "STR",
["Beweglichkeit"] = "AGI",
["Ausdauer"] = "STA",
["Intelligenz"] = "INT",
["Willenskraft"] = "SPI",
["Alle Widerstandsarten"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"},
["Angeln"] = "FISHING",
["Angelköder"] = "FISHING",
["Bergbau"] = "MINING",
["Kräuterkunde"] = "HERBALISM",
["Kürschnerei"] = "SKINNING",
["Verteidigung"] = "DEFENSE",
["Verteidigungsfertigkeit"] = "DEFENSE",
["Angriffskraft"] = "ATTACKPOWER",
["Angriffskraft gegen Untote"] = "ATTACKPOWERUNDEAD",
["Angriffskraft in Katzengestalt, Bärengestalt, Terrorbärengestalt oder Mondkingestalt"] = "ATTACKPOWERFERAL",
["Waffenschaden"] = "DMGWPN",
-- TBC Patterns Generic/Gems/Sockets
["Kritische Trefferwertung"] = "CRIT",
["kritische Trefferwertung"] = "CRIT",
["Zauberdurchschlagskraft"] = "SPELLPEN",
["Verteidigungswertung"] = "DEFENSE",
["Tempowertung"] = "HASTE",
["Mana Per 5 sec"] = "MANAREG",
["mana per 5 sec"] = "MANAREG",
["Mana per 5 Sec"] = "MANAREG",
["Mana per 5 sec"] = "MANAREG",
["Mana per 5 Sek"] = "MANAREG",
["Mana alle 5 Sekunden"] = "MANAREG",
["Mana alle 5 Sek"] = "MANAREG",
["Ausweichwertung"] = "DODGE",
["Parierwertung"] = "PARRY",
["Abhärtungswertung"] = "RESILIENCE",
["Nahkampfschaden"] = "DMGWPN",
["Waffenkundewertung"] = "EXPERTISE",
-- End TBC Patterns
["Ausweichen"] = "DODGE",
["Blocken"] = "BLOCKVALUE",
["Blockwert"] = "BLOCKVALUE",
["Blockwertung"] = "BLOCK",
["Trefferchance"] = "TOHIT",
["Trefferwertung"] = "TOHIT",
["Distanzangriffskraft"] = "RANGEDATTACKPOWER",
["distanzangriffskraft"] = "RANGEDATTACKPOWER", -- Experimental for TBC
["Gesundheit alle 5 Sek"] = "HEALTHREG",
["Gesundheit in 5 Sek"] = "HEALTHREG",
["Heilung"] = "HEAL",
["Heilzauber"] = "HEAL",
["Erhöht Heilung"] = "HEAL",
["Mana Regen"] = "MANAREG",
["Manaregeneration"] = "MANAREG",
--multivalue
["Zaubermacht"] = "SPELLPOW",
--/multivalue
["Kritischer Treffer"] = "CRIT",
["Gesundheit"] = "HEALTH",
["HP"] = "HEALTH",
["GP"] = "HEALTH",
["Mana"] = "MANA",
["Rüstung"] = "ARMOR",
["Verstärkte Rüstung"] = "ARMOR",
["Abhärtung"] = "RESILIENCE",
["Distanztrefferwertung"] = "RANGEDHIT",
-- Patterns for color coded/special lines
["erhöhter kritischer Schaden"] = "INCRCRITDMG",
};
-- next we try to match against one pattern of stage 1 and one pattern of stage 2 and concatenate the effect strings
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE1"] = {
{ pattern = "Arkan", effect = "ARCANE" },
{ pattern = "Feuer", effect = "FIRE" },
{ pattern = "Frost", effect = "FROST" },
{ pattern = "Heilig", effect = "HOLY" },
{ pattern = "Schatten", effect = "SHADOW" },
{ pattern = "Natur", effect = "NATURE" }
};
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE2"] = {
{ pattern = "widerstand", effect = "RES" },
{ pattern = "schaden", effect = "DMG" },
{ pattern = "zauber", effect = "DMG" },
{ pattern = "effekte", effect = "DMG" }
};
-- finally if we got no match, we match against some special enchantment patterns.
L["BONUSSCANNER_PATTERNS_OTHER"] = {
-- mage/warlock ZG patterns
-- Aldor/Scryer enchants that cannot be handled any other way
{ pattern = "%+15 Ausweichwertung und Verteidigungswertung %+10", effect = {"DODGE", "DEFENSE"}, value = {15, 10} },
-- special patterns that cannot be handled any other way
{ pattern = "+12 Beweglichkeit und um 3%% erhöhter kritischer Schaden", effect = {"AGI","INCRCRITDMG"}, value = {12, 3} },
{ pattern = "+21 Beweglichkeit und um 3%% erhöhter kritischer Schaden", effect = {"AGI","INCRCRITDMG"}, value = {21, 3} },
{ pattern = "+12 Kritische Trefferwertung und um 3%% erhöhter kritischer Schaden", effect = {"CRIT", "INCRCRITDMG"}, value = {12, 3} },
{ pattern = "+21 Kritische Trefferwertung und um 3%% erhöhter kritischer Schaden", effect = {"CRIT", "INCRCRITDMG"}, value = {21, 3} },
{ pattern = "+14 Kritische Trefferwertung und 1%% Zauberreflexion", effect = {"CRIT", "SPELLREFLECT"}, value = {14, 1} },
{ pattern = "+14 Zauberschaden und 5%% Betäubungswiderstand", effect = {"DMG", "STUNRESIST"}, value = {14, 5} },
{ pattern = "+24 Angriffskraft und 5%% Betäubungswiderstand", effect = {"ATTACKPOWER", "STUNRESIST"}, value = {24, 5} },
{ pattern = "+18 Ausdauer und 5%% Betäubungswiderstand", effect = {"STA", "STUNRESIST"}, value = {18, 5} },
{ pattern = "%+14 Zaubermacht und %+2%% Intelligenz", effect = {"SPELLPOW", "PERCINT"}, value = {14, 2} },
{ pattern = "%+12 Verteidigungswertung und %+10%% Blockwert des Schildes", effect = {"DEFENSE", "PERCBLOCKVALUE"}, value = {12, 10} },
--rest of custom patterns
{ pattern = "Erhöht die Angriffskraft um (%d+) nur in Katzen%-, Bären%-, Terrorbären%- und Mondkingestalt%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Manaregeneration (%d+) pro 5 Sek", effect = "MANAREG" },
{ pattern = "Manaregeneration (%d+) per 5 Sek", effect = "MANAREG" },
{ pattern = "alle 5 Sek%. (%d+) Mana", effect = "MANAREG" },
{ pattern = "Alle 5 Sek%. (%d+) Mana", effect = "MANAREG" },
{ pattern = "Verstärkt %(%+(%d+) Rüstung%)", effect = "ARMOR" },
{ pattern = "%+(%d+)%% Bedrohung", effect = "THREATINCREASE" },
{ pattern = "Zielfernrohr %(%+(%d+) Schaden%)", effect = "RANGEDDMG" },
};
-- localized strings
L["BONUSSCANNER_BONUSSUM_LABEL"] = "Item Bonus Zusammenfassung";
L["BONUSSCANNER_TOOLTIP_STRING"] = "BonusScanner Tooltip Bonus Zusammenfassung ";
L["BONUSSCANNER_TOOLTIPGEMS_STRING"] = "Edelsteinfarben ";
L["BONUSSCANNER_BASICLINKID_STRING"] = "Basis Itemlink ID's ";
L["BONUSSCANNER_EXTENDEDLINKID_STRING"] = "Erweiterte Itemlink ID's "; -- SENSITY
L["BONUSSCANNER_TOOLTIP_ENABLED"] = "Aktiviert";
L["BONUSSCANNER_TOOLTIP_DISABLED"] = "Deaktiviert";
L["BONUSSCANNER_IBONUS_LABEL"] = "Boni für ";
L["BONUSSCANNER_NOBONUS_LABEL"] = "Keine Boni.";
L["BONUSSCANNER_CUREQ_LABEL"] = "Derzeitige Ausrüstungs-Boni";
L["BONUSSCANNER_CUREQDET_LABEL"] = "Derzeitige Ausrüstungs-Boni Details";
L["BONUSSCANNER_OOR_LABEL"] = " ist ausserhalb der Reichweite."; -- SENSITY
L["BONUSSCANNER_GEMCOUNT_LABEL"] = "Gelten als ";
L["BONUSSCANNER_INVALIDTAR_LABEL"] ="Ungültiges Ziel zum Scannen."; -- SENSITY
L["BONUSSCANNER_SELTAR_LABEL"] = "Wählen Sie bitte zuerst ein Ziel."; -- SENSITY
L["BONUSSCANNER_SLOT_LABEL"] = "slot";
L["BONUSSCANNER_FAILEDPARSE_LABEL"] = "Gegenstand ist nicht gespeichert oder konnte nicht auf dem Server verglichen werden."; -- SENSITY
L["BONUSSCANNER_CACHESUMMARY_LABEL"] = "gespeicherte Bonusscanner-Items: "; -- SENSITY
L["BONUSSCANNER_CACHECLEAR_LABEL"] = "Bonusscanner-Itemcache gelöscht."; -- SENSITY
L["BONUSSCANNER_SPECIAL1_LABEL"] = " kritische Trefferchance"; -- SENSITY
L["BONUSSCANNER_SPECIAL2_LABEL"] = " ausgewichen/abgewehrt";
L["BONUSSCANNER_SPECIAL3_LABEL"] = " melee";
L["BONUSSCANNER_SPECIAL4_LABEL"] = " spells";
L["BONUSSCANNER_SPECIAL5_LABEL"] = " ranged/spells";
L["BONUSSCANNER_ITEMID_LABEL"] = "Gegenstands-ID: |cffffffff";
L["BONUSSCANNER_ILVL_LABEL"] = "Gegenstandslevel: |cffffffff";
L["BONUSSCANNER_ENCHANTID_LABEL"] = "Verzauberungs-ID: |cffffffff";
L["BONUSSCANNER_GEM1ID_LABEL"] = "Edelstein1 ID: |cffffffff";
L["BONUSSCANNER_GEM2ID_LABEL"] = "Edelstein2 ID: |cffffffff";
L["BONUSSCANNER_GEM3ID_LABEL"] = "Edelstein3 ID: |cffffffff";
L["BONUSSCANNER_GEMRED_LABEL"] = "Rot";
L["BONUSSCANNER_GEMBLUE_LABEL"] = "Blau";
L["BONUSSCANNER_GEMYELLOW_LABEL"] = "Gelb";
L["BONUSSCANNER_GEMPRISM_LABEL"] = "Prismatic";
L["BONUSSCANNER_AVERAGE_ILVL_LABEL"] = "Average item Level";
L["BONUSSCANNER_NEEDS_RELOADUI_LABEL"] = "Changes will take effect after the UI has been reloaded.";
L["BONUSSCANNER_LDB_PLUGIN_LABEL"] = "BonusScanner LDB Plugin ";
--bonus categories
L["BONUSSCANNER_CAT_ATT"] = "Attribute";
L["BONUSSCANNER_CAT_RES"] = "Widerstand";
L["BONUSSCANNER_CAT_SKILL"] = "Fertigkeiten";
L["BONUSSCANNER_CAT_BON"] = "Nah- und Fernkampf";
L["BONUSSCANNER_CAT_SBON"] = "Zauber";
L["BONUSSCANNER_CAT_OBON"] = "Leben und Mana";
L["BONUSSCANNER_CAT_EBON"] = "Spezielle Fähigkeiten";
L["BONUSSCANNER_CAT_GEMS"] = "Edelsteine";
--slash command text
L["BONUSSCANNER_SLASH_STRING1"] = GREEN_FONT_COLOR_CODE.."BonusScanner ";
L["BONUSSCANNER_SLASH_STRING1a"] = "|cffffffff by Crowley, Archarodim, jmsteele, Tristanian";
L["BONUSSCANNER_SLASH_STRING2"] = LIGHTYELLOW_FONT_COLOR_CODE.."Usage: |cffffffff/bs {show | details | tooltip | tooltip gems | itembasic | itemextend | broker | clearcache | target | target <player> | <itemlink> | <itemlink> <player> | <slotname>}";
L["BONUSSCANNER_SLASH_STRING3"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."show: |cffffffffZeige alle Boni der aktuellen Ausrüstung.";
L["BONUSSCANNER_SLASH_STRING4"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."details: |cffffffffZeige Boni nach Slot-Verteilung.";
L["BONUSSCANNER_SLASH_STRING5"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip: [";
L["BONUSSCANNER_SLASH_STRING5a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffErgänzt Tooltip mit Item-Zusammenfassung."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING14"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip gems: [";
L["BONUSSCANNER_SLASH_STRING14a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffErgänzt Tooltip mit Edelsteinfarben (erfordert aktivierte Tooltips)."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING12"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itembasic: [";
L["BONUSSCANNER_SLASH_STRING12a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffErgänzt Tooltip mit Gegenstandslevel und -ID."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING13"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itemextend: [";
L["BONUSSCANNER_SLASH_STRING13a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffErgänzt Tooltip mit Verzauberungs- u. Edelstein-ID."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING15"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."broker: [";
L["BONUSSCANNER_SLASH_STRING15a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffToggles the state of the LDB plugin, used to display gear bonuses for the current character.";
L["BONUSSCANNER_SLASH_STRING11"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."clearcache: |cffffffffLöscht den Item-Cache."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING6"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target: |cffffffffZeige Boni der Ausrüstung eines anderen Spielers.";
L["BONUSSCANNER_SLASH_STRING7"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target <player>: |cffffffffSendet Ausrüstungsboni des Ziels (muss in Reichweite sein) an einen ausgewählten Spieler."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING8"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink>: |cffffffffZeige Boni eines gelinkten Gegenstands."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING9"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink> <player>: |cffffffffSendet Gegenstandsboni an einen ausgewählten Spieler."; -- SENSITY
L["BONUSSCANNER_SLASH_STRING10"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<slotname>: |cffffffffZeige Boni für bestimten Slot.";

View File

@ -0,0 +1,402 @@
local L = LibStub("AceLocale-3.0"):NewLocale("BonusScanner","esES")
if not L then return end
-- bonus names
L["BONUSSCANNER_NAMES"] = {
--Base Stats
STR = "Fuerza",
AGI = "Agilidad",
STA = "Aguante",
INT = "Intelecto",
SPI = "Espíritu",
ARMOR = "Armadura",
--Resistances
ARCANERES = "Resistencia a lo Arcano",
FIRERES = "Resistencia al Fuego",
NATURERES = "Resistencia a la Naturaleza",
FROSTRES = "Resistencia a la Escarcha",
SHADOWRES = "Resistencia a las Sombras",
--Skills
FISHING = "Pesca",
MINING = "Minería",
HERBALISM = "Herboristería",
SKINNING = "Desuello",
DEFENSE = "Índice de Defensa",
EXPERTISE = "Índice de Pericia",
--Abilities
BLOCK = "Índice de Bloqueo",
BLOCKVALUE = "Valor de Bloqueo",
DODGE = "Índice de Esquivar",
PARRY = "Índice de Parar",
RESILIENCE = "Índice de Temple",
DMGWPN = "Daño cuerpo a cuerpo incrementado",
RANGEDDMG = "Daño a distancia incrementado",
ARMORPEN = "Índice de Penetración de armadura",
-- DPS
DPSMAIN = "DPS Arma principal",
DPSRANGED = "DPS Arma a distancia",
DPSTHROWN = "DPS Arma arrojadiza",
--Attack Power
ATTACKPOWER = "Poder de ataque",
ATTACKPOWERUNDEAD = "Poder de ataque contra No-muertos",
ATTACKPOWERFERAL = "Poder de ataque en forma feral",
RANGEDATTACKPOWER = "Poder de ataque a distancia",
--Critical
CRIT = "Índice de golpe crítico",
RANGEDCRIT = "Índice de golpe crítico a distancia",
--Hit
TOHIT = "Índice de Golpe",
RANGEDHIT = "Índice de Golpe a distancia",
--Haste
HASTE = "Índice de Celeridad",
--Spell Damage/healing
DMGUNDEAD = "Daño de Hechizos contra No-muertos",
ARCANEDMG = "Daño Arcano",
FIREDMG = "Daño de Fuego",
FROSTDMG = "Daño de Escarcha",
HOLYDMG = "Daño Sagrado",
NATUREDMG = "Daño de Naturaleza",
SHADOWDMG = "Daño de Sombras",
SPELLPEN = "Penetración de Hechizos",
SPELLPOW = "Poder con hechizos",
--Regen
HEALTHREG = "Regeneración de Vida",
MANAREG = "Regeneración de Maná",
--Health/mana
HEALTH = "Puntos de Vida",
MANA = "Puntos de Maná",
--Extra bonuses
THREATREDUCTION = "% Reducción de Amenaza",
THREATINCREASE = "% Incremento de Amenaza",
INCRCRITDMG = "% Incremento de Daño Crítico",
SPELLREFLECT = "% Reflejo de Hechizos",
STUNRESIST = "% Resistencia a Aturdir",
PERCINT = "% Intelecto",
PERCBLOCKVALUE = "% Valor de Bloqueo con Escudo",
-- WOTLK Metagems
PERCARMOR = "% Incremento de Valor de Armadura",
PERCMANA ="% Maná",
PERCREDSPELLDMG = "% Reducción de Daño de Hechizos recibido",
PERCSNARE = "% Reducción de la duración de Enraizar/Aturdir",
PERCSILENCE = "% Reducción de la duración de Silenciar",
PERCFEAR = "% Reducción de la duración de Miedo",
PERCSTUN = "% Reducción de la duración de Aturdir",
PERCCRITHEALING = "% Incremento de Curación crítica",
};
-- equip and set bonus prefixes:
--L["BONUSSCANNER_PREFIX_EQUIP"] = "Equipar: "; --no longer used but kept in case Blizzard decides to alter its own global string referring to this
L["BONUSSCANNER_PREFIX_SET"] = "Conjunto: ";
L["BONUSSCANNER_PREFIX_SOCKET"] = "Bonus ranura: ";
L["BONUSSCANNER_WEAPON_SPEED"] = "Speed";
L["BONUSCANNER_GEM_STRINGS"] = {
-- red
["Encaja en una ranura de color rojo."] = { red = 1, yellow = 0, blue = 0, prismatic = 0},
-- blue
["Encaja en una ranura de color azul."] = { red = 0, yellow = 0, blue = 1, prismatic = 0},
-- yellow
["Encaja en una ranura de color amarillo."] = { red = 0, yellow = 1, blue = 0, prismatic = 0},
-- purple
["Encaja en una ranura de color rojo o azul."] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
["Encaja en una ranura de color azul o rojo."] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
-- green
["Encaja en una ranura de color azul o amarillo."] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
["Encaja en una ranura de color amarillo o azul."] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
-- orange
["Encaja en una ranura de color rojo o amarillo."] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
["Encaja en una ranura de color amarillo o rojo."] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
-- prismatic
["Encaja en cualquier ranura."] = { red = 0, yellow = 0, blue = 0, prismatic = 1},
["Encaja en una ranura de color rojo, amarillo o azul."] = { red = 0, yellow = 0, blue = 0, prismatic = 1}
}
-- Enchant separators
L["BONUSSCANNER_GLOBAL_SEP"] = " +";
L["BONUSSCANNER_SEPARATORS"] = { "/", ", ", " & ", " y " };
-- passive bonus patterns. checked against lines which start with above prefixes
L["BONUSSCANNER_PATTERNS_PASSIVE"] = {
--Skills
{ pattern = "+(%d+)% p. de armadura%)", effect = "ARMOR" },
{ pattern = "+(%d+)% p. de índice de temple", effect = "RESILIENCE" },
{ pattern = "Aumenta tu índice de defensa (%d+)% p.", effect = "DEFENSE" },
{ pattern = "Aumenta tu índice de pericia (%d+)% p.", effect = "EXPERTISE" },
{ pattern = "Aumenta tu índice de temple (%d+)% p.", effect = "RESILIENCE" },
{ pattern = "Pesca aumentada %+(%d+)% p.", effect = "FISHING" },
-- Abilities
{ pattern = "%+(%d+) daño de arma", effect = "DMGWPN" },
{ pattern = "Aumenta tu índice de bloqueo (%d+)% p.", effect = "BLOCK" },
{ pattern = "Aumenta tu índice de esquivar (%d+)% p.", effect = "DODGE" },
{ pattern = "Aumenta tu índice de parada (%d+)% p.", effect = "PARRY" },
{ pattern = "Aumenta el valor de bloqueo de tu escudo (%d+)% p.", effect = "BLOCKVALUE" },
{ pattern = "Aumenta tu índice de bloqueo con escudo (%d+)% p.", effect = "BLOCKVALUE" },
--Crit
{ pattern = "Mejora tu índice de golpe crítico (%d+)% p.", effect = "CRIT" },
{ pattern = "Mejora tu índice de golpe crítico a distancia (%d+)% p.", effect = "RANGEDCRIT" },
--Damage/Heal/Spell Power
{ pattern = "Aumenta el poder con hechizos (%d+)% p.", effect = "SPELLPOW" },
{ pattern = "Increases spell power by (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases your spell power by (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases shadow spell power by (%d+)%.", effect = "SHADOWDMG" },
{ pattern = "Increases arcane spell power by (%d+)%.", effect = "ARCANEDMG" },
{ pattern = "Increases fire spell power by (%d+)%.", effect = "FIREDMG" },
{ pattern = "Increases frost spell power by (%d+)%.", effect = "FROSTDMG" },
{ pattern = "Increases holy spell power by (%d+)%.", effect = "HOLYDMG" },
{ pattern = "Increases nature spell power by (%d+)%.", effect = "NATUREDMG" },
{ pattern = "Increases spell power slightly%.", effect = "SPELLPOW", value = 6 },
{ pattern = "Increases damage done to Undead by magical spells and effects by up to (%d+)", effect = "DMGUNDEAD" },
-- Multibonus Equip patterns
{ pattern = "(%d+) aguante y reducción de duración de aturdir un (%d+)%", effect = {"STA","PERCSTUN"} },
{ pattern = "(%d+) resistencia a las sombras y (%d+) aguante", effect = {"SHADOWRES","STA"} },
{ pattern = "Increases spell power of all party members within %d+ yards by up to (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases your pet's resistances by 130 and increases your spell power by (%d+)%.", effect = "SPELLPOW" }, -- Void Star Talisman
{ pattern = "Restores (%d+) mana per 5 seconds to all party members within %d+ yards%.", effect = "MANAREG" },
{ pattern = "Increases the spell critical strike rating of all party members within %d+ yards by (%d+)%.", effect = "CRIT" }, --SPELLCRIT
{ pattern = "Increases defense rating by (%d+), Shadow resistance by (%d+) and your normal health regeneration by (%d+)%.", effect = {"DEFENSE", "SHADOWRES", "HEALTHREG"} },
--Attack power
{ pattern = "Aumenta el poder de ataque (%d+) p.", effect = "ATTACKPOWER" },
{ pattern = "Aumenta tu poder de ataque (%d+) p.", effect = "ATTACKPOWER" },
{ pattern = "Increases melee and ranged attack power by (%d+)%.", effect = {"ATTACKPOWER","RANGEDATTACKPOWER"} },
{ pattern = "+(%d+) ranged Attack Power%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Increases ranged attack power by (%d+)%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Increases attack power by (%d+) in Cat, Bear, Dire Bear, and Moonkin forms only%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Increases attack power by (%d+) when fighting Undead%.", effect = "ATTACKPOWERUNDEAD" },
{ pattern = "+(%d+) Attack Power when fighting Undead%.", effect = "ATTACKPOWERUNDEAD" },
--Regen
{ pattern = "Restaura (%d+)% p. de maná cada 5 s.", effect = "MANAREG" },
{ pattern = "Restaura (%d+)% p. de maná cada 9 s.", effect = "MANAREG" },
{ pattern = "Restaura (%d+)% p. de maná cada 16 s.", effect = "MANAREG" },
{ pattern = "Restaura (%d+)% p. de salud cada 5 s.", effect = "HEALTHREG" },
--Hit
{ pattern = "Mejora tu índice de golpe (%d+)% p.", effect = "TOHIT" },
--Haste
{ pattern = "Mejora tu índice de celeridad (%d+)% p.", effect = "HASTE" },
--Penetration
{ pattern = "Aumenta tu índice de penetración de armadura (%d+)% p.", effect = "ARMORPEN" },
{ pattern = "Aumenta el índice de penetración de armadura (%d+)% p.", effect = "ARMORPEN" },
{ pattern = "Decreases the magical resistances of your spell targets by (%d+).", effect = "SPELLPEN" },
{ pattern = "Increases your spell penetration by (%d+)%.", effect = "SPELLPEN" },
};
-- generic patterns have the form "+xx bonus" or "bonus +xx" or even "xx bonus" with an optional % sign after the value.
-- first the generic bonus string is looked up in the following table
L["BONUSSCANNER_PATTERNS_GENERIC_LOOKUP"] = {
["todas las estadísticas"] = {"STR", "AGI", "STA", "INT", "SPI"},
["agilidad"] = "AGI",
["Agilidad"] = "AGI",
["aguante"] = "STA",
["Aguante"] = "STA",
["espíritu"] = "SPI",
["Espíritu"] = "SPI",
["fuerza"] = "STR",
["Fuerza"] = "STR",
["intelecto"] = "INT",
["Intelecto"] = "INT",
["todas las resistencias"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- obsidian items
["Defensa"] = "DEFENSE",
["defensa"] = "DEFENSE",
["Defensa aumentada"] = "DEFENSE",
["Desuello"] = "SKINNING",
["Herboristería"] = "HERBALISM",
["Minería"] = "MINING",
["pesca"] = "FISHING",
["Pesca"] = "FISHING",
["Pesca aumentada"] = "FISHING",
["daño de arma"] = "DMGWPN",
["poder de ataque"] = "ATTACKPOWER",
["Attack Power when fighting Undead"] = "ATTACKPOWERUNDEAD",
["Attack Power in Cat, Bear, Dire Bear, and Moonkin forms only"] = "ATTACKPOWERFERAL",
-- TBC/Wotlk Patterns Generic/Gems/Sockets
["golpe crítico a distancia"] = "RANGEDCRIT",
["índice de celeridad"] = "HASTE",
["índice de defensa"] = "DEFENSE",
["índice de esquivar"] = "DODGE",
["índice de golpe crítico"] = "CRIT",
["índice de parada"] = "PARRY",
["índice de penetración de armadura"] = "ARMORPEN",
["índice de pericia"] = "EXPERTISE",
["índice de temple"] = "RESILIENCE",
["maná cada 5 s."] = "MANAREG",
["maná por 5 s."] = "MANAREG",
["penetración del hechizo"] = "SPELLPEN",
["poder con hechizos"] = "SPELLPOW",
["Melee Damage"] = "DMGWPN",
-- End TBC Patterns
["amenaza"] = "THREATINCREASE",
["armadura"] = "ARMOR",
["HP"] = "HEALTH",
["índice de bloqueo"] = "BLOCK",
["índice de golpe"] = "TOHIT",
["Reforzado"] = "ARMOR",
["salud"] = "HEALTH",
["Temple"] = "RESILIENCE",
["Dodge"] = "DODGE",
["Block"] = "BLOCKVALUE",
["Hit Rating"] = "TOHIT",
["Ranged Hit Rating"] = "RANGEDHIT",
["Ranged Attack Power"] = "RANGEDATTACKPOWER",
["Health per 5 sec"] = "HEALTHREG",
["Healing"] = "HEAL",
["Healing Spells"] = "HEAL",
["Increased Healing"] = "HEAL",
["Mana"] = "MANA",
["mana every 5 sec"] = "MANAREG",
-- Patterns for color coded/special lines
["de daño crítico aumentado"] = "INCRCRITDMG",
["reducción de duración de aturdir un"] = "PERCSTUN",
["valor de bloqueo de escudo"] = "PERCBLOCKVALUE",
["Reduced Threat"] = "THREATREDUCTION",
["Spell Reflect"] = "SPELLREFLECT",
["Stun Resistance"] = "STUNRESIST",
["Stun Resist"] = "STUNRESIST",
["Increased Armor Value from Items"] = "PERCARMOR",
["Reduce Spell Damage Taken by"] = "PERCREDSPELLDMG",
["Silence Duration Reduced by"] = "PERCSILENCE",
["Fear Duration Reduced by"] = "PERCFEAR",
["Root Duration by"] = "PERCSNARE",
["Increased Critical Healing Effect"] = "PERCCRITHEALING",
};
-- next we try to match against one pattern of stage 1 and one pattern of stage 2 and concatenate the effect strings
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE1"] = {
{ pattern = "Arcano", effect = "ARCANE" },
{ pattern = "Escarcha", effect = "FROST" },
{ pattern = "Fuego", effect = "FIRE" },
{ pattern = "Naturaleza", effect = "NATURE" },
{ pattern = "Sagrado", effect = "HOLY" },
{ pattern = "Sombras", effect = "SHADOW" }
};
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE2"] = {
{ pattern = "resistencia", effect = "RES" },
{ pattern = "daño", effect = "DMG" },
{ pattern = "Effects", effect = "DMG" }
};
-- finally if we got no match, we match against some special enchantment patterns.
L["BONUSSCANNER_PATTERNS_OTHER"] = {
-- Infused Amethyst
{ pattern = "Spell Power %+(%d+) and Stamina %+(%d+)", effect = {"SPELLPOW", "STA"} },
-- special patterns that cannot be handled any other way
{ pattern = "%+14 poder con hechizos y %+2%% intelecto", effect = {"SPELLPOW", "PERCINT"}, value = {14, 2} },
{ pattern = "%+25 poder con hechizos y %+2%% intelecto", effect = {"SPELLPOW", "PERCINT"}, value = {25, 2} },
{ pattern = "%+21 Critical Strike Rating and %+2%% Mana", effect = {"CRIT", "PERCMANA"}, value = {21, 2} },
{ pattern = "%+12 Critical Strike Rating and Reduces Snare/Root Duration by 15%%", effect = {"CRIT", "PERCSNARE"}, value = {12, 15} },
{ pattern = "%+21 Critical Strike Rating and Reduces Snare/Root Duration by 15%%", effect = {"CRIT", "PERCSNARE"}, value = {21, 15} },
{ pattern = "%+18 Stamina and Stun Duration Reduced by 15%% Stun Resist", effect = {"STA", "PERCSTUN"}, value = {18, 15} },
{ pattern = "%+18 Spell Power and %+4 Mana/5 seconds", effect = {"SPELLPOW", "MANAREG"}, value = {18, 4} },
{ pattern = "%+24 Spell Power and %+6 Mana/5 seconds", effect = {"SPELLPOW", "MANAREG"}, value = {24, 6} },
{ pattern = "%+61 Spell Power and %+6 Mana/5 seconds", effect = {"SPELLPOW", "MANAREG"}, value = {61, 6} },
{ pattern = "%+(%d+)%% amenaza y (%d+) índice de parada", effect = {"THREATINCREASE","PARRY"} },
-- rest of custom patterns
{ pattern = "%+(%d+) aguante y aumenta (%d+)%% de valor de armadura de objetos", effect = {"STA", "PERCARMOR"} },
{ pattern = "%+(%d+) índice de defensa %+(%d+)%% valor de bloqueo de escudo", effect = {"DEFENSE", "PERCBLOCKVALUE"} },
{ pattern = "Sigilo y agilidad aumentados en (%d+) p.", effect = "AGI" },
{ pattern = "Afilado (%+(%d+) daño)", effect = "DMGWPN" },
{ pattern = "Reforzado %(%+(%d+) armadura%)", effect = "ARMOR" },
{ pattern = "Increases attack power by (%d+) in Cat, Bear, Dire Bear, and Moonkin forms only%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Mana Regen (%d+) per 5 sec", effect = "MANAREG" },
{ pattern = "%+(%d+)%% Threat", effect = "THREATINCREASE" },
{ pattern = "Scope %(%+(%d+) Critical Strike Rating%)", effect = "CRIT" },
{ pattern = "Scope %(%+(%d+) Damage%)", effect = "RANGEDDMG" },
};
-- localized strings
L["BONUSSCANNER_BONUSSUM_LABEL"] = "Resumen de mejoras de objetos";
L["BONUSSCANNER_TOOLTIP_STRING"] = "Tooltip resumen de mejoras de BonusScanner";
L["BONUSSCANNER_TOOLTIPGEMS_STRING"] = "Número de gemas ";
L["BONUSSCANNER_BASICLINKID_STRING"] = "IDs Itemlink básicos ";
L["BONUSSCANNER_EXTENDEDLINKID_STRING"] = "IDs Itemlink extendidos ";
L["BONUSSCANNER_TOOLTIP_ENABLED"] = "Activado";
L["BONUSSCANNER_TOOLTIP_DISABLED"] = "Desactivado";
L["BONUSSCANNER_IBONUS_LABEL"] = "Mejoras de objetos ";
L["BONUSSCANNER_NOBONUS_LABEL"] = "No se han detectado Mejoras.";
L["BONUSSCANNER_CUREQ_LABEL"] = "Mejoras del equipo actual";
L["BONUSSCANNER_CUREQDET_LABEL"] = "Detalles de mejoras del equipo actual";
L["BONUSSCANNER_OOR_LABEL"] = " está fuera de alcance.";
L["BONUSSCANNER_GEMCOUNT_LABEL"] = "De color ";
L["BONUSSCANNER_INVALIDTAR_LABEL"] = "Objetivo para escanear no válido.";
L["BONUSSCANNER_SELTAR_LABEL"] = "Por favor elije un objetivo primero.";
L["BONUSSCANNER_SLOT_LABEL"] = "hueco";
L["BONUSSCANNER_FAILEDPARSE_LABEL"] = "El objeto no está en la caché o no ha sido validado en el servidor.";
L["BONUSSCANNER_CACHESUMMARY_LABEL"] = "Objetos cacheados por BonusScanner: ";
L["BONUSSCANNER_CACHECLEAR_LABEL"] = "La caché de BonusScanner ha sido limpiada.";
L["BONUSSCANNER_SPECIAL1_LABEL"] = " posibilidad de crítico";
L["BONUSSCANNER_SPECIAL2_LABEL"] = " esquivado/parado";
L["BONUSSCANNER_SPECIAL3_LABEL"] = " cuerpo a cuerpo";
L["BONUSSCANNER_SPECIAL4_LABEL"] = " hechizos";
L["BONUSSCANNER_SPECIAL5_LABEL"] = " ranged/spells";
L["BONUSSCANNER_ITEMID_LABEL"] = "ID de objeto: |cffffffff";
L["BONUSSCANNER_ILVL_LABEL"] = "Nivel de objeto: |cffffffff";
L["BONUSSCANNER_ENCHANTID_LABEL"] = "ID de encantamiento: |cffffffff";
L["BONUSSCANNER_GEM1ID_LABEL"] = "ID de gema 1: |cffffffff";
L["BONUSSCANNER_GEM2ID_LABEL"] = "ID de gema 2: |cffffffff";
L["BONUSSCANNER_GEM3ID_LABEL"] = "ID de gema 3: |cffffffff";
L["BONUSSCANNER_GEMRED_LABEL"] = "Rojo";
L["BONUSSCANNER_GEMBLUE_LABEL"] = "Azul";
L["BONUSSCANNER_GEMYELLOW_LABEL"] = "Amarillo";
L["BONUSSCANNER_GEMPRISM_LABEL"] = "Prismático";
L["BONUSSCANNER_AVERAGE_ILVL_LABEL"] = "Nivel medio de objetos";
L["BONUSSCANNER_NEEDS_RELOADUI_LABEL"] = "Los cambios tendrán efecto cuando el interface se vuelva a cargar.";
L["BONUSSCANNER_LDB_PLUGIN_LABEL"] = "BonusScanner LDB Plugin ";
--bonus categories
L["BONUSSCANNER_CAT_ATT"] = "Atributos";
L["BONUSSCANNER_CAT_RES"] = "Resistencias";
L["BONUSSCANNER_CAT_SKILL"] = "Habilidades";
L["BONUSSCANNER_CAT_BON"] = "Combate cuerpo a cuerpo y a distancia";
L["BONUSSCANNER_CAT_SBON"] = "Hechizos";
L["BONUSSCANNER_CAT_OBON"] = "Vida y Maná";
L["BONUSSCANNER_CAT_EBON"] = "Bonificaciones especiales";
L["BONUSSCANNER_CAT_GEMS"] = "Gemas en ranuras";
--slash command text
L["BONUSSCANNER_SLASH_STRING1"] = GREEN_FONT_COLOR_CODE.."BonusScanner ";
L["BONUSSCANNER_SLASH_STRING1a"] = "|cffffffff por Crowley, Archarodim, jmsteele, Tristanian";
L["BONUSSCANNER_SLASH_STRING2"] = LIGHTYELLOW_FONT_COLOR_CODE.."Uso: |cffffffff/bscan {show | details | tooltip | tooltip gems | itembasic | itemextend | broker | clearcache | target | target <player> | <itemlink> | <itemlink> <player> | <slotname>}";
L["BONUSSCANNER_SLASH_STRING3"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."show: |cffffffffMuestra todas las mejoras del equipo actual.";
L["BONUSSCANNER_SLASH_STRING4"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."details: |cffffffffMuestra mejoras en detalle.";
L["BONUSSCANNER_SLASH_STRING5"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip: [";
L["BONUSSCANNER_SLASH_STRING5a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAñade el resumen de mejoras al tooltip de un objeto.";
L["BONUSSCANNER_SLASH_STRING14"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip gems: [";
L["BONUSSCANNER_SLASH_STRING14a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAñade el recuento de gemas de color a los tooltips (requiere activar los tooltips).";
L["BONUSSCANNER_SLASH_STRING12"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itembasic: [";
L["BONUSSCANNER_SLASH_STRING12a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAñade nivel y propiedades de un objeto a los tooltips (requiere activar los tooltips).";
L["BONUSSCANNER_SLASH_STRING13"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itemextend: [";
L["BONUSSCANNER_SLASH_STRING13a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAñade información sobre gemas y encantamientos a los tooltips (requiere activar los tooltips).";
L["BONUSSCANNER_SLASH_STRING15"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."broker: [";
L["BONUSSCANNER_SLASH_STRING15a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffCambia el estado del origen LDB, usado para mostrar las mejoras de objetos para el personaje actual.";
L["BONUSSCANNER_SLASH_STRING11"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."clearcache: |cffffffffLimpia la cache de objetos y fuerza una recolección de basura.";
L["BONUSSCANNER_SLASH_STRING6"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target: |cffffffffMuestra las mejoras del equipo del objetivo seleccionado (ha de estar en rango de inspección).";
L["BONUSSCANNER_SLASH_STRING7"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target <jugador>: |cffffffffSusurra las mejoras del equipo del objetivo seleccionado al jugador especificado.";
L["BONUSSCANNER_SLASH_STRING8"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink>: |cffffffffMuestra las mejoras del objeto enlazado (inserta el enlace con Shift-Click).";
L["BONUSSCANNER_SLASH_STRING9"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink> <player>: |cffffffffSusurra las mejoras del objeto enlazado al jugador especificado.";
L["BONUSSCANNER_SLASH_STRING10"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<slotname>: |cffffffffMuestra las mejoras del objeto en la ubicación dada.";

View File

@ -0,0 +1,406 @@
local L = LibStub("AceLocale-3.0"):NewLocale("BonusScanner","frFR")
if not L then return end
-- bonus names
L["BONUSSCANNER_NAMES"] = {
--Base Stats
STR = "Force ",
AGI = "Agilit\195\169 ",
STA = "Endurance ",
INT = "Intelligence ",
SPI = "Esprit ",
ARMOR = "Armure ",
--Resistances
ARCANERES = "R\195\169sistance Arcane ",
FIRERES = "R\195\169sistance Feu ",
NATURERES = "R\195\169sistance Nature ",
FROSTRES = "R\195\169sistance Givre ",
SHADOWRES = "R\195\169sistance Ombre ",
--Skills
FISHING = "P\195\170che ",
MINING = "Minage ",
HERBALISM = "Herborisme ",
SKINNING = "D\195\169pe\195\167age ",
DEFENSE = "Score de d\195\169fense ",
EXPERTISE = "Score d'expertise ",
--Abilities
BLOCK = "Blocage ",
BLOCKVALUE = "Valeur de Blocage ",
DODGE = "Esquive ",
PARRY = "Score de parade ",
RESILIENCE = "Score de r\195\169silience ",
DMGWPN = "Augmentation de d\195\169\g\195\162ts en m\195\170l\195\169e ", -- Might of Cenarius etc.
RANGEDDMG = "D\195\169\g\195\162ts de l'arme \195\160 distance ",
ARMORPEN = "P\195\169n\195\169tration d'armure ",
-- DPS
DPSMAIN = "Main Weapon(s) DPS",
DPSRANGED = "Ranged Weapon DPS",
DPSTHROWN = "Thrown Weapon DPS",
--Attack Power
ATTACKPOWER = "Puissance d'attaque ",
ATTACKPOWERUNDEAD = "Puissance d'attaque contre les morts-vivants ",
ATTACKPOWERFERAL = "Puissance d'attaque en forme animale ",
RANGEDATTACKPOWER = "Puissance d'attaque \195\160 distance ",
--Critical
CRIT = "Score de coup critique ",
RANGEDCRIT = "Score de tirs critiques ",
--HOLYCRIT = "Score de coup critique des sorts du Sacr\195\169 ",
--Hit
TOHIT = "Score de toucher ",
RANGEDHIT = "Score de toucher \195\160 distance ",
--Haste
HASTE = "Score de h\195\162te ",
--Spell Damage/healing
DMGUNDEAD = "D\195\169\g\195\162ts des Sorts contre les morts-vivants ",
ARCANEDMG = "D\195\169\g\195\162ts d'Arcane ",
FIREDMG = "D\195\169\g\195\162ts de Feu ",
FROSTDMG = "D\195\169\g\195\162ts de Givre ",
HOLYDMG = "D\195\169\g\195\162ts du Sacr\195\169 ",
NATUREDMG = "D\195\169\g\195\162ts de Nature ",
SHADOWDMG = "D\195\169\g\195\162ts d'Ombre ",
SPELLPEN = "P\195\169n\195\169tration des sorts ",
SPELLPOW = "Puissance des sorts",
--Regen
HEALTHREG = "R\195\169g\195\169n\195\169ration de vie ",
MANAREG = "R\195\169g\195\169n\195\169ration de mana ",
--Health/mana
HEALTH = "Points de vie ",
MANA = "Points de mana ",
--Extra bonuses
THREATREDUCTION = "% de r\195\169duction de menace ",
THREATINCREASE = "% d'augmentation de menace ",
INCRCRITDMG = "% d'augmentation des dommages critiques ",
SPELLREFLECT = "% de r\195\169flexion des sorts ",
STUNRESIST = "% de r\195\169sistance aux effets d'\195\169tourdissement ",
PERCINT = "% d'intelligence ",
PERCBLOCKVALUE = "% de valeur de blocage ",
-- WOTLK Metagems--
PERCARMOR = "% Increased Armor Value",
PERCMANA ="% Mana",
PERCREDSPELLDMG = "% Reduced Spell Damage Taken",
PERCSNARE = "% Reduced Snare/Root Duration",
PERCSILENCE = "% Reduced Silence Duration",
PERCFEAR = "% Reduced Fear Duration",
PERCSTUN = "% Reduced Stun Duration",
PERCCRITHEALING = "% Increased Critical Healing",
};
-- equip and set bonus prefixes:
--L["BONUSSCANNER_PREFIX_EQUIP"] = "\195\137quip\195\169 : "; --no longer used but kept in case Blizzard decides to alter its own global string referring to this
L["BONUSSCANNER_PREFIX_SET"] = "Complet : "; -- Attention le blanc après complet cache un caractère de controle
L["BONUSSCANNER_PREFIX_SOCKET"] = "Bonus de sertissage : ";
L["BONUSSCANNER_WEAPON_SPEED"] = "Vitesse";
-- translation needed !
L["BONUSCANNER_GEM_STRINGS"] = {
-- red
["matches a red socket"] = { red = 1, yellow = 0, blue = 0, prismatic = 0},
-- blue
["matches a blue socket"] = { red = 0, yellow = 0, blue = 1, prismatic = 0},
-- yellow
["matches a yellow socket"] = { red = 0, yellow = 1, blue = 0, prismatic = 0},
-- purple
["matches a red or blue socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
["matches a blue or red socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
-- green
["matches a blue or yellow socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
["matches a yellow or blue socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
-- orange
["matches a red or yellow socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
["matches a yellow or red socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
-- prismatic
["matches any socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1},
["matches a red, yellow or blue socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1}
}
-- Enchant separators
L["BONUSSCANNER_GLOBAL_SEP"] = " +";
L["BONUSSCANNER_SEPARATORS"] = { "/", ", ", " & ", " et " };
-- passive bonus patterns. checked against lines which start with above prefixes
L["BONUSSCANNER_PATTERNS_PASSIVE"] = {
--Skills
{ pattern = "Augmente le score de d\195\169fense de (%d+)%.", effect = "DEFENSE" },
{ pattern = "Augmente de (%d+) le score de r\195\169silience%.", effect = "RESILIENCE" }, -- old way : "Augmente le score de r\195\169silience de (%d+)%."
{ pattern = "Augmente le score d'expertise de (%d+)%.", effect = "EXPERTISE" },
{ pattern = "P\195\170che augment\195\169e de (%d+)%.", effect = "FISHING" }, -- fishing poles
-- Abilities
{ pattern = "Augmente votre score de blocage de (%d+)%.", effect = "BLOCK" }, -- Gardien resplendissant
{ pattern = "Augmente de (%d+) le score de blocage%.", effect = "BLOCK" },
{ pattern = "Augmente la valeur de blocage de votre bouclier de (%d+)%.", effect = "BLOCKVALUE" },
{ pattern = "Augmente le score d'esquive de (%d+)%.", effect = "DODGE" }, -- Cape de maître des loups (Armurerie)
{ pattern = "Augmente de (%d+) le score d'esquive%.", effect = "DODGE" }, -- Cape de maître des loups
{ pattern = "Augmente de (%d+) le score de parade%.", effect = "PARRY" },
{ pattern = "%+(%d+) aux d\195\169g\195\162ts des armes%.", effect = "DMGWPN" }, -- Might of Cenarius...
{ pattern = "%+(%d+) aux d\195\169g\195\162ts de l'arme%.", effect = "DMGWPN" }, -- Might of Cenarius...
--Crit
{ pattern = "Augmente le score de coup critique de (%d+)%.", effect = "CRIT" }, -- Bague de jade lourde (Armurerie)
{ pattern = "Augmente de (%d+) le score de coup critique%.", effect = "CRIT" }, -- Bague de jade lourde
{ pattern = "Augmente de (%d+) le score de coup critique en m\195\170l\195\169e%.", effect = "CRIT" },
{ pattern = "Increases your ranged critical strike rating by (%d+)%.", effect = "RANGEDCRIT" },
--Damage/Heal
{ pattern = "Augmente les d\195\169g\195\162ts et les soins produits par les sorts et effets magiques de (%d+) au maximum%.", effect = "SPELLPOW" },
{ pattern = "Increases your spell power by (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Augmente les d\195\169g\195\162ts inflig\195\169s par les sorts et effets d'Ombre de (%d+) au maximum%.", effect = "SHADOWDMG" },
{ pattern = "Augmente les d\195\169g\195\162ts inflig\195\169s par les sorts et effets des Arcanes de (%d+) au maximum%.", effect = "ARCANEDMG" },
{ pattern = "Augmente les d\195\169g\195\162ts inflig\195\169s par les sorts et effets de Feu de (%d+) au maximum%.", effect = "FIREDMG" },
{ pattern = "Augmente les d\195\169g\195\162ts inflig\195\169s par les sorts et effets de Givre de (%d+) au maximum%.", effect = "FROSTDMG" },
{ pattern = "Augmente les d\195\169g\195\162ts inflig\195\169s par les sorts et effets du Sacr\195\169 de (%d+) au maximum%.", effect = "HOLYDMG" },
{ pattern = "Augmente les d\195\169g\195\162ts inflig\195\169s par les sorts et effets de Nature de (%d+) au maximum%.", effect = "NATUREDMG" },
-- { pattern = "Increases damage and healing done by magical spells and effects slightly%.", effect = {"HEAL", "DMG"}, value = {6, 6} },
{ pattern = "Increases damage done to Undead by magical spells and effects by up to (%d+)", effect = "DMGUNDEAD" },
-- Multibonus Equip patterns
{ pattern = "Increases spell power of all party members within %d+ yards by up to (%d+)%.", effect = "SPELLPOW" },
--{ pattern = "Augmente les soins prodigu\195\169s d'un maximum de (%d+) et les d\195\169\g\195\162ts d'un maximum de (%d+) pour tous les sorts et effets magiques%.", effect = {"HEAL","DMG"} },
--{ pattern = "Increases your pet's resistances by 130 and increases your spell damage by up to (%d+)%.", effect = "DMG" }, -- Void Star Talisman
--{ pattern = "Increases your spell damage by up to (%d+) and your healing by up to (%d+)%.", effect = {"DMG","HEAL"} },
--{ pattern = "Increases healing done by magical spells and effects of all party members within %d+ yards by up to (%d+)%. ", effect = "HEAL" },
--{ pattern = "Increases damage and healing done by magical spells and effects of all party members within %d+ yards by up to (%d+)%.", effect = {"HEAL", "DMG"} },
{ pattern = "Restores (%d+) mana per 5 seconds to all party members within %d+ yards%.", effect = "MANAREG" },
--{ pattern = "Increases the spell critical strike rating of all party members within %d+ yards by (%d+)%.", effect = "SPELLCRIT" },
{ pattern = "Increases defense rating by (%d+), Shadow resistance by (%d+) and your normal health regeneration by (%d+)%.", effect = {"DEFENSE", "SHADOWRES", "HEALTHREG"} },
--Attack power
{ pattern = "Augmente de (%d+) la puissance d'attaque%.", effect = "ATTACKPOWER" },
{ pattern = "Augmente de (%d+) la puissance d'attaque en m\195\170l\195\169e et \195\160 distance%.", effect = {"ATTACKPOWER","RANGEDATTACKPOWER"} }, -- Andonisus, Reaper of Souls pattern
{ pattern = "+(%d+) ranged Attack Power%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Increases ranged attack power by (%d+)%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Augmente de (%d+) la puissance d'attaque pour les formes de f\195\169lin, d'ours, d'ours redoutable et de s\195\169l\195\169nien uniquement%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Augmente de (%d+) la puissance d'attaque lorsque vous combattez les morts-vivants%.", effect = "ATTACKPOWERUNDEAD" },
{ pattern = "+(%d+) Attack Power when fighting Undead%.", effect = "ATTACKPOWERUNDEAD" },
--Regen
{ pattern = "Restores (%d+) health per 5 sec%.", effect = "HEALTHREG" },
{ pattern = "Rend (%d+) points de vie toutes les 5 sec%.", effect = "HEALTHREG" }, -- both versions ('per' and 'every') seem to be used
{ pattern = "Restores (%d+) mana per 5 sec%.", effect = "MANAREG" },
{ pattern = "Rend (%d+) points de mana toutes les 5 sec%.", effect = "MANAREG" },
--Hit
{ pattern = "Augmente le score de toucher de (%d+)%.", effect = "TOHIT" },
{ pattern = "Augmente votre score de toucher de (%d+)%.", effect = "TOHIT" }, -- Rune de capitaine de la garde
--Haste
{ pattern = "Augmente le score de h\195\162te de (%d+)%.", effect = "HASTE" },
--Penetration
{ pattern = "Decreases the magical resistances of your spell targets by (%d+).", effect = "SPELLPEN" },
{ pattern = "Augmente la p\195\169n\195\169tration de vos sorts de (%d+)%.", effect = "SPELLPEN" },
{ pattern = "Vos attaques ignorent (%d+) points de l'armure de votre adversaire%.", effect = "ARMORPEN" }
};
-- generic patterns have the form "+xx bonus" or "bonus +xx" or even "xx bonus" with an optional % sign after the value.
-- first the generic bonus string is looked up in the following table
L["BONUSSCANNER_PATTERNS_GENERIC_LOOKUP"] = {
["\195\160 toutes les caract\195\169ristiques"] = {"STR", "AGI", "STA", "INT", "SPI"}, -- enchantement
["Force"] = "STR",
["Agilit\195\169"] = "AGI",
["Endurance"] = "STA",
["Intelligence"] = "INT",
["Esprit"] = "SPI",
["\195\160 toutes les r\195\169sistances"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- obsidian items
--["Resist All"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- prismatic gems (same localization in french as obsidian items)
["P\195\170che"] = "FISHING",
["App\195\162t"] = "FISHING",
["P\195\170che augment\195\169e"] = "FISHING",
["Minage"] = "MINING",
["Herborisme"] = "HERBALISM",
["D\195\169pe\195\167age"] = "SKINNING",
["D\195\169fense"] = "DEFENSE",
["D\195\169fense augment\195\169e"] = "DEFENSE",
["la puissance d'attaque"] = "ATTACKPOWER",
["la puissance d'attaque lorsque vous combattez les morts-vivants"] = "ATTACKPOWERUNDEAD",
["la puissance d'attaque pour les formes de f\195\169lin, d'ours, d'ours redoutable et de s\195\169l\195\169nien uniquement"] = "ATTACKPOWERFERAL",
["aux d\195\169\g\195\162ts des armes"] = "DMGWPN",
["aux d\195\169\g\195\162ts de l'arme"] = "DMGWPN", -- bonus enchantement arme 1M
-- TBC Patterns Generic/Gems/Sockets
["\195\160 la puissance des sorts"] = "SPELLPOW",
["au score de coup critique"] = "CRIT",
["au score de critique"] = "CRIT",
["Crit Rating"] = "CRIT",
["\195\160 la p\195\169n\195\169tration des sorts"] = "SPELLPEN",
["au score de d\195\169fense"] = "DEFENSE",
["au score de h\195\162te"] = "HASTE",
["point de mana toutes les 5 sec"] = "MANAREG",
["points de mana toutes les 5 sec"] = "MANAREG",
["point de mana toutes les 5 secondes"] = "MANAREG",
["points de mana toutes les 5 secondes"] = "MANAREG",
["Mana restored per 5 seconds"] = "MANAREG",
["au score d'esquive"] = "DODGE",
["au score de parade"] = "PARRY",
["au score de r\195\169silience"] = "RESILIENCE",
["d\195\169\g\195\162ts subis en m\195\169l\195\169e"] = "DMGWPN",
["au score d'expertise"] = "EXPERTISE",
-- End TBC Patterns
["Esquive"] = "DODGE",
["Block"] = "BLOCKVALUE",
["Block Value"] = "BLOCKVALUE",
["Block Rating"] = "BLOCK",
["Bloquer"] = "BLOCK",
["Toucher"] = "TOHIT",
["au score de toucher"] = "TOHIT",
["au score de toucher \195\160 distance"] = "RANGEDHIT",
["Puissance d'attaque \195\160 distance"] = "RANGEDATTACKPOWER",
["puissance d'attaque \195\160 distance"] = "RANGEDATTACKPOWER", -- Experimental for TBC
["Health per 5 sec"] = "HEALTHREG",
["health every 5 sec"] = "HEALTHREG",
["aux soins"] = "HEAL",
["aux sorts de soins"] = "HEAL",
["Increased Healing"] = "HEAL",
["mana every 5 sec"] = "MANAREG",
["\195\160 la r\195\169g\195\169n. de mana"] = "MANAREG",
["Critical"] = "CRIT",
["Critical Hit"] = "CRIT",
["Health"] = "HEALTH",
["HP"] = "HEALTH",
["points de mana"] = "MANA",
["Armure"] = "ARMOR",
["Renforc\195\169"] = "ARMOR",
["R\195\169silience"] = "RESILIENCE",
-- Patterns for color coded/special lines
["Reduced Threat"] = "THREATREDUCTION",
["Increased Critical Damage"] = "INCRCRITDMG",
["Spell Reflect"] = "SPELLREFLECT",
["Stun Resistance"] = "STUNRESIST",
["Stun Resist"] = "STUNRESIST",
["Shield Block Value"] = "PERCBLOCKVALUE",
["Increased Armor Value from Items"] = "PERCARMOR",
["Reduce Spell Damage Taken by"] = "PERCREDSPELLDMG",
["Silence Duration Reduced by"] = "PERCSILENCE",
["Fear Duration Reduced by"] = "PERCFEAR",
["Stun Duration Reduced by"] = "PERCSTUN",
["Increased Critical Healing Effect"] = "PERCCRITHEALING",
};
-- next we try to match against one pattern of stage 1 and one pattern of stage 2 and concatenate the effect strings
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE1"] = {
{ pattern = "Arcane", effect = "ARCANE" },
{ pattern = "Feu", effect = "FIRE" },
{ pattern = "Givre", effect = "FROST" },
{ pattern = "Sacr\195\169", effect = "HOLY" },
{ pattern = "Ombre", effect = "SHADOW" },
{ pattern = "Nature", effect = "NATURE" }
};
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE2"] = {
{ pattern = "\195\160 la r\195\169sistance", effect = "RES" },
{ pattern = "Damage", effect = "DMG" },
{ pattern = "Effects", effect = "DMG" }
};
-- finally if we got no match, we match against some special enchantment patterns.
L["BONUSSCANNER_PATTERNS_OTHER"] = {
-- Infused Amethyst
{ pattern = "Spell Power %+(%d+) and Stamina %+(%d+)", effect = {"SPELLPOW", "STA"} },
-- special patterns that cannot be handled any other way
{ pattern = "%+21 Critical Strike Rating and %+2%% Mana", effect = {"CRIT", "PERCMANA"}, value = {21, 2} },
{ pattern = "%+12 Critical Strike Rating and Reduces Snare/Root Duration by 15%%", effect = {"CRIT", "PERCSNARE"}, value = {12, 15} },
{ pattern = "%+21 Critical Strike Rating and Reduces Snare/Root Duration by 15%%", effect = {"CRIT", "PERCSNARE"}, value = {21, 15} },
{ pattern = "%+14 Spell Power and %+2%% Intellect", effect = {"SPELLPOW", "PERCINT"}, value = {14, 2} },
{ pattern = "%+25 Spell Power and %+2%% Intellect", effect = {"SPELLPOW", "PERCINT"}, value = {25, 2} },
{ pattern = "%+18 Stamina and Stun Duration Reduced by 15%% Stun Resist", effect = {"STA", "PERCSTUN"}, value = {18, 15} },
-- rest of custom patterns
{ pattern = "Augmente de (%d+) la puissance d'attaque pour les formes de f\195\169lin, d'ours, d'ours redoutable et de s\195\169l\195\169nien uniquement%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Mana Regen (%d+) per 5 sec", effect = "MANAREG" },
{ pattern = "Renforc\195\169 %(%+(%d+) Armure%)", effect = "ARMOR" }, -- bonus des Renforts d'armure
{ pattern = "%+(%d+)%% Threat", effect = "THREATINCREASE" },
{ pattern = "Scope %(%+(%d+) Critical Strike Rating%)", effect = "CRIT" },
{ pattern = "Scope %(%+(%d+) Damage%)", effect = "RANGEDDMG" },
};
-- localized strings
L["BONUSSCANNER_BONUSSUM_LABEL"] = "Liste des bonus";
L["BONUSSCANNER_TOOLTIP_STRING"] = "BonusScanner Tooltip Bonus Summary ";
L["BONUSSCANNER_TOOLTIPGEMS_STRING"] = "Compteur de gemmes ";
L["BONUSSCANNER_BASICLINKID_STRING"] = "Basic Itemlink ID's ";
L["BONUSSCANNER_EXTENDEDLINKID_STRING"] = "Extended Itemlink ID's ";
L["BONUSSCANNER_TOOLTIP_ENABLED"] = "Activ\195\169";
L["BONUSSCANNER_TOOLTIP_DISABLED"] = "D\195\169sactiv\195\169";
L["BONUSSCANNER_IBONUS_LABEL"] = "Bonus de l'objet ";
L["BONUSSCANNER_NOBONUS_LABEL"] = "Aucun bonus d\195\169tect\195\169.";
L["BONUSSCANNER_CUREQ_LABEL"] = "Bonus de l'\195\169quipement en cours";
L["BONUSSCANNER_CUREQDET_LABEL"] = "D\195\169tail des bonus de l'\195\169quipement en cours";
L["BONUSSCANNER_OOR_LABEL"] = " est hors de port\195\169e.";
L["BONUSSCANNER_GEMCOUNT_LABEL"] = "Correspond \195\160 ";
L["BONUSSCANNER_INVALIDTAR_LABEL"] ="Cible invalide \195\160 scanner.";
L["BONUSSCANNER_SELTAR_LABEL"] = "Veuillez s\195\169lectionner la cible d'abord.";
L["BONUSSCANNER_SLOT_LABEL"] = "emplacement";
L["BONUSSCANNER_FAILEDPARSE_LABEL"] = "L'item n'est pas dans le cache ou n'a pas \195\169t\195\169 valid\195\169 sur le serveur.";
L["BONUSSCANNER_CACHESUMMARY_LABEL"] = "Objets dans le cache de BonusScanner : ";
L["BONUSSCANNER_CACHECLEAR_LABEL"] = "Le cache a \195\169t\195\169 nettoy\195\169.";
L["BONUSSCANNER_SPECIAL1_LABEL"] = " chance de crit";
L["BONUSSCANNER_SPECIAL2_LABEL"] = " esquiv\195\169/par\195\169";
L["BONUSSCANNER_SPECIAL3_LABEL"] = " m\195\170l\195\169e";
L["BONUSSCANNER_SPECIAL4_LABEL"] = " sorts";
L["BONUSSCANNER_SPECIAL5_LABEL"] = " ranged/spells";
L["BONUSSCANNER_ITEMID_LABEL"] = "ID de l'objet: |cffffffff";
L["BONUSSCANNER_ILVL_LABEL"] = "Niveau de l'objet: |cffffffff";
L["BONUSSCANNER_ENCHANTID_LABEL"] = "ID de l'enchant: |cffffffff";
L["BONUSSCANNER_GEM1ID_LABEL"] = "ID de la gemme 1: |cffffffff";
L["BONUSSCANNER_GEM2ID_LABEL"] = "ID de la gemme 2: |cffffffff";
L["BONUSSCANNER_GEM3ID_LABEL"] = "ID de la gemme 3: |cffffffff";
L["BONUSSCANNER_GEMRED_LABEL"] = "Rouge";
L["BONUSSCANNER_GEMBLUE_LABEL"] = "Bleu";
L["BONUSSCANNER_GEMYELLOW_LABEL"] = "Jaune";
L["BONUSSCANNER_GEMPRISM_LABEL"] = "Prismatique";
L["BONUSSCANNER_AVERAGE_ILVL_LABEL"] = "Average item Level";
L["BONUSSCANNER_NEEDS_RELOADUI_LABEL"] = "Les changements prendront effet apr\195\168s rechargement de l'UI.";
L["BONUSSCANNER_LDB_PLUGIN_LABEL"] = "Plugin LDB BonusScanner ";
--bonus categories
L["BONUSSCANNER_CAT_ATT"] = "Attributs";
L["BONUSSCANNER_CAT_RES"] = "R\195\169sistance";
L["BONUSSCANNER_CAT_SKILL"] = "Comp\195\169tences";
L["BONUSSCANNER_CAT_BON"] = "Combat en m\195\170l\195\169e et \195\160 distance";
L["BONUSSCANNER_CAT_SBON"] = "Sortil\195\168ges";
L["BONUSSCANNER_CAT_OBON"] = "Vie et mana";
L["BONUSSCANNER_CAT_EBON"] = "Bonus Sp\195\169ciaux";
L["BONUSSCANNER_CAT_GEMS"] = "Gemmes";
--slash command text
L["BONUSSCANNER_SLASH_STRING1"] = GREEN_FONT_COLOR_CODE.."BonusScanner ";
L["BONUSSCANNER_SLASH_STRING1a"] = "|cffffffff by Crowley, Archarodim, jmsteele, Tristanian";
L["BONUSSCANNER_SLASH_STRING2"] = LIGHTYELLOW_FONT_COLOR_CODE.."Utilisation: |cffffffff/bscan {show | details | tooltip | tooltip gems | itembasic | itemextend | broker | clearcache | target | target <player> | <itemlink> | <itemlink> <player> | <slotname>}";
L["BONUSSCANNER_SLASH_STRING3"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."show: |cffffffffAffiche les bonus de l'\195\169quipement actuel.";
L["BONUSSCANNER_SLASH_STRING4"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."details: |cffffffffAffiche les bonus tri\195\169 par emplacement.";
L["BONUSSCANNER_SLASH_STRING5"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip: [";
L["BONUSSCANNER_SLASH_STRING5a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAffiche les bonus dans les tooltips.";
L["BONUSSCANNER_SLASH_STRING14"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip gems: [";
L["BONUSSCANNER_SLASH_STRING14a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAffiche le nombre de gemmes dans les tooltips (les tooltips doivent \195\170tre activ\195\169s).";
L["BONUSSCANNER_SLASH_STRING12"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itembasic: [";
L["BONUSSCANNER_SLASH_STRING12a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAffiche l'ID et le niveau de l'objet dans les tooltips (les tooltips doivent \195\170tre activ\195\169s).";
L["BONUSSCANNER_SLASH_STRING13"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itemextend: [";
L["BONUSSCANNER_SLASH_STRING13a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAffiche l'ID de l'enchantement et l'ID des gemmes dans les tooltips (les tooltips doivent \195\170tre activ\195\169s).";
L["BONUSSCANNER_SLASH_STRING15"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."broker: [";
L["BONUSSCANNER_SLASH_STRING15a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffChange l'\195\169tat du plugin LDB, pour afficher les bonus d' \195\169quipement pour le personnage courant.";
L["BONUSSCANNER_SLASH_STRING11"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."clearcache: |cffffffffNettoyer le cache et vider la poubelle.";
L["BONUSSCANNER_SLASH_STRING6"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target: |cffffffffAffiche les bonus du personnage cibl\195\169 (doit \195\170tre \195\160 port\195\169e).";
L["BONUSSCANNER_SLASH_STRING7"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target <player>: |cffffffffChuchote les bonus de votre \195\169quipement en cours au joueur s\195\169lectionn\195\169.";
L["BONUSSCANNER_SLASH_STRING8"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink>: |cffffffffAffiche les bonus de l'objet en lien (ins\195\169rez le lien avec Shift-Clic).";
L["BONUSSCANNER_SLASH_STRING9"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink> <player>: |cffffffffChuchote les bonus de l'objet montr\195\169 au joueur indiqu\195\169.";
L["BONUSSCANNER_SLASH_STRING10"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<slotname>: |cffffffffAffiche les bonus de l'emplacement indiqu\195\169.";

View File

@ -0,0 +1,447 @@
--Chinese traditional translated by Juha.
local L = LibStub("AceLocale-3.0"):NewLocale("BonusScanner","zhTW")
if not L then return end
-- bonus names
L["BONUSSCANNER_NAMES"] = {
--Base Stats
STR = "力量",
AGI = "敏捷",
STA = "耐力",
INT = "智力",
SPI = "精神",
ARMOR = "護甲",
--Resistances
ARCANERES = "秘法抗性",
FIRERES = "火焰抗性",
NATURERES = "自然抗性",
FROSTRES = "冰霜抗性",
SHADOWRES = "暗影抗性",
--SKills
FISHING = "釣魚",
MINING = "採礦",
HERBALISM = "草藥",
SKINNING = "剝皮",
DEFENSE = "防禦",
EXPERTISE = "熟練等級",
--Abilities
BLOCK = "格擋等級",
BLOCKVALUE = "格檔值",
DODGE = "閃躲等級",
PARRY = "招架等級",
RESILIENCE = "韌性等級",
DMGWPN = "武器傷害提高", -- Might of Cenarius etc.
RANGEDDMG = "遠程武器傷害",
ARMORPEN = "無視護甲",
-- DPS
DPSMAIN = "Main Weapon(s) DPS",
DPSRANGED = "Ranged Weapon DPS",
DPSTHROWN = "Thrown Weapon DPS",
--Attack Power
ATTACKPOWER = "攻擊強度",
ATTACKPOWERUNDEAD = "對不死生物的攻擊強度",
ATTACKPOWERFERAL = "野性形態攻擊強度",
RANGEDATTACKPOWER = "遠程攻擊強度",
--Critical
CRIT = "致命等級",
RANGEDCRIT = "遠程致命等級",
--HOLYCRIT = "神聖法術爆擊", --沒有其他可用的相關參數
--Hit
TOHIT = "命中等級",
RANGEDHIT = "遠程命中等級",
--Haste
HASTE = "加速等級",
--Spell Damage/healing
DMGUNDEAD = "對不死生物的法術傷害",
ARCANEDMG = "秘法傷害",
FIREDMG = "火焰傷害",
FROSTDMG = "冰霜傷害",
HOLYDMG = "神聖傷害",
NATUREDMG = "自然傷害",
SHADOWDMG = "暗影傷害",
SPELLPEN = "法術穿透力",
SPELLPOW = "法術能量",
--Regen
HEALTHREG = "生命力恢復",
MANAREG = "法力恢復",
--Health/mana
HEALTH = "生命力",
MANA = "法力",
--Extra bonuses
THREATREDUCTION = "% 威脅值(降低)",
THREATINCREASE = "% 威脅值(提高)",
INCRCRITDMG = "% 致命一擊傷害(提高)",
SPELLREFLECT = "% 法術反射",
STUNRESIST = "% 昏迷抗性",
PERCINT = "% 智力", --v2.4
PERCBLOCKVALUE = "% 盾牌格檔值", --v2.4
-- WOTLK Metagems
PERCARMOR = "% 裝備提供的護甲值",
PERCMANA ="% 法力",
PERCREDSPELLDMG = "% 法術傷害(降低)",
PERCSNARE = "% 緩速及定身持續時間縮短",
PERCSILENCE = "% 沉默持續時間縮短",
PERCFEAR = "% 恐懼持續時間縮短",
PERCSTUN = "% 昏迷持續時間縮短",
PERCCRITHEALING = "% 極效治療效果",
};
-- equip and set bonus prefixes:
--L["BONUSSCANNER_PREFIX_EQUIP"] = "裝備: "; --no longer used but kept in case Blizzard decides to alter its own global string referring to this
L["BONUSSCANNER_PREFIX_SET"] = "套裝:";
L["BONUSSCANNER_PREFIX_SOCKET"] = "插槽加成:";
L["BONUSSCANNER_WEAPON_SPEED"] = "速度";
-- translation needed !
L["BONUSCANNER_GEM_STRINGS"] = {
-- red
["matches a red socket"] = { red = 1, yellow = 0, blue = 0, prismatic = 0},
-- blue
["matches a blue socket"] = { red = 0, yellow = 0, blue = 1, prismatic = 0},
-- yellow
["matches a yellow socket"] = { red = 0, yellow = 1, blue = 0, prismatic = 0},
-- purple
["matches a red or blue socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
["matches a blue or red socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
-- green
["matches a blue or yellow socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
["matches a yellow or blue socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
-- orange
["matches a red or yellow socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
["matches a yellow or red socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
-- prismatic
["matches any socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1},
["matches a red, yellow or blue socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1}
}
-- Enchant separators
L["BONUSSCANNER_GLOBAL_SEP"] = "+";
L["BONUSSCANNER_SEPARATORS"] = { "/", "", ",", "", " 持續 ", "&", "", "", "", };
-- passive bonus patterns. checked against lines which start with above prefixes
L["BONUSSCANNER_PATTERNS_PASSIVE"] = {
--Skills
{ pattern = "使防禦等級提高(%d+)點。", effect = "DEFENSE" }, --jmlsteele
{ pattern = "使你的韌性等級提高(%d+)點。", effect = "RESILIENCE" },
{ pattern = "使你的熟練等級提高(%d+)。", effect = "EXPERTISE" },
{ pattern = "%+(%d+)點釣魚技能。", effect = "FISHING" },
-- Abilities
{ pattern = "使你的格擋等級提高(%d+)點。", effect = "BLOCK" },
{ pattern = "提高你的盾牌格擋等級(%d+)點。", effect = "BLOCK" },
{ pattern = "使你盾牌的格擋值提高(%d+)點。", effect = "BLOCKVALUE" },
{ pattern = "使你的閃躲等級提高(%d+)點。", effect = "DODGE" },
{ pattern = "使你的招架等級提高(%d+)點。", effect = "PARRY" },
{ pattern = "%+(%d+)武器傷害", effect = "DMGWPN" },
--Crit
{ pattern = "使你的致命一擊等級提高(%d+)點。", effect = "CRIT" },
{ pattern = "提高致命一擊等級(%d+)點。", effect = "CRIT" },
{ pattern = "提高近戰致命一擊等級(%d+)點。", effect = "CRIT" },
{ pattern = "使你的遠程攻擊致命一擊等級提高(%d+)點。", effect = "RANGEDCRIT" },
--Damage/Heal/Spell Power
{ pattern = "提高(%d+)點法術能量。", effect = "SPELLPOW" },
{ pattern = "提高法術能量(%d+)點。", effect = "SPELLPOW" },
{ pattern = "提高(%d+)點暗影法術能量。", effect = "SHADOWDMG" },
{ pattern = "提高(%d+)點秘法法術能量。", effect = "ARCANEDMG" },
{ pattern = "提高(%d+)點火焰法術能量。", effect = "FIREDMG" },
{ pattern = "提高(%d+)點冰霜法術能量。", effect = "FROSTDMG" },
{ pattern = "使神聖法術能量提高(%d+)點。", effect = "HOLYDMG" },
{ pattern = "提高(%d+)點自然法術能量。", effect = "NATUREDMG" },
--{ pattern = "Increases damage and healing done by magical spells and effects slightly%.", effect = {"HEAL", "DMG"}, value = {6, 6} },
{ pattern = "提高(%d+)點對不死生物的法術能量。", effect = "DMGUNDEAD" },
-- Multibonus Equip patterns
{ pattern = "使半徑%d+碼範圍內所有小隊成員的法術致命一擊等級提高(%d+)點。", effect = "SPELLPOW" },
--{ pattern = "使法術和魔法效果所造成的治療效果提高最多(%d+)點,法術傷害提高最多(%d+)點。", effect = {"HEAL", "DMG"} },
--{ pattern = "使你寵物的抗性提高130點並提高你的法術傷害最多(%d+)點。", effect = "DMG" }, -- Void Star Talisman
--{ pattern = "使你的法術傷害提高最多(%d+)點,以及你的治療效果最多(%d+)點。", effect = {"DMG","HEAL"} }, -- Atiesh patterns
--{ pattern = "使周圍半徑%d+碼範圍內隊友的所有法術和魔法效果所造成的治療效果提高最多(%d+)點。", effect = "HEAL" }, -- Atiesh patterns
--{ pattern = "使周圍半徑%d+碼範圍內隊友的所有法術和魔法效果所造成的傷害和治療效果提高最多(%d+)點。", effect = {"HEAL", "DMG"} }, -- Atiesh patterns
{ pattern = "使周圍半徑%d+碼範圍內的隊友每5秒恢復(%d+)點法力。", effect = "MANAREG" }, -- Atiesh patterns
{ pattern = "使半徑%d+碼範圍內所有小隊成員的法術致命一擊等級提高(%d+)點。", effect = "SPELLCRIT" }, -- Atiesh patterns
{ pattern = "使防禦等級提高(%d+)點,暗影抗性提高(%d+)點和一般的生命力恢復速度提高(%d+)點。", effect = {"DEFENSE", "SHADOWRES", "HEALTHREG"} }, --10779
--Attack power
{ pattern = "提高攻擊強度(%d+)點。", effect = "ATTACKPOWER" },
{ pattern = "使近戰和遠程攻擊強度提高(%d+)點。", effect = {"ATTACKPOWER","RANGEDATTACKPOWER"} }, -- Andonisus, Reaper of Souls pattern
{ pattern = "%+(%d+) 遠程攻擊強度。 ", effect = "RANGEDATTACKPOWER" },
{ pattern = "遠程攻擊強度提高(%d+)點。", effect = "RANGEDATTACKPOWER" },
{ pattern = "在獵豹、熊、巨熊和梟獸形態下的攻擊強度提高(%d+)點。", effect = "ATTACKPOWERFERAL" },
{ pattern = "對不死生物的攻擊強度提高(%d+)點。", effect = "ATTACKPOWERUNDEAD" },
{ pattern = "%+(%d+) 對不死生物的攻擊強度", effect = "ATTACKPOWERUNDEAD" },
--Regen
{ pattern = "每5秒恢復(%d+)點生命力。", effect = "HEALTHREG" },
-- { pattern = "Restores (%d+) health every 5 sec%.", effect = "HEALTHREG" }, -- both versions ('per' and 'every') seem to be used
{ pattern = "每5秒恢復(%d+)點法力。", effect = "MANAREG" },
-- { pattern = "Restores (%d+) mana every 5 sec%.", effect = "MANAREG" },
--Hit
{ pattern = "使你的命中等級提高(%d+)點。", effect = "TOHIT" },
{ pattern = "提高命中等級(%d+)點。", effect = "TOHIT" },
--Haste
{ pattern = "提高加速等級(%d+)點。", effect = "HASTE" },
--Penetration
{ pattern = "降低你施法目標的魔法抗性(%d+)點。", effect = "SPELLPEN" },
{ pattern = "使你的法術穿透力提高(%d+)點。", effect = "SPELLPEN" },
{ pattern = "提高(%d+)點護甲穿透等級。", effect = "ARMORPEN" },
--{ pattern = "Increases armor penetration rating by (%d+)%.", effect = "ARMORPEN" }
};
-- generic patterns have the form "+xx bonus" or "bonus +xx" or even "xx bonus" with an optional % sign after the value.
-- first the generic bonus string is looked up in the following table
L["BONUSSCANNER_PATTERNS_GENERIC_LOOKUP"] = {
["所有屬性"] = {"STR", "AGI", "STA", "INT", "SPI"},
-- ["to All Stats"] = {"STR", "AGI", "STA", "INT", "SPI"},
["力量"] = "STR",
["敏捷"] = "AGI",
["耐力"] = "STA",
["智力"] = "INT",
["精神"] = "SPI",
["全部抗性"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"},
["所有抗性"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"},
["抵抗全部"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"},
["點所有魔法抗性"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- [鋸齒黑曜石之盾] ID:22198
["釣魚"] = "FISHING",
["魚餌"] = "FISHING",
["點釣魚技能"] = "FISHING",
["採礦"] = "MINING",
["草藥學"] = "HERBALISM",
["剝皮"] = "SKINNING",
["防禦"] = "DEFENSE",
["防禦等級提高"] = "DEFENSE",
["攻擊強度"] = "ATTACKPOWER",
-- ["對不死生物的攻擊強度"] = "ATTACKPOWERUNDEAD",
["獵豹、熊、巨熊和梟獸形態下的攻擊強度提高"] = "ATTACKPOWERFERAL",
["武器傷害"] = "DMGWPN",
-- TBC Patterns Generic/Gems/Sockets
["法術能量"] = "SPELLPOW",
["致命一擊等級"] = "CRIT",
-- ["Critical strike rating"] = "CRIT",
-- ["Critical Rating"] = "CRIT",
-- ["Crit Rating"] = "CRIT",
["遠程攻擊致命一擊"] = "RANGEDCRIT",
["法術穿透力"] = "SPELLPEN",
["護甲穿透等級"] = "ARMORPEN",
["防禦等級"] = "DEFENSE",
["加速等級"] = "HASTE",
-- ["Mana per 5 Seconds"] = "MANAREG",
-- ["mana per 5 seconds"] = "MANAREG",
-- ["Mana every 5 Sec"] = "MANAREG",
-- ["Mana every 5 seconds"] = "MANAREG",
-- ["Mana restored per 5 seconds"] = "MANAREG",
-- ["Mana Per 5 sec"] = "MANAREG",
-- ["mana per 5 sec"] = "MANAREG",
-- ["Mana per 5 Sec"] = "MANAREG",
-- ["Mana per 5 sec"] = "MANAREG",
["閃躲等級"] = "DODGE",
["招架等級"] = "PARRY",
["韌性等級"] = "RESILIENCE",
["點韌性等級"] = "RESILIENCE",
["物理傷害"] = "DMGWPN",
["傷害法術"] = "DMG",
["熟練等級"] = "EXPERTISE",
-- End TBC Patterns
["躲閃"] = "DODGE",
["格檔"] = "BLOCKVALUE",
["格擋值"] = "BLOCKVALUE",
["格檔等級"] = "BLOCK",
-- ["Blocking"] = "BLOCK",
["命中"] = "TOHIT",
["命中等級"] = "TOHIT",
["遠程命中等級"] = "RANGEDHIT",
["遠程攻擊強度"] = "RANGEDATTACKPOWER",
["遠程攻擊強度"] = "RANGEDATTACKPOWER", -- Experimental for TBC
-- ["Health per 5 sec"] = "HEALTHREG",
-- ["health every 5 sec"] = "HEALTHREG",
["治療"] = "HEAL",
["治療法術"] = "HEAL",
["治療效果"] = "HEAL",
["提高治療效果"] = "HEAL",
-- ["mana every 5 sec"] = "MANAREG",
["法力恢復"] = "MANAREG",
["致命"] = "CRIT",
["致命一擊"] = "CRIT",
["生命力"] = "HEALTH",
-- ["HP"] = "HEALTH",
["法力"] = "MANA",
["護甲"] = "ARMOR",
["護甲值"] = "ARMOR",
["強化"] = "ARMOR",
["韌性"] = "RESILIENCE",
-- Patterns for color coded/special lines
["降低威脅值"] = "THREATREDUCTION",
["威脅值"] = "THREATREDUCTION",
["致命一擊傷害"] = "INCRCRITDMG",
["法術反射"] = "SPELLREFLECT",
["昏迷抗性"] = "STUNRESIST",
--["Stun Resist"] = "STUNRESIST",
["盾牌格擋值"] = "PERCBLOCKVALUE",
--["Increased Armor Value from Items"] = "PERCARMOR", --2% Increased Armor Value from Items, 提高2%裝備提供的護甲值
--["Reduce Spell Damage Taken by"] = "PERCREDSPELLDMG", --Reduce Spell Damage Taken by 2%, 減少2%法術傷害
--["Silence Duration Reduced by"] = "PERCSILENCE", --Silence Duration Reduced by 10%, 縮短10%沉默持續時間
--["Fear Duration Reduced by"] = "PERCFEAR", --Fear Duration Reduced by 10%, 縮短10%恐懼持續時間
--["Stun Duration Reduced by"] = "PERCSTUN", --Stun Duration Reduced by 10%, 縮短10%昏迷持續時間
--["Root Duration by"] = "PERCSNARE", --Reduces Snare/Root Duration by 10%, 縮短10%緩速及定身持續時間
["極效治療效果"] = "PERCCRITHEALING",
};
-- next we try to match against one pattern of stage 1 and one pattern of stage 2 and concatenate the effect strings
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE1"] = {
{ pattern = "秘法", effect = "ARCANE" },
{ pattern = "火焰", effect = "FIRE" },
{ pattern = "冰霜", effect = "FROST" },
{ pattern = "神聖", effect = "HOLY" },
{ pattern = "暗影", effect = "SHADOW" },
{ pattern = "自然", effect = "NATURE" }
};
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE2"] = {
{ pattern = "抗性", effect = "RES" },
{ pattern = "傷害", effect = "DMG" },
{ pattern = "效果", effect = "DMG" },
};
-- finally if we got no match, we match against some special enchantment patterns.
L["BONUSSCANNER_PATTERNS_OTHER"] = {
-- Infused Amethyst
--{ pattern = "%+(%d+)法術能量和%+(%d+)耐力", effect = {"SPELLPOW", "STA"} },
-- special patterns that cannot be handled any other way
{ pattern = "%+21致命一擊等級和2%%法力", effect = {"CRIT", "PERCMANA"}, value = {21, 2} },
--{ pattern = "%+12致命一擊等級和縮短15%%緩速及定身持續時間", effect = {"CRIT", "PERCSNARE"}, value = {12, 15} },
--{ pattern = "%+21致命一擊等級和縮短15%%緩速及定身持續時間", effect = {"CRIT", "PERCSNARE"}, value = {21, 15} },
--{ pattern = "%+14法術能量和%+2%%智力", effect = {"SPELLPOW", "PERCINT"}, value = {14, 2} },
--{ pattern = "%+25法術能量和%+2%%智力", effect = {"SPELLPOW", "PERCINT"}, value = {25, 2} },
--{ pattern = "%+18耐力和縮短15%%昏迷持續時間", effect = {"STA", "PERCSTUN"}, value = {18, 15} },
--{ pattern = "%+18法術能量和每5秒恢復4點法力", effect = {"SPELLPOW", "MANAREG"}, value = {18, 4} },
--{ pattern = "%+24法術能量和每5秒恢復6點法力", effect = {"SPELLPOW", "MANAREG"}, value = {24, 6} },
-- rest of custom patterns
--{ pattern = "每5秒恢復(%d+)點法力。", effect = "MANAREG" },
{ pattern = "%+(%d+)強化護甲", effect = "ARMOR" }, --Reinforced (+40 Armor) +40強化護甲
{ pattern = "%+(%d+)%%威脅值", effect = "THREATINCREASE" },
{ pattern = "瞄準鏡%(%+(%d+)致命一擊等級%)", effect = "CRIT" },
{ pattern = "瞄準鏡%(%+(%d+)傷害%)", effect = "RANGEDDMG" },
--自訂
{ pattern = "每5秒恢復(%d+)點法力", effect = "MANAREG" },
{ pattern = "%+(%d+)法術能量和%+(%d+)%%智力", effect = {"SPELLPOW", "PERCINT"} },
{ pattern = "%+(%d+)法術能量和降低(%d+)%%威脅值", effect = {"SPELLPOW", "THREATINCREASE"} },
{ pattern = "%+(%d+)耐力和提高(%d+)%%裝備提供的護甲值", effect = {"STA", "PERCARMOR"} },
{ pattern = "%+(%d+)耐力和減少(%d+)%%法術傷害", effect = {"STA", "PERCREDSPELLDMG"} },
{ pattern = "%+(%d+)法術能量和縮短(%d+)%%沉默持續時間", effect = {"SPELLPOW", "PERCSILENCE"} },
{ pattern = "%+(%d+)致命一擊等級和縮短(%d+)%%恐懼持續時間", effect = {"CRIT", "PERCFEAR"} },
{ pattern = "%+(%d+)耐力和縮短(%d+)%%昏迷持續時間", effect = {"STA", "PERCSTUN"} },
{ pattern = "%+(%d+)攻擊強度和縮短(%d+)%%昏迷持續時間", effect = {"ATTACKPOWER", "PERCSTUN"} },
{ pattern = "%+(%d+)法術能量和縮短(%d+)%%昏迷持續時間", effect = {"SPELLPOW", "PERCSTUN"} },
{ pattern = "%+(%d+)致命一擊等級和縮短(%d+)%%緩速及定身持續時間", effect = {"CRIT", "PERCSNARE"} },
--以下英文已刪除
{ pattern = "初級巫師之油", effect = {"SPELLPOW"}, value = 8 },
{ pattern = "次級巫師之油", effect = {"SPELLPOW"}, value = 16 },
{ pattern = "巫師之油", effect = {"SPELLPOW"}, value = 24 },
{ pattern = "卓越巫師之油", effect = {"SPELLPOW", "SPELLCRIT"}, value = {36, 14} },
{ pattern = "超強巫師之油", effect = {"SPELLPOW"}, value = 42 },
{ pattern = "初級法力之油", effect = "MANAREG", value = 4 },
{ pattern = "次級法力之油", effect = "MANAREG", value = 8 },
{ pattern = "卓越法力之油", effect = {"MANAREG", "SPELLPOW"}, value = {12, 25} },
{ pattern = "超強法力之油", effect = "MANAREG", value = 14 },
};
-- localized strings
L["BONUSSCANNER_BONUSSUM_LABEL"] = "裝備加成統計";
L["BONUSSCANNER_TOOLTIP_STRING"] = "BonusScanner 統計加成提示訊息 ";
L["BONUSSCANNER_TOOLTIPGEMS_STRING"] = "寶石顏色數量 ";
L["BONUSSCANNER_BASICLINKID_STRING"] = "基本 Itemlink ID 的 ";
L["BONUSSCANNER_EXTENDEDLINKID_STRING"] = "延伸 Itemlink ID 的 ";
L["BONUSSCANNER_TOOLTIP_ENABLED"] = "啟用";
L["BONUSSCANNER_TOOLTIP_DISABLED"] = "關閉";
L["BONUSSCANNER_IBONUS_LABEL"] = "物品加成 / ";
L["BONUSSCANNER_NOBONUS_LABEL"] = "沒有偵測到任何加成。";
L["BONUSSCANNER_CUREQ_LABEL"] = "目前裝備的加成效果";
L["BONUSSCANNER_CUREQDET_LABEL"] = "目前裝備的詳細加成效果";
L["BONUSSCANNER_OOR_LABEL"] = " 超出距離。";
L["BONUSSCANNER_GEMCOUNT_LABEL"] = "數量 ";
L["BONUSSCANNER_INVALIDTAR_LABEL"] = "無目標可檢視。";
L["BONUSSCANNER_SELTAR_LABEL"] = "請選擇先一個目標。";
L["BONUSSCANNER_SLOT_LABEL"] = "插槽";
L["BONUSSCANNER_FAILEDPARSE_LABEL"] = "伺服器中無此物品的暫存或者未得到驗證。";
L["BONUSSCANNER_CACHESUMMARY_LABEL"] = "BonusScanner 物品暫存: ";
L["BONUSSCANNER_CACHECLEAR_LABEL"] = "BonusScanner 物品暫存已清除。";
L["BONUSSCANNER_SPECIAL1_LABEL"] = " 致命一擊機率";
L["BONUSSCANNER_SPECIAL2_LABEL"] = " 閃躲/招架";
L["BONUSSCANNER_SPECIAL3_LABEL"] = " 近戰";
L["BONUSSCANNER_SPECIAL4_LABEL"] = " 法術";
L["BONUSSCANNER_SPECIAL5_LABEL"] = " 遠程/法術";
L["BONUSSCANNER_ITEMID_LABEL"] = "物品 ID: |cffffffff";
L["BONUSSCANNER_ILVL_LABEL"] = "物品 Level: |cffffffff";
L["BONUSSCANNER_ENCHANTID_LABEL"] = "附魔 ID: |cffffffff";
L["BONUSSCANNER_GEM1ID_LABEL"] = "寶石 1 ID: |cffffffff";
L["BONUSSCANNER_GEM2ID_LABEL"] = "寶石 2 ID: |cffffffff";
L["BONUSSCANNER_GEM3ID_LABEL"] = "寶石 3 ID: |cffffffff";
L["BONUSSCANNER_GEMRED_LABEL"] = "紅色寶石";
L["BONUSSCANNER_GEMBLUE_LABEL"] = "藍色寶石";
L["BONUSSCANNER_GEMYELLOW_LABEL"] = "黃色寶石";
L["BONUSSCANNER_GEMPRISM_LABEL"] = "Prismatic";
L["BONUSSCANNER_AVERAGE_ILVL_LABEL"] = "平均物品等級";
L["BONUSSCANNER_NEEDS_RELOADUI_LABEL"] = "配置的改變會在插件重載后生效";
L["BONUSSCANNER_LDB_PLUGIN_LABEL"] = "BonusScanner LDB 模組 ";
--bonus categories
L["BONUSSCANNER_CAT_ATT"] = "屬性";
L["BONUSSCANNER_CAT_RES"] = "抗性";
L["BONUSSCANNER_CAT_SKILL"] = "技能";
L["BONUSSCANNER_CAT_BON"] = "近戰和遠程攻擊";
L["BONUSSCANNER_CAT_SBON"] = "法術";
L["BONUSSCANNER_CAT_OBON"] = "生命力與法力值";
L["BONUSSCANNER_CAT_EBON"] = "特殊加成";
L["BONUSSCANNER_CAT_GEMS"] = "寶石插槽";
--slash command text
L["BONUSSCANNER_SLASH_STRING1"] = GREEN_FONT_COLOR_CODE.."BonusScanner 物品加成統計";
L["BONUSSCANNER_SLASH_STRING1a"] = "|cffffffff 作者 Crowley, Archarodim, jmsteele, Tristanian";
L["BONUSSCANNER_SLASH_STRING2"] = LIGHTYELLOW_FONT_COLOR_CODE.."用法: |cffffffff/bscan {show | details | tooltip | tooltip gems | itembasic | itemextend | broker | clearcache | target | target <player> | <itemlink> | <itemlink> <player> | <slotname>}";
L["BONUSSCANNER_SLASH_STRING3"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."show: |cffffffff顯示當前裝備的所有加成統計.";
L["BONUSSCANNER_SLASH_STRING4"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."details: |cffffffff顯示詳細的各類統計.";
L["BONUSSCANNER_SLASH_STRING5"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip: [";
L["BONUSSCANNER_SLASH_STRING5a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上顯示加成.";
L["BONUSSCANNER_SLASH_STRING14"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip gems: [";
L["BONUSSCANNER_SLASH_STRING14a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上顯示寶石顏色.";
L["BONUSSCANNER_SLASH_STRING12"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itembasic: [";
L["BONUSSCANNER_SLASH_STRING12a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上顯示物品的ID和等級.";
L["BONUSSCANNER_SLASH_STRING13"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itemextend: [";
L["BONUSSCANNER_SLASH_STRING13a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff在提示上顯示物品的附魔和寶石ID.";
L["BONUSSCANNER_SLASH_STRING15"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."broker: [";
L["BONUSSCANNER_SLASH_STRING15a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffff 控制 LDB 插件的狀態,其用來顯示角色的統計信息.";
L["BONUSSCANNER_SLASH_STRING11"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."clearcache: |cffffffff清除緩存.";
L["BONUSSCANNER_SLASH_STRING6"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target: |cffffffff顯示你目標的加成統計(必須在距離內).";
L["BONUSSCANNER_SLASH_STRING7"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target <player>: |cffffffff把你當前目標的加成數據密語給指定人.";
L["BONUSSCANNER_SLASH_STRING8"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink>: |cffffffff顯示鏈接物品的加成(用Shift-Click插入鏈接).";
L["BONUSSCANNER_SLASH_STRING9"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink> <player>: |cffffffff把你當前鏈接的加成數據密語給指定人.";
L["BONUSSCANNER_SLASH_STRING10"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<slotname>: |cffffffff顯示指定類別的加成統計.";

View File

@ -0,0 +1,418 @@
local L = LibStub("AceLocale-3.0"):NewLocale("BonusScanner","enUS",true)
-- bonus names
L["BONUSSCANNER_NAMES"] = {
--Base Stats
STR = "Strength",
AGI = "Agility",
STA = "Stamina",
INT = "Intellect",
SPI = "Spirit",
ARMOR = "Armor",
--Resistances
ARCANERES = "Arcane Resistance",
FIRERES = "Fire Resistance",
NATURERES = "Nature Resistance",
FROSTRES = "Frost Resistance",
SHADOWRES = "Shadow Resistance",
--Skills
FISHING = "Fishing",
MINING = "Mining",
HERBALISM = "Herbalism",
SKINNING = "Skinning",
DEFENSE = "Defense Rating",
EXPERTISE = "Expertise Rating",
--Abilities
BLOCK = "Block Rating",
BLOCKVALUE = "Block Value",
DODGE = "Dodge Rating",
PARRY = "Parry Rating",
RESILIENCE = "Resilience Rating",
DMGWPN = "Increased Melee Damage",
RANGEDDMG = "Ranged Weapon Damage",
ARMORPEN = "Armor Penetration Rating",
-- DPS
DPSMAIN = "Main Weapon(s) DPS",
DPSRANGED = "Ranged Weapon DPS",
DPSTHROWN = "Thrown Weapon DPS",
--Attack Power
ATTACKPOWER = "Attack Power",
ATTACKPOWERUNDEAD = "Attack Power against Undead",
ATTACKPOWERFERAL = "Attack Power in feral form",
RANGEDATTACKPOWER = "Ranged Attack Power",
--Critical
CRIT = "Critical Strike Rating",
RANGEDCRIT = "Ranged Critical Strike",
--HOLYCRIT = "Crit. Holy Spell", -- Investigation
--Hit
TOHIT = "Hit Rating",
RANGEDHIT = "Ranged Hit Rating",
--Haste
HASTE = "Haste Rating",
--Spell Damage/healing
DMGUNDEAD = "Spell Damage against Undead",
ARCANEDMG = "Arcane Damage",
FIREDMG = "Fire Damage",
FROSTDMG = "Frost Damage",
HOLYDMG = "Holy Damage",
NATUREDMG = "Nature Damage",
SHADOWDMG = "Shadow Damage",
SPELLPEN = "Spell Penetration",
SPELLPOW = "Spell Power",
--Regen
HEALTHREG = "Life Regeneration",
MANAREG = "Mana Regeneration",
--Health/mana
HEALTH = "Life Points",
MANA = "Mana Points",
--Extra bonuses
THREATREDUCTION = "% Reduced Threat",
THREATINCREASE = "% Increased Threat",
INCRCRITDMG = "% Increased Critical Damage",
SPELLREFLECT = "% Spell Reflect",
STUNRESIST = "% Stun Resistance",
PERCINT = "% Intellect",
PERCBLOCKVALUE = "% Shield Block Value",
-- WOTLK Metagems
PERCARMOR = "% Increased Armor Value",
PERCMANA ="% Mana",
PERCREDSPELLDMG = "% Reduced Spell Damage Taken",
PERCSNARE = "% Reduced Snare/Root Duration",
PERCSILENCE = "% Reduced Silence Duration",
PERCFEAR = "% Reduced Fear Duration",
PERCSTUN = "% Reduced Stun Duration",
PERCCRITHEALING = "% Increased Critical Healing",
};
-- equip and set bonus prefixes:
--L["BONUSSCANNER_PREFIX_EQUIP"] = "Equip: "; --no longer used but kept in case Blizzard decides to alter its own global string referring to this
L["BONUSSCANNER_PREFIX_SET"] = "Set: ";
L["BONUSSCANNER_PREFIX_SOCKET"] = "Socket Bonus: ";
L["BONUSSCANNER_WEAPON_SPEED"] = "Speed";
L["BONUSCANNER_GEM_STRINGS"] = {
-- red
["matches a red socket"] = { red = 1, yellow = 0, blue = 0, prismatic = 0},
-- blue
["matches a blue socket"] = { red = 0, yellow = 0, blue = 1, prismatic = 0},
-- yellow
["matches a yellow socket"] = { red = 0, yellow = 1, blue = 0, prismatic = 0},
-- purple
["matches a red or blue socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
["matches a blue or red socket"] = { red = 1, yellow = 0, blue = 1, prismatic = 0},
-- green
["matches a blue or yellow socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
["matches a yellow or blue socket"] = { red = 0, yellow = 1, blue = 1, prismatic = 0},
-- orange
["matches a red or yellow socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
["matches a yellow or red socket"] = { red = 1, yellow = 1, blue = 0, prismatic = 0},
-- prismatic
["matches any socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1},
["matches a red, yellow or blue socket"] = { red = 0, yellow = 0, blue = 0, prismatic = 1}
}
-- Enchant separators
L["BONUSSCANNER_GLOBAL_SEP"] = " +";
L["BONUSSCANNER_SEPARATORS"] = { "/", ", ", " & ", " and " };
-- passive bonus patterns. checked against lines which start with above prefixes
L["BONUSSCANNER_PATTERNS_PASSIVE"] = {
--Skills
{ pattern = "Increases defense rating by (%d+)%.", effect = "DEFENSE" }, --jmlsteele
{ pattern = "Improves your resilience rating by (%d+)%.", effect = "RESILIENCE" },
{ pattern = "Increases your expertise rating by (%d+)%.", effect = "EXPERTISE" },
{ pattern = "Increased Fishing %+(%d+)%.", effect = "FISHING" }, -- fishing poles
-- Abilities
{ pattern = "Increases your block rating by (%d+)%.", effect = "BLOCK" },
{ pattern = "Increases your shield block rating by (%d+)%.", effect = "BLOCK" },
{ pattern = "Increases the block value of your shield by (%d+)%.", effect = "BLOCKVALUE" },
{ pattern = "Increases your dodge rating by (%d+)%.", effect = "DODGE" },
{ pattern = "Increases your parry rating by (%d+)%.", effect = "PARRY" },
{ pattern = "%+(%d+) Weapon Damage%.", effect = "DMGWPN" }, -- Might of Cenarius...
--Crit
{ pattern = "Increases your critical strike rating by (%d+)%.", effect = "CRIT" },
{ pattern = "Improves critical strike rating by (%d+)%.", effect = "CRIT" },
{ pattern = "Improves melee critical strike rating by (%d+)%.", effect = "CRIT" },
{ pattern = "Increases your ranged critical strike rating by (%d+)%.", effect = "RANGEDCRIT" },
--Damage/Heal/Spell Power
{ pattern = "Increases spell power by (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases your spell power by (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases damage done by magical spells and effects by up to (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases shadow spell power by (%d+)%.", effect = "SHADOWDMG" },
{ pattern = "Increases arcane spell power by (%d+)%.", effect = "ARCANEDMG" },
{ pattern = "Increases fire spell power by (%d+)%.", effect = "FIREDMG" },
{ pattern = "Increases frost spell power by (%d+)%.", effect = "FROSTDMG" },
{ pattern = "Increases holy spell power by (%d+)%.", effect = "HOLYDMG" },
{ pattern = "Increases nature spell power by (%d+)%.", effect = "NATUREDMG" },
{ pattern = "Increases spell power slightly%.", effect = "SPELLPOW", value = 6 },
{ pattern = "Increases damage done to Undead by magical spells and effects by up to (%d+)", effect = "DMGUNDEAD" },
-- Multibonus Equip patterns
{ pattern = "Increases spell power of all party members within %d+ yards by up to (%d+)%.", effect = "SPELLPOW" },
{ pattern = "Increases your pet's resistances by 130 and increases your spell power by (%d+)%.", effect = "SPELLPOW" }, -- Void Star Talisman
--{ pattern = "Increases healing done by up to (%d+) and damage done by up to (%d+) for all magical spells and effects%.", effect = {"HEAL","DMG"} },
--{ pattern = "Increases your spell damage by up to (%d+) and your healing by up to (%d+)%.", effect = {"DMG","HEAL"} },
--{ pattern = "Increases healing done by magical spells and effects of all party members within %d+ yards by up to (%d+)%. ", effect = "HEAL" },
--{ pattern = "Increases damage and healing done by magical spells and effects of all party members within %d+ yards by up to (%d+)%.", effect = {"HEAL", "DMG"} },
{ pattern = "Restores (%d+) mana per 5 seconds to all party members within %d+ yards%.", effect = "MANAREG" },
{ pattern = "Increases the spell critical strike rating of all party members within %d+ yards by (%d+)%.", effect = "CRIT" }, --SPELLCRIT
{ pattern = "Increases defense rating by (%d+), Shadow resistance by (%d+) and your normal health regeneration by (%d+)%.", effect = {"DEFENSE", "SHADOWRES", "HEALTHREG"} },
--Attack power
{ pattern = "Increases attack power by (%d+)%.", effect = "ATTACKPOWER" },
{ pattern = "Increases melee and ranged attack power by (%d+)%.", effect = {"ATTACKPOWER","RANGEDATTACKPOWER"} }, -- Andonisus, Reaper of Souls pattern
{ pattern = "+(%d+) ranged Attack Power%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Increases ranged attack power by (%d+)%.", effect = "RANGEDATTACKPOWER" },
{ pattern = "Increases attack power by (%d+) in Cat, Bear, Dire Bear, and Moonkin forms only%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Increases attack power by (%d+) when fighting Undead%.", effect = "ATTACKPOWERUNDEAD" },
{ pattern = "+(%d+) Attack Power when fighting Undead%.", effect = "ATTACKPOWERUNDEAD" },
--Regen
{ pattern = "Restores (%d+) health per 5 sec%.", effect = "HEALTHREG" },
{ pattern = "Restores (%d+) health every 5 sec%.", effect = "HEALTHREG" }, -- both versions ('per' and 'every') seem to be used
{ pattern = "Restores (%d+) mana per 5 sec%.", effect = "MANAREG" },
{ pattern = "Restores (%d+) mana every 5 sec%.", effect = "MANAREG" },
--Hit
{ pattern = "Increases your hit rating by (%d+)%.", effect = "TOHIT" },
{ pattern = "Improves hit rating by (%d+)%.", effect = "TOHIT" },
--Haste
{ pattern = "Improves haste rating by (%d+)%.", effect = "HASTE" },
--Penetration
{ pattern = "Decreases the magical resistances of your spell targets by (%d+).", effect = "SPELLPEN" },
{ pattern = "Increases your spell penetration by (%d+)%.", effect = "SPELLPEN" },
{ pattern = "Increases your armor penetration rating by (%d+)%.", effect = "ARMORPEN" },
{ pattern = "Increases armor penetration rating by (%d+)%.", effect = "ARMORPEN" }
};
-- generic patterns have the form "+xx bonus" or "bonus +xx" or even "xx bonus" with an optional % sign after the value.
-- first the generic bonus string is looked up in the following table
L["BONUSSCANNER_PATTERNS_GENERIC_LOOKUP"] = {
["All Stats"] = {"STR", "AGI", "STA", "INT", "SPI"},
["to All Stats"] = {"STR", "AGI", "STA", "INT", "SPI"},
["Strength"] = "STR",
["Agility"] = "AGI",
["Stamina"] = "STA",
["Intellect"] = "INT",
["Spirit"] = "SPI",
["All Resistances"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- obsidian items
["Resist All"] = { "ARCANERES", "FIRERES", "FROSTRES", "NATURERES", "SHADOWRES"}, -- prismatic gems
["Fishing"] = "FISHING",
["Fishing Lure"] = "FISHING",
["Increased Fishing"] = "FISHING",
["Mining"] = "MINING",
["Herbalism"] = "HERBALISM",
["Skinning"] = "SKINNING",
["Defense"] = "DEFENSE",
["Increased Defense"] = "DEFENSE",
["Attack Power"] = "ATTACKPOWER",
["Attack Power when fighting Undead"] = "ATTACKPOWERUNDEAD",
["Attack Power versus Undead"] = "ATTACKPOWERUNDEAD",
["Attack Power in Cat, Bear, Dire Bear, and Moonkin forms only"] = "ATTACKPOWERFERAL",
["Weapon Damage"] = "DMGWPN",
-- TBC/Wotlk Patterns Generic/Gems/Sockets
["Spell Power"] = "SPELLPOW",
["Critical Strike Rating"] = "CRIT",
["Critical strike rating"] = "CRIT",
["Critical Rating"] = "CRIT",
["Crit Rating"] = "CRIT",
["Ranged Critical Strike"] = "RANGEDCRIT",
["Spell Penetration"] = "SPELLPEN",
["Armor Penetration Rating"] = "ARMORPEN",
["Defense Rating"] = "DEFENSE",
["Haste Rating"] = "HASTE",
["Mana per 5 Seconds"] = "MANAREG",
["mana per 5 seconds"] = "MANAREG",
["Mana every 5 Sec"] = "MANAREG",
["Mana every 5 seconds"] = "MANAREG",
["Mana restored per 5 seconds"] = "MANAREG",
["Mana Per 5 sec"] = "MANAREG",
["mana per 5 sec"] = "MANAREG",
["Mana per 5 Sec"] = "MANAREG",
["Mana per 5 sec"] = "MANAREG",
["Dodge Rating"] = "DODGE",
["Parry Rating"] = "PARRY",
["Resilience Rating"] = "RESILIENCE",
["Melee Damage"] = "DMGWPN",
["Expertise Rating"] = "EXPERTISE",
-- End TBC Patterns
["Dodge"] = "DODGE",
["Block"] = "BLOCKVALUE",
["Block Value"] = "BLOCKVALUE",
["Block Rating"] = "BLOCK",
["Blocking"] = "BLOCK",
["Hit"] = "TOHIT",
["Hit Rating"] = "TOHIT",
["Ranged Hit Rating"] = "RANGEDHIT",
["Ranged Attack Power"] = "RANGEDATTACKPOWER",
["ranged Attack Power"] = "RANGEDATTACKPOWER", -- Experimental for TBC
["Health per 5 sec"] = "HEALTHREG",
["health every 5 sec"] = "HEALTHREG",
["Healing"] = "HEAL",
["Healing Spells"] = "HEAL",
["Increased Healing"] = "HEAL",
["mana every 5 sec"] = "MANAREG",
["Mana Regen"] = "MANAREG",
["Critical"] = "CRIT",
["Critical Hit"] = "CRIT",
["Health"] = "HEALTH",
["HP"] = "HEALTH",
["Mana"] = "MANA",
["Armor"] = "ARMOR",
["Reinforced"] = "ARMOR",
["Resilience"] = "RESILIENCE",
-- Patterns for color coded/special lines
["Reduced Threat"] = "THREATREDUCTION",
["Increased Critical Damage"] = "INCRCRITDMG",
["Spell Reflect"] = "SPELLREFLECT",
["Stun Resistance"] = "STUNRESIST",
["Stun Resist"] = "STUNRESIST",
["Shield Block Value"] = "PERCBLOCKVALUE",
["Increased Armor Value from Items"] = "PERCARMOR",
["Reduce Spell Damage Taken by"] = "PERCREDSPELLDMG",
["Silence Duration Reduced by"] = "PERCSILENCE",
["Fear Duration Reduced by"] = "PERCFEAR",
["Stun Duration Reduced by"] = "PERCSTUN",
["Root Duration by"] = "PERCSNARE",
["Increased Critical Healing Effect"] = "PERCCRITHEALING",
};
-- next we try to match against one pattern of stage 1 and one pattern of stage 2 and concatenate the effect strings
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE1"] = {
{ pattern = "Arcane", effect = "ARCANE" },
{ pattern = "Fire", effect = "FIRE" },
{ pattern = "Frost", effect = "FROST" },
{ pattern = "Holy", effect = "HOLY" },
{ pattern = "Shadow", effect = "SHADOW" },
{ pattern = "Nature", effect = "NATURE" }
};
L["BONUSSCANNER_PATTERNS_GENERIC_STAGE2"] = {
{ pattern = "Resist", effect = "RES" },
{ pattern = "Damage", effect = "DMG" },
{ pattern = "Effects", effect = "DMG" }
};
-- finally if we got no match, we match against some special enchantment patterns.
L["BONUSSCANNER_PATTERNS_OTHER"] = {
-- Infused Amethyst
{ pattern = "Spell Power %+(%d+) and Stamina %+(%d+)", effect = {"SPELLPOW", "STA"} },
-- special patterns that cannot be handled any other way
{ pattern = "%+21 Critical Strike Rating and %+2%% Mana", effect = {"CRIT", "PERCMANA"}, value = {21, 2} },
{ pattern = "%+12 Critical Strike Rating and Reduces Snare/Root Duration by 15%%", effect = {"CRIT", "PERCSNARE"}, value = {12, 15} },
{ pattern = "%+21 Critical Strike Rating and Reduces Snare/Root Duration by 15%%", effect = {"CRIT", "PERCSNARE"}, value = {21, 15} },
{ pattern = "%+14 Spell Power and %+2%% Intellect", effect = {"SPELLPOW", "PERCINT"}, value = {14, 2} },
{ pattern = "%+25 Spell Power and %+2%% Intellect", effect = {"SPELLPOW", "PERCINT"}, value = {25, 2} },
{ pattern = "%+18 Stamina and Stun Duration Reduced by 15%% Stun Resist", effect = {"STA", "PERCSTUN"}, value = {18, 15} },
{ pattern = "%+18 Spell Power and %+4 Mana/5 seconds", effect = {"SPELLPOW", "MANAREG"}, value = {18, 4} },
{ pattern = "%+24 Spell Power and %+6 Mana/5 seconds", effect = {"SPELLPOW", "MANAREG"}, value = {24, 6} },
{ pattern = "%+61 Spell Power and %+6 Mana/5 seconds", effect = {"SPELLPOW", "MANAREG"}, value = {61, 6} },
{ pattern = "%+2%% Threat and 10 Parry Rating", effect = {"THREATINCREASE","PARRY"}, value = {2 , 10} },
-- rest of custom patterns
{ pattern = "Increases attack power by (%d+) in Cat, Bear, Dire Bear, and Moonkin forms only%.", effect = "ATTACKPOWERFERAL" },
{ pattern = "Mana Regen (%d+) per 5 sec", effect = "MANAREG" },
{ pattern = "%+(%d+)% Health and Mana every 5 sec", effect = {"MANAREG", "HEALTHREG"} },
{ pattern = "%+(%d+)% Mana and Health every 5 sec", effect = {"MANAREG", "HEALTHREG"} },
{ pattern = "Reinforced %(%+(%d+) Armor%)", effect = "ARMOR" },
{ pattern = "%+(%d+)%% Threat", effect = "THREATINCREASE" },
{ pattern = "Scope %(%+(%d+) Critical Strike Rating%)", effect = "CRIT" },
{ pattern = "Scope %(%+(%d+) Damage%)", effect = "RANGEDDMG" },
};
-- localized strings
L["BONUSSCANNER_BONUSSUM_LABEL"] = "Item Bonus Summary";
L["BONUSSCANNER_TOOLTIP_STRING"] = "BonusScanner Tooltip Bonus Summary ";
L["BONUSSCANNER_TOOLTIPGEMS_STRING"] = "Gem color count ";
L["BONUSSCANNER_BASICLINKID_STRING"] = "Basic Itemlink ID's ";
L["BONUSSCANNER_EXTENDEDLINKID_STRING"] = "Extended Itemlink ID's ";
L["BONUSSCANNER_TOOLTIP_ENABLED"] = "Enabled";
L["BONUSSCANNER_TOOLTIP_DISABLED"] = "Disabled";
L["BONUSSCANNER_IBONUS_LABEL"] = "Item bonuses of ";
L["BONUSSCANNER_NOBONUS_LABEL"] = "No bonuses detected.";
L["BONUSSCANNER_CUREQ_LABEL"] = "Current equipment bonuses";
L["BONUSSCANNER_CUREQDET_LABEL"] = "Current equipment bonus details";
L["BONUSSCANNER_OOR_LABEL"] = " is out of range.";
L["BONUSSCANNER_GEMCOUNT_LABEL"] = "Counts as ";
L["BONUSSCANNER_INVALIDTAR_LABEL"] = "Invalid target to scan.";
L["BONUSSCANNER_SELTAR_LABEL"] = "Please select a target first.";
L["BONUSSCANNER_SLOT_LABEL"] = "slot";
L["BONUSSCANNER_FAILEDPARSE_LABEL"] = "Item is either not cached or hasn't been validated on the server.";
L["BONUSSCANNER_CACHESUMMARY_LABEL"] = "BonusScanner items cached: ";
L["BONUSSCANNER_CACHECLEAR_LABEL"] = "BonusScanner item cache has been cleared.";
L["BONUSSCANNER_SPECIAL1_LABEL"] = " crit chance";
L["BONUSSCANNER_SPECIAL2_LABEL"] = " dodged/parried";
L["BONUSSCANNER_SPECIAL3_LABEL"] = " melee";
L["BONUSSCANNER_SPECIAL4_LABEL"] = " spells";
L["BONUSSCANNER_SPECIAL5_LABEL"] = " ranged/spells";
L["BONUSSCANNER_ITEMID_LABEL"] = "Item ID: |cffffffff";
L["BONUSSCANNER_ILVL_LABEL"] = "Item Level: |cffffffff";
L["BONUSSCANNER_ENCHANTID_LABEL"] = "Enchant ID: |cffffffff";
L["BONUSSCANNER_GEM1ID_LABEL"] = "Gem1 ID: |cffffffff";
L["BONUSSCANNER_GEM2ID_LABEL"] = "Gem2 ID: |cffffffff";
L["BONUSSCANNER_GEM3ID_LABEL"] = "Gem3 ID: |cffffffff";
L["BONUSSCANNER_GEMRED_LABEL"] = "Red";
L["BONUSSCANNER_GEMBLUE_LABEL"] = "Blue";
L["BONUSSCANNER_GEMYELLOW_LABEL"] = "Yellow";
L["BONUSSCANNER_GEMPRISM_LABEL"] = "Prismatic";
L["BONUSSCANNER_AVERAGE_ILVL_LABEL"] = "Average item Level";
L["BONUSSCANNER_NEEDS_RELOADUI_LABEL"] = "Changes will take effect after the UI has been reloaded.";
L["BONUSSCANNER_LDB_PLUGIN_LABEL"] = "BonusScanner LDB Plugin ";
--bonus categories
L["BONUSSCANNER_CAT_ATT"] = "Attributes";
L["BONUSSCANNER_CAT_RES"] = "Resistance";
L["BONUSSCANNER_CAT_SKILL"] = "Skills";
L["BONUSSCANNER_CAT_BON"] = "Melee and ranged combat";
L["BONUSSCANNER_CAT_SBON"] = "Spells";
L["BONUSSCANNER_CAT_OBON"] = "Life and mana";
L["BONUSSCANNER_CAT_EBON"] = "Special Bonuses";
L["BONUSSCANNER_CAT_GEMS"] = "Socketed Gems";
--slash command text
L["BONUSSCANNER_SLASH_STRING1"] = GREEN_FONT_COLOR_CODE.."BonusScanner ";
L["BONUSSCANNER_SLASH_STRING1a"] = "|cffffffff by Crowley, Archarodim, jmsteele, Tristanian";
L["BONUSSCANNER_SLASH_STRING2"] = LIGHTYELLOW_FONT_COLOR_CODE.."Usage: |cffffffff/bscan {show | details | tooltip | tooltip gems | itembasic | itemextend | broker | clearcache | target | target <player> | <itemlink> | <itemlink> <player> | <slotname>}";
L["BONUSSCANNER_SLASH_STRING3"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."show: |cffffffffShows all the bonuses of the current equipment.";
L["BONUSSCANNER_SLASH_STRING4"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."details: |cffffffffShows bonuses with slot distribution.";
L["BONUSSCANNER_SLASH_STRING5"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip: [";
L["BONUSSCANNER_SLASH_STRING5a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAttaches item bonus summary on tooltips.";
L["BONUSSCANNER_SLASH_STRING14"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."tooltip gems: [";
L["BONUSSCANNER_SLASH_STRING14a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAttaches gem color count on tooltips (requires tooltips enabled).";
L["BONUSSCANNER_SLASH_STRING12"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itembasic: [";
L["BONUSSCANNER_SLASH_STRING12a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAttaches item level and item ID properties on tooltips (requires tooltips enabled).";
L["BONUSSCANNER_SLASH_STRING13"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."itemextend: [";
L["BONUSSCANNER_SLASH_STRING13a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffAttaches enchant and gem ID properties on tooltips (requires tooltips enabled).";
L["BONUSSCANNER_SLASH_STRING15"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."broker: [";
L["BONUSSCANNER_SLASH_STRING15a"] = LIGHTYELLOW_FONT_COLOR_CODE.."] |cffffffffToggles the state of the LDB feed, used to display gear bonuses for the current character.";
L["BONUSSCANNER_SLASH_STRING11"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."clearcache: |cffffffffClears the item cache and forces a garbage collection.";
L["BONUSSCANNER_SLASH_STRING6"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target: |cffffffffShows bonuses for your target's equipped gear (must be in inspect range).";
L["BONUSSCANNER_SLASH_STRING7"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."target <player>: |cffffffffWhispers bonuses for your target's equipped gear to the player specified.";
L["BONUSSCANNER_SLASH_STRING8"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink>: |cffffffffShows bonuses of linked item (insert link with Shift-Click).";
L["BONUSSCANNER_SLASH_STRING9"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<itemlink> <player>: |cffffffffWhispers bonuses of linked item to the player specified.";
L["BONUSSCANNER_SLASH_STRING10"] = " - "..LIGHTYELLOW_FONT_COLOR_CODE.."<slotname>: |cffffffffShows bonuses of given equipment slot.";

62
GearScore/Broker.lua Normal file
View File

@ -0,0 +1,62 @@
--Created by Fyrye
--@Fyrye:
--I intergrated this directly within the addon.
--I also commented off the "Pruneing" function because it doesnt really work in the same way anymore. The pruning is down almost all automatically and it doesnt actually remove "low" scores anymore.
--Next, when Opening the options menu I set the variable "GearScore_DontDisplayDataAfterClosingOptions = true" so that when they open the options menu from this method
--it wont cause the profiles screen to display afterwards. (I made the appropriate changes within the addon as well)
GearScoreLDB = {}
function GearScoreLDB:Initialize()
self.LDB = LibStub("LibDataBroker-1.1", true);
self.DataObj = self.LDB:NewDataObject("GearScore",
{
type = "data source",
icon = "Interface\\ICONS\\INV_Chest_Plate12",
text = "GearScore",
OnClick = function(pFrame, pButton) self:OnClick(pFrame, pButton); end,
OnTooltipShow = function(tooltip)
if not tooltip or not tooltip.AddLine then return end
tooltip:AddLine("GearScore",1,1,1)
tooltip:AddLine("|cff7fff7fClick|r to show GearScore profile UI.")
tooltip:AddLine("|cff7fff7fShift-click|r to show the GearScore database.")
--tooltip:AddLine("|cff7fff7fAlt-click|r to Prune the database of low GearScores.")
tooltip:AddLine("|cff7fff7fRight-click|r to show GearScore Options.")
tooltip:AddLine(" ")
end,
});
StaticPopupDialogs["GearScoreLDBPrompt"] = {
text = "Are you sure you want to prune your GearScore Database?",
button1 = "Yes",
button2 = "No",
OnAccept = function()
GearScore_Prune()
end,
timeout = 0,
whileDead = 1,
hideOnEscape = 1
};
end
local pTarget
function GearScoreLDB:OnClick(pFrame, pButton)
if pButton == "LeftButton" then
if IsAltKeyDown() then
--StaticPopup_Show("GearScoreLDBPrompt")
elseif IsShiftKeyDown() then
GearScore_HideOptions()
GearScore_DisplayDatabase()
else
GS_SCANSET("")
end
else
GearScore_DontDisplayDataAfterClosingOptions = true
GearScore_ShowOptions()
end
end
GearScoreLDB:Initialize();

2209
GearScore/Frame.xml Normal file

File diff suppressed because it is too large Load Diff

4
GearScore/GearScore.lbf Normal file
View File

@ -0,0 +1,4 @@
[Breakpoint1]
Line=218
Status=1
Condition=

1512
GearScore/GearScore.lua Normal file

File diff suppressed because it is too large Load Diff

25
GearScore/GearScore.toc Normal file
View File

@ -0,0 +1,25 @@
## Interface: 30300
## Title: GearScore
## Notes: Quickly and easily judge a player's level of Gear
## Version: 3.1.17 - Release
## Author: Mirrikat45
## SavedVariables: GS_Data, GS_Settings
## Dependencies: BonusScanner
## OptionalDeps: Ace3, LibQTip-1.0, LibQTipClick-1.1, LibDataBroker-1.1, Recount
embeds.xml
locales\GearScore-enUS.lua
locales\GearScore-frFR.lua
locales\GearScore-koKR.lua
locales\GearScore-zhTW.lua
locales\GearScore-esES.lua
information.lua
Frame.xml
GearScore.lua
recount.lua
Broker.lua
weights.lua

View File

@ -0,0 +1,634 @@
--- **AceAddon-3.0** provides a template for creating addon objects.
-- It'll provide you with a set of callback functions that allow you to simplify the loading
-- process of your addon.\\
-- Callbacks provided are:\\
-- * **OnInitialize**, which is called directly after the addon is fully loaded.
-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
-- * **OnDisable**, which is only called when your addon is manually being disabled.
-- @usage
-- -- A small (but complete) addon, that doesn't do anything,
-- -- but shows usage of the callbacks.
-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
--
-- function MyAddon:OnInitialize()
-- -- do init tasks here, like loading the Saved Variables,
-- -- or setting up slash commands.
-- end
--
-- function MyAddon:OnEnable()
-- -- Do more initialization here, that really enables the use of your addon.
-- -- Register Events, Hook functions, Create Frames, Get information from
-- -- the game that wasn't available in OnInitialize
-- end
--
-- function MyAddon:OnDisable()
-- -- Unhook, Unregister Events, Hide frames that you created.
-- -- You would probably only use an OnDisable if you want to
-- -- build a "standby" mode, or be able to toggle modules on/off.
-- end
-- @class file
-- @name AceAddon-3.0.lua
-- @release $Id: AceAddon-3.0.lua 777 2009-04-04 20:16:09Z nevcairiel $
local MAJOR, MINOR = "AceAddon-3.0", 5
local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceAddon then return end -- No Upgrade needed.
AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
AceAddon.addons = AceAddon.addons or {} -- addons in general
AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
local tinsert, tconcat = table.insert, table.concat
local fmt = string.format
local pairs, next, type = pairs, next, type
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ...
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
return Dispatchers[select('#', ...)](func, ...)
end
end
-- local functions that will be implemented further down
local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
-- used in the addon metatable
local function addontostring( self ) return self.name end
--- Create a new AceAddon-3.0 addon.
-- Any libraries you specified will be embeded, and the addon will be scheduled for
-- its OnInitialize and OnEnable callbacks.
-- The final addon object, with all libraries embeded, will be returned.
-- @paramsig [object ,]name[, lib, ...]
-- @param object Table to use as a base for the addon (optional)
-- @param name Name of the addon object to create
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create a simple addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
--
-- -- Create a Addon object based on the table of a frame
-- local MyFrame = CreateFrame("Frame")
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
function AceAddon:NewAddon(objectorname, ...)
local object,name
local i=1
if type(objectorname)=="table" then
object=objectorname
name=...
i=2
else
name=objectorname
end
if type(name)~="string" then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
end
if self.addons[name] then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
end
object = object or {}
object.name = name
local addonmeta = {}
local oldmeta = getmetatable(object)
if oldmeta then
for k, v in pairs(oldmeta) do addonmeta[k] = v end
end
addonmeta.__tostring = addontostring
setmetatable( object, addonmeta )
self.addons[name] = object
object.modules = {}
object.defaultModuleLibraries = {}
Embed( object ) -- embed NewModule, GetModule methods
self:EmbedLibraries(object, select(i,...))
-- add to queue of addons to be initialized upon ADDON_LOADED
tinsert(self.initializequeue, object)
return object
end
--- Get the addon object by its name from the internal AceAddon registry.
-- Throws an error if the addon object cannot be found (except if silent is set).
-- @param name unique name of the addon object
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- -- Get the Addon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
function AceAddon:GetAddon(name, silent)
if not silent and not self.addons[name] then
error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
end
return self.addons[name]
end
-- - Embed a list of libraries into the specified addon.
-- This function will try to embed all of the listed libraries into the addon
-- and error if a single one fails.
--
-- **Note:** This function is for internal use by :NewAddon/:NewModule
-- @paramsig addon, [lib, ...]
-- @param addon addon object to embed the libs in
-- @param lib List of libraries to embed into the addon
function AceAddon:EmbedLibraries(addon, ...)
for i=1,select("#", ... ) do
local libname = select(i, ...)
self:EmbedLibrary(addon, libname, false, 4)
end
end
-- - Embed a library into the addon object.
-- This function will check if the specified library is registered with LibStub
-- and if it has a :Embed function to call. It'll error if any of those conditions
-- fails.
--
-- **Note:** This function is for internal use by :EmbedLibraries
-- @paramsig addon, libname[, silent[, offset]]
-- @param addon addon object to embed the library in
-- @param libname name of the library to embed
-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
function AceAddon:EmbedLibrary(addon, libname, silent, offset)
local lib = LibStub:GetLibrary(libname, true)
if not lib and not silent then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
elseif lib and type(lib.Embed) == "function" then
lib:Embed(addon)
tinsert(self.embeds[addon], libname)
return true
elseif lib then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
end
end
--- Return the specified module from an addon object.
-- Throws an error if the addon object cannot be found (except if silent is set)
-- @name //addon//:GetModule
-- @paramsig name[, silent]
-- @param name unique name of the module
-- @param silent if true, the module is optional, silently return nil if its not found (optional)
-- @usage
-- -- Get the Addon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- -- Get the Module
-- MyModule = MyAddon:GetModule("MyModule")
function GetModule(self, name, silent)
if not self.modules[name] and not silent then
error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
end
return self.modules[name]
end
local function IsModuleTrue(self) return true end
--- Create a new module for the addon.
-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
-- an addon object.
-- @name //addon//:NewModule
-- @paramsig name[, prototype|lib[, lib, ...]]
-- @param name unique name of the module
-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create a module with some embeded libraries
-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
--
-- -- Create a module with a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
function NewModule(self, name, prototype, ...)
if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
-- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
-- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
module.IsModule = IsModuleTrue
module:SetEnabledState(self.defaultModuleState)
module.moduleName = name
if type(prototype) == "string" then
AceAddon:EmbedLibraries(module, prototype, ...)
else
AceAddon:EmbedLibraries(module, ...)
end
AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
if not prototype or type(prototype) == "string" then
prototype = self.defaultModulePrototype or nil
end
if type(prototype) == "table" then
local mt = getmetatable(module)
mt.__index = prototype
setmetatable(module, mt) -- More of a Base class type feel.
end
safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
self.modules[name] = module
return module
end
--- Returns the real name of the addon or module, without any prefix.
-- @name //addon//:GetName
-- @paramsig
-- @usage
-- print(MyAddon:GetName())
-- -- prints "MyAddon"
function GetName(self)
return self.moduleName or self.name
end
--- Enables the Addon, if possible, return true or false depending on success.
-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
-- and enabling all modules of the addon (unless explicitly disabled).\\
-- :Enable() also sets the internal `enableState` variable to true
-- @name //addon//:Enable
-- @paramsig
-- @usage
-- -- Enable MyModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Enable()
function Enable(self)
self:SetEnabledState(true)
return AceAddon:EnableAddon(self)
end
--- Disables the Addon, if possible, return true or false depending on success.
-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
-- and disabling all modules of the addon.\\
-- :Disable() also sets the internal `enableState` variable to false
-- @name //addon//:Disable
-- @paramsig
-- @usage
-- -- Disable MyAddon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:Disable()
function Disable(self)
self:SetEnabledState(false)
return AceAddon:DisableAddon(self)
end
--- Enables the Module, if possible, return true or false depending on success.
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
-- @name //addon//:EnableModule
-- @paramsig name
-- @usage
-- -- Enable MyModule using :GetModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Enable()
--
-- -- Enable MyModule using the short-hand
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:EnableModule("MyModule")
function EnableModule(self, name)
local module = self:GetModule( name )
return module:Enable()
end
--- Disables the Module, if possible, return true or false depending on success.
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
-- @name //addon//:DisableModule
-- @paramsig name
-- @usage
-- -- Disable MyModule using :GetModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Disable()
--
-- -- Disable MyModule using the short-hand
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:DisableModule("MyModule")
function DisableModule(self, name)
local module = self:GetModule( name )
return module:Disable()
end
--- Set the default libraries to be mixed into all modules created by this object.
-- Note that you can only change the default module libraries before any module is created.
-- @name //addon//:SetDefaultModuleLibraries
-- @paramsig lib[, lib, ...]
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create the addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
-- -- Create a module
-- MyModule = MyAddon:NewModule("MyModule")
function SetDefaultModuleLibraries(self, ...)
if next(self.modules) then
error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleLibraries = {...}
end
--- Set the default state in which new modules are being created.
-- Note that you can only change the default state before any module is created.
-- @name //addon//:SetDefaultModuleState
-- @paramsig state
-- @param state Default state for new modules, true for enabled, false for disabled
-- @usage
-- -- Create the addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- -- Set the default state to "disabled"
-- MyAddon:SetDefaultModuleState(false)
-- -- Create a module and explicilty enable it
-- MyModule = MyAddon:NewModule("MyModule")
-- MyModule:Enable()
function SetDefaultModuleState(self, state)
if next(self.modules) then
error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleState = state
end
--- Set the default prototype to use for new modules on creation.
-- Note that you can only change the default prototype before any module is created.
-- @name //addon//:SetDefaultModulePrototype
-- @paramsig prototype
-- @param prototype Default prototype for the new modules (table)
-- @usage
-- -- Define a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- -- Set the default prototype
-- MyAddon:SetDefaultModulePrototype(prototype)
-- -- Create a module and explicitly Enable it
-- MyModule = MyAddon:NewModule("MyModule")
-- MyModule:Enable()
-- -- should print "OnEnable called!" now
-- @see NewModule
function SetDefaultModulePrototype(self, prototype)
if next(self.modules) then
error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
end
if type(prototype) ~= "table" then
error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
end
self.defaultModulePrototype = prototype
end
--- Set the state of an addon or module
-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
-- @name //addon//:SetEnabledState
-- @paramsig state
-- @param state the state of an addon or module (enabled=true, disabled=false)
function SetEnabledState(self, state)
self.enabledState = state
end
--- Return an iterator of all modules associated to the addon.
-- @name //addon//:IterateModules
-- @paramsig
-- @usage
-- -- Enable all modules
-- for name, module in MyAddon:IterateModules() do
-- module:Enable()
-- end
local function IterateModules(self) return pairs(self.modules) end
-- Returns an iterator of all embeds in the addon
-- @name //addon//:IterateEmbeds
-- @paramsig
local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
--- Query the enabledState of an addon.
-- @name //addon//:IsEnabled
-- @paramsig
-- @usage
-- if MyAddon:IsEnabled() then
-- MyAddon:Disable()
-- end
local function IsEnabled(self) return self.enabledState end
local mixins = {
NewModule = NewModule,
GetModule = GetModule,
Enable = Enable,
Disable = Disable,
EnableModule = EnableModule,
DisableModule = DisableModule,
IsEnabled = IsEnabled,
SetDefaultModuleLibraries = SetDefaultModuleLibraries,
SetDefaultModuleState = SetDefaultModuleState,
SetDefaultModulePrototype = SetDefaultModulePrototype,
SetEnabledState = SetEnabledState,
IterateModules = IterateModules,
IterateEmbeds = IterateEmbeds,
GetName = GetName,
}
local function IsModule(self) return false end
local pmixins = {
defaultModuleState = true,
enabledState = true,
IsModule = IsModule,
}
-- Embed( target )
-- target (object) - target object to embed aceaddon in
--
-- this is a local function specifically since it's meant to be only called internally
function Embed(target)
for k, v in pairs(mixins) do
target[k] = v
end
for k, v in pairs(pmixins) do
target[k] = target[k] or v
end
end
-- - Initialize the addon after creation.
-- This function is only used internally during the ADDON_LOADED event
-- It will call the **OnInitialize** function on the addon object (if present),
-- and the **OnEmbedInitialize** function on all embeded libraries.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- @param addon addon object to intialize
function AceAddon:InitializeAddon(addon)
safecall(addon.OnInitialize, addon)
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
end
-- we don't call InitializeAddon on modules specifically, this is handled
-- from the event handler and only done _once_
end
-- - Enable the addon after creation.
-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
-- It will call the **OnEnable** function on the addon object (if present),
-- and the **OnEmbedEnable** function on all embeded libraries.\\
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- Use :Enable on the addon itself instead.
-- @param addon addon object to enable
function AceAddon:EnableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if self.statuses[addon.name] or not addon.enabledState then return false end
-- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
self.statuses[addon.name] = true
safecall(addon.OnEnable, addon)
-- make sure we're still enabled before continueing
if self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedEnable, lib, addon) end
end
-- enable possible modules.
for name, module in pairs(addon.modules) do
self:EnableAddon(module)
end
end
return self.statuses[addon.name] -- return true if we're disabled
end
-- - Disable the addon
-- Note: This function is only used internally.
-- It will call the **OnDisable** function on the addon object (if present),
-- and the **OnEmbedDisable** function on all embeded libraries.\\
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- Use :Disable on the addon itself instead.
-- @param addon addon object to enable
function AceAddon:DisableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if not self.statuses[addon.name] then return false end
-- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
self.statuses[addon.name] = false
safecall( addon.OnDisable, addon )
-- make sure we're still disabling...
if not self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedDisable, lib, addon) end
end
-- disable possible modules.
for name, module in pairs(addon.modules) do
self:DisableAddon(module)
end
end
return not self.statuses[addon.name] -- return true if we're disabled
end
--- Get an iterator over all registered addons.
-- @usage
-- -- Print a list of all installed AceAddon's
-- for name, addon in AceAddon:IterateAddons() do
-- print("Addon: " .. name)
-- end
function AceAddon:IterateAddons() return pairs(self.addons) end
--- Get an iterator over the internal status registry.
-- @usage
-- -- Print a list of all enabled addons
-- for name, status in AceAddon:IterateAddonStatus() do
-- if status then
-- print("EnabledAddon: " .. name)
-- end
-- end
function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
-- Following Iterators are deprecated, and their addon specific versions should be used
-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
-- Event Handling
local function onEvent(this, event, arg1)
if event == "ADDON_LOADED" or event == "PLAYER_LOGIN" then
-- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
while(#AceAddon.initializequeue > 0) do
local addon = tremove(AceAddon.initializequeue, 1)
-- this might be an issue with recursion - TODO: validate
if event == "ADDON_LOADED" then addon.baseName = arg1 end
AceAddon:InitializeAddon(addon)
tinsert(AceAddon.enablequeue, addon)
end
if IsLoggedIn() then
while(#AceAddon.enablequeue > 0) do
local addon = tremove(AceAddon.enablequeue, 1)
AceAddon:EnableAddon(addon)
end
end
end
end
AceAddon.frame:RegisterEvent("ADDON_LOADED")
AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
AceAddon.frame:SetScript("OnEvent", onEvent)
-- upgrade embeded
for name, addon in pairs(AceAddon.addons) do
Embed(addon)
end

View File

@ -0,0 +1,4 @@
<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="AceAddon-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,128 @@
--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
-- @class file
-- @name AceLocale-3.0
-- @release $Id: AceLocale-3.0.lua 766 2009-04-04 08:26:05Z nevcairiel $
local MAJOR,MINOR = "AceLocale-3.0", 2
local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceLocale then return end -- no upgrade needed
local gameLocale = GetLocale()
if gameLocale == "enGB" then
gameLocale = "enUS"
end
AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
-- This metatable is used on all tables returned from GetLocale
local readmeta = {
__index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
rawset(self, key, key) -- only need to see the warning once, really
geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
return key
end
}
-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
local readmetasilent = {
__index = function(self, key) -- requesting totally unknown entries: return key
rawset(self, key, key) -- only need to invoke this function once
return key
end
}
-- Remember the locale table being registered right now (it gets set by :NewLocale())
-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
local registering
-- local assert false function
local assertfalse = function() assert(false) end
-- This metatable proxy is used when registering nondefault locales
local writeproxy = setmetatable({}, {
__newindex = function(self, key, value)
rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
end,
__index = assertfalse
})
-- This metatable proxy is used when registering the default locale.
-- It refuses to overwrite existing values
-- Reason 1: Allows loading locales in any order
-- Reason 2: If 2 modules have the same string, but only the first one to be
-- loaded has a translation for the current locale, the translation
-- doesn't get overwritten.
--
local writedefaultproxy = setmetatable({}, {
__newindex = function(self, key, value)
if not rawget(registering, key) then
rawset(registering, key, value == true and key or value)
end
end,
__index = assertfalse
})
--- Register a new locale (or extend an existing one) for the specified application.
-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
-- game locale.
-- @paramsig application, locale[, isDefault[, silent]]
-- @param application Unique name of addon / module
-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
-- @param silent If true, the locale will not issue warnings for missing keys. Can only be set on the default locale.
-- @usage
-- -- enUS.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
-- L["string1"] = true
--
-- -- deDE.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
-- if not L then return end
-- L["string1"] = "Zeichenkette1"
-- @return Locale Table to add localizations to, or nil if the current locale is not required.
function AceLocale:NewLocale(application, locale, isDefault, silent)
if silent and not isDefault then
error("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' can only be specified for the default locale", 2)
end
-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
-- Ammo: I still think this is a bad idea, for instance an addon that checks for some ingame string will fail, just because some other addon
-- gives the user the illusion that they can run in a different locale? Ditch this whole thing or allow a setting per 'application'. I'm of the
-- opinion to remove this.
local gameLocale = GAME_LOCALE or gameLocale
if locale ~= gameLocale and not isDefault then
return -- nop, we don't need these translations
end
local app = AceLocale.apps[application]
if not app then
app = setmetatable({}, silent and readmetasilent or readmeta)
AceLocale.apps[application] = app
AceLocale.appnames[app] = application
end
registering = app -- remember globally for writeproxy and writedefaultproxy
if isDefault then
return writedefaultproxy
end
return writeproxy
end
--- Returns localizations for the current locale (or default locale if translations are missing).
-- Errors if nothing is registered (spank developer, not just a missing translation)
-- @param application Unique name of addon / module
-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
-- @return The locale table for the current language.
function AceLocale:GetLocale(application, silent)
if not silent and not AceLocale.apps[application] then
error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
end
return AceLocale.apps[application]
end

View File

@ -0,0 +1,4 @@
<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="AceLocale-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,239 @@
--[[ $Id: CallbackHandler-1.0.lua 3 2008-09-29 16:54:20Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 3
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}
local type = type
local pcall = pcall
local pairs = pairs
local assert = assert
local concat = table.concat
local loadstring = loadstring
local next = next
local select = select
local type = type
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", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(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"
if type(self)~="table" and type(self)~="string" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string 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.

View File

@ -0,0 +1,4 @@
<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>

View File

@ -0,0 +1,13 @@
------------------------------------------------------------------------
r41 | galmok | 2009-08-05 20:02:23 +0000 (Wed, 05 Aug 2009) | 1 line
Changed paths:
A /tags/LibCompress r40-release (from /trunk:40)
Tagging as LibCompress r40-release
------------------------------------------------------------------------
r40 | galmok | 2009-08-05 16:51:21 +0000 (Wed, 05 Aug 2009) | 1 line
Changed paths:
M /trunk/LibCompress.toc
Upped toc to patch 3.2 (30200).
------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
## Interface: 30200
## X-Curse-Packaged-Version: LibCompress r40-release
## X-Curse-Project-Name: LibCompress
## X-Curse-Project-ID: libcompress
## X-Curse-Repository-ID: wow/libcompress/mainline
## Title: Lib: Compress
## Notes: Compression and Decompression library
## Author: JJSheets and Galmok at Stormrage-EU (Horde)
## X-Website: http://www.wowace.com
## X-Category: Library
## X-eMail: sheets DOT jeff AT gmail DOT com, galmok AT gmail DOT com
## X-License: LGPL v2.1
lib.xml

View File

@ -0,0 +1,5 @@
<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="lib\LibStub\LibStub.lua" />
<Script file="LibCompress.lua" />
</Ui>

View File

@ -0,0 +1,30 @@
-- 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]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
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
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
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

View File

@ -0,0 +1,13 @@
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
LibStub.lua

View File

@ -0,0 +1,61 @@
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 2)
if not lib then return end
oldminor = oldminor or 0
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
lib.domt = lib.domt or {
__metatable = "access denied",
__newindex = function(self, key, value)
if not attributestorage[self] then attributestorage[self] = {} end
if attributestorage[self][key] == value then return end
attributestorage[self][key] = value
local name = namestorage[self]
if not name then return end
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value)
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value)
end,
__index = function(self, key)
return attributestorage[self] and attributestorage[self][key]
end,
}
function lib:NewDataObject(name, dataobj)
if self.proxystorage[name] then return end
if dataobj then
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
self.attributestorage[dataobj] = {}
for i,v in pairs(dataobj) do
self.attributestorage[dataobj][i] = v
dataobj[i] = nil
end
end
dataobj = setmetatable(dataobj or {}, self.domt)
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
return dataobj
end
if oldminor < 1 then
function lib:DataObjectIterator()
return pairs(self.proxystorage)
end
function lib:GetDataObjectByName(dataobjectname)
return self.proxystorage[dataobjectname]
end
function lib:GetNameByDataObject(dataobject)
return self.namestorage[dataobject]
end
end

View File

@ -0,0 +1,29 @@
Copyright (c) 2008, LibQTip Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Redistribution of a stand alone version is strictly prohibited without
prior written authorization from the Lead of the LibQTip Development Team.
* Neither the name of the LibQTip Development Team nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
## Interface: 30100
## Title: Lib: QTip-1.0
## Notes: Library providing multi-column tooltips.
## Author: Torhal, Adirelle, Elkano, Tristanian
## Version: r120-release
## X-Date: 2009-07-21T03:46:58Z
## X-Credits: Kaelten (input on initial design)
## X-Category: Library, Tooltip
## X-License: Ace3 BSD-like license
## X-Curse-Packaged-Version: r120-release
## X-Curse-Project-Name: LibQTip-1.0
## X-Curse-Project-ID: libqtip-1-0
## X-Curse-Repository-ID: wow/libqtip-1-0/mainline
LibStub\LibStub.lua
lib.xml

View File

@ -0,0 +1,30 @@
-- 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]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
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
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
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

View File

@ -0,0 +1,13 @@
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
LibStub.lua

View File

@ -0,0 +1,4 @@
<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="LibQTip-1.0.lua"/>
</Ui>

View File

@ -0,0 +1,239 @@
--[[ $Id: CallbackHandler-1.0.lua 3 2008-09-29 16:54:20Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 3
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}
local type = type
local pcall = pcall
local pairs = pairs
local assert = assert
local concat = table.concat
local loadstring = loadstring
local next = next
local select = select
local type = type
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", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(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"
if type(self)~="table" and type(self)~="string" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string 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.

View File

@ -0,0 +1,4 @@
<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>

View File

@ -0,0 +1,29 @@
Copyright (c) 2008, LibQTipClick Development Team
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Redistribution of a stand alone version is strictly prohibited without
prior written authorization from the Lead of the LibQTipClick Development Team.
* Neither the name of the LibQTipClick Development Team nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,135 @@
local MAJOR = "LibQTipClick-1.1"
local MINOR = 3
assert(LibStub, MAJOR.." requires LibStub")
local lib, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not lib then return end -- No upgrade needed
local QTip = LibStub:GetLibrary("LibQTip-1.0")
assert(QTip, MAJOR.." requires LibQTip-1.0")
local CBH = LibStub:GetLibrary("CallbackHandler-1.0")
assert(CBH, MAJOR.." requires CallbackHandler-1.0")
-------------------------------------------------------------------------------
-- Local variables
-------------------------------------------------------------------------------
lib.LabelProvider, lib.LabelPrototype, lib.BaseProvider = QTip:CreateCellProvider(QTip.LabelProvider)
local cell_provider, cell_prototype, cell_base = lib.LabelProvider, lib.LabelPrototype, lib.BaseProvider
-------------------------------------------------------------------------------
-- Public library API
-------------------------------------------------------------------------------
local highlighter = CreateFrame("Frame", nil, UIParent)
highlighter:SetFrameStrata("TOOLTIP")
highlighter:Hide()
local cell_highlight = highlighter:CreateTexture(nil, "OVERLAY")
cell_highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
cell_highlight:SetBlendMode("ADD")
cell_highlight:SetAllPoints(highlighter)
function lib.OnEnter(event, cell, arg)
highlighter:SetAllPoints(cell)
highlighter:SetFrameLevel(cell:GetFrameLevel())
highlighter:Show()
end
function lib.OnLeave(event, cell, arg)
highlighter:ClearAllPoints()
highlighter:Hide()
end
function lib.OnMouseDown(event, cell, arg, button) PlaySound("igMainMenuOpen") end
function lib.OnMouseUp(event, cell, arg, button) end
local function Cell_OnEnter(cell) cell.callbacks:Fire("OnEnter", cell, cell.arg) end
local function Cell_OnLeave(cell) cell.callbacks:Fire("OnLeave", cell, cell.arg) end
local function Cell_OnMouseDown(cell, button) cell.callbacks:Fire("OnMouseDown", cell, cell.arg, button) end
local function Cell_OnMouseUp(cell, button) cell.callbacks:Fire("OnMouseUp", cell, cell.arg, button) end
function cell_prototype:InitializeCell() cell_base.InitializeCell(self) end
function cell_prototype:SetupCell(tooltip, value, justification, font, arg, ...)
local width, height = cell_base.SetupCell(self, tooltip, value, justification, font, ...)
self:EnableMouse(true)
self.arg = arg
self.callbacks = tooltip.callbacks
self:SetScript("OnEnter", Cell_OnEnter)
self:SetScript("OnLeave", Cell_OnLeave)
self:SetScript("OnMouseDown", Cell_OnMouseDown)
self:SetScript("OnMouseUp", Cell_OnMouseUp)
return width, height
end
function cell_prototype:ReleaseCell()
self:EnableMouse(false)
self:SetScript("OnEnter", nil)
self:SetScript("OnLeave", nil)
self:SetScript("OnMouseDown", nil)
self:SetScript("OnMouseUp", nil)
self.arg = nil
self.callbacks = nil
end
-------------------------------------------------------------------------------
-- LibQTip wrapper API
-------------------------------------------------------------------------------
local function AddNormalLine(tooltip, ...)
local oldProvider = tooltip:GetDefaultProvider()
tooltip:SetDefaultProvider(QTip.LabelProvider)
local lineNum, colNum = tooltip:AddLine(...)
tooltip:SetDefaultProvider(oldProvider)
return lineNum, colNum
end
local function AddNormalHeader(tooltip, ...)
local oldProvider = tooltip:GetDefaultProvider()
tooltip:SetDefaultProvider(QTip.LabelProvider)
local lineNum, colNum = tooltip:AddHeader(...)
tooltip:SetDefaultProvider(oldProvider)
return lineNum, colNum
end
local function SetNormalCell(tooltip, ...)
local oldProvider = tooltip:GetDefaultProvider()
tooltip:SetDefaultProvider(QTip.LabelProvider)
local lineNum, colNum = tooltip:SetCell(...)
tooltip:SetDefaultProvider(oldProvider)
return lineNum, colNum
end
function lib:Acquire(key, ...)
local tooltip = QTip:Acquire(key, ...)
tooltip:EnableMouse(true)
tooltip.callbacks = CBH:New(tooltip, "SetCallback", "UnSetCallback", "UnSetAllCallbacks" or false)
tooltip:SetCallback("OnEnter", self.OnEnter)
tooltip:SetCallback("OnLeave", self.OnLeave)
tooltip:SetCallback("OnMouseDown", self.OnMouseDown)
tooltip:SetCallback("OnMouseUp", self.OnMouseUp)
tooltip.AddNormalLine = AddNormalLine
tooltip.AddNormalHeader = AddNormalHeader
tooltip.SetNormalCell = SetNormalCell
tooltip:SetDefaultProvider(cell_provider)
return tooltip
end
function lib:IsAcquired(key) return QTip:IsAcquired(key) end
function lib:Release(tooltip)
if not tooltip then return end
tooltip:EnableMouse(false)
tooltip:UnSetAllCallbacks(tooltip)
tooltip.callbacks = nil
tooltip["SetCallback"] = nil
tooltip["UnSetCallback"] = nil
tooltip["UnSetAllCallbacks"] = nil
QTip:Release(tooltip)
end
function lib:IterateTooltips() return QTip:IterateTooltips() end
function lib:CreateCellProvider(baseProvider) return QTip:CreateCellProvider(baseProvider) end

View File

@ -0,0 +1,17 @@
## Interface: 30100
## Title: Lib: QTipClick-1.1
## Notes: Library providing mouse-click support for LibQTip-1.0.
## Author: Torhal
## Version: r9
## X-Date: 2009-06-12T03:55:01Z
## X-Category: Library, Tooltip
## X-License: Ace3 BSD-like license
## OptionalDeps: LibQTip-1.0
## X-Curse-Packaged-Version: r9
## X-Curse-Project-Name: LibQTipClick-1.1
## X-Curse-Project-ID: libqtipclick-1-1
## X-Curse-Repository-ID: wow/libqtipclick-1-1/mainline
LibStub\LibStub.lua
CallbackHandler-1.0\CallbackHandler-1.0.lua
lib.xml

View File

@ -0,0 +1,30 @@
-- 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]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
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
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
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

View File

@ -0,0 +1,13 @@
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
LibStub.lua

View File

@ -0,0 +1,4 @@
<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="LibQTipClick-1.1.lua"/>
</Ui>

View File

@ -0,0 +1,30 @@
-- 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]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
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
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
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

View File

@ -0,0 +1,13 @@
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
LibStub.lua

View File

@ -0,0 +1,33 @@
tag v1.1.4
ddb0519a000c69ddf3a28c3f9fe2e62bb3fd00c5
Tekkub <tekkub@gmail.com>
2008-11-06 22:03:04 -0700
Build 1.1.4
--------------------
Tekkub:
Add pairs and ipairs iters, since we can't use the normal iters on our dataobjs
Simplify readme, all docs have been moved into GitHub wiki pages
Documentation on how to use LDB data (for display addons)
Add StatBlockCore forum link
Add link to Fortress thread
And rearrange the addon list a bit too
Make field lists into nice pretty tables
Add list of who is using LDB
Always with the typos, I hate my fingers
Add tooltiptext and OnTooltipShow to data addon spec
Readme rejiggering
Add in some documentation on how to push data into LDB
Meh, fuck you textile
Adding readme
Pass current dataobj with attr change callbacks to avoid excessive calls to :GetDataObjectByName
Tekkub Stoutwrithe:
Make passed dataobj actually work
I always forget the 'then'
Minor memory optimization
- Only hold upvalues to locals in the functions called frequently
- Retain the metatable across future lib upgrades (the one in v1 will be lost)
Allow caller to pass a pre-populated table to NewDataObject

View File

@ -0,0 +1,66 @@
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 3)
if not lib then return end
oldminor = oldminor or 0
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
if oldminor < 2 then
lib.domt = {
__metatable = "access denied",
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
}
end
if oldminor < 3 then
lib.domt.__newindex = function(self, key, value)
if not attributestorage[self] then attributestorage[self] = {} end
if attributestorage[self][key] == value then return end
attributestorage[self][key] = value
local name = namestorage[self]
if not name then return end
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
end
end
if oldminor < 2 then
function lib:NewDataObject(name, dataobj)
if self.proxystorage[name] then return end
if dataobj then
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
self.attributestorage[dataobj] = {}
for i,v in pairs(dataobj) do
self.attributestorage[dataobj][i] = v
dataobj[i] = nil
end
end
dataobj = setmetatable(dataobj or {}, self.domt)
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
return dataobj
end
end
if oldminor < 1 then
function lib:DataObjectIterator()
return pairs(self.proxystorage)
end
function lib:GetDataObjectByName(dataobjectname)
return self.proxystorage[dataobjectname]
end
function lib:GetNameByDataObject(dataobject)
return self.namestorage[dataobject]
end
end

View File

@ -0,0 +1,13 @@
LibDataBroker is a small WoW addon library designed to provide a "MVC":http://en.wikipedia.org/wiki/Model-view-controller interface for use in various addons.
LDB's primary goal is to "detach" plugins for TitanPanel and FuBar from the display addon.
Plugins can provide data into a simple table, and display addons can receive callbacks to refresh their display of this data.
LDB also provides a place for addons to register "quicklaunch" functions, removing the need for authors to embed many large libraries to create minimap buttons.
Users who do not wish to be "plagued" by these buttons simply do not install an addon to render them.
Due to it's simple generic design, LDB can be used for any design where you wish to have an addon notified of changes to a table.
h2. Links
* "API documentation":http://github.com/tekkub/libdatabroker-1-1/wikis/api
* "Data specifications":http://github.com/tekkub/libdatabroker-1-1/wikis/data-specifications
* "Addons using LDB":http://github.com/tekkub/libdatabroker-1-1/wikis/addons-using-ldb

13
GearScore/embeds.xml Normal file
View File

@ -0,0 +1,13 @@
<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">
<!--@no-lib-strip@-->
<Script file="Libs\LibStub\LibStub.lua"/>
<Include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="Libs\AceLocale-3.0\AceLocale-3.0.xml"/>
<Include file="Libs\LibQTip-1.0\lib.xml"/>
<Include file="Libs\LibQTipClick-1.1\lib.xml"/>
<!--@end-no-lib-strip@-->
<Include file="Libs\LibCompress\lib.xml"/>
<Script file="Libs\LibDataBroker-1.1.lua"/>
</Ui>

1294
GearScore/information.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("GearScore", "enUS", true)
if not L then return end
L["Human"] = true
L["Dwarf"] = true
L["Gnome"] = true
L["BloodElf"] = true
L["NightElf"] = true
L["Orc"] = true
L["Tauren"] = true
L["Troll"] = true
L["Draenei"] = true
L["Undead"] = true
L["Warrior"] = true
L["Death Knight"] = true
L["Paladin"] = true
L["Shaman"] = true
L["Hunter"] = true
L["Druid"] = true
L["Rogue"] = true
L["Warlock"] = true
L["Priest"] = true
L["Mage"] = true

View File

@ -0,0 +1,26 @@
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("GearScore", "esES", false)
if not L then return end
-- L["Alliance"] = ""
L["BloodElf"] = "Elfo de Sangre"
L["Death Knight"] = "Caballero de la Muerte"
-- L["Defaults"] = ""
L["Draenei"] = "Draenei"
L["Druid"] = "Druida"
L["Dwarf"] = "Enano"
L["Gnome"] = "Gnomo"
-- L["Horde"] = ""
L["Human"] = "Humano"
L["Hunter"] = "Cazador"
L["Mage"] = "Mago"
L["NightElf"] = "Elfo de la Noche"
L["Orc"] = "Orco"
L["Paladin"] = "Palad\195\173n"
L["Priest"] = "Sacerdote"
L["Rogue"] = "P\195\173caro"
L["Shaman"] = "Cham\195\161n"
L["Tauren"] = "Tauren"
L["Troll"] = "Trol"
L["Undead"] = "No-muerto"
L["Warlock"] = "Brujo"
L["Warrior"] = "Guerrero"

View File

@ -0,0 +1,24 @@
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("GearScore", "frFR", false)
if not L then return end
L["Human"] = "Humain"
L["Dwarf"] = "Nain"
L["Gnome"] = "Gnome"
L["BloodElf"] = "ElfeSang"
L["NightElf"] = "EfleNuit"
L["Orc"] = "Orc"
L["Tauren"] = "Tauren"
L["Troll"] = "Troll"
L["Draenei"] = "Draeneï"
L["Undead"] = "Mort-Vivant"
L["Warrior"] = "Guerrier"
L["Death Knight"] = "ChevalierMort"
L["Paladin"] = "Paladin"
L["Shaman"] = "Chaman"
L["Hunter"] = "Chasseur"
L["Druid"] = "Druide"
L["Rogue"] = "Voleur"
L["Warlock"] = "Démoniste"
L["Priest"] = "Prêtre"
L["Mage"] = "Mage"

View File

@ -0,0 +1,27 @@
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("GearScore", "koKR", false)
if not L then return end
-- L["Alliance"] = ""
L["BloodElf"] = "\235\184\148\235\159\172\235\147\156 \236\151\152\237\148\132"
L["Death Knight"] = "\236\163\189\236\157\140\236\157\152 \234\184\176\236\130\172"
-- L["Defaults"] = ""
L["Draenei"] = "\235\147\156\235\160\136\235\130\152\236\157\180"
L["Druid"] = "\235\147\156\235\163\168\236\157\180\235\147\156"
L["Dwarf"] = "\235\147\156\236\155\140\237\148\132"
L["Gnome"] = "\235\133\184\236\155\128"
-- L["Horde"] = ""
L["Human"] = "\236\157\184\234\176\132"
L["Hunter"] = "\236\130\172\235\131\165\234\190\188"
L["Mage"] = " \235\167\136\235\178\149\236\130\172"
L["NightElf"] = "\235\130\152\236\157\180\237\138\184 \236\151\152\237\148\132"
L["Orc"] = "\236\152\164\237\129\172"
L["Paladin"] = "\236\132\177\234\184\176\236\130\172"
L["Priest"] = "\236\130\172\236\160\156"
L["Rogue"] = "\235\143\132\236\160\129"
L["Shaman"] = "\236\163\188\236\136\160\236\130\172"
L["Tauren"] = "\237\131\128\236\154\176\235\160\140"
L["Troll"] = "\237\138\184\235\161\164"
L["Undead"] = "\236\150\184\235\141\176\235\147\156"
L["Warlock"] = "\237\157\145\235\167\136\235\178\149\236\130\172"
L["Warrior"] = "\236\160\132\236\130\172"

View File

@ -0,0 +1,26 @@
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local L = AceLocale:NewLocale("GearScore", "zhTW", false)
if not L then return end
-- L["Alliance"] = ""
L["BloodElf"] = "\232\161\128\231\178\190\233\157\136"
L["Death Knight"] = "\230\173\187\228\186\161\233\168\142\229\163\171"
-- L["Defaults"] = ""
L["Draenei"] = "\229\190\183\232\144\138\229\176\188"
L["Druid"] = "\229\190\183\233\173\175\228\190\157"
L["Dwarf"] = "\231\159\174\228\186\186"
L["Gnome"] = "\229\156\176\231\178\190"
-- L["Horde"] = ""
L["Human"] = "\228\186\186\233\161\158"
L["Hunter"] = "\231\141\181\228\186\186"
L["Mage"] = "\230\179\149\229\184\171"
L["NightElf"] = "\229\164\156\231\178\190\233\157\136"
L["Orc"] = "\231\141\184\228\186\186"
L["Paladin"] = "\232\129\150\233\168\142\229\163\171"
L["Priest"] = "\231\137\167\229\184\171"
L["Rogue"] = "\231\155\156\232\179\138"
L["Shaman"] = "\232\150\169\230\187\191"
L["Tauren"] = "\231\137\155\233\160\173\228\186\186"
L["Troll"] = "\233\163\159\228\186\186\229\166\150"
L["Undead"] = "\228\184\141\230\173\187\230\151\143"
L["Warlock"] = "\232\161\147\229\163\171"
L["Warrior"] = "\230\136\176\229\163\171"

106
GearScore/recount.lua Normal file
View File

@ -0,0 +1,106 @@
--Obviously Thanks to Recount!
if not Recount then return end
local GearScore_Recount = LibStub("AceAddon-3.0"):NewAddon("GearScore_Recount", "AceEvent-3.0", "AceTimer-3.0","AceConsole-3.0")
------------------------------Recount Mode--------------------------------------
function GearScore_Recount:DataModesGearScore(data, num)
if not data then return 0,0 end
MyVariable = data
TempName = data.unit
local damage, dps = Recount:MergedPetDamageDPS(data,Recount.db.profile.CurDataSet);
local hps = (data.Fights[Recount.db.profile.CurDataSet].Healing or 0)/((data.Fights[Recount.db.profile.CurDataSet].ActiveTime or 0) + 0);
hps = (floor(hps*10)/10)
dps = (floor(dps*10)/10)
local ttps = ""
if ( hps > dps ) then
tps = hps
ttps = "HPS - "
else
tps = dps;
ttps = "DPS - "
end
if num==1 then
if ( GS_Data[GetRealmName()].Players[TempName] ) then return GS_Data[GetRealmName()].Players[TempName].GearScore, (ttps..tostring(tps)); else return 0; end
end
if ( GS_Data[GetRealmName()].Players[TempName] ) then return GS_Data[GetRealmName()].Players[TempName].GearScore, (ttps..tostring(tps)); else return 0; end
end
function GearScore_Recount:DataModesPerformanceGearScore(data, num)
if not data then return 0,0 end
TempName = data.unit
local damage, dps = Recount:MergedPetDamageDPS(data,Recount.db.profile.CurDataSet);
-- local hps = (data.Fights[Recount.db.profile.CurDataSet].Healing or 0)/((data.Fights[Recount.db.profile.CurDataSet].ActiveTime or 0) + 0);
-- hps = (floor(hps*10)/10); dps = (floor(dps*10)/10)
local GearScore = 0
if ( GS_Data[GetRealmName()].Players[TempName] ) then GearScore = GS_Data[GetRealmName()].Players[TempName].GearScore or 0; end
-- if num==1 then
-- if ( GearScore > 0 ) then return floor(dps * 100 / GearScore), (dps.." DPS / "..GearScore.." GS"); else return 0; end
-- end
if ( GearScore > 0 ) then return floor(dps * 100 / GearScore), (floor(dps).." DPS / "..GearScore.." GS"); else return 0; end
end
function GearScore_Recount:DataModesHealingDoneGearScore(data, num)
if not data then return 0,0 end
local TempName = data.unit; local GearScore = 0
-- local damage, dps = Recount:MergedPetDamageDPS(data,Recount.db.profile.CurDataSet);
local healing = data.Fights[Recount.db.profile.CurDataSet].Healing or 0
if ( GS_Data[GetRealmName()].Players[TempName] ) then GearScore = GS_Data[GetRealmName()].Players[TempName].GearScore or 0; end
-- if num==1 then if ( GearScore > 0 ) then return floor(healing / GearScore), (healing.." Healing / "..GearScore.." GS"); else return 0; end; end
if ( GearScore > 0 ) then return floor(healing / GearScore), (healing.." Healing / "..GearScore.." GS"); else return 0; end
end
function GearScore_Recount:DataModesDamageDoneGearScore(data, num)
if not data then return 0,0 end
local TempName = data.unit; local GearScore = 0
local damage, dps = Recount:MergedPetDamageDPS(data,Recount.db.profile.CurDataSet);
if ( GS_Data[GetRealmName()].Players[TempName] ) then GearScore = GS_Data[GetRealmName()].Players[TempName].GearScore or 0; end
-- if num==1 then if ( GearScore > 0 ) then return floor(damage / GearScore), (damage.." Damage / "..GearScore.." GS"); else return 0; end; end
if ( GearScore > 0 ) then return floor(damage / GearScore), (damage.." Damage / "..GearScore.." GS"); else return 0; end
end
function GearScore_Recount:TooltipFuncsGearScore(name,data)
GameTooltip:ClearLines()
GameTooltip:AddLine(name)
local GS_Target = data.unit
local damage, dps = Recount:MergedPetDamageDPS(data,Recount.db.profile.CurDataSet);
local hps = (data.Fights[Recount.db.profile.CurDataSet].Healing or 0)/((data.Fights[Recount.db.profile.CurDataSet].ActiveTime or 0) + 0);
local GS_GearScore = GS_Data[GetRealmName()].Players[GS_Target].GearScore
if not ( GS_GearScore ) then GS_GearScore = 0; end
local GS_QualityRed, GS_QualityBlue, GS_QualityGreen, GS_QualityDescription = GearScore_GetQuality(GS_GearScore)
GameTooltip:AddLine("GearScore: "..GS_GearScore, GS_QualityRed, GS_QualityGreen, GS_QualityBlue)
if hps > dps then
GameTooltip:AddLine( "Healing Performance / GearScore: ".. (floor((hps * 100) / GS_GearScore)) )
else
GameTooltip:AddLine( "Damage Performance / GearScore: ".. (floor((dps * 100) / GS_GearScore)) )
end
if ( GS_Data[GetRealmName()].Players[GS_Target] ) then GearScore_SetDetails(GameTooltip, GS_Target); end
end
--Recount:AddModeTooltip("GearScore",GearScore_Recount.DataModesGearScore,GearScore_Recount.TooltipFuncsGearScore,"GearScore","GearScore", "GearScore", "GearScore")
Recount:AddModeTooltip("Damage / GearScore",GearScore_Recount.DataModesDamageDoneGearScore,GearScore_Recount.TooltipFuncsGearScore,"GearScore","GearScore", "GearScore", "GearScore")
Recount:AddModeTooltip("Healing / GearScore",GearScore_Recount.DataModesHealingDoneGearScore,GearScore_Recount.TooltipFuncsGearScore,"GearScore","GearScore", "GearScore", "GearScore")
Recount:AddModeTooltip("Performance(DPS) / GearScore",GearScore_Recount.DataModesPerformanceGearScore,GearScore_Recount.TooltipFuncsGearScore,"GearScore","GearScore", "GearScore", "GearScore")

1027
GearScore/weights.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,251 @@
------------------------------------------------------------------------
r218 | adjo | 2010-10-12 21:16:20 +0000 (Tue, 12 Oct 2010) | 4 lines
Changed paths:
M /trunk/Genie.lua
REMOVE; Genie.Container; _G removed
BUGFIX; Genie.Container; G bag injection
REMOVE; GuildBag:IsEnabled()
------------------------------------------------------------------------
r217 | adjo | 2010-10-12 17:37:14 +0000 (Tue, 12 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI/GenieUI.lua
BUGFIX; GENIE_UI; Module:CreateRankEditor() : family name will now be correcly reset
------------------------------------------------------------------------
r216 | adjo | 2010-10-12 17:18:57 +0000 (Tue, 12 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI/GenieUI.lua
BUGFIX; Module.OnGenieEditButtonClick
------------------------------------------------------------------------
r215 | adjo | 2010-10-12 16:48:58 +0000 (Tue, 12 Oct 2010) | 25 lines
Changed paths:
M /trunk/.pkgmeta
M /trunk/Genie.lua
M /trunk/Genie.toc
D /trunk/LDB+I.lua
D /trunk/Libs/LibDataBroker
A /trunk/Modules/Genie_LDB
A /trunk/Modules/Genie_LDB/Genie_LDB.toc
A /trunk/Modules/Genie_LDB/LDB+I.lua
A /trunk/Modules/Genie_LDB/Libs
A /trunk/Modules/Genie_LDB/Libs/LibDataBroker-1.1
A /trunk/Modules/Genie_LDB/Libs/LibDataBroker-1.1/LibDataBroker-1.1.lua
A /trunk/Modules/Genie_LDB/embeds.xml
M /trunk/Modules/Genie_UI/AceGUIContainer-GenieFrame.lua
M /trunk/Modules/Genie_UI/AceGUIContainer-GenieTreeGroup.lua
M /trunk/Modules/Genie_UI/AceGUIWidget-GenieIcon.lua
M /trunk/Modules/Genie_UI/GenieUI.lua
M /trunk/Modules/Genie_UI/Genie_UI.toc
A /trunk/Modules/Genie_UI/embeds.xml
M /trunk/embeds.xml
WARNING; DO NOT USE;
UPDATE; GenieIcon:SetMinQualityForGlow(quality) ; uses GetItemQualityColor()
BUGFIX; GenieTreeGroup:SetSelect/Select(); functionaliy inverted
UPDATE; GenieTreeGroup:Select(); Fire:OnPairSelected()
ADD; GenieFrame; overviewbutton, ignorebutton
ADD; GenieFrame:SetButtonText(button, text);
ADD; GenieFrame:GetButtonText(button);
REMOVE; GenieFrame; resetbutton
UPDATE; Genie; Genie.UTILS.ConcatTable(table1, table2, appendKey)
ADD; Genie.UTILS.GroupGetParent(group)
ADD; Genie.UTILS.GroupGetBags(group, parent, all)
ADD; Genie.UTILS.GroupGetAllBags(group)
ADD; Genie.UTILS.GroupGetName(group)
ADD; Genie.UTILS.GroupGetVisibleUser(); returns all groups that the user can safely know about
UPDATE; Genie.Container; bags are now injected to be save with bag/bank-slot additions
BUGFIX; Genie:DoUpdateContainer(); soundbug fixed
UPDATE; Genie:DoBag(); new container api
UPDATE; Genie:DoBank(); new container api
UPDATE; Genie:DoGuildbank(); new container api
BUGFIX; Genie:FamilyUpdate(); Genie.FLAG_RSS = true moved
UPDATE; Genie:FamilyIgnore(); new container api
REMOVE; Genie:FamilyEnable()
UPDATE; finalized functions moved out of new features section
UPDATE; .toc; OptionalDependencies
UPDATE; .pkgmeta; OptionalDependencies
------------------------------------------------------------------------
r214 | adjo | 2010-10-07 11:57:23 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/.docmeta
UPDATE; again .docmeta (last try)
------------------------------------------------------------------------
r213 | adjo | 2010-10-07 11:36:46 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/.docmeta
UPDATE; again .docmeta
------------------------------------------------------------------------
r212 | adjo | 2010-10-07 11:14:02 +0000 (Thu, 07 Oct 2010) | 2 lines
Changed paths:
M /trunk/Modules/Genie_UI/GenieUI.lua
BUGFIX; GUI; API:EditButtonSetContainer
------------------------------------------------------------------------
r211 | adjo | 2010-10-07 11:04:50 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI/AceGUIContainer-GenieFrame.lua
M /trunk/Modules/Genie_UI/AceGUIContainer-GenieTreeGroup.lua
M /trunk/Modules/Genie_UI/AceGUIWidget-GenieIcon.lua
UPDATE; correctly formatted comments
------------------------------------------------------------------------
r210 | adjo | 2010-10-07 10:30:49 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/.docmeta
UPDATE; again .docmeta
------------------------------------------------------------------------
r209 | adjo | 2010-10-07 09:21:25 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/Genie.lua
BUGFIX; Added Genie.FLAG_RSS = true to most of the family functions
------------------------------------------------------------------------
r208 | adjo | 2010-10-07 09:04:21 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/.docmeta
UPDATE; .docmeta
------------------------------------------------------------------------
r207 | adjo | 2010-10-07 08:49:03 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/.docmeta
UPDATE; still testing .docmeta
------------------------------------------------------------------------
r206 | adjo | 2010-10-07 08:43:33 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI/GenieUI.lua
UPDATE; documentaion API:EditButtonSetContainer
------------------------------------------------------------------------
r205 | adjo | 2010-10-07 08:28:24 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/.docmeta
UPDATE; still testing
------------------------------------------------------------------------
r204 | adjo | 2010-10-07 08:15:53 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI/GenieUI.lua
BUGFIX; GUI; API.SetGenieEdit -> API.SetEditmode
------------------------------------------------------------------------
r203 | adjo | 2010-10-07 08:07:38 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
A /trunk/.docmeta
ADD; .docmeta (test; may be removed in future)
------------------------------------------------------------------------
r202 | adjo | 2010-10-07 08:06:18 +0000 (Thu, 07 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI/GenieUI.lua
BUGFIX; GUI; families[class.criteria].ignore == nil
------------------------------------------------------------------------
r201 | adjo | 2010-10-06 23:23:53 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/Modules/Genie_UI
M /trunk/Modules/Genie_UI/GenieUI.lua
UPDATE; GUI; Families ignorable on a <bagtype> basis
------------------------------------------------------------------------
r200 | adjo | 2010-10-06 23:17:48 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/Genie.lua
BUGFIX; Genie:FamilyIgnore
------------------------------------------------------------------------
r199 | adjo | 2010-10-06 21:28:40 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/.pkgmeta
UPDATE; Module Genie_UI -> Addons
------------------------------------------------------------------------
r198 | adjo | 2010-10-06 21:24:33 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/Genie.lua
A /trunk/LDB+I.lua
UPDATE; LDB and LDBIcon moved out of Genie.lua
------------------------------------------------------------------------
r197 | adjo | 2010-10-06 21:23:24 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/Locale/deDE.lua
M /trunk/Locale/enUS.lua
M /trunk/Locale/esES.lua
M /trunk/Locale/esMX.lua
M /trunk/Locale/frFR.lua
M /trunk/Locale/koKR.lua
M /trunk/Locale/ruRU.lua
M /trunk/Locale/zhCN.lua
M /trunk/Locale/zhTW.lua
UPDATE;
------------------------------------------------------------------------
r196 | adjo | 2010-10-06 21:22:31 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/Genie.toc
UPDATE; LibDataBroker now directy embedded
------------------------------------------------------------------------
r195 | adjo | 2010-10-06 21:20:42 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
D /trunk/Modules/Genie_UI/GenieUI.lua.bak
REMOVED;
------------------------------------------------------------------------
r194 | adjo | 2010-10-06 21:19:31 +0000 (Wed, 06 Oct 2010) | 2 lines
Changed paths:
A /trunk/Media
A /trunk/Media/icon_default.tga
A /trunk/Media/icon_editmode.tga
A /trunk/Modules
A /trunk/Modules/Genie_UI
A /trunk/Modules/Genie_UI/AceGUIContainer-GenieFrame.lua
A /trunk/Modules/Genie_UI/AceGUIContainer-GenieTreeGroup.lua
A /trunk/Modules/Genie_UI/AceGUIWidget-GenieIcon.lua
A /trunk/Modules/Genie_UI/GenieUI.lua
A /trunk/Modules/Genie_UI/GenieUI.lua.bak
A /trunk/Modules/Genie_UI/Genie_UI.toc
ADD; UI Module
------------------------------------------------------------------------
r193 | adjo | 2010-10-06 21:16:39 +0000 (Wed, 06 Oct 2010) | 1 line
Changed paths:
M /trunk/embeds.xml
UPDATE; LibDataBroker now directy embedded
------------------------------------------------------------------------
r192 | adjo | 2010-09-15 13:46:46 +0000 (Wed, 15 Sep 2010) | 2 lines
Changed paths:
M /trunk/Genie.toc
ADD; ## X-Compatible-With: 40000
------------------------------------------------------------------------
r191 | adjo | 2010-08-06 15:13:34 +0000 (Fri, 06 Aug 2010) | 3 lines
Changed paths:
M /trunk/Genie.lua
M /trunk/Locale
M /trunk/Locale/deDE.lua
M /trunk/Locale/enUS.lua
M /trunk/Locale/esES.lua
M /trunk/Locale/esMX.lua
M /trunk/Locale/frFR.lua
M /trunk/Locale/koKR.lua
M /trunk/Locale/ruRU.lua
M /trunk/Locale/zhCN.lua
M /trunk/Locale/zhTW.lua
UPDATE; aic localization
UPDATE; Item.Id -> ItemID
ADDED; L.UseProfile, L.Sync, L.ItemID
------------------------------------------------------------------------

4839
Genie/Genie.lua Normal file

File diff suppressed because it is too large Load Diff

29
Genie/Genie.toc Normal file
View File

@ -0,0 +1,29 @@
## Title: Genie
## Notes: Genie helps you organize your bags, bank and/or guildbank
## Notes-deDE: Genie hilft dir deine Taschen, Bank und/oder Gildenbank ordentlich zu halten
## X-Curse-Packaged-Version: r218
## X-Curse-Project-Name: Genie
## X-Curse-Project-ID: genie
## X-Curse-Repository-ID: wow/genie/mainline
## Interface: 30300
## X-Compatible-With: 40000
## Version: r218
## X-Date: 2010-10-12T21:16:20Z
## X-Revision: 218
## Author: adjo
## X-Website: http://wow.curseforge.com/projects/genie
## X-Feedback: http://wow.curseforge.com/projects/genie/tickets/
## SavedVariables: GenieDB
## OptionalDependencies: Ace3
#@no-lib-strip@
embeds.xml
#@end-no-lib-strip@
locale.xml
Genie.lua

View File

@ -0,0 +1,642 @@
--- **AceAddon-3.0** provides a template for creating addon objects.
-- It'll provide you with a set of callback functions that allow you to simplify the loading
-- process of your addon.\\
-- Callbacks provided are:\\
-- * **OnInitialize**, which is called directly after the addon is fully loaded.
-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
-- * **OnDisable**, which is only called when your addon is manually being disabled.
-- @usage
-- -- A small (but complete) addon, that doesn't do anything,
-- -- but shows usage of the callbacks.
-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
--
-- function MyAddon:OnInitialize()
-- -- do init tasks here, like loading the Saved Variables,
-- -- or setting up slash commands.
-- end
--
-- function MyAddon:OnEnable()
-- -- Do more initialization here, that really enables the use of your addon.
-- -- Register Events, Hook functions, Create Frames, Get information from
-- -- the game that wasn't available in OnInitialize
-- end
--
-- function MyAddon:OnDisable()
-- -- Unhook, Unregister Events, Hide frames that you created.
-- -- You would probably only use an OnDisable if you want to
-- -- build a "standby" mode, or be able to toggle modules on/off.
-- end
-- @class file
-- @name AceAddon-3.0.lua
-- @release $Id: AceAddon-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
local MAJOR, MINOR = "AceAddon-3.0", 5
local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceAddon then return end -- No Upgrade needed.
AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
AceAddon.addons = AceAddon.addons or {} -- addons in general
AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
-- Lua APIs
local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
local fmt, tostring = string.format, tostring
local select, pairs, next, type, unpack = select, pairs, next, type, unpack
local loadstring, assert, error = loadstring, assert, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ...
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
return Dispatchers[select('#', ...)](func, ...)
end
end
-- local functions that will be implemented further down
local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
-- used in the addon metatable
local function addontostring( self ) return self.name end
--- Create a new AceAddon-3.0 addon.
-- Any libraries you specified will be embeded, and the addon will be scheduled for
-- its OnInitialize and OnEnable callbacks.
-- The final addon object, with all libraries embeded, will be returned.
-- @paramsig [object ,]name[, lib, ...]
-- @param object Table to use as a base for the addon (optional)
-- @param name Name of the addon object to create
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create a simple addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
--
-- -- Create a Addon object based on the table of a frame
-- local MyFrame = CreateFrame("Frame")
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
function AceAddon:NewAddon(objectorname, ...)
local object,name
local i=1
if type(objectorname)=="table" then
object=objectorname
name=...
i=2
else
name=objectorname
end
if type(name)~="string" then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
end
if self.addons[name] then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
end
object = object or {}
object.name = name
local addonmeta = {}
local oldmeta = getmetatable(object)
if oldmeta then
for k, v in pairs(oldmeta) do addonmeta[k] = v end
end
addonmeta.__tostring = addontostring
setmetatable( object, addonmeta )
self.addons[name] = object
object.modules = {}
object.defaultModuleLibraries = {}
Embed( object ) -- embed NewModule, GetModule methods
self:EmbedLibraries(object, select(i,...))
-- add to queue of addons to be initialized upon ADDON_LOADED
tinsert(self.initializequeue, object)
return object
end
--- Get the addon object by its name from the internal AceAddon registry.
-- Throws an error if the addon object cannot be found (except if silent is set).
-- @param name unique name of the addon object
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- -- Get the Addon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
function AceAddon:GetAddon(name, silent)
if not silent and not self.addons[name] then
error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
end
return self.addons[name]
end
-- - Embed a list of libraries into the specified addon.
-- This function will try to embed all of the listed libraries into the addon
-- and error if a single one fails.
--
-- **Note:** This function is for internal use by :NewAddon/:NewModule
-- @paramsig addon, [lib, ...]
-- @param addon addon object to embed the libs in
-- @param lib List of libraries to embed into the addon
function AceAddon:EmbedLibraries(addon, ...)
for i=1,select("#", ... ) do
local libname = select(i, ...)
self:EmbedLibrary(addon, libname, false, 4)
end
end
-- - Embed a library into the addon object.
-- This function will check if the specified library is registered with LibStub
-- and if it has a :Embed function to call. It'll error if any of those conditions
-- fails.
--
-- **Note:** This function is for internal use by :EmbedLibraries
-- @paramsig addon, libname[, silent[, offset]]
-- @param addon addon object to embed the library in
-- @param libname name of the library to embed
-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
function AceAddon:EmbedLibrary(addon, libname, silent, offset)
local lib = LibStub:GetLibrary(libname, true)
if not lib and not silent then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
elseif lib and type(lib.Embed) == "function" then
lib:Embed(addon)
tinsert(self.embeds[addon], libname)
return true
elseif lib then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
end
end
--- Return the specified module from an addon object.
-- Throws an error if the addon object cannot be found (except if silent is set)
-- @name //addon//:GetModule
-- @paramsig name[, silent]
-- @param name unique name of the module
-- @param silent if true, the module is optional, silently return nil if its not found (optional)
-- @usage
-- -- Get the Addon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- -- Get the Module
-- MyModule = MyAddon:GetModule("MyModule")
function GetModule(self, name, silent)
if not self.modules[name] and not silent then
error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
end
return self.modules[name]
end
local function IsModuleTrue(self) return true end
--- Create a new module for the addon.
-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
-- an addon object.
-- @name //addon//:NewModule
-- @paramsig name[, prototype|lib[, lib, ...]]
-- @param name unique name of the module
-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create a module with some embeded libraries
-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
--
-- -- Create a module with a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
function NewModule(self, name, prototype, ...)
if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
-- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
-- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
module.IsModule = IsModuleTrue
module:SetEnabledState(self.defaultModuleState)
module.moduleName = name
if type(prototype) == "string" then
AceAddon:EmbedLibraries(module, prototype, ...)
else
AceAddon:EmbedLibraries(module, ...)
end
AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
if not prototype or type(prototype) == "string" then
prototype = self.defaultModulePrototype or nil
end
if type(prototype) == "table" then
local mt = getmetatable(module)
mt.__index = prototype
setmetatable(module, mt) -- More of a Base class type feel.
end
safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
self.modules[name] = module
return module
end
--- Returns the real name of the addon or module, without any prefix.
-- @name //addon//:GetName
-- @paramsig
-- @usage
-- print(MyAddon:GetName())
-- -- prints "MyAddon"
function GetName(self)
return self.moduleName or self.name
end
--- Enables the Addon, if possible, return true or false depending on success.
-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
-- and enabling all modules of the addon (unless explicitly disabled).\\
-- :Enable() also sets the internal `enableState` variable to true
-- @name //addon//:Enable
-- @paramsig
-- @usage
-- -- Enable MyModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Enable()
function Enable(self)
self:SetEnabledState(true)
return AceAddon:EnableAddon(self)
end
--- Disables the Addon, if possible, return true or false depending on success.
-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
-- and disabling all modules of the addon.\\
-- :Disable() also sets the internal `enableState` variable to false
-- @name //addon//:Disable
-- @paramsig
-- @usage
-- -- Disable MyAddon
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:Disable()
function Disable(self)
self:SetEnabledState(false)
return AceAddon:DisableAddon(self)
end
--- Enables the Module, if possible, return true or false depending on success.
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
-- @name //addon//:EnableModule
-- @paramsig name
-- @usage
-- -- Enable MyModule using :GetModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Enable()
--
-- -- Enable MyModule using the short-hand
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:EnableModule("MyModule")
function EnableModule(self, name)
local module = self:GetModule( name )
return module:Enable()
end
--- Disables the Module, if possible, return true or false depending on success.
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
-- @name //addon//:DisableModule
-- @paramsig name
-- @usage
-- -- Disable MyModule using :GetModule
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyModule = MyAddon:GetModule("MyModule")
-- MyModule:Disable()
--
-- -- Disable MyModule using the short-hand
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- MyAddon:DisableModule("MyModule")
function DisableModule(self, name)
local module = self:GetModule( name )
return module:Disable()
end
--- Set the default libraries to be mixed into all modules created by this object.
-- Note that you can only change the default module libraries before any module is created.
-- @name //addon//:SetDefaultModuleLibraries
-- @paramsig lib[, lib, ...]
-- @param lib List of libraries to embed into the addon
-- @usage
-- -- Create the addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
-- -- Create a module
-- MyModule = MyAddon:NewModule("MyModule")
function SetDefaultModuleLibraries(self, ...)
if next(self.modules) then
error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleLibraries = {...}
end
--- Set the default state in which new modules are being created.
-- Note that you can only change the default state before any module is created.
-- @name //addon//:SetDefaultModuleState
-- @paramsig state
-- @param state Default state for new modules, true for enabled, false for disabled
-- @usage
-- -- Create the addon object
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- -- Set the default state to "disabled"
-- MyAddon:SetDefaultModuleState(false)
-- -- Create a module and explicilty enable it
-- MyModule = MyAddon:NewModule("MyModule")
-- MyModule:Enable()
function SetDefaultModuleState(self, state)
if next(self.modules) then
error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleState = state
end
--- Set the default prototype to use for new modules on creation.
-- Note that you can only change the default prototype before any module is created.
-- @name //addon//:SetDefaultModulePrototype
-- @paramsig prototype
-- @param prototype Default prototype for the new modules (table)
-- @usage
-- -- Define a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- -- Set the default prototype
-- MyAddon:SetDefaultModulePrototype(prototype)
-- -- Create a module and explicitly Enable it
-- MyModule = MyAddon:NewModule("MyModule")
-- MyModule:Enable()
-- -- should print "OnEnable called!" now
-- @see NewModule
function SetDefaultModulePrototype(self, prototype)
if next(self.modules) then
error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
end
if type(prototype) ~= "table" then
error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
end
self.defaultModulePrototype = prototype
end
--- Set the state of an addon or module
-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
-- @name //addon//:SetEnabledState
-- @paramsig state
-- @param state the state of an addon or module (enabled=true, disabled=false)
function SetEnabledState(self, state)
self.enabledState = state
end
--- Return an iterator of all modules associated to the addon.
-- @name //addon//:IterateModules
-- @paramsig
-- @usage
-- -- Enable all modules
-- for name, module in MyAddon:IterateModules() do
-- module:Enable()
-- end
local function IterateModules(self) return pairs(self.modules) end
-- Returns an iterator of all embeds in the addon
-- @name //addon//:IterateEmbeds
-- @paramsig
local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
--- Query the enabledState of an addon.
-- @name //addon//:IsEnabled
-- @paramsig
-- @usage
-- if MyAddon:IsEnabled() then
-- MyAddon:Disable()
-- end
local function IsEnabled(self) return self.enabledState end
local mixins = {
NewModule = NewModule,
GetModule = GetModule,
Enable = Enable,
Disable = Disable,
EnableModule = EnableModule,
DisableModule = DisableModule,
IsEnabled = IsEnabled,
SetDefaultModuleLibraries = SetDefaultModuleLibraries,
SetDefaultModuleState = SetDefaultModuleState,
SetDefaultModulePrototype = SetDefaultModulePrototype,
SetEnabledState = SetEnabledState,
IterateModules = IterateModules,
IterateEmbeds = IterateEmbeds,
GetName = GetName,
}
local function IsModule(self) return false end
local pmixins = {
defaultModuleState = true,
enabledState = true,
IsModule = IsModule,
}
-- Embed( target )
-- target (object) - target object to embed aceaddon in
--
-- this is a local function specifically since it's meant to be only called internally
function Embed(target)
for k, v in pairs(mixins) do
target[k] = v
end
for k, v in pairs(pmixins) do
target[k] = target[k] or v
end
end
-- - Initialize the addon after creation.
-- This function is only used internally during the ADDON_LOADED event
-- It will call the **OnInitialize** function on the addon object (if present),
-- and the **OnEmbedInitialize** function on all embeded libraries.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- @param addon addon object to intialize
function AceAddon:InitializeAddon(addon)
safecall(addon.OnInitialize, addon)
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
end
-- we don't call InitializeAddon on modules specifically, this is handled
-- from the event handler and only done _once_
end
-- - Enable the addon after creation.
-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
-- It will call the **OnEnable** function on the addon object (if present),
-- and the **OnEmbedEnable** function on all embeded libraries.\\
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- Use :Enable on the addon itself instead.
-- @param addon addon object to enable
function AceAddon:EnableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if self.statuses[addon.name] or not addon.enabledState then return false end
-- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
self.statuses[addon.name] = true
safecall(addon.OnEnable, addon)
-- make sure we're still enabled before continueing
if self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedEnable, lib, addon) end
end
-- enable possible modules.
for name, module in pairs(addon.modules) do
self:EnableAddon(module)
end
end
return self.statuses[addon.name] -- return true if we're disabled
end
-- - Disable the addon
-- Note: This function is only used internally.
-- It will call the **OnDisable** function on the addon object (if present),
-- and the **OnEmbedDisable** function on all embeded libraries.\\
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
--
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- Use :Disable on the addon itself instead.
-- @param addon addon object to enable
function AceAddon:DisableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if not self.statuses[addon.name] then return false end
-- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
self.statuses[addon.name] = false
safecall( addon.OnDisable, addon )
-- make sure we're still disabling...
if not self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedDisable, lib, addon) end
end
-- disable possible modules.
for name, module in pairs(addon.modules) do
self:DisableAddon(module)
end
end
return not self.statuses[addon.name] -- return true if we're disabled
end
--- Get an iterator over all registered addons.
-- @usage
-- -- Print a list of all installed AceAddon's
-- for name, addon in AceAddon:IterateAddons() do
-- print("Addon: " .. name)
-- end
function AceAddon:IterateAddons() return pairs(self.addons) end
--- Get an iterator over the internal status registry.
-- @usage
-- -- Print a list of all enabled addons
-- for name, status in AceAddon:IterateAddonStatus() do
-- if status then
-- print("EnabledAddon: " .. name)
-- end
-- end
function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
-- Following Iterators are deprecated, and their addon specific versions should be used
-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
-- Event Handling
local function onEvent(this, event, arg1)
if event == "ADDON_LOADED" or event == "PLAYER_LOGIN" then
-- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
while(#AceAddon.initializequeue > 0) do
local addon = tremove(AceAddon.initializequeue, 1)
-- this might be an issue with recursion - TODO: validate
if event == "ADDON_LOADED" then addon.baseName = arg1 end
AceAddon:InitializeAddon(addon)
tinsert(AceAddon.enablequeue, addon)
end
if IsLoggedIn() then
while(#AceAddon.enablequeue > 0) do
local addon = tremove(AceAddon.enablequeue, 1)
AceAddon:EnableAddon(addon)
end
end
end
end
AceAddon.frame:RegisterEvent("ADDON_LOADED")
AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
AceAddon.frame:SetScript("OnEvent", onEvent)
-- upgrade embeded
for name, addon in pairs(AceAddon.addons) do
Embed(addon)
end

View File

@ -0,0 +1,4 @@
<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="AceAddon-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,309 @@
--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels.
-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\
-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server.
--
-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceComm itself.\\
-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceComm.
-- @class file
-- @name AceComm-3.0
-- @release $Id: AceComm-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
--[[ AceComm-3.0
TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited.
]]
local MAJOR, MINOR = "AceComm-3.0", 6
local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceComm then return end
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
-- Lua APIs
local type, next, pairs, tostring = type, next, pairs, tostring
local strsub, strfind = string.sub, string.find
local tinsert, tconcat = table.insert, table.concat
local error, assert = error, assert
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler
AceComm.embeds = AceComm.embeds or {}
-- for my sanity and yours, let's give the message type bytes some names
local MSG_MULTI_FIRST = "\001"
local MSG_MULTI_NEXT = "\002"
local MSG_MULTI_LAST = "\003"
AceComm.multipart_origprefixes = AceComm.multipart_origprefixes or {} -- e.g. "Prefix\001"="Prefix", "Prefix\002"="Prefix"
AceComm.multipart_reassemblers = AceComm.multipart_reassemblers or {} -- e.g. "Prefix\001"="OnReceiveMultipartFirst"
-- the multipart message spool: indexed by a combination of sender+distribution+
AceComm.multipart_spool = AceComm.multipart_spool or {}
--- Register for Addon Traffic on a specified prefix
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
function AceComm:RegisterComm(prefix, method)
if method == nil then
method = "OnCommReceived"
end
return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
end
local warnedPrefix=false
--- Send a message over the Addon Channel
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- @param text Data to send, nils (\000) not allowed. Any length.
-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
-- @param target Destination for some distributions; see SendAddonMessage API
-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send.
-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified.
function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg)
prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery!
if not( type(prefix)=="string" and
type(text)=="string" and
type(distribution)=="string" and
(target==nil or type(target)=="string") and
(prio=="BULK" or prio=="NORMAL" or prio=="ALERT")
) then
error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2)
end
if strfind(prefix, "[\001-\009]") then
if strfind(prefix, "[\001-\003]") then
error("SendCommMessage: Characters \\001--\\003 in prefix are reserved for AceComm metadata", 2)
elseif not warnedPrefix then
-- I have some ideas about future extensions that require more control characters /mikk, 20090808
geterrorhandler()("SendCommMessage: Heads-up developers: Characters \\004--\\009 in prefix are reserved for AceComm future extension")
warnedPrefix = true
end
end
local textlen = #text
local maxtextlen = 254 - #prefix -- 254 is the max length of prefix + text that can be sent in one message
local queueName = prefix..distribution..(target or "")
local ctlCallback = nil
if callbackFn then
ctlCallback = function(sent)
return callbackFn(callbackArg, sent, textlen)
end
end
if textlen <= maxtextlen then
-- fits all in one message
CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen)
else
maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix
-- first part
local chunk = strsub(text, 1, maxtextlen)
CTL:SendAddonMessage(prio, prefix..MSG_MULTI_FIRST, chunk, distribution, target, queueName, ctlCallback, maxtextlen)
-- continuation
local pos = 1+maxtextlen
local prefix2 = prefix..MSG_MULTI_NEXT
while pos+maxtextlen <= textlen do
chunk = strsub(text, pos, pos+maxtextlen-1)
CTL:SendAddonMessage(prio, prefix2, chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
pos = pos + maxtextlen
end
-- final part
chunk = strsub(text, pos)
CTL:SendAddonMessage(prio, prefix..MSG_MULTI_LAST, chunk, distribution, target, queueName, ctlCallback, textlen)
end
end
----------------------------------------
-- Message receiving
----------------------------------------
do
local compost = setmetatable({}, {__mode = "k"})
local function new()
local t = next(compost)
if t then
compost[t]=nil
for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
t[i]=nil
end
return t
end
return {}
end
local function lostdatawarning(prefix,sender,where)
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
end
function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
--[[
if spool[key] then
lostdatawarning(prefix,sender,"First")
-- continue and overwrite
end
--]]
spool[key] = message -- plain string for now
end
function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
if not olddata then
--lostdatawarning(prefix,sender,"Next")
return
end
if type(olddata)~="table" then
-- ... but what we have is not a table. So make it one. (Pull a composted one if available)
local t = new()
t[1] = olddata -- add old data as first string
t[2] = message -- and new message as second string
spool[key] = t -- and put the table in the spool instead of the old string
else
tinsert(olddata, message)
end
end
function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
if not olddata then
--lostdatawarning(prefix,sender,"End")
return
end
spool[key] = nil
if type(olddata) == "table" then
-- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
tinsert(olddata, message)
AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender)
compost[olddata] = true
else
-- if we've only received a "first", the spooled data will still only be a string
AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender)
end
end
end
----------------------------------------
-- Embed CallbackHandler
----------------------------------------
if not AceComm.callbacks then
-- ensure that 'prefix to watch' table is consistent with registered
-- callbacks
AceComm.__prefixes = {}
AceComm.callbacks = CallbackHandler:New(AceComm,
"_RegisterComm",
"UnregisterComm",
"UnregisterAllComm")
end
function AceComm.callbacks:OnUsed(target, prefix)
AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = "OnReceiveMultipartFirst"
AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = "OnReceiveMultipartNext"
AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = "OnReceiveMultipartLast"
end
function AceComm.callbacks:OnUnused(target, prefix)
AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = nil
AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = nil
AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = nil
end
local function OnEvent(this, event, ...)
if event == "CHAT_MSG_ADDON" then
local prefix,message,distribution,sender = ...
local reassemblername = AceComm.multipart_reassemblers[prefix]
if reassemblername then
-- multipart: reassemble
local aceCommReassemblerFunc = AceComm[reassemblername]
local origprefix = AceComm.multipart_origprefixes[prefix]
aceCommReassemblerFunc(AceComm, origprefix, message, distribution, sender)
else
-- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
AceComm.callbacks:Fire(prefix, message, distribution, sender)
end
else
assert(false, "Received "..tostring(event).." event?!")
end
end
AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
AceComm.frame:SetScript("OnEvent", OnEvent)
AceComm.frame:UnregisterAllEvents()
AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
----------------------------------------
-- Base library stuff
----------------------------------------
local mixins = {
"RegisterComm",
"UnregisterComm",
"UnregisterAllComm",
"SendCommMessage",
}
-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceComm-3.0 in
function AceComm:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
function AceComm:OnEmbedDisable(target)
target:UnregisterAllComm()
end
-- Update embeds
for target, v in pairs(AceComm.embeds) do
AceComm:Embed(target)
end

View File

@ -0,0 +1,5 @@
<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="ChatThrottleLib.lua"/>
<Script file="AceComm-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,503 @@
--
-- ChatThrottleLib by Mikk
--
-- Manages AddOn chat output to keep player from getting kicked off.
--
-- ChatThrottleLib:SendChatMessage/:SendAddonMessage functions that accept
-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
--
-- Priorities get an equal share of available bandwidth when fully loaded.
-- Communication channels are separated on extension+chattype+destination and
-- get round-robinned. (Destination only matters for whispers and channels,
-- obviously)
--
-- Will install hooks for SendChatMessage and SendAddonMessage to measure
-- bandwidth bypassing the library and use less bandwidth itself.
--
--
-- Fully embeddable library. Just copy this file into your addon directory,
-- add it to the .toc, and it's done.
--
-- Can run as a standalone addon also, but, really, just embed it! :-)
--
local CTL_VERSION = 21
local _G = _G
if _G.ChatThrottleLib then
if _G.ChatThrottleLib.version >= CTL_VERSION then
-- There's already a newer (or same) version loaded. Buh-bye.
return
elseif not _G.ChatThrottleLib.securelyHooked then
print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, <v16) in an addon somewhere. Get the addon updated or copy in a newer ChatThrottleLib.lua (>=v16) in it!")
-- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
-- ... and if someone has securehooked, they can kiss that goodbye too... >.<
_G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage
if _G.ChatThrottleLib.ORIG_SendAddonMessage then
_G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage
end
end
_G.ChatThrottleLib.ORIG_SendChatMessage = nil
_G.ChatThrottleLib.ORIG_SendAddonMessage = nil
end
if not _G.ChatThrottleLib then
_G.ChatThrottleLib = {}
end
ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
local ChatThrottleLib = _G.ChatThrottleLib
ChatThrottleLib.version = CTL_VERSION
------------------ TWEAKABLES -----------------
ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
local setmetatable = setmetatable
local table_remove = table.remove
local tostring = tostring
local GetTime = GetTime
local math_min = math.min
local math_max = math.max
local next = next
local strlen = string.len
local GetFrameRate = GetFrameRate
-----------------------------------------------------------------------
-- Double-linked ring implementation
local Ring = {}
local RingMeta = { __index = Ring }
function Ring:New()
local ret = {}
setmetatable(ret, RingMeta)
return ret
end
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
if self.pos then
obj.prev = self.pos.prev
obj.prev.next = obj
obj.next = self.pos
obj.next.prev = obj
else
obj.next = obj
obj.prev = obj
self.pos = obj
end
end
function Ring:Remove(obj)
obj.next.prev = obj.prev
obj.prev.next = obj.next
if self.pos == obj then
self.pos = obj.next
if self.pos == obj then
self.pos = nil
end
end
end
-----------------------------------------------------------------------
-- Recycling bin for pipes
-- A pipe is a plain integer-indexed queue, which also happens to be a ring member
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
local PipeBin = setmetatable({}, {__mode="k"})
local function DelPipe(pipe)
for i = #pipe, 1, -1 do
pipe[i] = nil
end
pipe.prev = nil
pipe.next = nil
PipeBin[pipe] = true
end
local function NewPipe()
local pipe = next(PipeBin)
if pipe then
PipeBin[pipe] = nil
return pipe
end
return {}
end
-----------------------------------------------------------------------
-- Recycling bin for messages
ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
local MsgBin = setmetatable({}, {__mode="k"})
local function DelMsg(msg)
msg[1] = nil
-- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
MsgBin[msg] = true
end
local function NewMsg()
local msg = next(MsgBin)
if msg then
MsgBin[msg] = nil
return msg
end
return {}
end
-----------------------------------------------------------------------
-- ChatThrottleLib:Init
-- Initialize queues, set up frame for OnUpdate, etc
function ChatThrottleLib:Init()
-- Set up queues
if not self.Prio then
self.Prio = {}
self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
end
-- v4: total send counters per priority
for _, Prio in pairs(self.Prio) do
Prio.nTotalSent = Prio.nTotalSent or 0
end
if not self.avail then
self.avail = 0 -- v5
end
if not self.nTotalSent then
self.nTotalSent = 0 -- v5
end
-- Set up a frame to get OnUpdate events
if not self.Frame then
self.Frame = CreateFrame("Frame")
self.Frame:Hide()
end
self.Frame:SetScript("OnUpdate", self.OnUpdate)
self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
self.OnUpdateDelay = 0
self.LastAvailUpdate = GetTime()
self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
if not self.securelyHooked then
-- Use secure hooks as of v16. Old regular hook support yanked out in v21.
self.securelyHooked = true
--SendChatMessage
hooksecurefunc("SendChatMessage", function(...)
return ChatThrottleLib.Hook_SendChatMessage(...)
end)
--SendAddonMessage
hooksecurefunc("SendAddonMessage", function(...)
return ChatThrottleLib.Hook_SendAddonMessage(...)
end)
end
self.nBypass = 0
end
-----------------------------------------------------------------------
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
local bMyTraffic = false
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
if bMyTraffic then
return
end
local self = ChatThrottleLib
local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
if bMyTraffic then
return
end
local self = ChatThrottleLib
local size = tostring(text or ""):len() + tostring(prefix or ""):len();
size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
end
-----------------------------------------------------------------------
-- ChatThrottleLib:UpdateAvail
-- Update self.avail with how much bandwidth is currently available
function ChatThrottleLib:UpdateAvail()
local now = GetTime()
local MAX_CPS = self.MAX_CPS;
local newavail = MAX_CPS * (now - self.LastAvailUpdate)
local avail = self.avail
if now - self.HardThrottlingBeginTime < 5 then
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
self.bChoking = true
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
avail = math_min(MAX_CPS, avail + newavail*0.5)
self.bChoking = true -- just a statistic
else
avail = math_min(self.BURST, avail + newavail)
self.bChoking = false
end
avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
self.avail = avail
self.LastAvailUpdate = now
return avail
end
-----------------------------------------------------------------------
-- Despooling logic
function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring
while ring.pos and Prio.avail > ring.pos[1].nSize do
local msg = table_remove(Prio.Ring.pos, 1)
if not Prio.Ring.pos[1] then
local pipe = Prio.Ring.pos
Prio.Ring:Remove(pipe)
Prio.ByName[pipe.name] = nil
DelPipe(pipe)
else
Prio.Ring.pos = Prio.Ring.pos.next
end
Prio.avail = Prio.avail - msg.nSize
bMyTraffic = true
msg.f(unpack(msg, 1, msg.n))
bMyTraffic = false
Prio.nTotalSent = Prio.nTotalSent + msg.nSize
DelMsg(msg)
if msg.callbackFn then
msg.callbackFn (msg.callbackArg)
end
end
end
function ChatThrottleLib.OnEvent(this,event)
-- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
local self = ChatThrottleLib
if event == "PLAYER_ENTERING_WORLD" then
self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
self.avail = 0
end
end
function ChatThrottleLib.OnUpdate(this,delay)
local self = ChatThrottleLib
self.OnUpdateDelay = self.OnUpdateDelay + delay
if self.OnUpdateDelay < 0.08 then
return
end
self.OnUpdateDelay = 0
self:UpdateAvail()
if self.avail < 0 then
return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
end
-- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
local n = 0
for prioname,Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
n = n + 1
end
end
-- Anything queued still?
if n<1 then
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
for prioname, Prio in pairs(self.Prio) do
self.avail = self.avail + Prio.avail
Prio.avail = 0
end
self.bQueueing = false
self.Frame:Hide()
return
end
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
local avail = self.avail/n
self.avail = 0
for prioname, Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
Prio.avail = Prio.avail + avail
if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
self:Despool(Prio)
-- Note: We might not get here if the user-supplied callback function errors out! Take care!
end
end
end
end
-----------------------------------------------------------------------
-- Spooling logic
function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname]
local pipe = Prio.ByName[pipename]
if not pipe then
self.Frame:Show()
pipe = NewPipe()
pipe.name = pipename
Prio.ByName[pipename] = pipe
Prio.Ring:Add(pipe)
end
pipe[#pipe + 1] = msg
self.bQueueing = true
end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
end
if callbackFn and type(callbackFn)~="function" then
error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end
local nSize = text:len()
if nSize>255 then
error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
end
nSize = nSize + self.MSG_OVERHEAD
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
bMyTraffic = true
_G.SendChatMessage(text, chattype, language, destination)
bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then
callbackFn (callbackArg)
end
return
end
-- Message needs to be queued
local msg = NewMsg()
msg.f = _G.SendChatMessage
msg[1] = text
msg[2] = chattype or "SAY"
msg[3] = language
msg[4] = destination
msg.n = 4
msg.nSize = nSize
msg.callbackFn = callbackFn
msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
end
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
end
if callbackFn and type(callbackFn)~="function" then
error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end
local nSize = prefix:len() + 1 + text:len();
if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
end
nSize = nSize + self.MSG_OVERHEAD;
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
bMyTraffic = true
_G.SendAddonMessage(prefix, text, chattype, target)
bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then
callbackFn (callbackArg)
end
return
end
-- Message needs to be queued
local msg = NewMsg()
msg.f = _G.SendAddonMessage
msg[1] = prefix
msg[2] = text
msg[3] = chattype
msg[4] = target
msg.n = (target~=nil) and 4 or 3;
msg.nSize = nSize
msg.callbackFn = callbackFn
msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
end
-----------------------------------------------------------------------
-- Get the ball rolling!
ChatThrottleLib:Init()
--[[ WoWBench debugging snippet
if(WOWB_VER) then
local function SayTimer()
print("SAY: "..GetTime().." "..arg1)
end
ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
end
]]

View File

@ -0,0 +1,57 @@
--- AceConfig-3.0 wrapper library.
-- Provides an API to register an options table with the config registry,
-- as well as associate it with a slash command.
-- @class file
-- @name AceConfig-3.0
-- @release $Id: AceConfig-3.0.lua 969 2010-10-07 02:11:48Z shefki $
--[[
AceConfig-3.0
Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
]]
local MAJOR, MINOR = "AceConfig-3.0", 2
local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfig then return end
local cfgreg = LibStub("AceConfigRegistry-3.0")
local cfgcmd = LibStub("AceConfigCmd-3.0")
--TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true)
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true)
-- Lua APIs
local pcall, error, type, pairs = pcall, error, type, pairs
-- -------------------------------------------------------------------
-- :RegisterOptionsTable(appName, options, slashcmd, persist)
--
-- - appName - (string) application name
-- - options - table or function ref, see AceConfigRegistry
-- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
--- Register a option table with the AceConfig registry.
-- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
-- @paramsig appName, options [, slashcmd]
-- @param appName The application name for the config table.
-- @param options The option table (or a function to generate one on demand). http://www.wowace.com/addons/ace3/pages/ace-config-3-0-options-tables/
-- @param slashcmd A slash command to register for the option table, or a table of slash commands.
-- @usage
-- local AceConfig = LibStub("AceConfig-3.0")
-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
if not ok then error(msg, 2) end
if slashcmd then
if type(slashcmd) == "table" then
for _,cmd in pairs(slashcmd) do
cfgcmd:CreateChatCommand(cmd, appName)
end
else
cfgcmd:CreateChatCommand(slashcmd, appName)
end
end
end

View File

@ -0,0 +1,8 @@
<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">
<Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/>
<Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/>
<Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/>
<!--<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/>-->
<Script file="AceConfig-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,787 @@
--- AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames.
-- @class file
-- @name AceConfigCmd-3.0
-- @release $Id: AceConfigCmd-3.0.lua 904 2009-12-13 11:56:37Z nevcairiel $
--[[
AceConfigCmd-3.0
Handles commandline optionstable access
REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
]]
-- TODO: plugin args
local MAJOR, MINOR = "AceConfigCmd-3.0", 12
local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigCmd then return end
AceConfigCmd.commands = AceConfigCmd.commands or {}
local commands = AceConfigCmd.commands
local cfgreg = LibStub("AceConfigRegistry-3.0")
local AceConsole -- LoD
local AceConsoleName = "AceConsole-3.0"
-- Lua APIs
local strsub, strsplit, strlower, strmatch, strtrim = string.sub, string.split, string.lower, string.match, string.trim
local format, tonumber, tostring = string.format, tonumber, tostring
local tsort, tinsert = table.sort, table.insert
local select, pairs, next, type = select, pairs, next, type
local error, assert = error, assert
-- WoW APIs
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, SELECTED_CHAT_FRAME, DEFAULT_CHAT_FRAME
local L = setmetatable({}, { -- TODO: replace with proper locale
__index = function(self,k) return k end
})
local function print(msg)
(SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg)
end
-- constants used by getparam() calls below
local handlertypes = {["table"]=true}
local handlermsg = "expected a table"
local functypes = {["function"]=true, ["string"]=true}
local funcmsg = "expected function or member name"
-- pickfirstset() - picks the first non-nil value and returns it
local function pickfirstset(...)
for i=1,select("#",...) do
if select(i,...)~=nil then
return select(i,...)
end
end
end
-- err() - produce real error() regarding malformed options tables etc
local function err(info,inputpos,msg )
local cmdstr=" "..strsub(info.input, 1, inputpos-1)
error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2)
end
-- usererr() - produce chatframe message regarding bad slash syntax etc
local function usererr(info,inputpos,msg )
local cmdstr=strsub(info.input, 1, inputpos-1);
print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table"))
end
-- callmethod() - call a given named method (e.g. "get", "set") with given arguments
local function callmethod(info, inputpos, tab, methodtype, ...)
local method = info[methodtype]
if not method then
err(info, inputpos, "'"..methodtype.."': not set")
end
info.arg = tab.arg
info.option = tab
info.type = tab.type
if type(method)=="function" then
return method(info, ...)
elseif type(method)=="string" then
if type(info.handler[method])~="function" then
err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
end
return info.handler[method](info.handler, info, ...)
else
assert(false) -- type should have already been checked on read
end
end
-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
local function callfunction(info, tab, methodtype, ...)
local method = tab[methodtype]
info.arg = tab.arg
info.option = tab
info.type = tab.type
if type(method)=="function" then
return method(info, ...)
else
assert(false) -- type should have already been checked on read
end
end
-- do_final() - do the final step (set/execute) along with validation and confirmation
local function do_final(info, inputpos, tab, methodtype, ...)
if info.validate then
local res = callmethod(info,inputpos,tab,"validate",...)
if type(res)=="string" then
usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
return
end
end
-- console ignores .confirm
callmethod(info,inputpos,tab,methodtype, ...)
end
-- getparam() - used by handle() to retreive and store "handler", "get", "set", etc
local function getparam(info, inputpos, tab, depth, paramname, types, errormsg)
local old,oldat = info[paramname], info[paramname.."_at"]
local val=tab[paramname]
if val~=nil then
if val==false then
val=nil
elseif not types[type(val)] then
err(info, inputpos, "'" .. paramname.. "' - "..errormsg)
end
info[paramname] = val
info[paramname.."_at"] = depth
end
return old,oldat
end
-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
local dummytable={}
local function iterateargs(tab)
if not tab.plugins then
return pairs(tab.args)
end
local argtabkey,argtab=next(tab.plugins)
local v
return function(_, k)
while argtab do
k,v = next(argtab, k)
if k then return k,v end
if argtab==tab.args then
argtab=nil
else
argtabkey,argtab = next(tab.plugins, argtabkey)
if not argtabkey then
argtab=tab.args
end
end
end
end
end
local function checkhidden(info, inputpos, tab)
if tab.cmdHidden~=nil then
return tab.cmdHidden
end
local hidden = tab.hidden
if type(hidden) == "function" or type(hidden) == "string" then
info.hidden = hidden
hidden = callmethod(info, inputpos, tab, 'hidden')
info.hidden = nil
end
return hidden
end
local function showhelp(info, inputpos, tab, depth, noHead)
if not noHead then
print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
end
local sortTbl = {} -- [1..n]=name
local refTbl = {} -- [name]=tableref
for k,v in iterateargs(tab) do
if not refTbl[k] then -- a plugin overriding something in .args
tinsert(sortTbl, k)
refTbl[k] = v
end
end
tsort(sortTbl, function(one, two)
local o1 = refTbl[one].order or 100
local o2 = refTbl[two].order or 100
if type(o1) == "function" or type(o1) == "string" then
info.order = o1
info[#info+1] = one
o1 = callmethod(info, inputpos, refTbl[one], "order")
info[#info] = nil
info.order = nil
end
if type(o2) == "function" or type(o1) == "string" then
info.order = o2
info[#info+1] = two
o2 = callmethod(info, inputpos, refTbl[two], "order")
info[#info] = nil
info.order = nil
end
if o1<0 and o2<0 then return o1<o2 end
if o2<0 then return true end
if o1<0 then return false end
if o1==o2 then return tostring(one)<tostring(two) end -- compare names
return o1<o2
end)
for i = 1, #sortTbl do
local k = sortTbl[i]
local v = refTbl[k]
if not checkhidden(info, inputpos, v) then
if v.type ~= "description" and v.type ~= "header" then
-- recursively show all inline groups
local name, desc = v.name, v.desc
if type(name) == "function" then
name = callfunction(info, v, 'name')
end
if type(desc) == "function" then
desc = callfunction(info, v, 'desc')
end
if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then
print(" "..(desc or name)..":")
local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg)
showhelp(info, inputpos, v, depth, true)
info.handler,info.handler_at = oldhandler,oldhandler_at
else
local key = k:gsub(" ", "_")
print(" |cffffff78"..key.."|r - "..(desc or name or ""))
end
end
end
end
end
local function keybindingValidateFunc(text)
if text == nil or text == "NONE" then
return nil
end
text = text:upper()
local shift, ctrl, alt
local modifier
while true do
if text == "-" then
break
end
modifier, text = strsplit('-', text, 2)
if text then
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then
return false
end
if modifier == "SHIFT" then
if shift then
return false
end
shift = true
end
if modifier == "CTRL" then
if ctrl then
return false
end
ctrl = true
end
if modifier == "ALT" then
if alt then
return false
end
alt = true
end
else
text = modifier
break
end
end
if text == "" then
return false
end
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then
return false
end
local s = text
if shift then
s = "SHIFT-" .. s
end
if ctrl then
s = "CTRL-" .. s
end
if alt then
s = "ALT-" .. s
end
return s
end
-- handle() - selfrecursing function that processes input->optiontable
-- - depth - starts at 0
-- - retfalse - return false rather than produce error if a match is not found (used by inlined groups)
local function handle(info, inputpos, tab, depth, retfalse)
if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end
-------------------------------------------------------------------
-- Grab hold of handler,set,get,func,etc if set (and remember old ones)
-- Note that we do NOT validate if method names are correct at this stage,
-- the handler may change before they're actually used!
local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg)
local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg)
local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg)
local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg)
local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg)
--local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg)
-------------------------------------------------------------------
-- Act according to .type of this table
if tab.type=="group" then
------------ group --------------------------------------------
if type(tab.args)~="table" then err(info, inputpos) end
if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end
-- grab next arg from input
local _,nextpos,arg = (info.input):find(" *([^ ]+) *", inputpos)
if not arg then
showhelp(info, inputpos, tab, depth)
return
end
nextpos=nextpos+1
-- loop .args and try to find a key with a matching name
for k,v in iterateargs(tab) do
if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
-- is this child an inline group? if so, traverse into it
if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then
info[depth+1] = k
if handle(info, inputpos, v, depth+1, true)==false then
info[depth+1] = nil
-- wasn't found in there, but that's ok, we just keep looking down here
else
return -- done, name was found in inline group
end
-- matching name and not a inline group
elseif strlower(arg)==strlower(k:gsub(" ", "_")) then
info[depth+1] = k
return handle(info,nextpos,v,depth+1)
end
end
-- no match
if retfalse then
-- restore old infotable members and return false to indicate failure
info.handler,info.handler_at = oldhandler,oldhandler_at
info.set,info.set_at = oldset,oldset_at
info.get,info.get_at = oldget,oldget_at
info.func,info.func_at = oldfunc,oldfunc_at
info.validate,info.validate_at = oldvalidate,oldvalidate_at
--info.confirm,info.confirm_at = oldconfirm,oldconfirm_at
return false
end
-- couldn't find the command, display error
usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"])
return
end
local str = strsub(info.input,inputpos);
if tab.type=="execute" then
------------ execute --------------------------------------------
do_final(info, inputpos, tab, "func")
elseif tab.type=="input" then
------------ input --------------------------------------------
local res = true
if tab.pattern then
if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
if not strmatch(str, tab.pattern) then
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
return
end
end
do_final(info, inputpos, tab, "set", str)
elseif tab.type=="toggle" then
------------ toggle --------------------------------------------
local b
local str = strtrim(strlower(str))
if str=="" then
b = callmethod(info, inputpos, tab, "get")
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
elseif str==L["on"] then
b = true
elseif str==L["off"] then
b = false
elseif tab.tristate and str==L["default"] then
b = nil
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str))
else
usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str))
end
return
end
do_final(info, inputpos, tab, "set", b)
elseif tab.type=="range" then
------------ range --------------------------------------------
local val = tonumber(str)
if not val then
usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
return
end
if type(info.step)=="number" then
val = val- (val % info.step)
end
if type(info.min)=="number" and val<info.min then
usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) )
return
end
if type(info.max)=="number" and val>info.max then
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) )
return
end
do_final(info, inputpos, tab, "set", val)
elseif tab.type=="select" then
------------ select ------------------------------------
local str = strtrim(strlower(str))
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
if str == "" then
local b = callmethod(info, inputpos, tab, "get")
local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[#info].."|r:"])
for k, v in pairs(values) do
if b == k then
print(fmt_sel:format(k, v))
else
print(fmt:format(k, v))
end
end
return
end
local ok
for k,v in pairs(values) do
if strlower(k)==str then
str = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
if not ok then
usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
return
end
do_final(info, inputpos, tab, "set", str)
elseif tab.type=="multiselect" then
------------ multiselect -------------------------------------------
local str = strtrim(strlower(str))
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
if str == "" then
local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[#info].."|r (multiple possible):"])
for k, v in pairs(values) do
if callmethod(info, inputpos, tab, "get", k) then
print(fmt_sel:format(k, v))
else
print(fmt:format(k, v))
end
end
return
end
--build a table of the selections, checking that they exist
--parse for =on =off =default in the process
--table will be key = true for options that should toggle, key = [on|off|default] for options to be set
local sels = {}
for v in str:gmatch("[^ ]+") do
--parse option=on etc
local opt, val = v:match('(.+)=(.+)')
--get option if toggling
if not opt then
opt = v
end
--check that the opt is valid
local ok
for k,v in pairs(values) do
if strlower(k)==opt then
opt = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
if not ok then
usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
return
end
--check that if val was supplied it is valid
if val then
if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then
--val is valid insert it
sels[opt] = val
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val))
else
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
end
return
end
else
-- no val supplied, toggle
sels[opt] = true
end
end
for opt, val in pairs(sels) do
local newval
if (val == true) then
--toggle the option
local b = callmethod(info, inputpos, tab, "get", opt)
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
newval = b
else
--set the option as specified
if val==L["on"] then
newval = true
elseif val==L["off"] then
newval = false
elseif val==L["default"] then
newval = nil
end
end
do_final(info, inputpos, tab, "set", opt, newval)
end
elseif tab.type=="color" then
------------ color --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
local r, g, b, a
if tab.hasAlpha then
if str:len() == 8 and str:find("^%x*$") then
--parse a hex string
r,g,b,a = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255, tonumber(str:sub(7, 8), 16) / 255
else
--parse seperate values
r,g,b,a = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a)
end
if not (r and g and b and a) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str))
return
end
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
a = a / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str))
end
else
a = 1.0
if str:len() == 6 and str:find("^%x*$") then
--parse a hex string
r,g,b = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255
else
--parse seperate values
r,g,b = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b = tonumber(r), tonumber(g), tonumber(b)
end
if not (r and g and b) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str))
return
end
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str))
end
end
do_final(info, inputpos, tab, "set", r,g,b,a)
elseif tab.type=="keybinding" then
------------ keybinding --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
local value = keybindingValidateFunc(str:upper())
if value == false then
usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str))
return
end
do_final(info, inputpos, tab, "set", value)
elseif tab.type=="description" then
------------ description --------------------
-- ignore description, GUI config only
else
err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'")
end
end
--- Handle the chat command.
-- This is usually called from a chat command handler to parse the command input as operations on an aceoptions table.\\
-- AceConfigCmd uses this function internally when a slash command is registered with `:CreateChatCommand`
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param input The commandline input (as given by the WoW handler, i.e. without the command itself)
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
-- -- Use AceConsole-3.0 to register a Chat Command
-- MyAddon:RegisterChatCommand("mychat", "ChatCommand")
--
-- -- Show the GUI if no input is supplied, otherwise handle the chat input.
-- function MyAddon:ChatCommand(input)
-- -- Assuming "MyOptions" is the appName of a valid options table
-- if not input or input:trim() == "" then
-- LibStub("AceConfigDialog-3.0"):Open("MyOptions")
-- else
-- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
-- end
-- end
function AceConfigCmd:HandleCommand(slashcmd, appName, input)
local optgetter = cfgreg:GetOptionsTable(appName)
if not optgetter then
error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2)
end
local options = assert( optgetter("cmd", MAJOR) )
local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
[0] = slashcmd,
appName = appName,
options = options,
input = input,
self = self,
handler = self,
uiType = "cmd",
uiName = MAJOR,
}
handle(info, 1, options, 0) -- (info, inputpos, table, depth)
end
--- Utility function to create a slash command handler.
-- Also registers tab completion with AceTab
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigCmd:CreateChatCommand(slashcmd, appName)
if not AceConsole then
AceConsole = LibStub(AceConsoleName)
end
if AceConsole.RegisterChatCommand(self, slashcmd, function(input)
AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable
end,
true) then -- succesfully registered so lets get the command -> app table in
commands[slashcmd] = appName
end
end
--- Utility function that returns the options table that belongs to a slashcommand.
-- Designed to be used for the AceTab interface.
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @return The options table associated with the slash command (or nil if the slash command was not registered)
function AceConfigCmd:GetChatCommandOptions(slashcmd)
return commands[slashcmd]
end

View File

@ -0,0 +1,4 @@
<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="AceConfigCmd-3.0.lua"/>
</Ui>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
<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="AceConfigDialog-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,346 @@
--- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
-- Options tables can be registered as raw tables, OR as function refs that return a table.\\
-- Such functions receive three arguments: "uiType", "uiName", "appName". \\
-- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
-- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\
-- * The **appName** field is the options table name as given at registration time \\
--
-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
-- @class file
-- @name AceConfigRegistry-3.0
-- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $
local MAJOR, MINOR = "AceConfigRegistry-3.0", 12
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigRegistry then return end
AceConfigRegistry.tables = AceConfigRegistry.tables or {}
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
if not AceConfigRegistry.callbacks then
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
end
-- Lua APIs
local tinsert, tconcat = table.insert, table.concat
local strfind, strmatch = string.find, string.match
local type, tostring, select, pairs = type, tostring, select, pairs
local error, assert = error, assert
-----------------------------------------------------------------------
-- Validating options table consistency:
AceConfigRegistry.validated = {
-- list of options table names ran through :ValidateOptionsTable automatically.
-- CLEARED ON PURPOSE, since newer versions may have newer validators
cmd = {},
dropdown = {},
dialog = {},
}
local function err(msg, errlvl, ...)
local t = {}
for i=select("#",...),1,-1 do
tinsert(t, (select(i, ...)))
end
error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
end
local isstring={["string"]=true, _="string"}
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
local istable={["table"]=true, _="table"}
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
local optstring={["nil"]=true,["string"]=true, _="string"}
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
local optnumber={["nil"]=true,["number"]=true, _="number"}
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
local opttable={["nil"]=true,["table"]=true, _="table"}
local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
local basekeys={
type=isstring,
name=isstringfunc,
desc=optstringfunc,
descStyle=optstring,
order=optmethodnumber,
validate=optmethodfalse,
confirm=optmethodbool,
confirmText=optstring,
disabled=optmethodbool,
hidden=optmethodbool,
guiHidden=optmethodbool,
dialogHidden=optmethodbool,
dropdownHidden=optmethodbool,
cmdHidden=optmethodbool,
icon=optstringfunc,
iconCoords=optmethodtable,
handler=opttable,
get=optmethodfalse,
set=optmethodfalse,
func=optmethodfalse,
arg={["*"]=true},
width=optstring,
}
local typedkeys={
header={},
description={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
fontSize=optstringfunc,
},
group={
args=istable,
plugins=opttable,
inline=optbool,
cmdInline=optbool,
guiInline=optbool,
dropdownInline=optbool,
dialogInline=optbool,
childGroups=optstring,
},
execute={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
},
input={
pattern=optstring,
usage=optstring,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
multiline=optboolnumber,
},
toggle={
tristate=optbool,
image=optstringfunc,
imageCoords=optmethodtable,
},
tristate={
},
range={
min=optnumber,
softMin=optnumber,
max=optnumber,
softMax=optnumber,
step=optnumber,
bigStep=optnumber,
isPercent=optbool,
},
select={
values=ismethodtable,
style={
["nil"]=true,
["string"]={dropdown=true,radio=true},
_="string: 'dropdown' or 'radio'"
},
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
multiselect={
values=ismethodtable,
style=optstring,
tristate=optbool,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
color={
hasAlpha=optbool,
},
keybinding={
-- TODO
},
}
local function validateKey(k,errlvl,...)
errlvl=(errlvl or 0)+1
if type(k)~="string" then
err("["..tostring(k).."] - key is not a string", errlvl,...)
end
if strfind(k, "[%c\127]") then
err("["..tostring(k).."] - key name contained control characters", errlvl,...)
end
end
local function validateVal(v, oktypes, errlvl,...)
errlvl=(errlvl or 0)+1
local isok=oktypes[type(v)] or oktypes["*"]
if not isok then
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
end
if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
if not isok[v] then
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
end
end
end
local function validate(options,errlvl,...)
errlvl=(errlvl or 0)+1
-- basic consistency
if type(options)~="table" then
err(": expected a table, got a "..type(options), errlvl,...)
end
if type(options.type)~="string" then
err(".type: expected a string, got a "..type(options.type), errlvl,...)
end
-- get type and 'typedkeys' member
local tk = typedkeys[options.type]
if not tk then
err(".type: unknown type '"..options.type.."'", errlvl,...)
end
-- make sure that all options[] are known parameters
for k,v in pairs(options) do
if not (tk[k] or basekeys[k]) then
err(": unknown parameter", errlvl,tostring(k),...)
end
end
-- verify that required params are there, and that everything is the right type
for k,oktypes in pairs(basekeys) do
validateVal(options[k], oktypes, errlvl,k,...)
end
for k,oktypes in pairs(tk) do
validateVal(options[k], oktypes, errlvl,k,...)
end
-- extra logic for groups
if options.type=="group" then
for k,v in pairs(options.args) do
validateKey(k,errlvl,"args",...)
validate(v, errlvl,k,"args",...)
end
if options.plugins then
for plugname,plugin in pairs(options.plugins) do
if type(plugin)~="table" then
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
end
for k,v in pairs(plugin) do
validateKey(k,errlvl,tostring(plugname),"plugins",...)
validate(v, errlvl,k,tostring(plugname),"plugins",...)
end
end
end
end
end
--- Validates basic structure and integrity of an options table \\
-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
-- @param options The table to be validated
-- @param name The name of the table to be validated (shown in any error message)
-- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
errlvl=(errlvl or 0)+1
name = name or "Optionstable"
if not options.name then
options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
end
validate(options,errlvl,name)
end
--- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
-- You should call this function if your options table changed from any outside event, like a game event
-- or a timer.
-- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigRegistry:NotifyChange(appName)
if not AceConfigRegistry.tables[appName] then return end
AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
end
-- -------------------------------------------------------------------
-- Registering and retreiving options tables:
-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
local function validateGetterArgs(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+2
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
end
if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
end
end
--- Register an options table with the config registry.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param options The options table, OR a function reference that generates it on demand. \\
-- See the top of the page for info on arguments passed to such functions.
function AceConfigRegistry:RegisterOptionsTable(appName, options)
if type(options)=="table" then
if options.type~="group" then -- quick sanity checker
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
end
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
if not AceConfigRegistry.validated[uiType][appName] then
AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
AceConfigRegistry.validated[uiType][appName] = true
end
return options
end
elseif type(options)=="function" then
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
local tab = assert(options(uiType, uiName, appName))
if not AceConfigRegistry.validated[uiType][appName] then
AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
AceConfigRegistry.validated[uiType][appName] = true
end
return tab
end
else
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
end
end
--- Returns an iterator of ["appName"]=funcref pairs
function AceConfigRegistry:IterateOptionsTables()
return pairs(AceConfigRegistry.tables)
end
--- Query the registry for a specific options table.
-- If only appName is given, a function is returned which you
-- can call with (uiType,uiName) to get the table.\\
-- If uiType&uiName are given, the table is returned.
-- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
-- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
local f = AceConfigRegistry.tables[appName]
if not f then
return nil
end
if uiType then
return f(uiType,uiName,1) -- get the table for us
else
return f -- return the function
end
end

View File

@ -0,0 +1,4 @@
<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="AceConfigRegistry-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,250 @@
--- **AceConsole-3.0** provides registration facilities for slash commands.
-- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
-- to your addons individual needs.
--
-- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceConsole itself.\\
-- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceConsole.
-- @class file
-- @name AceConsole-3.0
-- @release $Id: AceConsole-3.0.lua 878 2009-11-02 18:51:58Z nevcairiel $
local MAJOR,MINOR = "AceConsole-3.0", 7
local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConsole then return end -- No upgrade needed
AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
-- Lua APIs
local tconcat, tostring, select = table.concat, tostring, select
local type, pairs, error = type, pairs, error
local format, strfind, strsub = string.format, string.find, string.sub
local max = math.max
-- WoW APIs
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
local tmp={}
local function Print(self,frame,...)
local n=0
if self ~= AceConsole then
n=n+1
tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
end
for i=1, select("#", ...) do
n=n+1
tmp[n] = tostring(select(i, ...))
end
frame:AddMessage( tconcat(tmp," ",1,n) )
end
--- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
-- @paramsig [chatframe ,] ...
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
-- @param ... List of any values to be printed
function AceConsole:Print(...)
local frame = ...
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, frame, select(2,...))
else
return Print(self, DEFAULT_CHAT_FRAME, ...)
end
end
--- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
-- @paramsig [chatframe ,] "format"[, ...]
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
-- @param format Format string - same syntax as standard Lua format()
-- @param ... Arguments to the format string
function AceConsole:Printf(...)
local frame = ...
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, frame, format(select(2,...)))
else
return Print(self, DEFAULT_CHAT_FRAME, format(...))
end
end
--- Register a simple chat command
-- @param command Chat command to be registered WITHOUT leading "/"
-- @param func Function to call when the slash command is being used (funcref or methodname)
-- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
function AceConsole:RegisterChatCommand( command, func, persist )
if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
local name = "ACECONSOLE_"..command:upper()
if type( func ) == "string" then
SlashCmdList[name] = function(input, editBox)
self[func](self, input, editBox)
end
else
SlashCmdList[name] = func
end
_G["SLASH_"..name.."1"] = "/"..command:lower()
AceConsole.commands[command] = name
-- non-persisting commands are registered for enabling disabling
if not persist then
if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
AceConsole.weakcommands[self][command] = func
end
return true
end
--- Unregister a chatcommand
-- @param command Chat command to be unregistered WITHOUT leading "/"
function AceConsole:UnregisterChatCommand( command )
local name = AceConsole.commands[command]
if name then
SlashCmdList[name] = nil
_G["SLASH_" .. name .. "1"] = nil
hash_SlashCmdList["/" .. command:upper()] = nil
AceConsole.commands[command] = nil
end
end
--- Get an iterator over all Chat Commands registered with AceConsole
-- @return Iterator (pairs) over all commands
function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
local function nils(n, ...)
if n>1 then
return nil, nils(n-1, ...)
elseif n==1 then
return nil, ...
else
return ...
end
end
--- Retreive one or more space-separated arguments from a string.
-- Treats quoted strings and itemlinks as non-spaced.
-- @param string The raw argument string
-- @param numargs How many arguments to get (default 1)
-- @param startpos Where in the string to start scanning (default 1)
-- @return Returns arg1, arg2, ..., nextposition\\
-- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
function AceConsole:GetArgs(str, numargs, startpos)
numargs = numargs or 1
startpos = max(startpos or 1, 1)
local pos=startpos
-- find start of new arg
pos = strfind(str, "[^ ]", pos)
if not pos then -- whoops, end of string
return nils(numargs, 1e9)
end
if numargs<1 then
return pos
end
-- quoted or space separated? find out which pattern to use
local delim_or_pipe
local ch = strsub(str, pos, pos)
if ch=='"' then
pos = pos + 1
delim_or_pipe='([|"])'
elseif ch=="'" then
pos = pos + 1
delim_or_pipe="([|'])"
else
delim_or_pipe="([| ])"
end
startpos = pos
while true do
-- find delimiter or hyperlink
local ch,_
pos,_,ch = strfind(str, delim_or_pipe, pos)
if not pos then break end
if ch=="|" then
-- some kind of escape
if strsub(str,pos,pos+1)=="|H" then
-- It's a |H....|hhyper link!|h
pos=strfind(str, "|h", pos+2) -- first |h
if not pos then break end
pos=strfind(str, "|h", pos+2) -- second |h
if not pos then break end
elseif strsub(str,pos, pos+1) == "|T" then
-- It's a |T....|t texture
pos=strfind(str, "|t", pos+2)
if not pos then break end
end
pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
else
-- found delimiter, done with this arg
return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
end
end
-- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
return strsub(str, startpos), nils(numargs-1, 1e9)
end
--- embedding and embed handling
local mixins = {
"Print",
"Printf",
"RegisterChatCommand",
"UnregisterChatCommand",
"GetArgs",
}
-- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceBucket in
function AceConsole:Embed( target )
for k, v in pairs( mixins ) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
function AceConsole:OnEmbedEnable( target )
if AceConsole.weakcommands[target] then
for command, func in pairs( AceConsole.weakcommands[target] ) do
target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
end
end
end
function AceConsole:OnEmbedDisable( target )
if AceConsole.weakcommands[target] then
for command, func in pairs( AceConsole.weakcommands[target] ) do
target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
end
end
end
for addon in pairs(AceConsole.embeds) do
AceConsole:Embed(addon)
end

View File

@ -0,0 +1,4 @@
<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="AceConsole-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,728 @@
--- **AceDB-3.0** manages the SavedVariables of your addon.
-- It offers profile management, smart defaults and namespaces for modules.\\
-- Data can be saved in different data-types, depending on its intended usage.
-- The most common data-type is the `profile` type, which allows the user to choose
-- the active profile, and manage the profiles of all of his characters.\\
-- The following data types are available:
-- * **char** Character-specific data. Every character has its own database.
-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
-- * **class** Class-specific data. All of the players characters of the same class share this database.
-- * **race** Race-specific data. All of the players characters of the same race share this database.
-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
-- * **global** Global Data. All characters on the same account share this database.
-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
--
-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
-- of the DBObjectLib listed here. \\
-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
--
-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
--
-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
--
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
--
-- -- declare defaults to be used in the DB
-- local defaults = {
-- profile = {
-- setting = true,
-- }
-- }
--
-- function MyAddon:OnInitialize()
-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
-- end
-- @class file
-- @name AceDB-3.0.lua
-- @release $Id: AceDB-3.0.lua 940 2010-06-19 08:01:47Z nevcairiel $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 21
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
if not AceDB then return end -- No upgrade needed
-- Lua APIs
local type, pairs, next, error = type, pairs, next, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
-- WoW APIs
local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub
AceDB.db_registry = AceDB.db_registry or {}
AceDB.frame = AceDB.frame or CreateFrame("Frame")
local CallbackHandler
local CallbackDummy = { Fire = function() end }
local DBObjectLib = {}
--[[-------------------------------------------------------------------------
AceDB Utility Functions
---------------------------------------------------------------------------]]
-- Simple shallow copy for copying defaults
local function copyTable(src, dest)
if type(dest) ~= "table" then dest = {} end
if type(src) == "table" then
for k,v in pairs(src) do
if type(v) == "table" then
-- try to index the key first so that the metatable creates the defaults, if set, and use that table
v = copyTable(v, dest[k])
end
dest[k] = v
end
end
return dest
end
-- Called to add defaults to a section of the database
--
-- When a ["*"] default section is indexed with a new key, a table is returned
-- and set in the host table. These tables must be cleaned up by removeDefaults
-- in order to ensure we don't write empty default tables.
local function copyDefaults(dest, src)
-- this happens if some value in the SV overwrites our default value with a non-table
--if type(dest) ~= "table" then return end
for k, v in pairs(src) do
if k == "*" or k == "**" then
if type(v) == "table" then
-- This is a metatable used for table defaults
local mt = {
-- This handles the lookup and creation of new subtables
__index = function(t,k)
if k == nil then return nil end
local tbl = {}
copyDefaults(tbl, v)
rawset(t, k, tbl)
return tbl
end,
}
setmetatable(dest, mt)
-- handle already existing tables in the SV
for dk, dv in pairs(dest) do
if not rawget(src, dk) and type(dv) == "table" then
copyDefaults(dv, v)
end
end
else
-- Values are not tables, so this is just a simple return
local mt = {__index = function(t,k) return k~=nil and v or nil end}
setmetatable(dest, mt)
end
elseif type(v) == "table" then
if not rawget(dest, k) then rawset(dest, k, {}) end
if type(dest[k]) == "table" then
copyDefaults(dest[k], v)
if src['**'] then
copyDefaults(dest[k], src['**'])
end
end
else
if rawget(dest, k) == nil then
rawset(dest, k, v)
end
end
end
end
-- Called to remove all defaults in the default table from the database
local function removeDefaults(db, defaults, blocker)
-- remove all metatables from the db, so we don't accidentally create new sub-tables through them
setmetatable(db, nil)
-- loop through the defaults and remove their content
for k,v in pairs(defaults) do
if k == "*" or k == "**" then
if type(v) == "table" then
-- Loop through all the actual k,v pairs and remove
for key, value in pairs(db) do
if type(value) == "table" then
-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
if defaults[key] == nil and (not blocker or blocker[key] == nil) then
removeDefaults(value, v)
-- if the table is empty afterwards, remove it
if next(value) == nil then
db[key] = nil
end
-- if it was specified, only strip ** content, but block values which were set in the key table
elseif k == "**" then
removeDefaults(value, v, defaults[key])
end
end
end
elseif k == "*" then
-- check for non-table default
for key, value in pairs(db) do
if defaults[key] == nil and v == value then
db[key] = nil
end
end
end
elseif type(v) == "table" and type(db[k]) == "table" then
-- if a blocker was set, dive into it, to allow multi-level defaults
removeDefaults(db[k], v, blocker and blocker[k])
if next(db[k]) == nil then
db[k] = nil
end
else
-- check if the current value matches the default, and that its not blocked by another defaults table
if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
db[k] = nil
end
end
end
end
-- This is called when a table section is first accessed, to set up the defaults
local function initSection(db, section, svstore, key, defaults)
local sv = rawget(db, "sv")
local tableCreated
if not sv[svstore] then sv[svstore] = {} end
if not sv[svstore][key] then
sv[svstore][key] = {}
tableCreated = true
end
local tbl = sv[svstore][key]
if defaults then
copyDefaults(tbl, defaults)
end
rawset(db, section, tbl)
return tableCreated, tbl
end
-- Metatable to handle the dynamic creation of sections and copying of sections.
local dbmt = {
__index = function(t, section)
local keys = rawget(t, "keys")
local key = keys[section]
if key then
local defaultTbl = rawget(t, "defaults")
local defaults = defaultTbl and defaultTbl[section]
if section == "profile" then
local new = initSection(t, section, "profiles", key, defaults)
if new then
-- Callback: OnNewProfile, database, newProfileKey
t.callbacks:Fire("OnNewProfile", t, key)
end
elseif section == "profiles" then
local sv = rawget(t, "sv")
if not sv.profiles then sv.profiles = {} end
rawset(t, "profiles", sv.profiles)
elseif section == "global" then
local sv = rawget(t, "sv")
if not sv.global then sv.global = {} end
if defaults then
copyDefaults(sv.global, defaults)
end
rawset(t, section, sv.global)
else
initSection(t, section, section, key, defaults)
end
end
return rawget(t, section)
end
}
local function validateDefaults(defaults, keyTbl, offset)
if not defaults then return end
offset = offset or 0
for k in pairs(defaults) do
if not keyTbl[k] or k == "profiles" then
error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
end
end
end
local preserve_keys = {
["callbacks"] = true,
["RegisterCallback"] = true,
["UnregisterCallback"] = true,
["UnregisterAllCallbacks"] = true,
["children"] = true,
}
local realmKey = GetRealmName()
local charKey = UnitName("player") .. " - " .. realmKey
local _, classKey = UnitClass("player")
local _, raceKey = UnitRace("player")
local factionKey = UnitFactionGroup("player")
local factionrealmKey = factionKey .. " - " .. realmKey
-- Actual database initialization function
local function initdb(sv, defaults, defaultProfile, olddb, parent)
-- Generate the database keys for each section
-- map "true" to our "Default" profile
if defaultProfile == true then defaultProfile = "Default" end
local profileKey
if not parent then
-- Make a container for profile keys
if not sv.profileKeys then sv.profileKeys = {} end
-- Try to get the profile selected from the char db
profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
-- save the selected profile for later
sv.profileKeys[charKey] = profileKey
else
-- Use the profile of the parents DB
profileKey = parent.keys.profile or defaultProfile or charKey
-- clear the profileKeys in the DB, namespaces don't need to store them
sv.profileKeys = nil
end
-- This table contains keys that enable the dynamic creation
-- of each section of the table. The 'global' and 'profiles'
-- have a key of true, since they are handled in a special case
local keyTbl= {
["char"] = charKey,
["realm"] = realmKey,
["class"] = classKey,
["race"] = raceKey,
["faction"] = factionKey,
["factionrealm"] = factionrealmKey,
["profile"] = profileKey,
["global"] = true,
["profiles"] = true,
}
validateDefaults(defaults, keyTbl, 1)
-- This allows us to use this function to reset an entire database
-- Clear out the old database
if olddb then
for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
end
-- Give this database the metatable so it initializes dynamically
local db = setmetatable(olddb or {}, dbmt)
if not rawget(db, "callbacks") then
-- try to load CallbackHandler-1.0 if it loaded after our library
if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
end
-- Copy methods locally into the database object, to avoid hitting
-- the metatable when calling methods
if not parent then
for name, func in pairs(DBObjectLib) do
db[name] = func
end
else
-- hack this one in
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
-- Set some properties in the database object
db.profiles = sv.profiles
db.keys = keyTbl
db.sv = sv
--db.sv_name = name
db.defaults = defaults
db.parent = parent
-- store the DB in the registry
AceDB.db_registry[db] = true
return db
end
-- handle PLAYER_LOGOUT
-- strip all defaults from all databases
-- and cleans up empty sections
local function logoutHandler(frame, event)
if event == "PLAYER_LOGOUT" then
for db in pairs(AceDB.db_registry) do
db.callbacks:Fire("OnDatabaseShutdown", db)
db:RegisterDefaults(nil)
-- cleanup sections that are empty without defaults
local sv = rawget(db, "sv")
for section in pairs(db.keys) do
if rawget(sv, section) then
-- global is special, all other sections have sub-entrys
-- also don't delete empty profiles on main dbs, only on namespaces
if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
for key in pairs(sv[section]) do
if not next(sv[section][key]) then
sv[section][key] = nil
end
end
end
if not next(sv[section]) then
sv[section] = nil
end
end
end
end
end
end
AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
AceDB.frame:SetScript("OnEvent", logoutHandler)
--[[-------------------------------------------------------------------------
AceDB Object Method Definitions
---------------------------------------------------------------------------]]
--- Sets the defaults table for the given database object by clearing any
-- that are currently set, and then setting the new defaults.
-- @param defaults A table of defaults for this database
function DBObjectLib:RegisterDefaults(defaults)
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
end
validateDefaults(defaults, self.keys)
-- Remove any currently set defaults
if self.defaults then
for section,key in pairs(self.keys) do
if self.defaults[section] and rawget(self, section) then
removeDefaults(self[section], self.defaults[section])
end
end
end
-- Set the DBObject.defaults table
self.defaults = defaults
-- Copy in any defaults, only touching those sections already created
if defaults then
for section,key in pairs(self.keys) do
if defaults[section] and rawget(self, section) then
copyDefaults(self[section], defaults[section])
end
end
end
end
--- Changes the profile of the database and all of it's namespaces to the
-- supplied named profile
-- @param name The name of the profile to set as the current profile
function DBObjectLib:SetProfile(name)
if type(name) ~= "string" then
error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
end
-- changing to the same profile, dont do anything
if name == self.keys.profile then return end
local oldProfile = self.profile
local defaults = self.defaults and self.defaults.profile
-- Callback: OnProfileShutdown, database
self.callbacks:Fire("OnProfileShutdown", self)
if oldProfile and defaults then
-- Remove the defaults from the old profile
removeDefaults(oldProfile, defaults)
end
self.profile = nil
self.keys["profile"] = name
-- if the storage exists, save the new profile
-- this won't exist on namespaces.
if self.sv.profileKeys then
self.sv.profileKeys[charKey] = name
end
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.SetProfile(db, name)
end
end
-- Callback: OnProfileChanged, database, newProfileKey
self.callbacks:Fire("OnProfileChanged", self, name)
end
--- Returns a table with the names of the existing profiles in the database.
-- You can optionally supply a table to re-use for this purpose.
-- @param tbl A table to store the profile names in (optional)
function DBObjectLib:GetProfiles(tbl)
if tbl and type(tbl) ~= "table" then
error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
end
-- Clear the container table
if tbl then
for k,v in pairs(tbl) do tbl[k] = nil end
else
tbl = {}
end
local curProfile = self.keys.profile
local i = 0
for profileKey in pairs(self.profiles) do
i = i + 1
tbl[i] = profileKey
if curProfile and profileKey == curProfile then curProfile = nil end
end
-- Add the current profile, if it hasn't been created yet
if curProfile then
i = i + 1
tbl[i] = curProfile
end
return tbl, i
end
--- Returns the current profile name used by the database
function DBObjectLib:GetCurrentProfile()
return self.keys.profile
end
--- Deletes a named profile. This profile must not be the active profile.
-- @param name The name of the profile to be deleted
-- @param silent If true, do not raise an error when the profile does not exist
function DBObjectLib:DeleteProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
end
if self.keys.profile == name then
error("Cannot delete the active profile in an AceDBObject.", 2)
end
if not rawget(self.profiles, name) and not silent then
error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
end
self.profiles[name] = nil
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.DeleteProfile(db, name, true)
end
end
-- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", self, name)
end
--- Copies a named profile into the current profile, overwriting any conflicting
-- settings.
-- @param name The name of the profile to be copied into the current profile
-- @param silent If true, do not raise an error when the profile does not exist
function DBObjectLib:CopyProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
end
if name == self.keys.profile then
error("Cannot have the same source and destination profiles.", 2)
end
if not rawget(self.profiles, name) and not silent then
error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
end
-- Reset the profile before copying
DBObjectLib.ResetProfile(self, nil, true)
local profile = self.profile
local source = self.profiles[name]
copyTable(source, profile)
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.CopyProfile(db, name, true)
end
end
-- Callback: OnProfileCopied, database, sourceProfileKey
self.callbacks:Fire("OnProfileCopied", self, name)
end
--- Resets the current profile to the default values (if specified).
-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
function DBObjectLib:ResetProfile(noChildren, noCallbacks)
local profile = self.profile
for k,v in pairs(profile) do
profile[k] = nil
end
local defaults = self.defaults and self.defaults.profile
if defaults then
copyDefaults(profile, defaults)
end
-- populate to child namespaces
if self.children and not noChildren then
for _, db in pairs(self.children) do
DBObjectLib.ResetProfile(db, nil, noCallbacks)
end
end
-- Callback: OnProfileReset, database
if not noCallbacks then
self.callbacks:Fire("OnProfileReset", self)
end
end
--- Resets the entire database, using the string defaultProfile as the new default
-- profile.
-- @param defaultProfile The profile name to use as the default
function DBObjectLib:ResetDB(defaultProfile)
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
end
local sv = self.sv
for k,v in pairs(sv) do
sv[k] = nil
end
local parent = self.parent
initdb(sv, self.defaults, defaultProfile, self)
-- fix the child namespaces
if self.children then
if not sv.namespaces then sv.namespaces = {} end
for name, db in pairs(self.children) do
if not sv.namespaces[name] then sv.namespaces[name] = {} end
initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
end
end
-- Callback: OnDatabaseReset, database
self.callbacks:Fire("OnDatabaseReset", self)
-- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
return self
end
--- Creates a new database namespace, directly tied to the database. This
-- is a full scale database in it's own rights other than the fact that
-- it cannot control its profile individually
-- @param name The name of the new namespace
-- @param defaults A table of values to use as defaults
function DBObjectLib:RegisterNamespace(name, defaults)
if type(name) ~= "string" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
end
if self.children and self.children[name] then
error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
end
local sv = self.sv
if not sv.namespaces then sv.namespaces = {} end
if not sv.namespaces[name] then
sv.namespaces[name] = {}
end
local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
if not self.children then self.children = {} end
self.children[name] = newDB
return newDB
end
--- Returns an already existing namespace from the database object.
-- @param name The name of the new namespace
-- @param silent if true, the addon is optional, silently return nil if its not found
-- @usage
-- local namespace = self.db:GetNamespace('namespace')
-- @return the namespace object if found
function DBObjectLib:GetNamespace(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
end
if not silent and not (self.children and self.children[name]) then
error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
end
if not self.children then self.children = {} end
return self.children[name]
end
--[[-------------------------------------------------------------------------
AceDB Exposed Methods
---------------------------------------------------------------------------]]
--- Creates a new database object that can be used to handle database settings and profiles.
-- By default, an empty DB is created, using a character specific profile.
--
-- You can override the default profile used by passing any profile name as the third argument,
-- or by passing //true// as the third argument to use a globally shared profile called "Default".
--
-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
-- will use a profile named "char", and not a character-specific profile.
-- @param tbl The name of variable, or table to use for the database
-- @param defaults A table of database defaults
-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
-- You can also pass //true// to use a shared global profile called "Default".
-- @usage
-- -- Create an empty DB using a character-specific default profile.
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
-- @usage
-- -- Create a DB using defaults and using a shared default profile
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
function AceDB:New(tbl, defaults, defaultProfile)
if type(tbl) == "string" then
local name = tbl
tbl = _G[name]
if not tbl then
tbl = {}
_G[name] = tbl
end
end
if type(tbl) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
end
if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
end
return initdb(tbl, defaults, defaultProfile)
end
-- upgrade existing databases
for db in pairs(AceDB.db_registry) do
if not db.parent then
for name,func in pairs(DBObjectLib) do
db[name] = func
end
else
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
end

View File

@ -0,0 +1,4 @@
<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="AceDB-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,420 @@
--- AceDBOptions-3.0 provides a universal AceConfig options screen for managing AceDB-3.0 profiles.
-- @class file
-- @name AceDBOptions-3.0
-- @release $Id: AceDBOptions-3.0.lua 938 2010-06-13 07:21:38Z nevcairiel $
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 12
local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR)
if not AceDBOptions then return end -- No upgrade needed
-- Lua APIs
local pairs, next = pairs, next
-- WoW APIs
local UnitClass = UnitClass
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: NORMAL_FONT_COLOR_CODE, FONT_COLOR_CODE_CLOSE
AceDBOptions.optionTables = AceDBOptions.optionTables or {}
AceDBOptions.handlers = AceDBOptions.handlers or {}
--[[
Localization of AceDBOptions-3.0
]]
local L = {
default = "Default",
intro = "You can change the active database profile, so you can have different settings for every character.",
reset_desc = "Reset the current profile back to its default values, in case your configuration is broken, or you simply want to start over.",
reset = "Reset Profile",
reset_sub = "Reset the current profile to the default",
choose_desc = "You can either create a new profile by entering a name in the editbox, or choose one of the already existing profiles.",
new = "New",
new_sub = "Create a new empty profile.",
choose = "Existing Profiles",
choose_sub = "Select one of your currently available profiles.",
copy_desc = "Copy the settings from one existing profile into the currently active profile.",
copy = "Copy From",
delete_desc = "Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.",
delete = "Delete a Profile",
delete_sub = "Deletes a profile from the database.",
delete_confirm = "Are you sure you want to delete the selected profile?",
profiles = "Profiles",
profiles_sub = "Manage Profiles",
current = "Current Profile:",
}
local LOCALE = GetLocale()
if LOCALE == "deDE" then
L["default"] = "Standard"
L["intro"] = "Hier kannst du das aktive Datenbankprofile \195\164ndern, damit du verschiedene Einstellungen f\195\188r jeden Charakter erstellen kannst, wodurch eine sehr flexible Konfiguration m\195\182glich wird."
L["reset_desc"] = "Setzt das momentane Profil auf Standardwerte zur\195\188ck, f\195\188r den Fall das mit der Konfiguration etwas schief lief oder weil du einfach neu starten willst."
L["reset"] = "Profil zur\195\188cksetzen"
L["reset_sub"] = "Das aktuelle Profil auf Standard zur\195\188cksetzen."
L["choose_desc"] = "Du kannst ein neues Profil erstellen, indem du einen neuen Namen in der Eingabebox 'Neu' eingibst, oder w\195\164hle eines der vorhandenen Profile aus."
L["new"] = "Neu"
L["new_sub"] = "Ein neues Profil erstellen."
L["choose"] = "Vorhandene Profile"
L["choose_sub"] = "W\195\164hlt ein bereits vorhandenes Profil aus."
L["copy_desc"] = "Kopiere die Einstellungen von einem vorhandenen Profil in das aktive Profil."
L["copy"] = "Kopieren von..."
L["delete_desc"] = "L\195\182sche vorhandene oder unbenutzte Profile aus der Datenbank um Platz zu sparen und um die SavedVariables Datei 'sauber' zu halten."
L["delete"] = "Profil l\195\182schen"
L["delete_sub"] = "L\195\182scht ein Profil aus der Datenbank."
L["delete_confirm"] = "Willst du das ausgew\195\164hlte Profil wirklich l\195\182schen?"
L["profiles"] = "Profile"
L["profiles_sub"] = "Profile verwalten"
--L["current"] = "Current Profile:"
elseif LOCALE == "frFR" then
L["default"] = "D\195\169faut"
L["intro"] = "Vous pouvez changer le profil actuel afin d'avoir des param\195\168tres diff\195\169rents pour chaque personnage, permettant ainsi d'avoir une configuration tr\195\168s flexible."
L["reset_desc"] = "R\195\169initialise le profil actuel au cas o\195\185 votre configuration est corrompue ou si vous voulez tout simplement faire table rase."
L["reset"] = "R\195\169initialiser le profil"
L["reset_sub"] = "R\195\169initialise le profil actuel avec les param\195\168tres par d\195\169faut."
L["choose_desc"] = "Vous pouvez cr\195\169er un nouveau profil en entrant un nouveau nom dans la bo\195\174te de saisie, ou en choississant un des profils d\195\169j\195\160 existants."
L["new"] = "Nouveau"
L["new_sub"] = "Cr\195\169\195\169e un nouveau profil vierge."
L["choose"] = "Profils existants"
L["choose_sub"] = "Permet de choisir un des profils d\195\169j\195\160 disponibles."
L["copy_desc"] = "Copie les param\195\168tres d'un profil d\195\169j\195\160 existant dans le profil actuellement actif."
L["copy"] = "Copier \195\160 partir de"
L["delete_desc"] = "Supprime les profils existants inutilis\195\169s de la base de donn\195\169es afin de gagner de la place et de nettoyer le fichier SavedVariables."
L["delete"] = "Supprimer un profil"
L["delete_sub"] = "Supprime un profil de la base de donn\195\169es."
L["delete_confirm"] = "Etes-vous s\195\187r de vouloir supprimer le profil s\195\169lectionn\195\169 ?"
L["profiles"] = "Profils"
L["profiles_sub"] = "Gestion des profils"
--L["current"] = "Current Profile:"
elseif LOCALE == "koKR" then
L["default"] = "기본값"
L["intro"] = "모든 캐릭터의 다양한 설정과 사용중인 데이터베이스 프로필, 어느것이던지 매우 다루기 쉽게 바꿀수 있습니다."
L["reset_desc"] = "단순히 다시 새롭게 구성을 원하는 경우, 현재 프로필을 기본값으로 초기화 합니다."
L["reset"] = "프로필 초기화"
L["reset_sub"] = "현재의 프로필을 기본값으로 초기화 합니다"
L["choose_desc"] = "새로운 이름을 입력하거나, 이미 있는 프로필중 하나를 선택하여 새로운 프로필을 만들 수 있습니다."
L["new"] = "새로운 프로필"
L["new_sub"] = "새로운 프로필을 만듭니다."
L["choose"] = "프로필 선택"
L["choose_sub"] = "당신이 현재 이용할수 있는 프로필을 선택합니다."
L["copy_desc"] = "현재 사용중인 프로필에, 선택한 프로필의 설정을 복사합니다."
L["copy"] = "복사"
L["delete_desc"] = "데이터베이스에 사용중이거나 저장된 프로파일 삭제로 SavedVariables 파일의 정리와 공간 절약이 됩니다."
L["delete"] = "프로필 삭제"
L["delete_sub"] = "데이터베이스의 프로필을 삭제합니다."
L["delete_confirm"] = "정말로 선택한 프로필의 삭제를 원하십니까?"
L["profiles"] = "프로필"
L["profiles_sub"] = "프로필 설정"
--L["current"] = "Current Profile:"
elseif LOCALE == "esES" or LOCALE == "esMX" then
L["default"] = "Por defecto"
L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones."
L["reset_desc"] = "Reinicia el perfil actual a los valores por defectos, en caso de que se haya estropeado la configuración o quieras volver a empezar de nuevo."
L["reset"] = "Reiniciar Perfil"
L["reset_sub"] = "Reinicar el perfil actual al de por defecto"
L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes."
L["new"] = "Nuevo"
L["new_sub"] = "Crear un nuevo perfil vacio."
L["choose"] = "Perfiles existentes"
L["choose_sub"] = "Selecciona uno de los perfiles disponibles."
L["copy_desc"] = "Copia los ajustes de un perfil existente al perfil actual."
L["copy"] = "Copiar de"
L["delete_desc"] = "Borra los perfiles existentes y sin uso de la base de datos para ganar espacio y limpiar el archivo SavedVariables."
L["delete"] = "Borrar un Perfil"
L["delete_sub"] = "Borra un perfil de la base de datos."
L["delete_confirm"] = "¿Estas seguro que quieres borrar el perfil seleccionado?"
L["profiles"] = "Perfiles"
L["profiles_sub"] = "Manejar Perfiles"
--L["current"] = "Current Profile:"
elseif LOCALE == "zhTW" then
L["default"] = "預設"
L["intro"] = "你可以選擇一個活動的資料設定檔,這樣你的每個角色就可以擁有不同的設定值,可以給你的插件設定帶來極大的靈活性。"
L["reset_desc"] = "將當前的設定檔恢復到它的預設值,用於你的設定檔損壞,或者你只是想重來的情況。"
L["reset"] = "重置設定檔"
L["reset_sub"] = "將當前的設定檔恢復為預設值"
L["choose_desc"] = "你可以通過在文本框內輸入一個名字創立一個新的設定檔,也可以選擇一個已經存在的設定檔。"
L["new"] = "新建"
L["new_sub"] = "新建一個空的設定檔。"
L["choose"] = "現有的設定檔"
L["choose_sub"] = "從當前可用的設定檔裏面選擇一個。"
L["copy_desc"] = "從當前某個已保存的設定檔複製到當前正使用的設定檔。"
L["copy"] = "複製自"
L["delete_desc"] = "從資料庫裏刪除不再使用的設定檔以節省空間並且清理SavedVariables檔。"
L["delete"] = "刪除一個設定檔"
L["delete_sub"] = "從資料庫裏刪除一個設定檔。"
L["delete_confirm"] = "你確定要刪除所選擇的設定檔嗎?"
L["profiles"] = "設定檔"
L["profiles_sub"] = "管理設定檔"
--L["current"] = "Current Profile:"
elseif LOCALE == "zhCN" then
L["default"] = "默认"
L["intro"] = "你可以选择一个活动的数据配置文件,这样你的每个角色就可以拥有不同的设置值,可以给你的插件配置带来极大的灵活性。"
L["reset_desc"] = "将当前的配置文件恢复到它的默认值,用于你的配置文件损坏,或者你只是想重来的情况。"
L["reset"] = "重置配置文件"
L["reset_sub"] = "将当前的配置文件恢复为默认值"
L["choose_desc"] = "你可以通过在文本框内输入一个名字创立一个新的配置文件,也可以选择一个已经存在的配置文件。"
L["new"] = "新建"
L["new_sub"] = "新建一个空的配置文件。"
L["choose"] = "现有的配置文件"
L["choose_sub"] = "从当前可用的配置文件里面选择一个。"
L["copy_desc"] = "从当前某个已保存的配置文件复制到当前正使用的配置文件。"
L["copy"] = "复制自"
L["delete_desc"] = "从数据库里删除不再使用的配置文件以节省空间并且清理SavedVariables文件。"
L["delete"] = "删除一个配置文件"
L["delete_sub"] = "从数据库里删除一个配置文件。"
L["delete_confirm"] = "你确定要删除所选择的配置文件么?"
L["profiles"] = "配置文件"
L["profiles_sub"] = "管理配置文件"
--L["current"] = "Current Profile:"
elseif LOCALE == "ruRU" then
L["default"] = "По умолчанию"
L["intro"] = "Изменяя активный профиль, вы можете задать различные настройки модификаций для каждого персонажа."
L["reset_desc"] = "Если ваша конфигурации испорчена или если вы хотите настроить всё заново - сбросьте текущий профиль на стандартные значения."
L["reset"] = "Сброс профиля"
L["reset_sub"] = "Сброс текущего профиля на стандартный"
L["choose_desc"] = "Вы можете создать новый профиль, введя название в поле ввода, или выбрать один из уже существующих профилей."
L["new"] = "Новый"
L["new_sub"] = "Создать новый чистый профиль"
L["choose"] = "Существующие профили"
L["choose_sub"] = "Выбор одиного из уже доступных профилей"
L["copy_desc"] = "Скопировать настройки из выбранного профиля в активный."
L["copy"] = "Скопировать из"
L["delete_desc"] = "Удалить существующий и неиспользуемый профиль из БД для сохранения места, и очистить SavedVariables файл."
L["delete"] = "Удалить профиль"
L["delete_sub"] = "Удаление профиля из БД"
L["delete_confirm"] = "Вы уверены, что вы хотите удалить выбранный профиль?"
L["profiles"] = "Профили"
L["profiles_sub"] = "Управление профилями"
--L["current"] = "Current Profile:"
end
local defaultProfiles
local tmpprofiles = {}
-- Get a list of available profiles for the specified database.
-- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below.
-- @param db The db object to retrieve the profiles from
-- @param common If true, getProfileList will add the default profiles to the return list, even if they have not been created yet
-- @param nocurrent If true, then getProfileList will not display the current profile in the list
-- @return Hashtable of all profiles with the internal name as keys and the display name as value.
local function getProfileList(db, common, nocurrent)
local profiles = {}
-- copy existing profiles into the table
local currentProfile = db:GetCurrentProfile()
for i,v in pairs(db:GetProfiles(tmpprofiles)) do
if not (nocurrent and v == currentProfile) then
profiles[v] = v
end
end
-- add our default profiles to choose from ( or rename existing profiles)
for k,v in pairs(defaultProfiles) do
if (common or profiles[k]) and not (nocurrent and k == currentProfile) then
profiles[k] = v
end
end
return profiles
end
--[[
OptionsHandlerPrototype
prototype class for handling the options in a sane way
]]
local OptionsHandlerPrototype = {}
--[[ Reset the profile ]]
function OptionsHandlerPrototype:Reset()
self.db:ResetProfile()
end
--[[ Set the profile to value ]]
function OptionsHandlerPrototype:SetProfile(info, value)
self.db:SetProfile(value)
end
--[[ returns the currently active profile ]]
function OptionsHandlerPrototype:GetCurrentProfile()
return self.db:GetCurrentProfile()
end
--[[
List all active profiles
you can control the output with the .arg variable
currently four modes are supported
(empty) - return all available profiles
"nocurrent" - returns all available profiles except the currently active profile
"common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default")
"both" - common except the active profile
]]
function OptionsHandlerPrototype:ListProfiles(info)
local arg = info.arg
local profiles
if arg == "common" and not self.noDefaultProfiles then
profiles = getProfileList(self.db, true, nil)
elseif arg == "nocurrent" then
profiles = getProfileList(self.db, nil, true)
elseif arg == "both" then -- currently not used
profiles = getProfileList(self.db, (not self.noDefaultProfiles) and true, true)
else
profiles = getProfileList(self.db)
end
return profiles
end
function OptionsHandlerPrototype:HasNoProfiles(info)
local profiles = self:ListProfiles(info)
return ((not next(profiles)) and true or false)
end
--[[ Copy a profile ]]
function OptionsHandlerPrototype:CopyProfile(info, value)
self.db:CopyProfile(value)
end
--[[ Delete a profile from the db ]]
function OptionsHandlerPrototype:DeleteProfile(info, value)
self.db:DeleteProfile(value)
end
--[[ fill defaultProfiles with some generic values ]]
local function generateDefaultProfiles(db)
defaultProfiles = {
["Default"] = L["default"],
[db.keys.char] = db.keys.char,
[db.keys.realm] = db.keys.realm,
[db.keys.class] = UnitClass("player")
}
end
--[[ create and return a handler object for the db, or upgrade it if it already existed ]]
local function getOptionsHandler(db, noDefaultProfiles)
if not defaultProfiles then
generateDefaultProfiles(db)
end
local handler = AceDBOptions.handlers[db] or { db = db, noDefaultProfiles = noDefaultProfiles }
for k,v in pairs(OptionsHandlerPrototype) do
handler[k] = v
end
AceDBOptions.handlers[db] = handler
return handler
end
--[[
the real options table
]]
local optionsTable = {
desc = {
order = 1,
type = "description",
name = L["intro"] .. "\n",
},
descreset = {
order = 9,
type = "description",
name = L["reset_desc"],
},
reset = {
order = 10,
type = "execute",
name = L["reset"],
desc = L["reset_sub"],
func = "Reset",
},
current = {
order = 11,
type = "description",
name = function(info) return L["current"] .. " " .. NORMAL_FONT_COLOR_CODE .. info.handler:GetCurrentProfile() .. FONT_COLOR_CODE_CLOSE end,
width = "default",
},
choosedesc = {
order = 20,
type = "description",
name = "\n" .. L["choose_desc"],
},
new = {
name = L["new"],
desc = L["new_sub"],
type = "input",
order = 30,
get = false,
set = "SetProfile",
},
choose = {
name = L["choose"],
desc = L["choose_sub"],
type = "select",
order = 40,
get = "GetCurrentProfile",
set = "SetProfile",
values = "ListProfiles",
arg = "common",
},
copydesc = {
order = 50,
type = "description",
name = "\n" .. L["copy_desc"],
},
copyfrom = {
order = 60,
type = "select",
name = L["copy"],
desc = L["copy_desc"],
get = false,
set = "CopyProfile",
values = "ListProfiles",
disabled = "HasNoProfiles",
arg = "nocurrent",
},
deldesc = {
order = 70,
type = "description",
name = "\n" .. L["delete_desc"],
},
delete = {
order = 80,
type = "select",
name = L["delete"],
desc = L["delete_sub"],
get = false,
set = "DeleteProfile",
values = "ListProfiles",
disabled = "HasNoProfiles",
arg = "nocurrent",
confirm = true,
confirmText = L["delete_confirm"],
},
}
--- Get/Create a option table that you can use in your addon to control the profiles of AceDB-3.0.
-- @param db The database object to create the options table for.
-- @return The options table to be used in AceConfig-3.0
-- @usage
-- -- Assuming `options` is your top-level options table and `self.db` is your database:
-- options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
function AceDBOptions:GetOptionsTable(db, noDefaultProfiles)
local tbl = AceDBOptions.optionTables[db] or {
type = "group",
name = L["profiles"],
desc = L["profiles_sub"],
}
tbl.handler = getOptionsHandler(db, noDefaultProfiles)
tbl.args = optionsTable
AceDBOptions.optionTables[db] = tbl
return tbl
end
-- upgrade existing tables
for db,tbl in pairs(AceDBOptions.optionTables) do
tbl.handler = getOptionsHandler(db)
tbl.args = optionsTable
end

View File

@ -0,0 +1,4 @@
<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="AceDBOptions-3.0.lua"/>
</Ui>

View File

@ -0,0 +1,126 @@
--- AceEvent-3.0 provides event registration and secure dispatching.
-- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
-- CallbackHandler, and dispatches all game events or addon message to the registrees.
--
-- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceEvent itself.\\
-- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceEvent.
-- @class file
-- @name AceEvent-3.0
-- @release $Id: AceEvent-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
local MAJOR, MINOR = "AceEvent-3.0", 3
local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
if not AceEvent then return end
-- Lua APIs
local pairs = pairs
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
-- APIs and registry for blizzard events, using CallbackHandler lib
if not AceEvent.events then
AceEvent.events = CallbackHandler:New(AceEvent,
"RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
end
function AceEvent.events:OnUsed(target, eventname)
AceEvent.frame:RegisterEvent(eventname)
end
function AceEvent.events:OnUnused(target, eventname)
AceEvent.frame:UnregisterEvent(eventname)
end
-- APIs and registry for IPC messages, using CallbackHandler lib
if not AceEvent.messages then
AceEvent.messages = CallbackHandler:New(AceEvent,
"RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
)
AceEvent.SendMessage = AceEvent.messages.Fire
end
--- embedding and embed handling
local mixins = {
"RegisterEvent", "UnregisterEvent",
"RegisterMessage", "UnregisterMessage",
"SendMessage",
"UnregisterAllEvents", "UnregisterAllMessages",
}
--- Register for a Blizzard Event.
-- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument.
-- Any arguments to the event will be passed on after that.
-- @name AceEvent:RegisterEvent
-- @class function
-- @paramsig event[, callback [, arg]]
-- @param event The event to register for
-- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
-- @param arg An optional argument to pass to the callback function
--- Unregister an event.
-- @name AceEvent:UnregisterEvent
-- @class function
-- @paramsig event
-- @param event The event to unregister
--- Register for a custom AceEvent-internal message.
-- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument.
-- Any arguments to the event will be passed on after that.
-- @name AceEvent:RegisterMessage
-- @class function
-- @paramsig message[, callback [, arg]]
-- @param message The message to register for
-- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
-- @param arg An optional argument to pass to the callback function
--- Unregister a message
-- @name AceEvent:UnregisterMessage
-- @class function
-- @paramsig message
-- @param message The message to unregister
--- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
-- @name AceEvent:SendMessage
-- @class function
-- @paramsig message, ...
-- @param message The message to send
-- @param ... Any arguments to the message
-- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceEvent in
function AceEvent:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
-- AceEvent:OnEmbedDisable( target )
-- target (object) - target object that is being disabled
--
-- Unregister all events messages etc when the target disables.
-- this method should be called by the target manually or by an addon framework
function AceEvent:OnEmbedDisable(target)
target:UnregisterAllEvents()
target:UnregisterAllMessages()
end
-- Script to fire blizzard events into the event listeners
local events = AceEvent.events
AceEvent.frame:SetScript("OnEvent", function(this, event, ...)
events:Fire(event, ...)
end)
--- Finally: upgrade our old embeds
for target, v in pairs(AceEvent.embeds) do
AceEvent:Embed(target)
end

Some files were not shown because too many files have changed in this diff Show More