update
parent
b570f6ffb5
commit
d3efdf98de
|
@ -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>
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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 以 rMCP(MCP,由 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
|
|
@ -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>
|
|
@ -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
|
||||
|
||||
|
|
@ -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@
|
|
@ -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@
|
|
@ -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@
|
|
@ -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@
|
|
@ -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@
|
|
@ -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@
|
|
@ -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@
|
|
@ -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
|
@ -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
|
|
@ -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>
|
|
@ -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/
|
|
@ -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
|
|
@ -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>
|
|
@ -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.
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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显示指定类别的加成统计.";
|
|
@ -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.";
|
|
@ -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.";
|
|
@ -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.";
|
|
@ -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顯示指定類別的加成統計.";
|
|
@ -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.";
|
|
@ -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();
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
[Breakpoint1]
|
||||
Line=218
|
||||
Status=1
|
||||
Condition=
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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.
|
||||
|
|
@ -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>
|
|
@ -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
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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.
|
||||
|
|
@ -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>
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
|
@ -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")
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
------------------------------------------------------------------------
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
||||
]]
|
||||
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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
Loading…
Reference in New Issue