创建 WoW 插件 - 第 8 部分:计算货币

Part 8: Counting Currency
第 8 部分:计算货币

Difficulty: ??? Medium
难度: ??? 中等

Now, we're going to get into some juicy stuff. Let's see what's in store for this part.
现在,我们将进入一些有趣的东西。让我们看看这部分的内容。

We'll be doing the following:
我们将执行以下操作:

  • Reading Chat Messages  阅读聊天消息

  • Utilizing pattern matching to find Gold, Silver and Copper amounts looted.
    利用模式匹配来查找掠夺的黄金、白银和铜数量。

This will be a larger part of the tutorial as we will be explaining quite a bit of the code and exactly what it's doing. Let's not make this any longer and get onto some code!
这将是本教程的很大一部分,因为我们将解释相当多的代码以及它的确切作用。让我们不要再做这个了,让我们开始一些代码吧!

As a side note, you don't need to understand everything that's going on here. Matching strings to patterns would normally be considered fairly advanced code and these are things you can learn from documentation or future projects. Heck, you can just ask AI how to pattern match a string for what you're looking for and it can teach you a fairly good amount about how patterns work in any language.
顺便说一句,你不需要了解这里发生的一切。将字符串与模式匹配通常被认为是相当高级的代码,这些是您可以从文档或未来项目中学到的东西。哎呀,你可以告诉 AI 如何根据你正在寻找的内容对字符串进行模式匹配,它可以教你相当多的关于模式在任何语言中是如何工作的。


Step 1: Registering a New Event
第 1 步:注册新活动

For this portion of our addon to function, we will need to first register a new event that our addon is going to listen for.
对于插件的这一部分功能,我们需要首先注册一个插件将要监听的新事件。

We already have our eventListenerFrame created, and currently it's registered to the COMBAT_LOG_EVENT_UNFILTERED event. Now, we'll need to register it to another event called "CHAT_MSG_MONEY".
我们已经创建了 eventListenerFrame,目前它已注册到 COMBAT_LOG_EVENT_UNFILTERED 事件。现在,我们需要将其注册到另一个名为 “CHAT_MSG_MONEY” 的事件中。

This event, when fired, means that a player has looted money (gold, silver, copper), and that money is displayed as a message to the player. The great thing about using "CHAT_MSG_MONEY" is that even if the player has these messages hidden in the chat log, our addon can still read them.
此事件在触发时表示玩家掠夺了金钱(金、银、铜),并且该金钱将作为消息显示给玩家。使用 “CHAT_MSG_MONEY” 的好处是,即使玩家在聊天记录中隐藏了这些消息,我们的插件仍然可以读取它们。

Let's register this by finding our eventListenerFrame:RegisterEvent line and add a new one below it.
让我们通过找到我们的 eventListenerFrame:RegisterEvent 行并在其下方添加一行来注册它。

Ctrl + F and searching for eventListenerFrame is a fast way to find this line. Ctrl + F is a fantastic way to search your code for something you need.
Ctrl + F 并搜索 eventListenerFrame 是查找此行的快速方法。Ctrl + F 是搜索代码以查找所需内容的绝佳方式。

eventListenerFrame:RegisterEvent("CHAT_MSG_MONEY")

Now that we have that registered, we can modify our eventHandler to handle this event.
现在我们已经注册了它,我们可以修改我们的 eventHandler 来处理这个事件。

if event == "COMBAT_LOG_EVENT_UNFILTERED" then
    if eventType == "PARTY_KILL" then
        if not MyAddonDB.kills then
            MyAddonDB.kills = 1
        else
            MyAddonDB.kills = MyAddonDB.kills + 1
        end
    end
elseif event == "CHAT_MSG_MONEY" then
    -- Our code for this event will go here.
end

Above, we changed the following code from:
在上面,我们将以下代码从:

if event == "COMBAT_LOG_EVENT_UNFILTERED" then
    -- Our code for this event is here...
end

to:  自:

if event == "COMBAT_LOG_EVENT_UNFILTERED" then
    -- Our code for this event is here...
elseif event == "CHAT_MSG_MONEY" then
    -- Our code for this event is here...
end

With this modified code, when someone loots something, it fires an event. If that event is "CHAT_MSG_MONEY" then our code inside of that event in the function will execute. Currently, it does nothing.
使用这个修改后的代码,当有人掠夺某物时,它会触发一个事件。如果该事件是 “CHAT_MSG_MONEY”,那么我们将在函数中执行该事件内的代码。目前,它不执行任何操作。

Let's move on to doing something with that code instead of the nothing that it's doing now.
让我们继续对该代码执行一些操作,而不是它现在什么都不做。


Step 2: Using the Chat Message
第 2 步:使用聊天消息

To use this information, we will now append some code to our if else statement. We'll be using string matching to check if the chat message contains GoldSilver, or Copper.
为了使用这些信息,我们现在将一些代码附加到我们的 if else 语句中。我们将使用字符串匹配来检查聊天消息是否包含 GoldSilver 或 Copper

Inside of our if else statement, let's add this code:
在我们的 if else 语句中,让我们添加以下代码:

local msg = ...
local gold = tonumber(string.match(msg, "(%d+) Gold")) or 0
local silver = tonumber(string.match(msg, "(%d+) Silver")) or 0
local copper = tonumber(string.match(msg, "(%d+) Copper")) or 0

The msg variable assigns ... to it. ... is pulling the only payload information from "CHAT_MSG_MONEY" that it provides, which is a string that says something along the lines of:
msg 变量将 ... 分配给它。...从它提供的 “CHAT_MSG_MONEY” 中提取唯一的有效负载信息,这是一个字符串,表示如下内容:

You loot 42 Copper.  你掠夺了 42 铜币。

With this information, our goldsilver and copper variables are searching the msg string for a pattern. The (%d+) portion of our parse is looking for any one or more digits (d+) information before " Gold"" Silver" or " Copper" and converts it to a number. Thankfully, the message you receive when looting money in-game is always followed by ' Copper'' Silver' or ' Gold'. This makes this pattern work flawlessly for us forever unless Blizzard changes this message in the future.
有了这些信息,我们的 goldsilver 和 copper 变量正在 msg 字符串中搜索模式。解析的 (%d+) 部分是查找 “Gold”、“Silver” 或 “Copper” 之前的任意一个或多个数字 (d+) 信息,并将其转换为数字。值得庆幸的是,您在游戏中掠夺金钱时收到的消息总是跟着“铜”、“银”“金”。这使得这种模式永远完美地为我们工作,除非暴雪将来更改此消息。


Step 3: Making Our Variables Work
第 3 步:让我们的变量工作

We're now going to store this information to our database. Here's how we can do this:
现在,我们将此信息存储到我们的数据库中。以下是我们如何做到这一点:

MyAddonDB.gold = (MyAddonDB.gold or 0) + gold

The above code stores any looted gold into our MyAddonDB.gold database. This is short-hand code that checks to make sure MyAddonDB.gold exists, or makes it 0, before writing to it. If it doesn't exist, it will create it and make its value 0 + gold upon creation.
上面的代码将任何掠夺的黄金存储到我们的 MyAddonDB.gold 数据库中。这是一段速记代码,用于检查以确保 MyAddonDB.gold 存在,或者在写入之前将其设为 0。如果它不存在,它将创建它并在创建时使其值为 0 + 金币

We can simply copy and paste the above code for silver and copper as well.
我们也可以简单地复制并粘贴上述 silver 和 copper 代码。

MyAddonDB.silver = (MyAddonDB.silver or 0) + silver
MyAddonDB.copper = (MyAddonDB.copper or 0) + copper

These strings we're parsing are case-sensitive in our case, hence the capitals in GoldSilver and Copper. There is a way to ignore case sensitivity when searching for patterns, and if you'd like to do this, you're more than welcome to. Consider it a bonus project!
我们正在解析的这些字符串在我们的例子中区分大小写,因此 GoldSilver 和 Copper 中的大写字母。在搜索模式时,有一种方法可以忽略区分大小写,如果您想这样做,我们非常欢迎您这样做。把它当作一个额外的项目吧!


Step 4: Handling >= 100 for Our Currencies
第 4 步:处理我们的货币 >= 100

We want to convert our copper and silver gained to their respective higher currencies, if they go above 100. To do this, we're going to start with copper, as it's the lowest currency value World of Warcraft has.
如果铜和白银的价格超过 100,我们想将获得的铜和白银转换为各自的更高货币。为此,我们将从 copper 开始,因为它是 World of Warcraft 中最低的货币价值。

if MyAddonDB.copper >= 100 then
    MyAddonDB.silver = MyAddonDB.silver + math.floor(MyAddonDB.copper / 100)
    MyAddonDB.copper = MyAddonDB.copper % 100
end

The above code checks for copper. If it exists and is equal to or over 100.
上面的代码检查。如果存在且等于大于 100

It then converts the copper to silver, dividing the copper by 100 in whole number form (using math.floor).
然后它将转换为,以整数形式除以 100(使用 math.floor)。

Let's duplicate this code for silver to convert to gold.
让我们复制此代码,以便将 silver 转换为 gold

if MyAddonDB.copper >= 100 then
    MyAddonDB.silver = MyAddonDB.silver + math.floor(MyAddonDB.copper / 100)
    MyAddonDB.copper = MyAddonDB.copper % 100
end

if MyAddonDB.silver >= 100 then
    MyAddonDB.gold = MyAddonDB.gold + math.floor(MyAddonDB.silver / 100)
    MyAddonDB.silver = MyAddonDB.silver % 100
end

The entire above code will now write goldsilver and copper information to our database and convert any amount >= 100.
上面的整个代码现在会将黄金白银信息写入我们的数据库,并转换任何数量的 >= 100