Table of Contents
Introduction
ParserLib is an embedded library which does all the combat message
parsing and converting them into meaningful information.
To use ParserLib, your addon register events to ParserLib like this:
local parser = ParserLib:GetInstance("1.1')
parser:RegisterEvent("MyAddon", "CHAT_MSG_COMBAT_SELF_HIT", "MyAddonEventHandler")
Very similar to what you do to frame:RegisterEvent(), when the
registered event is fired, ParserLib will call your registered handler,
but instead of arg1, it passes a table as the second parameter:
function MyAddonEventHandler(event, info)
if info.type == "hit" then ChatFrame1:AddMessage( info.source .. " hit " .. info.victim .. " for " .. info.damount .. "damage!" ) end
end
All ParserLib do is convert the arg1 into a table, for now you'll still
need to know which event to register.
So what's the benefits for using ParserLib?
- By dynamically sorting the patterns in a special way,
ParserLib works on all
localizations. No worrying about:
- "Greater Heal critically" being parsed as spell name for
"Your %s heals you for %d."
- "you" being parsed as victim name for "%s hits %s for %s."
- "30 mana from Someone's Blessing of Wisdom" being parsed
as buff name for "%s gains %s."
- Minimal memory usage, if you don't register any event then
almost only the raw codes are loaded.
- Multiple client addons share the same instance of
ParserLib.
- Only listen to an event when a client registers for it.
- Load event-pattern list only when the event is actually
fired.
- Load pattern table only when that pattern is required to
parse.
- Recycles tables by using CompostLib.
- Better Efficiency
- ParserLib knows what event will fire what patterns, and
only parse through the possible patterns.
- When there are multiple client addons, the patterns are
only parsed once. Without using a common library, everyone will have to
do their own parsing, which is a waste of resource.
Back to top
Supported
Events
Click the link to see what patterns will be fired from the event.
(They''re still not very complete though, I'm working hard on it.)
Currently supported
Planned to
support in the future
Won't be supported
Currently supported
CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_HITS
CHAT_MSG_COMBAT_CREATURE_VS_CREATURE_MISSES
CHAT_MSG_COMBAT_CREATURE_VS_PARTY_HITS
CHAT_MSG_COMBAT_CREATURE_VS_PARTY_MISSES
CHAT_MSG_COMBAT_CREATURE_VS_SELF_HITS
CHAT_MSG_COMBAT_CREATURE_VS_SELF_MISSES
CHAT_MSG_COMBAT_FACTION_CHANGE
CHAT_MSG_COMBAT_FRIENDLYPLAYER_HITS
CHAT_MSG_COMBAT_FRIENDLYPLAYER_MISSES
CHAT_MSG_COMBAT_FRIENDLY_DEATH
CHAT_MSG_COMBAT_HONOR_GAIN
CHAT_MSG_COMBAT_HOSTILEPLAYER_HITS
CHAT_MSG_COMBAT_HOSTILEPLAYER_MISSES
CHAT_MSG_COMBAT_HOSTILE_DEATH
CHAT_MSG_COMBAT_PARTY_HITS
CHAT_MSG_COMBAT_PARTY_MISSES
CHAT_MSG_COMBAT_PET_HITS
CHAT_MSG_COMBAT_PET_MISSES
CHAT_MSG_COMBAT_SELF_HITS
CHAT_MSG_COMBAT_SELF_MISSES
CHAT_MSG_COMBAT_XP_GAIN
CHAT_MSG_SPELL_AURA_GONE_OTHER
CHAT_MSG_SPELL_AURA_GONE_SELF
CHAT_MSG_SPELL_AURA_GONE_PARTY
CHAT_MSG_SPELL_BREAK_AURA
CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF
CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE
CHAT_MSG_SPELL_CREATURE_VS_PARTY_BUFF
CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE
CHAT_MSG_SPELL_CREATURE_VS_SELF_BUFF
CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE
CHAT_MSG_SPELL_DAMAGESHIELDS_ON_OTHERS
CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF
CHAT_MSG_SPELL_FAILED_LOCALPLAYER
CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF
CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE
CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF
CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE
CHAT_MSG_SPELL_ITEM_ENCHANTMENTS
CHAT_MSG_SPELL_PARTY_BUFF
CHAT_MSG_SPELL_PARTY_DAMAGE
CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS
CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE
CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS
CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE
CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS
CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE
CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS
CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE
CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS
CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE
CHAT_MSG_SPELL_PET_BUFF
CHAT_MSG_SPELL_PET_DAMAGE
CHAT_MSG_SPELL_SELF_BUFF
CHAT_MSG_SPELL_SELF_DAMAGE
CHAT_MSG_SPELL_TRADESKILLS
Planned to support in the future
CHAT_MSG_COMBAT_MISC_INFO
CHAT_MSG_SKILL
CHAT_MSG_LOOT
Won't be supported
CHAT_MSG
CHAT_MSG_AFK
CHAT_MSG_BG_SYSTEM_ALLIANCE
CHAT_MSG_BG_SYSTEM_HORDE
CHAT_MSG_BG_SYSTEM_NEUTRAL
CHAT_MSG_CHANNEL
CHAT_MSG_CHANNEL_JOIN
CHAT_MSG_CHANNEL_LEAVE
CHAT_MSG_CHANNEL_LIST
CHAT_MSG_CHANNEL_NOTICE
CHAT_MSG_CHANNEL_NOTICE_USER
CHAT_MSG_COMBAT_ERROR
CHAT_MSG_DND
CHAT_MSG_EMOTE
CHAT_MSG_GUILD
CHAT_MSG_IGNORED
CHAT_MSG_MONSTER_EMOTE
CHAT_MSG_MONSTER_SAY
CHAT_MSG_MONSTER_WHISPER
CHAT_MSG_MONSTER_YELL
CHAT_MSG_OFFICER
CHAT_MSG_PARTY
CHAT_MSG_RAID
CHAT_MSG_SAY
CHAT_MSG_SYSTEM
CHAT_MSG_TEXT_EMOTE
CHAT_MSG_WHISPER
CHAT_MSG_WHISPER_INFORM
CHAT_MSG_YELL
Back to top
How To Use
1. Put both CompostLib and ParserLib folder in your addon.
2. Add CompostLib and ParserLib to .toc so it looks like this:
## Interface: 11000
## Title: MyAddOn
## Notes: A ParserLib client addon.
CompostLib\CompostLib.lua
ParserLib\ParserLib.lua
SimpleCombatLog.xml
3. In your lua file, get an instance of ParserLib by calling the
ParserLib:GetInstance() method.
local parser = ParserLib:GetInstance("1.1")
Where the "1.1" is the major version
number (variable vmajor)
which can be found at the top of ParserLib.lua
4. To listen to an event, do not Frame:RegisterEvent(), instead
register the events to ParserLib:
parser:RegisterEvent("MyAddOn", "CHAT_MSG_COMBAT_SELF_HITS", "MyAddOn_OnParserEvent")
5. Now define your event handler, ParserLib will call it when the
registered event occurs.
function MyAddOn_OnParserEvent(event, info)
-- check info.type to know what's inside info.
-- do whatever you want with the data.
end
6. info is a table which contains parsed information. To know what
information you can get from the table, check the info.type variable,
detailed description for each type is here.
NOTE: ParserLib recycles the info table to reduce memory usage, if you
want to do something with the table after the event handler, make sure
you store them in your own data structure.
Let me say it again, the info table will be CLEARED after the event
handler has finished.
YOU ARE EXPECTED TO COPY DOWN THE VARIABLES YOU NEED BEFORE THE END OF
YOUR EVENT HANDLER.
Back to top
Example
function MyAddOn_OnParserEvent(event, info)
if info.type == "hit" then
if info.source == ParserLib_SELF then info.source = "you" end
if info.victim == ParserLib_SELF then info.source = "you" end
if info.skill == ParserLib_MELEE then info.skill = "melee" end
ChatFrame1:AddMessage(info.source .. " hits " .. info.victim .. " with " .. info.skill .. " for " .. info.amount)
end
end
parser = ParserLib:GetInstance("1.1")
parser:AddEventHandler("MyAddOn", "CHAT_MSG_COMBAT_SELF_HITS", "MyAddOn_OnParserEvent")
parser:AddEventHandler("MyAddOn", "CHAT_MSG_COMBAT_PET_HITS", "MyAddOn_OnParserEvent")
parser:AddEventHandler("MyAddOn", "CHAT_MSG_SPELL_SELF_DAMAGE", "MyAddOn_OnParserEvent")
parser:AddEventHandler("MyAddOn", "CHAT_MSG_SPELL_PET_DAMAGE", "MyAddOn_OnParserEvent")
parser:AddEventHandler("MyAddOn", "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE", "MyAddOn_OnParserEvent")
parser:AddEventHandler("MyAddOn", "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE", "MyAddOn_OnParserEvent")
Now you got yourself an addon which will report melee and spell hits of
you and your pet!
Back to top
Optimizer
ParserLib currently includes a file called optimizer-enUS.lua, it can increase the parsing speed of ParserLib by around 20~30% on english locaization. By looking at the source code of optimizer-enUS.lua, you
can easily create an optimizer file for other localizations. Basically
the optimizer is simply a table which contains 'keyword string' for the
patterns in WoW. For example the keyword 'hit' in
COMBATHITSCHOOLOTHEROTHER (%s hits %s for %d %s damage.). The
optimizer is completely optional, ParserLib works fine without any
optimizer, just that the existance of an optimizer for your
localization can increase the parsing speed.
To load an optimizer, simply include that file on your .toc, so it looks like this:
## Interface: 11000
## Title: MyAddOn
## Notes: A ParserLib client addon.
CompostLib\CompostLib.lua
ParserLib\ParserLib.lua
ParserLib\optimizer-enUS.lua
SimpleCombatLog.xml
Note that the optimizer is global, which means if
someone added an optimizer table which has the wrong keyword, it could
mess out ParserLib which will affect all the ParserLib clients. This is
not good so this part will probably get reworked, for now I suggest you
don't try to add your own optimizer file, but optimizer-enUS.lua should
work fine.
Back to top
API
- RegisterEvent(addonID, event, handler) :
Register an event with the event handler.
- UnregisterEvent(addonID, event) :
Unregister an event for the addonID.
- UnregisterAllEvents(addonID) :
Unregister all events for the addonID.
- Deformat(text, pattern) : Use this to parse for custom patterns which is not supported by ParserLib.
attacker, victim, amount, element = parser:Deformat("Rophy hits Pig for 500 fire damage.", COMBATHITSCHOOLOTHEROTHER)
Back to top
Variable
Description
The table passed to your event handler will always contains a variable
called type, which you can
check to know what other variables are stored in the table.
'type' is one of the following strings:
Back to top
Normally all the variables are string tokens parsed
from the combat message, with a few exceptions:
- source,
victim, sourceGained might be a numeric constant ParserLib_SELF,
which means it's you.
- skill
might be the numeric constant ParserLib_MELEE
for melee, or ParserLib_DAMAGESHIELD
for damage shields.
- amount
and its variations (amountGained,
amountRaidPenality
etc ) are numbers.
- missType
is one of the following strings: miss, dodge, block, deflect, immune, evade, parry, resist, reflect, absorb
- damageType
is one of the following strings: drown,
fall, exhaust, fire, lava, slime.
- Variables starting with is are
booleans, for example isDOT,
isCrit,
isItem
etc.
Here is the list of all possible type,
with the variables associated with them, a starting @ means that
variable may not exist, depends on the combat message parsed.
The list is in the following format:
TYPE : simple description.
* example combat message.
Variable : value
@OptionalVariable : value
hit
: including melee/spell/skill hits, crits, dots.
* Your Shadow Bolt crits
Pig for 50 shadow damage. (30 resisted)
source
: ParserLib_YOU
victim
: "Pig"
skill
: "Shadow Bolt"
amount
: 50
@element
: "shadow"
isCrit : true
isDOT : false
isCrushing : false
isGlancing : false
@amountAbsorb : nil
@amountBlock : nil
@amountResist : 30
@amountVulnerable : nil
Back to list
heal
: including heals and HoTs.
* You gains 50 health
from Priest's Renew.
source
: "Priest"
victim
: ParserLib_YOU
skill
: "Renew"
amount
: 50
isCrit : false
isDOT : true
Back to list
miss
: Including miss, dodge, block, deflect, immune, evade, parry, resist,
reflect, absorb.
* Warrior's Overpower
was parried by Flamewaker.
source
: "Warrior"
victim
: "Flamewaker"
skill
: "Overpower"
missType
: "parry" (This is a fixed string, not parsed)
Back to list
death
* Rophy is slain by
Bigpotato!
victim
: "Rophy"
@source
: "Bigpotato"
isItem : nil
* Magma Totem IV is
destroyed.
victim
: "Magma Totem IV"
@source
: nil
isItem : true
Back to list
debuff
* Peter is afflicted by
Shadow Vulnerability (2).
victim
: "Peter"
skill
: "Shadow Vulnerability"
@amountRank
: 2
Back to list
buff
* Rophy gains Power
Word: Shield.
victim
: "Rophy"
skill
: "Power Word: Shield"
@amountRank
: nil
Back to list
fade : this might be
buff or debuff, can't be distinguished by the message.
* Cheap Shot fades from
Alterac Ram.
victim
: "Alterac Ram"
skill
: "Cheap Shot"
Back to list
cast
: note that this includes "cast" and "perform".
* Doggy casts Growl on
Mirefin Oracle.
source
: "Doggy"
skill
: "Growl"
@victim
: "Mirefin Oracle"
isBegin :
nil
<- only one will exist between isBegin and victim.
isPerform
: nil
* Rophy performs Opening
on Onyxia's Gate.
source
: "Rophy"
skill
: "Opening"
@victim
: "Onyxia's Gate"
isBegin
: nil
isPerform
: true
* Stormpike Mountaineer
begins to perform Shoot.
source
: "Stormpike Mountaineer"
skill
: "Shoot"
@victim
: nil
isBegin : true
isPerform
: true
Back to list
gain
* You gain 10 Mana from
Pally's Blessing of Wisdom.
source
: "Pally"
victim
: ParserLib_YOU
skill
: "Blessing of Wisdim"
amount
: 10
attribute
: "Mana"
Back to list
drain
* Hunter's Viper Sting
drains 277 Mana from Priest.
source
: "Hunter"
victim
: "Priest"
skill
: "Viper Sting"
amount
: 277
attribute
: "Mana"
Back to list
leech
* Your Drain Mana drains
140 Mana from Mage. You gain 140 Mana.
source
: ParserLib_YOU
victim
: "Mage"
skill
: "Drain Mana"
amount
: 140
attribute
: "Mana"
sourceGained:
ParserLib_YOU
amountGained:
140
attributeGained:
"Mana"
Back to list
dispel
: There are two kinds of message so I'll show two examples here.
* Seasoned Guardian's
Sap is removed.
victim
: "Seasoned Guardian"
skill
"Sap"
isFailed : false
@source
: nil
* Nino fails to dispel
Librabear's Gehennas' Curse.
victim
: "Librabear"
skill
: "Gehennas' Curse"
isFailed
: true
@source
: "Nino"
Back to list
extraattack
* Rophy gains 2 extra
attacks through Windfury Attack.
victim
: "Rophy"
skill
: "Windfury Attack"
amount
: 2
Back to list
environment
: falling, fire, lava dmg etc
* Rophy suffers 468 points of fire damage. (298 absorbed)
victim
: "Rophy"
amount
: 468
damageType
: "fire"
@amountAbsorb : 298
@amountBlock : nil
@amountResist : nil
@amountVulnerable : nil
Back to list
honor
: Two examples here.
* You have been awarded
198 honor points.
@amount
: 198
@source
: nil
@sourceRank
: nil
isDishonor : nil
* Nino dies, honorable
kill Rank: Stone Guard (Estimated Honor Points: 80)
@amount
: 80
@source
: "Nino"
@sourceRank
: "Stone Guard" <-- if source exists then sourceRank
exists too.
isDishonor : nil
* Someone dies, dishonorable kill.
@amount : nil
@source : "Someone"
@sourceRank nil
isDishonor :
true
<-- amount is nil if and only if isDishonor
is true,
Back to list
experience
: This one is complicated, most of the time you just need to look for amount
though.
* Mob dies, you gain 300
experience. (+160 exp Rested bonus, -20 raid penalty)
amount
: 300
@source
: "Mob"
@victim
: nil
<-
if nil then it's you who got the exp.
@bonusAmount
: "+160" <- Note that
this is a string with '+', not a number.
@bonusType
: "Rested"
<- if bonusAmount exists then this
exists too.
@penaltyAmount
: nil
@penaltyType
: nil
@amountRaidPenalty
: 20
@amountGroupBonus
: nil
* Someone gains 200
experience.
amount : 200
@victim
: "Someone"
(all
others are nil)
(This is the only pattern which has a victim, I have never seen it, but
it exists anyway.)
Note: the message of exp gained by discovering
an area is fired by CHAT_MSG_SYSTEM,
which will NOT be supported by ParserLib.
Back to list
reputation
* Your
reputation with Undercity has slightly increased. (50 reputation gained)
faction
: "Undercity"
@amount
: 50
<- if amount exists then rank is nil.
@rank
: nil
isNegative : nil
<- make sure you check this.
* You are now Friendly with Steamwheedle Cartel.
faction
: "Steamwheedle Cartel"
@amount
: nil
@rank
: "Friendly" <- if rank exists then amount
is nil.
isNegative : nil
Back to list
feedpet
* Hunter's pet begins eating a Moist Cornbread.
victim : "Hunter"
item : "Moist Cornbread"
Back to list
enchant
* Rophy casts Scope (+7 Damage) on Mondain's Precisely
Calibrated Boomstick.
source
: "Rophy"
victim
: "Mondain"
skill
: "Scope (+7 Damage)"
item
: "Precisely Calibrated Boomstick"
Back to list
fail
* You fail to cast
Immune Charm/Fear/Polymorph: Item is not ready yet.
source
: ParserLib_SELF
skill
: "Immune
Charm/Fear/Polymorph"
reason
: "Item is not ready yet"
Back to list
interrupt
* Bigpotato interrupts
Scholomance Neophyte's Shadow Bolt.
source
: "Bigpotato"
victim
: "Scholomance Neophyte"
skill
: "Shadow Bolt"
Back to list
create
* You create Blinding
Powder.
source
: ParserLib_SELF
item
: "Blinding Powder"
Back to list
durability
* Ragnaros casts Melt Weapon on Dragonx: Bloodlord's Defender damaged.
source : "Ragnaros"
skill : "Melt Weapon"
victim : ParserLib_SELF
@item: "Bloodlord's Defender"
isAllItems :
false
<- if isAllItems true then
item will be nil
Back to list