summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-addons/addons/battlemod
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/battlemod')
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/README.md42
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua508
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-DNC.xml153
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WAR.xml155
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WHM.xml155
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/generic_helpers.lua389
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/parse_action_packet.lua947
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/statics.lua699
8 files changed, 3048 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/README.md b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/README.md
new file mode 100644
index 0000000..2a9a823
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/README.md
@@ -0,0 +1,42 @@
+Author: Byrth
+
+Version: 3.21
+
+Date: 20/9/15
+
+Battlemod, packet version
+
+Abbreviation: //bm
+
+Commands:
+
+Toggles:
+* simplify - Condenses battle text using custom messages (Default: True)
+* condensetargets - Collapse similar messages with multiple targets (Default: True)
+ * targetnumber - Toggle condensed target number display (Default: True)
+ * condensetargetname - Toggle target name condensation (Default: False)
+ * oxford - Toggle use of oxford comma (Default: True)
+ * commamode - Toggle comma-only mode (Default: False)
+* condensedamage - Collapses similar damage messages with the same target (Default: True)
+ * swingnumber - Toggle condensed damage number display (Default: True)
+ * sumdamage - Sums condensed damage if true, comma-separated if false (Default: True)
+ * condensecrits - Condenses critical hits and normal hits together (Default: False)
+* cancelmulti - Cancels multiple consecutive identical lines (Default: True)
+* showonernames - Shows the name of the owner on pet messages (Default: False)
+* crafting - Toggle early display of crafting results (Default: True)
+
+Utilities:
+* colortest - Shows the 509 possible colors for use with the settings file
+* reload - Reloads the settings file
+* unload - unloads Battlemod
+* help - shows a menu of these commands in game
+
+Purpose: To allow chat log customization.
+
+Settings Files:
+The settings files for battlemod are composed of 3 to 25 xml files (depending on how much you like unique filters). XML files can be opened with Notepad, edited, and saved safely. If you are going to "Save As..." an xml from Notepad, be sure to change "Text Documents (.txt)" to "All Files" file type and make sure the file ends in ".xml"
+
+* data/settings.xml - contains basic flags that control the features of the program.
+* data/colors.xml - contains all the color codes relevant to the program, which can be adjusted using colors from the colortext command.
+* filters/filters.xml - contains the chat filter settings and is explained more thoroughly therein.
+* filters/filters-<job>.xml - Several examples are provided, but these are specific filter files that will load for your individual jobs. You can use this to, for instance, make sure your healing jobs can always see damage taken (by unfiltering the <monsters></monsters> section or make sure your zerg jobs don't have to see the entire alliance's damage spam. The filter file is organized by actor, so if you wanted to filter by target you would have to go through each class of actor and change the setting that affected the given target.
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua
new file mode 100644
index 0000000..5ae3426
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua
@@ -0,0 +1,508 @@
+require 'tables'
+require 'sets'
+file = require 'files'
+config = require 'config'
+require 'strings'
+res = require 'resources'
+require 'actions'
+require 'pack'
+bit = require 'bit'
+
+require 'generic_helpers'
+require 'parse_action_packet'
+require 'statics'
+
+_addon.version = '3.31'
+_addon.name = 'BattleMod'
+_addon.author = 'Byrth, maintainer: SnickySnacks'
+_addon.commands = {'bm','battlemod'}
+
+windower.register_event('load',function()
+ if debugging then windower.debug('load') end
+ options_load()
+end)
+
+windower.register_event('login',function (name)
+ if debugging then windower.debug('login') end
+ options_load:schedule(10)
+end)
+
+windower.register_event('addon command', function(command, ...)
+ if debugging then windower.debug('addon command') end
+ local args = {...}
+ command = command and command:lower()
+ if command then
+ if command:lower() == 'commamode' then
+ commamode = not commamode
+ windower.add_to_chat(121,'Battlemod: Comma Mode flipped! - '..tostring(commamode))
+ elseif command:lower() == 'oxford' then
+ oxford = not oxford
+ windower.add_to_chat(121,'Battlemod: Oxford Mode flipped! - '..tostring(oxford))
+ elseif command:lower() == 'targetnumber' then
+ targetnumber = not targetnumber
+ windower.add_to_chat(121,'Battlemod: Target Number flipped! - '..tostring(targetnumber))
+ elseif command:lower() == 'condensetargetname' then
+ condensetargetname = not condensetargetname
+ windower.add_to_chat(121,'Battlemod: Target Name Condensation flipped! - '..tostring(condensetargetname))
+ elseif command:lower() == 'swingnumber' then
+ swingnumber = not swingnumber
+ windower.add_to_chat(121,'Battlemod: Round Number flipped! - '..tostring(swingnumber))
+ elseif command:lower() == 'sumdamage' then
+ sumdamage = not sumdamage
+ windower.add_to_chat(121,'Battlemod: Sum Damage flipped! - '..tostring(sumdamage))
+ elseif command:lower() == 'condensecrits' then
+ condensecrits = not condensecrits
+ windower.add_to_chat(121,'Battlemod: Condense Crits flipped! - '..tostring(condensecrits))
+ elseif command:lower() == 'cancelmulti' then
+ cancelmulti = not cancelmulti
+ windower.add_to_chat(121,'Battlemod: Multi-canceling flipped! - '..tostring(cancelmulti))
+ elseif command:lower() == 'reload' then
+ current_job = 'NONE'
+ options_load()
+ elseif command:lower() == 'unload' then
+ windower.send_command('@lua u battlemod')
+ elseif command:lower() == 'simplify' then
+ simplify = not simplify
+ windower.add_to_chat(121,'Battlemod: Text simplification flipped! - '..tostring(simplify))
+ elseif command:lower() == 'condensedamage' then
+ condensedamage = not condensedamage
+ windower.add_to_chat(121,'Battlemod: Condensed Damage text flipped! - '..tostring(condensedamage))
+ elseif command:lower() == 'condensetargets' then
+ condensetargets = not condensetargets
+ windower.add_to_chat(121,'Battlemod: Condensed Targets flipped! - '..tostring(condensetargets))
+ elseif command:lower() == 'showownernames' then
+ showownernames = not showownernames
+ windower.add_to_chat(121,'Battlemod: Show pet owner names flipped! - '..tostring(showownernames))
+ elseif command:lower() == 'crafting' then
+ crafting = not crafting
+ windower.add_to_chat(121,'Battlemod: Display crafting results flipped! - '..tostring(crafting))
+ elseif command:lower() == 'showblocks' then
+ showblocks = not showblocks
+ windower.add_to_chat(121,'Battlemod: Show blocks with shield flipped! - '..tostring(showblocks))
+ elseif command:lower() == 'showguards' then
+ showguards = not showguards
+ windower.add_to_chat(121,'Battlemod: Show guarding on hits flipped! - '..tostring(showguards))
+ elseif command:lower() == 'showcritws' then
+ showcritws = not showcritws
+ windower.add_to_chat(121,'Battlemod: Show critical hit on ws/mob tp flipped! - '..tostring(showcritws))
+ elseif command:lower() == 'showrollinfo' then
+ showrollinfo = not showrollinfo
+ windower.add_to_chat(121,'Battlemod: Show lucky/unlucky rolls flipped! - '..tostring(showrollinfo))
+ elseif command:lower() == 'colortest' then
+ local counter = 0
+ local line = ''
+ for n = 1, 262 do
+ if not color_redundant:contains(n) and not black_colors:contains(n) then
+ if n <= 255 then
+ loc_col = string.char(0x1F, n)
+ else
+ loc_col = string.char(0x1E, n - 254)
+ end
+ line = line..loc_col..string.format('%03d ', n)
+ counter = counter + 1
+ end
+ if counter == 16 or n == 262 then
+ windower.add_to_chat(6, line)
+ counter = 0
+ line = ''
+ end
+ end
+ windower.add_to_chat(122,'Colors Tested!')
+ elseif command:lower() == 'help' then
+ print(' ::: '.._addon.name..' ('.._addon.version..') :::')
+ print('Toggles: (* subtoggles)')
+ print(' 1. simplify - Condenses battle text using custom messages ('..tostring(simplify)..')')
+ print(' 2. condensetargets - Collapse similar messages with multiple targets ('..tostring(condensetargets)..')')
+ print(' * targetnumber - Toggle target number display ('..tostring(targetnumber)..')')
+ print(' * condensetargetname - Toggle target name condensation ('..tostring(condensetargetname)..')')
+ print(' * oxford - Toggle use of oxford comma ('..tostring(oxford)..')')
+ print(' * commamode - Toggle comma-only mode ('..tostring(commamode)..')')
+ print(' 3. condensedamage - Condenses damage messages within attack rounds ('..tostring(condensedamage)..')')
+ print(' * swingnumber - Show # of attack rounds ('..tostring(swingnumber)..')')
+ print(' * sumdamage - Sums condensed damage if true, comma-separated if false ('..tostring(sumdamage)..')')
+ print(' * condensecrits - Condenses critical hits and normal hits together ('..tostring(condensecrits)..')')
+ print(' 4. cancelmulti - Cancels multiple consecutive identical lines ('..tostring(cancelmulti)..')')
+ print(' 5. showonernames - Shows the name of the owner on pet messages ('..tostring(showownernames)..')')
+ print(' 6. crafting - Enables early display of crafting results ('..tostring(crafting)..')')
+ print(' 7. showblocks - Shows if a hit was blocked with shield ('..tostring(showblocks)..')')
+ print(' 8. showguards - Shows if a hit was guarded ('..tostring(showguards)..')')
+ print(' 9. showcritws - Shows if a ws or mob ability was a critical hit (shows on multihit if atleast 1 hit was a crit) ('..tostring(showcritws)..')')
+ print(' 10. showrollinfo - Shows lucky/unlucky rolls ('..tostring(showrollinfo)..')')
+ print('Utilities: 1. colortest - Shows the 509 possible colors for use with the settings file')
+ print(' 2. reload - Reloads settings file')
+ print(' 3. unload - Unloads Battlemod')
+ end
+ end
+end)
+
+windower.register_event('incoming text',function (original, modified, color, color_m, blocked)
+ if debugging then windower.debug('incoming text') end
+ local redcol = color%256
+
+ if redcol == 121 and cancelmulti then
+ a,z = string.find(original,'Equipment changed')
+
+ if a and not block_equip then
+ flip_block_equip:schedule(1)
+ block_equip = true
+ elseif a and block_equip then
+ modified = true
+ end
+ elseif redcol == 123 and cancelmulti then
+ a,z = string.find(original,'You were unable to change your equipped items')
+ b,z = string.find(original,'You cannot use that command while viewing the chat log')
+ c,z = string.find(original,'You must close the currently open window to use that command')
+
+ if (a or b or c) and not block_cannot then
+ flip_block_cannot:schedule(1)
+ block_cannot = true
+ elseif (a or b or c) and block_cannot then
+ modified = true
+ end
+ end
+ if block_modes:contains(color) then
+ local endline = string.char(0x7F, 0x31)
+ local item = string.char(0x1E)
+ if not bm_message(original) then
+ if original:endswith(endline) then --allow add_to_chat messages with the modes we blocking
+ return true
+ end
+ elseif original:endswith(endline) and string.find(original, item) then --block items action messages
+ return true
+ end
+ end
+
+ return modified,color
+end)
+
+function bm_message(original)
+ local check = string.char(0x1E)
+ local check2 = string.char(0x1F)
+ if string.find(original, check) or string.find(original, check2) then
+ return true
+ end
+end
+
+function flip_block_equip()
+ block_equip = not block_equip
+end
+
+function flip_block_cannot()
+ block_cannot = not block_cannot
+end
+
+function options_load()
+ if windower.ffxi.get_player() then
+ Self = windower.ffxi.get_player()
+ end
+ if not windower.dir_exists(windower.addon_path..'data\\') then
+ windower.create_dir(windower.addon_path..'data\\')
+ end
+ if not windower.dir_exists(windower.addon_path..'data\\filters\\') then
+ windower.create_dir(windower.addon_path..'data\\filters\\')
+ end
+
+ local settingsFile = file.new('data\\settings.xml',true)
+ local filterFile=file.new('data\\filters\\filters.xml',true)
+ local colorsFile=file.new('data\\colors.xml',true)
+
+ if not file.exists('data\\settings.xml') then
+ settingsFile:write(default_settings)
+ print('Default settings xml file created')
+ end
+
+ local settingtab = config.load('data\\settings.xml',default_settings_table)
+ config.save(settingtab)
+
+ for i,v in pairs(settingtab) do
+ _G[i] = v
+ end
+
+ if not file.exists('data\\filters\\filters.xml') then
+ filterFile:write(default_filters)
+ print('Default filters xml file created')
+ end
+ local tempplayer = windower.ffxi.get_player()
+ if tempplayer then
+ if tempplayer.main_job ~= 'NONE' then
+ filterload(tempplayer.main_job)
+ elseif windower.ffxi.get_mob_by_id(tempplayer.id)['race'] == 0 then
+ filterload('MON')
+ else
+ filterload('DEFAULT')
+ end
+ else
+ filterload('DEFAULT')
+ end
+ if not file.exists('data\\colors.xml') then
+ colorsFile:write(default_colors)
+ print('Default colors xml file created')
+ end
+ local colortab = config.load('data\\colors.xml',default_color_table)
+ config.save(colortab)
+ for i,v in pairs(colortab) do
+ color_arr[i] = colconv(v,i)
+ end
+end
+
+function filterload(job)
+ if current_job == job then return end
+ if file.exists('data\\filters\\filters-'..job..'.xml') then
+ default_filt = false
+ filter = config.load('data\\filters\\filters-'..job..'.xml',default_filter_table,false)
+ config.save(filter)
+ windower.add_to_chat(4,'Loaded '..job..' Battlemod filters')
+ elseif not default_filt then
+ default_filt = true
+ filter = config.load('data\\filters\\filters.xml',default_filter_table,false)
+ config.save(filter)
+ windower.add_to_chat(4,'Loaded default Battlemod filters')
+ end
+ current_job = job
+end
+
+ActionPacket.open_listener(parse_action_packet)
+
+windower.register_event('incoming chunk',function (id,original,modified,is_injected,is_blocked)
+ if debugging then windower.debug('incoming chunk '..id) end
+
+------- ITEM QUANTITY -------
+ if id == 0x020 and parse_quantity then
+ --local packet = packets.parse('incoming', original)
+ local item = original:unpack('H',0x0D)
+ local count = original:unpack('I',0x05)
+ if item == 0 then return end
+ if item_quantity.id == item then
+ item_quantity.count = count..' '
+ end
+
+------- NOUNS AND PLURAL ENTITIES -------
+ elseif id == 0x00E then
+ local mob_id = original:unpack('I',0x05)
+ local mask = original:unpack('C',0x0B)
+ local chat_info = original:unpack('C',0x28)
+ if bit.band(mask,4) == 4 then
+ if bit.band(chat_info,32) == 0 and not common_nouns:contains(mob_id) then
+ table.insert(common_nouns, mob_id)
+ elseif bit.band(chat_info,64) == 64 and not plural_entities:contains(mob_id) then
+ table.insert(plural_entities, mob_id)
+ elseif bit.band(chat_info,64) == 0 and plural_entities:contains(mob_id) then --Gears can change their grammatical number when they lose 2 gear?
+ for i, v in pairs(plural_entities) do
+ if v == mob_id then
+ table.remove(plural_entities, i)
+ break
+ end
+ end
+ end
+ end
+ elseif id == 0x00B then --Reset tables on Zoning
+ common_nouns = T{}
+ plural_entities = T{}
+
+------- ACTION MESSAGE -------
+ elseif id == 0x29 then
+ local am = {}
+ am.actor_id = original:unpack('I',0x05)
+ am.target_id = original:unpack('I',0x09)
+ am.param_1 = original:unpack('I',0x0D)
+ am.param_2 = original:unpack('H',0x11)%2^9 -- First 7 bits
+ am.param_3 = math.floor(original:unpack('I',0x11)/2^5) -- Rest
+ am.actor_index = original:unpack('H',0x15)
+ am.target_index = original:unpack('H',0x17)
+ am.message_id = original:unpack('H',0x19)%2^15 -- Cut off the most significant bit
+
+ local actor = player_info(am.actor_id)
+ local target = player_info(am.target_id)
+ local actor_article = common_nouns:contains(am.actor_id) and 'The ' or ''
+ local target_article = common_nouns:contains(am.target_id) and 'The ' or ''
+ targets_condensed = false
+
+ -- Filter these messages
+ if not check_filter(actor,target,0,am.message_id) then return true end
+
+ if not actor or not target then -- If the actor or target table is nil, ignore the packet
+ elseif am.message_id == 800 then -- Spirit bond message
+ local status = color_it(res.buffs[am.param_1][language],color_arr.statuscol)
+ local targ = color_it(target.name or '',color_arr[target.owner or target.type])
+ local number = am.param_2
+ local color = color_filt(res.action_messages[am.message_id].color, am.target_id==Self.id)
+ if simplify then
+ local msg = line_noactor
+ :gsub('${abil}',status or '')
+ :gsub('${target}',targ)
+ :gsub('${numb}',number or '')
+ windower.add_to_chat(color, msg)
+ else
+ local msg = res.action_messages[am.message_id][language]
+ msg = grammatical_number_fix(msg, number, am.message_id)
+ if plural_entities:contains(am.actor_id) then
+ msg = plural_actor(msg, am.message_id)
+ end
+ if plural_entities:contains(am.target_id) then
+ msg = plural_target(msg, am.message_id)
+ end
+ local msg = clean_msg(msg
+ :gsub('${status}',status or '')
+ :gsub('${target}',target_article..targ)
+ :gsub('${number}',number or ''), am.message_id)
+ windower.add_to_chat(color, msg)
+ end
+ elseif am.message_id == 206 and condensetargets then -- Wears off messages
+ -- Condenses across multiple packets
+ local status
+
+ if enfeebling:contains(am.param_1) and res.buffs[param_1] then
+ status = color_it(res.buffs[param_1][language],color_arr.enfeebcol)
+ elseif color_arr.statuscol == rcol then
+ status = color_it(res.buffs[am.param_1][language],string.char(0x1F,191))
+ else
+ status = color_it(res.buffs[am.param_1][language],color_arr.statuscol)
+ end
+
+ if not multi_actor[status] then multi_actor[status] = player_info(am.actor_id) end
+ if not multi_msg[status] then multi_msg[status] = am.message_id end
+
+ if not multi_targs[status] and not stat_ignore:contains(am.param_1) then
+ multi_targs[status] = {}
+ multi_targs[status][1] = target
+ multi_packet:schedule(0.5, status)
+ elseif not (stat_ignore:contains(am.param_1)) then
+ multi_targs[status][#multi_targs[status]+1] = target
+ else
+ -- This handles the stat_ignore values, which are things like Utsusemi,
+ -- Sneak, Invis, etc. that you don't want to see on a delay
+ multi_targs[status] = {}
+ multi_targs[status][1] = target
+ multi_packet(status)
+ end
+ am.message_id = false
+ elseif passed_messages:contains(am.message_id) then
+ local item,status,spell,skill,number,number2
+ local outstr = res.action_messages[am.message_id][language]
+ if plural_entities:contains(am.actor_id) then
+ outstr = plural_actor(outstr, am.message_id)
+ end
+ if plural_entities:contains(am.target_id) then
+ outstr = plural_target(outstr, am.message_id)
+ end
+
+ local fields = fieldsearch(outstr)
+
+ if fields.status then
+ if log_form_messages:contains(am.message_id) then
+ status = res.buffs[am.param_1].english_log
+ else
+ status = nf(res.buffs[am.param_1],language)
+ end
+ if enfeebling:contains(am.param_1) then
+ status = color_it(status,color_arr.enfeebcol)
+ else
+ status = color_it(status,color_arr.statuscol)
+ end
+ end
+
+ if fields.spell then
+ if not res.spells[am.param_1] then
+ return false
+ end
+ spell = nf(res.spells[am.param_1],language)
+ end
+
+ if fields.item then
+ if not res.items[am.param_1] then
+ return false
+ end
+ item = nf(res.items[am.param_1],'english_log')
+ end
+
+ if fields.number then
+ number = am.param_1
+ end
+
+ if fields.number2 then
+ number2 = am.param_2
+ end
+
+ if fields.skill and res.skills[am.param_1] then
+ skill = res.skills[am.param_1][language]:lower()
+ end
+
+ if am.message_id > 169 and am.message_id <179 then
+ if am.param_1 > 2147483647 then
+ skill = 'to be level -1 ('..ratings_arr[am.param_2-63]..')'
+ else
+ skill = 'to be level '..am.param_1..' ('..ratings_arr[am.param_2-63]..')'
+ end
+ end
+ outstr = (clean_msg(outstr
+ :gsub('${actor}\'s',actor_article..color_it(actor.name or '',color_arr[actor.owner or actor.type])..'\'s'..actor.owner_name)
+ :gsub('${actor}',actor_article..color_it(actor.name or '',color_arr[actor.owner or actor.type])..actor.owner_name)
+ :gsub('${status}',status or '')
+ :gsub('${item}',color_it(item or '',color_arr.itemcol))
+ :gsub('${target}\'s',target_article..color_it(target.name or '',color_arr[target.owner or target.type])..'\'s'..target.owner_name)
+ :gsub('${target}',target_article..color_it(target.name or '',color_arr[target.owner or target.type])..target.owner_name)
+ :gsub('${spell}',color_it(spell or '',color_arr.spellcol))
+ :gsub('${skill}',color_it(skill or '',color_arr.abilcol))
+ :gsub('${number}',number or '')
+ :gsub('${number2}',number2 or '')
+ :gsub('${skill}',skill or '')
+ :gsub('${lb}','\7'), am.message_id))
+ windower.add_to_chat(res.action_messages[am.message_id]['color'],outstr)
+ am.message_id = false
+ elseif debugging and res.action_messages[am.message_id] then
+ -- 38 is the Skill Up message, which (interestingly) uses all the number params.
+ -- 202 is the Time Remaining message, which (interestingly) uses all the number params.
+ print('debug_EAM#'..am.message_id..': '..res.action_messages[am.message_id][language]..' '..am.param_1..' '..am.param_2..' '..am.param_3)
+ elseif debugging then
+ print('debug_EAM#'..am.message_id..': '..'Unknown'..' '..am.param_1..' '..am.param_2..' '..am.param_3)
+ end
+ if not am.message_id then
+ return true
+ end
+
+------------ SYNTHESIS ANIMATION --------------
+ elseif id == 0x030 and crafting then
+ if windower.ffxi.get_player().id == original:unpack('I',5) or windower.ffxi.get_mob_by_target('t') and windower.ffxi.get_mob_by_target('t').id == original:unpack('I',5) then
+ local crafter_name = (windower.ffxi.get_player().id == original:unpack('I',5) and windower.ffxi.get_player().name) or windower.ffxi.get_mob_by_target('t').name
+ local result = original:byte(13)
+ if result == 0 then
+ windower.add_to_chat(8,' ------------- NQ Synthesis ('..crafter_name..') -------------')
+ elseif result == 1 then
+ windower.add_to_chat(8,' ---------------- Break ('..crafter_name..') -----------------')
+ elseif result == 2 then
+ windower.add_to_chat(8,' ------------- HQ Synthesis ('..crafter_name..') -------------')
+ else
+ windower.add_to_chat(8,'Craftmod: Unhandled result '..tostring(result))
+ end
+ end
+ elseif id == 0x06F and crafting then
+ if original:byte(5) == 0 or original:byte(5) == 12 then
+ local result = original:byte(6)
+ if result == 1 then
+ windower.add_to_chat(8,' -------------- HQ Tier 1! --------------')
+ elseif result == 2 then
+ windower.add_to_chat(8,' -------------- HQ Tier 2! --------------')
+ elseif result == 3 then
+ windower.add_to_chat(8,' -------------- HQ Tier 3! --------------')
+ end
+ end
+
+ ------------- JOB INFO ----------------
+ elseif id == 0x01B then
+ filterload(res.jobs[original:byte(9)][language..'_short'])
+ end
+end)
+
+function multi_packet(...)
+ local ind = table.concat({...},' ')
+ local targets = assemble_targets(multi_actor[ind],multi_targs[ind],0,multi_msg[ind])
+ local outstr = targets_condensed and plural_target(res.action_messages[multi_msg[ind]][language], multi_msg[ind]) or res.action_messages[multi_msg[ind]][language]
+ outstr = clean_msg(outstr
+ :gsub('${target}\'s',targets)
+ :gsub('${target}',targets)
+ :gsub('${status}',ind), multi_msg[ind])
+ windower.add_to_chat(res.action_messages[multi_msg[ind]].color,outstr)
+ multi_targs[ind] = nil
+ multi_msg[ind] = nil
+ multi_actor[ind] = nil
+end
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-DNC.xml b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-DNC.xml
new file mode 100644
index 0000000..7eddfdc
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-DNC.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" ?>
+<!-- Filters are customizable based on the action user. So if you filter other pets, you're going
+ to eliminate all messages initiated by everyone's pet but your own.
+ True means "filter this"
+ False means "don't filter this"
+
+ Generally, the outer tag is the actor and the inner tag is the action.
+ If the monster is the actor, then the inner tag is the target and the tag beyond that is the action.-->
+<settings>
+ <global>
+ <me> <!-- You're doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- A party member is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>true</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- An alliance member is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>false</items>
+ <uses>true</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- Some guy nearby is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>true</items>
+ <uses>true</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>true</all>
+ </others>
+ <my_pet> <!-- Your pet is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <other_pets> <!-- Someone else's pet is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>true</all>
+ </other_pets>
+
+
+ <monsters> <!-- Monster is doing something with one of the below targets -->
+ <me> <!-- He's targeting you! -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- He's targeting a party member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- He's targeting an alliance member -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- He's targeting some guy nearby -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </others>
+ <my_pet> <!-- He's targeting your pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <other_pets> <!-- He's targeting someone else's pet -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </other_pets>
+
+ <monsters> <!-- He's targeting himself or another monster -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </monsters>
+ </monsters>
+ </global>
+</settings>
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WAR.xml b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WAR.xml
new file mode 100644
index 0000000..2dcbf00
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WAR.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" ?>
+<!-- Filters are customizable based on the action user. So if you filter other pets, you're going
+ to eliminate all messages initiated by everyone's pet but your own.
+ True means "filter this"
+ False means "don't filter this"
+
+ Generally, the outer tag is the actor and the inner tag is the action.
+ If the monster is the actor, then the inner tag is the target and the tag beyond that is the action.-->
+<settings>
+ <global>
+ <me> <!-- You're doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- A party member is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>false</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>false</items>
+ <uses>true</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- An alliance member is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>false</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>false</items>
+ <uses>true</uses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- Some guy nearby is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>true</items>
+ <uses>true</uses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>true</all>
+ </others>
+ <my_pet> <!-- Your pet is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>true</all>
+ </my_pet>
+ <other_pets> <!-- Someone else's pet is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>true</all>
+ </other_pets>
+
+
+ <monsters> <!-- Monster is doing something with one of the below targets -->
+ <me> <!-- He's targeting you! -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- He's targeting a party member -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- He's targeting an alliance member -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- He's targeting some guy nearby -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </others>
+ <my_pet> <!-- He's targeting your pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>true</all>
+ </my_pet>
+ <other_pets> <!-- He's targeting someone else's pet -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </other_pets>
+
+ <monsters> <!-- He's targeting himself or another monster -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </monsters>
+ </monsters>
+ </global>
+</settings>
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WHM.xml b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WHM.xml
new file mode 100644
index 0000000..257100b
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/data/filters/filters-WHM.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" ?>
+<!-- Filters are customizable based on the action user. So if you filter other pets, you're going
+ to eliminate all messages initiated by everyone's pet but your own.
+ True means "filter this"
+ False means "don't filter this"
+
+ Generally, the outer tag is the actor and the inner tag is the action.
+ If the monster is the actor, then the inner tag is the target and the tag beyond that is the action.-->
+<settings>
+ <global>
+ <me> <!-- You're doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- A party member is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>false</items>
+ <uses>true</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- An alliance member is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>false</items>
+ <uses>true</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- Some guy nearby is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <items>true</items>
+ <uses>true</uses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>true</all>
+ </others>
+ <my_pet> <!-- Your pet is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <other_pets> <!-- Someone else's pet is doing something -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>true</all>
+ </other_pets>
+
+
+ <monsters> <!-- Monster is doing something with one of the below targets -->
+ <me> <!-- He's targeting you! -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- He's targeting a party member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- He's targeting an alliance member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- He's targeting some guy nearby -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>true</all>
+ </others>
+ <my_pet> <!-- He's targeting your pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <other_pets> <!-- He's targeting someone else's pet -->
+ <melee>true</melee>
+ <ranged>true</ranged>
+ <damage>true</damage>
+ <healing>true</healing>
+ <misses>true</misses>
+ <readies>true</readies>
+ <casting>true</casting>
+ <all>true</all>
+ </other_pets>
+
+ <monsters> <!-- He's targeting himself or another monster -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>true</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </monsters>
+ </monsters>
+ </global>
+</settings>
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/generic_helpers.lua b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/generic_helpers.lua
new file mode 100644
index 0000000..1f015ae
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/generic_helpers.lua
@@ -0,0 +1,389 @@
+--Copyright © 2013, Byrthnoth
+--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.
+-- * Neither the name of <addon name> 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 <your name> 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.
+
+function nf(field,subfield)
+ if field ~= nil then
+ return field[subfield]
+ else
+ return nil
+ end
+end
+
+function flip(p1,p1t,p2,p2t,cond)
+ return p2,p2t,p1,p1t,not cond
+end
+
+function colconv(str,key)
+ -- Used in the options_load() function
+ local out
+ local strnum = tonumber(str)
+ if strnum >= 256 and strnum < 509 then
+ strnum = strnum - 254
+ if strnum == 4 then strnum = 3 end --color 258 can bug chatlog
+ out = string.char(0x1E,strnum)
+ elseif strnum >0 then
+ out = string.char(0x1F,strnum)
+ elseif strnum == 0 then
+ out = rcol
+ else
+ print('You have an invalid color '..key)
+ out = string.char(0x1F,1)
+ end
+ return out
+end
+
+
+function color_it(to_color,color)
+ if not color and debugging then windower.add_to_chat(8,'Color was invalid.') end
+ if not color or color == 0 then return to_color end
+
+ if to_color then
+ local colarr = string.split(to_color,' ')
+ colarr.n = nil
+ return color..table.concat(colarr,rcol..' '..color)..rcol
+ end
+end
+
+
+function conjunctions(pre,post,target_count,current)
+ if current < target_count or commamode then
+ pre = pre..', '
+ else
+ if oxford and target_count >2 then
+ pre = pre..','
+ end
+ pre = pre..' and '
+ end
+ return pre..post
+end
+
+
+
+function fieldsearch(message)
+ local fieldarr = {}
+ string.gsub(message,'{(.-)}', function(a) fieldarr[a] = true end)
+ return fieldarr
+end
+
+
+function check_filter(actor,target,category,msg)
+ -- This determines whether the message should be displayed or filtered
+ -- Returns true (don't filter) or false (filter), boolean
+ if not actor.filter or not target.filter then return false end
+
+ if not filter[actor.filter] and debugging then windower.add_to_chat(8,'Battlemod - Filter Not Recognized: '..tostring(actor.filter)) end
+
+ local filtertab = (filter[actor.filter] and filter[actor.filter][target.filter]) or filter[actor.filter]
+
+ if filtertab['all']
+ or category == 1 and filtertab['melee']
+ or category == 2 and filtertab['ranged']
+ or category == 12 and filtertab['ranged']
+ or category == 5 and filtertab['items']
+ or category == 9 and filtertab['uses']
+ or nf(res.action_messages[msg],'color')=='D' and filtertab['damage']
+ or nf(res.action_messages[msg],'color')=='M' and filtertab['misses']
+ or nf(res.action_messages[msg],'color')=='H' and filtertab['healing']
+ or (msg == 43 or msg == 326) and filtertab['readies']
+ or (msg == 3 or msg==327) and filtertab['casting']
+ then
+ return false
+ end
+
+ return true
+end
+
+function actor_noun(msg)
+ if msg then
+ msg = msg
+ :gsub('${actor}', 'The ${actor}')
+ end
+ return msg
+end
+
+function plural_actor(msg, msg_id)
+ if msg then
+ if msg_id == 6 then
+ msg = msg:gsub('${actor} defeats ', '${actor} defeat ')
+ elseif msg_id == 9 then
+ msg = msg:gsub('${actor} attains ', '${actor} attain ')
+ elseif msg_id == 10 then
+ msg = msg:gsub('${actor} loses ', '${actor} lose ')
+ elseif msg_id == 11 then
+ msg = msg:gsub('${actor} falls ', '${actor} fall ')
+ elseif msg_id == 19 then
+ msg = msg:gsub('${actor} calls ' , '${actor} call ')
+ elseif msg_id == 35 then
+ msg = msg:gsub('${actor} lacks ' , '${actor} lack ')
+ elseif msg_id == 67 then
+ msg = msg:gsub('${actor} scores ' , '${actor} score ')
+ elseif msg_id == 124 then
+ msg = msg:gsub('${actor} achieves ' , '${actor} achieve ')
+ elseif msg_id == 129 then
+ msg = msg:gsub('${actor} mugs ' , '${actor} mug ')
+ elseif msg_id == 244 then
+ msg = msg:gsub('${actor} fails ' , '${actor} fail ')
+ elseif msg_id == 311 then
+ msg = msg:gsub('${actor} covers ' , '${actor} cover ')
+ elseif msg_id == 315 then
+ msg = msg:gsub('${actor} already has ' , '${actor} already have ')
+ elseif msg_id ==411 then
+ msg = msg
+ :gsub('${actor} attempts ' , '${actor} attempt ')
+ :gsub(' but lacks ' , ' but lack ')
+ elseif msg_id == 536 then
+ msg = msg:gsub('${actor} takes ' , '${actor} take ')
+ elseif msg_id == 563 then
+ msg = msg:gsub('${actor} destroys ' , '${actor} destroy ')
+ elseif msg_id == 772 then
+ msg = msg:gsub('${actor} stands ', '${actor} stand ')
+ elseif replacements_map.actor.hits:contains(msg_id) then
+ msg = msg:gsub('${actor} hits ', '${actor} hit ')
+ elseif replacements_map.actor.misses:contains(msg_id) then
+ msg = msg:gsub('${actor} misses ' , '${actor} miss ')
+ elseif replacements_map.actor.starts:contains(msg_id) then
+ msg = msg:gsub('${actor} starts ', '${actor} start ')
+ elseif replacements_map.actor.casts:contains(msg_id) then
+ msg = msg:gsub('${actor} casts ', '${actor} cast ')
+ if msg_id == 83 then
+ msg = msg:gsub('${actor} successfully removes ' , '${actor} successfully remove ')
+ elseif msg_id == 572 or msg_id == 642 then
+ msg = msg:gsub('${actor} absorbs ' , '${actor} absorb ')
+ end
+ elseif replacements_map.actor.readies:contains(msg_id) then
+ msg = msg:gsub('${actor} readies ' , '${actor} ready ')
+ elseif replacements_map.actor.recovers:contains(msg_id) then
+ msg = msg:gsub('${actor} recovers ' , '${actor} recover ')
+ elseif replacements_map.actor.gains:contains(msg_id) then
+ msg = msg:gsub('${actor} gains ', '${actor} gain ')
+ elseif replacements_map.actor.apos:contains(msg_id) then
+ msg = msg:gsub('${actor}\'s ', '${actor}\' ')
+ if msg_id == 33 then
+ msg = msg:gsub('${actor} takes ' , '${actor} take ')
+ elseif msg_id == 606 then
+ msg = msg:gsub('${actor} recovers ' , '${actor} recover ')
+ elseif msg_id == 799 then
+ msg = msg:gsub('${actor} is ' , '${actor} are ')
+ end
+ elseif replacements_map.actor.uses:contains(msg_id) then
+ msg = msg:gsub('${actor} uses ' , '${actor} use ')
+ if msg_id == 122 then
+ msg = msg:gsub('${actor} recovers ' , '${actor} recover ')
+ elseif msg_id == 123 then
+ msg = msg:gsub('${actor} successfully removes ' , '${actor} successfully remove ')
+ elseif msg_id == 126 or msg_id == 136 or msg_id == 528 then
+ msg = msg:gsub('${actor}\'s ', '${actor}\' ')
+ elseif msg_id == 137 or msg_id == 153 then
+ msg = msg:gsub('${actor} fails ' , '${actor} fail ')
+ elseif msg_id == 139 then
+ msg = msg:gsub(' but finds nothing' , ' but find nothing')
+ elseif msg_id == 140 then
+ msg = msg:gsub(' and finds a ${item2}' , ' and find a ${item2}')
+ elseif msg_id == 158 then
+ msg = msg:gsub('${ability}, but misses' , '${ability}, but miss')
+ elseif msg_id == 585 then
+ msg = msg:gsub('${actor} is ' , '${actor} are ')
+ elseif msg_id == 674 then
+ msg = msg:gsub(' and finds ${number}' , ' and find ${number}')
+ elseif msg_id == 780 then
+ msg = msg:gsub('${actor} takes ' , '${actor} take ')
+ elseif replacements_map.actor.steals:contains(msg_id) then
+ msg = msg:gsub('${actor} steals ' , '${actor} steal ')
+ elseif replacements_map.actor.butmissestarget:contains(msg_id) then
+ msg = msg:gsub(' but misses ${target}' , ' but miss ${target}')
+ end
+ elseif replacements_map.actor.is:contains(msg_id) then
+ msg = msg:gsub('${actor} is ' , '${actor} are ')
+ elseif replacements_map.actor.learns:contains(msg_id) then
+ msg = msg:gsub('${actor} learns ' , '${actor} learn ')
+ elseif replacements_map.actor.has:contains(msg_id) then
+ msg = msg:gsub('${actor} has ' , '${actor} have ')
+ elseif replacements_map.actor.obtains:contains(msg_id) then
+ msg = msg:gsub('${actor} obtains ' , '${actor} obtain ')
+ elseif replacements_map.actor.does:contains(msg_id) then
+ msg = msg:gsub('${actor} does ' , '${actor} do ')
+ elseif replacements_map.actor.leads:contains(msg_id) then
+ msg = msg:gsub('${actor} leads ' , '${actor} lead ')
+ elseif replacements_map.actor.eats:contains(msg_id) then
+ msg = msg:gsub('${actor} eats ' , '${actor} eat ')
+ if msg_id == 604 then
+ msg = msg:gsub(' but finds nothing' , ' but find nothing')
+ end
+ elseif replacements_map.actor.earns:contains(msg_id) then
+ msg = msg:gsub('${actor} earns ' , '${actor} earn ')
+ end
+ end
+ return msg
+end
+
+function plural_target(msg, msg_id)
+ if msg then
+ if msg_id == 282 then
+ msg = msg:gsub('${target} evades', '${target} evade')
+ elseif msg_id == 359 then
+ msg = msg:gsub('${target} narrowly escapes ', '${target} narrowly escape ')
+ elseif msg_id == 419 then
+ msg = msg:gsub('${target} learns ', '${target} learn ')
+ elseif msg_id == 671 then
+ msg = msg:gsub('${target} now has ', '${target} now have ')
+ elseif msg_id == 764 then
+ msg = msg:gsub('${target} feels ', '${target} feel ')
+ elseif replacements_map.target.takes:contains(msg_id) then
+ msg = msg:gsub('${target} takes ', '${target} take ')
+ if msg_id == 197 then
+ msg = msg:gsub('${target} resists', '${target} resist')
+ end
+ elseif replacements_map.target.is:contains(msg_id) then
+ msg = msg:gsub('${target} is ', '${target} are ')
+ elseif replacements_map.target.recovers:contains(msg_id) then
+ msg = msg:gsub('${target} recovers ', '${target} recover ')
+ elseif replacements_map.target.apos:contains(msg_id) then --coincidence in 439 and 440
+ msg = msg:gsub('${target}\'s ', targets_condensed and '${target} ' or '${target}\' ')
+ if msg_id == 439 or msg_id == 440 then
+ msg = msg:gsub('${target} regains ', '${target} regain ')
+ end
+ elseif replacements_map.target.falls:contains(msg_id) then
+ msg = msg:gsub('${target} falls ', '${target} fall ')
+ elseif replacements_map.target.uses:contains(msg_id) then
+ msg = msg:gsub('${target} uses ', '${target} use ')
+ elseif replacements_map.target.resists:contains(msg_id) then
+ msg = msg:gsub('${target} resists', '${target} resist')
+ elseif replacements_map.target.vanishes:contains(msg_id) then
+ msg = msg:gsub('${target} vanishes', '${target} vanish')
+ elseif replacements_map.target.receives:contains(msg_id) then
+ msg = msg:gsub('${target} receives ', '${target} receive ')
+ elseif replacements_map.target.seems:contains(msg_id) then
+ msg = msg:gsub('${target} seems ${skill}', '${target} seem ${skill}')
+ if msg_id ~= 174 then
+ msg = msg:gsub('${lb}It seems to have ', '${lb}They seem to have ')
+ end
+ elseif replacements_map.target.gains:contains(msg_id) then
+ msg = msg:gsub('${target} gains ', '${target} gain ')
+ elseif replacements_map.target.regains:contains(msg_id) then
+ msg = msg:gsub('${target} regains ', '${target} regain ')
+ elseif replacements_map.target.obtains:contains(msg_id) then
+ msg = msg:gsub('${target} obtains ', '${target} obtain ')
+ elseif replacements_map.target.loses:contains(msg_id) then
+ msg = msg:gsub('${target} loses ', '${target} lose ')
+ elseif replacements_map.target.was:contains(msg_id) then
+ msg = msg:gsub('${target} was ', '${target} were ')
+ elseif replacements_map.target.has:contains(msg_id) then
+ msg = msg:gsub('${target} has ', '${target} have ')
+ elseif replacements_map.target.compresists:contains(msg_id) then
+ msg = msg:gsub('${target} completely resists ', '${target} completely resist ')
+ end
+ end
+ return msg
+end
+
+function clean_msg(msg, msg_id)
+ if msg then
+ msg = msg
+ :gsub(' The ', ' the ')
+ :gsub(': the ', ': The ')
+ :gsub('! the ', '! The ')
+ if replacements_map.the.point:contains(msg_id) then
+ msg = msg:gsub('%. the ', '. The ')
+ end
+ end
+ return msg
+end
+
+function grammatical_number_fix(msg, number, msg_id)
+ if msg then
+ if number == 1 then
+ if replacements_map.number.points:contains(msg_id) then
+ msg = msg:gsub(' points', ' point')
+ elseif msg_id == 411 then
+ msg = msg:gsub('${number} Ballista Points', '${number} Ballista Point')
+ elseif msg_id == 589 then
+ msg = msg:gsub('healed of ${number} status ailments', 'healed of ${number} status ailment')
+ elseif msg_id == 778 then
+ msg = msg:gsub('magical effects from', 'magical effect from')
+ end
+ else
+ if replacements_map.number.absorbs:contains(msg_id) then
+ msg = msg:gsub(' absorbs', ' absorb')
+ elseif msg_id == 133 then
+ msg = msg:gsub(' Petra', ' Petras')
+ elseif replacements_map.number.attributes:contains(msg_id) then
+ msg = msg:gsub('attributes is', 'attributes are')
+ elseif replacements_map.number.status:contains(msg_id) then
+ msg = msg:gsub('status effect is', 'status effects are')
+ elseif msg_id == 557 then
+ msg = msg:gsub('piece', 'pieces')
+ elseif msg_id == 560 then
+ msg = msg:gsub('Finishing move now ', 'Finishing moves now ')
+ end
+ if replacements_map.number.disappears:contains(msg_id) then
+ msg = msg:gsub('disappears', 'disappear')
+ end
+ end
+ end
+ return msg
+end
+
+function item_article_fix(id,id2,msg)
+ if id then
+ if string.gmatch(msg, ' a ${item}') then
+ local article = res.items_grammar[id] and res.items_grammar[id].article
+ if article == 1 then
+ msg = string.gsub(msg,' a ${item}',' an ${item}')
+ end
+ end
+ end
+ if id2 then
+ if string.gmatch(msg, ' a ${item2}') then
+ local article = res.items_grammar[id2] and res.items_grammar[id2].article
+ if article == 1 then
+ msg = string.gsub(msg,' a ${item2}',' an ${item2}')
+ end
+ end
+ end
+ return msg
+end
+
+function add_item_article(id)
+ local article = ''
+ local article_type = res.items_grammar[id] and res.items_grammar[id].article or nil
+ if id then
+ if article_type == 2 then
+ article = 'pair of '
+ elseif article_type == 3 then
+ article = 'suit of '
+ end
+ end
+ return article
+end
+
+function send_delayed_message(color,msg)
+ local message = msg
+ :gsub('${count}', item_quantity.count)
+ windower.add_to_chat(color,message)
+ item_quantity.id = 0
+ item_quantity.count = ''
+ parse_quantity = false
+end
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/parse_action_packet.lua b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/parse_action_packet.lua
new file mode 100644
index 0000000..05cfd36
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/parse_action_packet.lua
@@ -0,0 +1,947 @@
+function parse_action_packet(act)
+ -- Make a function that returns the action array with additional information
+ -- actor : type, name, is_npc
+ -- target : type, name, is_npc
+ if not Self then
+ Self = windower.ffxi.get_player()
+ if not Self then
+ return act
+ end
+ end
+ act.actor = player_info(act.actor_id)
+ act.action = get_spell(act) -- Pulls the resources line for the action
+ act.actor.name = act.actor and act.actor.name and string.gsub(act.actor.name,'[- ]', {['-'] = string.char(0x81,0x7C), [' '] = string.char(0x81,0x3F)}) --fix for ffxi chat splits on trusts with - and spaces
+ targets_condensed = false
+
+ if not act.action then
+ return act
+ end
+ for i,v in ipairs(act.targets) do
+ v.target = {}
+ v.target[1] = player_info(v.id)
+ if #v.actions > 1 then
+ for n,m in ipairs(v.actions) do
+ if res.action_messages[m.message] then m.fields = fieldsearch(res.action_messages[m.message][language]) end
+ if res.action_messages[m.add_effect_message] then m.add_effect_fields = fieldsearch(res.action_messages[m.add_effect_message][language]) end
+ if res.action_messages[m.spike_effect_message] then m.spike_effect_fields = fieldsearch(res.action_messages[m.spike_effect_message][language]) end
+
+ if res.buffs[m.param] then --and m.param ~= 0 then
+ m.status = res.buffs[m.param][language]
+ end
+ if res.buffs[m.add_effect_param] then -- and m.add_effect_param ~= 0 then
+ m.add_effect_status = res.buffs[m.add_effect_param][language]
+ end
+ if res.buffs[m.spike_effect_param] then -- and m.spike_effect_param ~= 0 then
+ m.spike_effect_status = res.buffs[m.spike_effect_param][language]
+ end
+ m.number = 1
+ if m.has_add_effect then
+ m.add_effect_number = 1
+ end
+ if m.has_spike_effect then
+ m.spike_effect_number = 1
+ end
+ if not check_filter(act.actor,v.target[1],act.category,m.message) then
+ m.message = 0
+ m.add_effect_message = 0
+ end
+ if m.spike_effect_message ~= 0 and not check_filter(v.target[1],act.actor,act.category,m.message) then
+ m.spike_effect_message = 0
+ end
+ if condensedamage and n > 1 then -- Damage/Action condensation within one target
+ for q=1,n-1 do
+ local r = v.actions[q]
+
+ if r.message ~= 0 and m.message ~= 0 then
+ if m.message == r.message or (condensecrits and S{1,67}:contains(m.message) and S{1,67}:contains(r.message)) then
+ if (m.effect == r.effect) or (S{1,67}:contains(m.message) and S{0,1,2,3}:contains(m.effect) and S{0,1,2,3}:contains(r.effect)) then -- combine kicks and crits
+ if m.reaction == r.reaction then --or (S{8,10}:contains(m.reaction) and S{8,10}:contains(r.reaction)) then -- combine hits and guards
+-- windower.add_to_chat(8, 'Condensed: '..m.message..':'..r.message..' - '..m.effect..':'..r.effect..' - '..m.reaction..':'..r.reaction)
+ r.number = r.number + 1
+ if not sumdamage then
+ if not r.cparam then
+ r.cparam = r.param
+ if condensecrits and r.message == 67 then
+ r.cparam = r.cparam..'!'
+ end
+ end
+ r.cparam = r.cparam..', '..m.param
+ if condensecrits and m.message == 67 then
+ r.cparam = r.cparam..'!'
+ end
+ end
+ r.param = m.param + r.param
+ if condensecrits and m.message == 67 then
+ r.message = m.message
+ r.effect = m.effect
+ end
+ m.message = 0
+ else
+-- windower.add_to_chat(8, 'Didn\'t condense: '..m.message..':'..r.message..' - '..m.effect..':'..r.effect..' - '..m.reaction..':'..r.reaction)
+ end
+ else
+-- windower.add_to_chat(8, 'Didn\'t condense: '..m.message..':'..r.message..' - '..m.effect..':'..r.effect..' - '..m.reaction..':'..r.reaction)
+ end
+ else
+-- windower.add_to_chat(8, 'Didn\'t condense: '..m.message..':'..r.message..' - '..m.effect..':'..r.effect..' - '..m.reaction..':'..r.reaction)
+ end
+ end
+ if m.has_add_effect and r.add_effect_message ~= 0 then
+ if m.add_effect_effect == r.add_effect_effect and m.add_effect_message == r.add_effect_message and m.add_effect_message ~= 0 then
+ r.add_effect_number = r.add_effect_number + 1
+ if not sumdamage then
+ r.cadd_effect_param = (r.cadd_effect_param or r.add_effect_param)..', '..m.add_effect_param
+ end
+ r.add_effect_param = m.add_effect_param + r.add_effect_param
+ m.add_effect_message = 0
+ end
+ end
+ if m.has_spike_effect and r.spike_effect_message ~= 0 then
+ if r.spike_effect_effect == r.spike_effect_effect and m.spike_effect_message == r.spike_effect_message and m.spike_effect_message ~= 0 then
+ r.spike_effect_number = r.spike_effect_number + 1
+ if not sumdamage then
+ r.cspike_effect_param = (r.cspike_effect_param or r.spike_effect_param)..', '..m.spike_effect_param
+ end
+ r.spike_effect_param = m.spike_effect_param + r.spike_effect_param
+ m.spike_effect_message = 0
+ end
+ end
+ end
+ end
+ end
+ else
+ local tempact = v.actions[1]
+ if res.action_messages[tempact.message] then tempact.fields = fieldsearch(res.action_messages[tempact.message][language]) end
+ if res.action_messages[tempact.add_effect_message] then tempact.add_effect_fields = fieldsearch(res.action_messages[tempact.add_effect_message][language]) end
+ if res.action_messages[tempact.spike_effect_message] then tempact.spike_effect_fields = fieldsearch(res.action_messages[tempact.spike_effect_message][language]) end
+
+
+ --if tempact.add_effect_fields and tempact.add_effect_fields.status then windower.add_to_chat(8,tostring(tempact.add_effect_fields.status)..' '..res.action_messages[tempact.add_effect_message][language]) end
+
+ if not check_filter(act.actor,v.target[1],act.category,tempact.message) then
+ tempact.message = 0
+ tempact.add_effect_message = 0
+ end
+ if tempact.spike_effect_message ~= 0 and not check_filter(v.target[1],act.actor,act.category,tempact.message) then
+ tempact.spike_effect_message = 0
+ end
+ tempact.number = 1
+ if tempact.has_add_effect and tempact.message ~= 674 then
+ tempact.add_effect_number = 1
+ end
+ if tempact.has_spike_effect then
+ tempact.spike_effect_number = 1
+ end
+ if res.buffs[tempact.param] then -- and tempact.param ~= 0 then
+ tempact.status = res.buffs[tempact.param][language]
+ end
+ if res.buffs[tempact.add_effect_param] then -- and tempact.add_effect_param ~= 0 then
+ tempact.add_effect_status = res.buffs[tempact.add_effect_param][language]
+ end
+ if res.buffs[tempact.spike_effect_param] then -- and tempact.spike_effect_param ~= 0 then
+ tempact.spike_effect_status = res.buffs[tempact.spike_effect_param][language]
+ end
+ end
+
+ if condensetargets and i > 1 then
+ for n=1,i-1 do
+ local m = act.targets[n]
+ --windower.add_to_chat(8,m.actions[1].message..' '..v.actions[1].message)
+ if (v.actions[1].message == m.actions[1].message and v.actions[1].param == m.actions[1].param) or
+ (message_map[m.actions[1].message] and message_map[m.actions[1].message]:contains(v.actions[1].message) and v.actions[1].param == m.actions[1].param) or
+ (message_map[m.actions[1].message] and message_map[m.actions[1].message]:contains(v.actions[1].message) and v.actions[1].param == m.actions[1].param) then
+ m.target[#m.target+1] = v.target[1]
+ v.target[1] = nil
+ v.actions[1].message = 0
+ end
+ end
+ end
+ end
+
+ for i,v in pairs(act.targets) do
+ for n,m in pairs(v.actions) do
+ if m.message ~= 0 and res.action_messages[m.message] ~= nil then
+ local col = res.action_messages[m.message].color
+ local targ = assemble_targets(act.actor,v.target,act.category,m.message)
+ local color = color_filt(col,v.target[1].id==Self.id)
+ if m.reaction == 11 and act.category == 1 then m.simp_name = 'parried by'
+ --elseif m.reaction == 12 and act.category == 1 then m.simp_name = 'blocked by'
+ elseif m.message == 1 and (act.category == 1 or act.category == 11) then m.simp_name = 'hit'
+ elseif m.message == 15 then m.simp_name = 'missed'
+ elseif m.message == 29 or m.message == 84 then m.simp_name = 'is paralyzed'
+ elseif m.message == 30 then m.simp_name = 'anticipated by'
+ elseif m.message == 31 then m.simp_name = 'absorbed by'
+ elseif m.message == 32 then m.simp_name = 'dodged by'
+ elseif m.message == 67 and (act.category == 1 or act.category == 11) then m.simp_name = 'critical hit'
+ elseif m.message == 106 then m.simp_name = 'intimidated by'
+ elseif m.message == 153 then m.simp_name = act.action.name..' fails'
+ elseif m.message == 244 then m.simp_name = 'Mug fails'
+ elseif m.message == 282 then m.simp_name = 'evaded by'
+ elseif m.message == 373 then m.simp_name = 'absorbed by'
+ elseif m.message == 352 then m.simp_name = 'RA'
+ elseif m.message == 353 then m.simp_name = 'critical RA'
+ elseif m.message == 354 then m.simp_name = 'missed RA'
+ elseif m.message == 576 then m.simp_name = 'RA hit squarely'
+ elseif m.message == 577 then m.simp_name = 'RA struck true'
+ elseif m.message == 157 then m.simp_name = 'Barrage'
+ elseif m.message == 76 then m.simp_name = 'No targets within range'
+ elseif m.message == 77 then m.simp_name = 'Sange'
+ elseif m.message == 360 then m.simp_name = act.action.name..' (JA reset)'
+ elseif m.message == 426 or m.message == 427 then m.simp_name = 'Bust! '..act.action.name
+ elseif m.message == 435 or m.message == 436 then m.simp_name = act.action.name..' (JAs)'
+ elseif m.message == 437 or m.message == 438 then m.simp_name = act.action.name..' (JAs and TP)'
+ elseif m.message == 439 or m.message == 440 then m.simp_name = act.action.name..' (SPs, JAs, TP, and MP)'
+ elseif T{252,265,268,269,271,272,274,275,379,650,747}:contains(m.message) then m.simp_name = 'Magic Burst! '..act.action.name
+ elseif not act.action then
+ m.simp_name = ''
+ act.action = {}
+ else m.simp_name = act.action.name or ''
+ end
+
+ -- Debuff Application Messages
+ if simplify and message_map[82]:contains(m.message) then
+ if m.status == 'Evasion Down' then
+ m.message = 237
+ end
+ if m.status == 'addle' then m.status = 'addled'
+ elseif m.status == 'bind' then m.status = 'bound'
+ elseif m.status == 'blindness' then m.status = 'blinded'
+ elseif m.status == 'Inundation' then m.status = 'inundated'
+ elseif m.status == 'paralysis' then m.status = 'paralyzed'
+ elseif m.status == 'petrification' then m.status = 'petrified'
+ elseif m.status == 'poison' then m.status = 'poisoned'
+ elseif m.status == 'silence' then m.status = 'silenced'
+ elseif m.status == 'sleep' then m.status = 'asleep'
+ elseif m.status == 'slow' then m.status = 'slowed'
+ elseif m.status == 'stun' then m.status = 'stunned'
+ elseif m.status == 'weight' then m.status = 'weighed down'
+ end
+ end
+
+ -- Some messages uses the english log version of the buff
+ if not simplify and log_form_messages:contains(m.message) then
+ m.status = res.buffs[m.param].enl
+ end
+
+ -- if m.message == 93 or m.message == 273 then m.status=color_it('Vanish',color_arr['statuscol']) end
+
+ -- Special Message Handling
+ if m.message == 93 or m.message == 273 then
+ m.status=color_it('Vanish',color_arr['statuscol'])
+ elseif m.message == 522 and simplify then
+ targ = targ..' ('..color_it('stunned',color_arr['statuscol'])..')'
+ elseif m.message == 416 and simplify then
+ targ = targ..' ('..color_it('Magic Attack Boost and Magic Defense Boost',color_arr['statuscol'])..')'
+ elseif m.message == 1023 and simplify then
+ targ = targ..' ('..color_it('attacks and defenses enhanced',color_arr['statuscol'])..')'
+ elseif m.message == 762 and simplify then
+ targ = targ..' ('..color_it('all status parameters boosted',color_arr['statuscol'])..')'
+ elseif m.message == 779 and simplify then
+ targ = 'A barrier pulsates around '..targ
+ elseif m.message == 780 and simplify then
+ targ = 'Takes aim on '..targ
+ elseif T{158,188,245,324,592,658}:contains(m.message) and simplify then
+ -- When you miss a WS or JA. Relevant for condensed battle.
+ m.status = 'Miss' --- This probably doesn't work due to the if a==nil statement below.
+ elseif m.message == 653 or m.message == 654 then
+ m.status = color_it('Immunobreak',color_arr['statuscol'])
+ elseif m.message == 655 or m.message == 656 then
+ m.status = color_it('Completely Resists',color_arr['statuscol'])
+ elseif m.message == 85 or m.message == 284 then
+ if m.unknown == 2 then
+ m.status = color_it('Resists!',color_arr['statuscol'])
+ else
+ m.status = color_it('Resists',color_arr['statuscol'])
+ end
+ elseif m.message == 351 then
+ m.status = color_it('status ailments',color_arr['statuscol'])
+ m.simp_name = color_it('remedy',color_arr['itemcol'])
+ elseif T{75,114,156,189,248,283,312,323,336,355,408,422,423,425,659}:contains(m.message) then
+ m.status = color_it('No effect',color_arr['statuscol']) -- The status code for "No Effect" is 255, so it might actually work without this line
+ end
+ if m.message == 188 then
+ m.simp_name = m.simp_name..' (Miss)'
+ -- elseif m.message == 189 then
+ -- m.simp_name = m.simp_name..' (No Effect)'
+ elseif T{78,198,328}:contains(m.message) then
+ m.simp_name = '(Too Far)'
+ end
+ local msg,numb = simplify_message(m.message)
+ if not color_arr[act.actor.owner or act.actor.type] then windower.add_to_chat(123,'Battlemod error, missing filter:'..tostring(act.actor.owner)..' '..tostring(act.actor.type)) end
+ if m.fields.status then numb = m.status else numb = pref_suf((m.message == 674 and m.add_effect_param or m.cparam or m.param),m.message,act.actor.damage,col) end
+
+ if msg and m.message == 70 and not simplify then -- fix pronoun on parry
+ if v.target[1].race == 0 then
+ msg = msg:gsub(' his ',' its ')
+ elseif female_races:contains(v.target[1].race) then
+ msg = msg:gsub(' his ',' her ')
+ end
+ end
+
+ local count = ''
+ if m.message == 377 and act.actor_id == Self.id then
+ parse_quantity = true
+ item_quantity.id = act.action.item2_id
+ count = '${count}'
+ end
+
+ if not simplify then
+ if col == 'D' or grammar_numb_msg:contains(m.message) then
+ msg = grammatical_number_fix(msg, (m.cparam or m.param), m.message)
+ end
+ if act.action.item_id or act.action.item2_id then
+ msg = item_article_fix(act.action.item_id,act.action.item2_id,msg)
+ end
+ if common_nouns:contains(act.actor.id) then
+ msg = actor_noun(msg)
+ end
+ if plural_entities:contains(act.actor.id) then
+ msg = plural_actor(msg, m.message)
+ end
+ if targets_condensed or plural_entities:contains(v.target[1].id) then
+ msg = plural_target(msg, m.message)
+ end
+ end
+
+ local roll = showrollinfo and act.category == 6 and corsair_rolls[act.param] and corsair_rolls[act.param][m.param] or ''
+ local reaction_lookup = reaction_offsets[act.category] and (m.reaction - reaction_offsets[act.category]) or 0
+ local has_line_break = string.find(res.action_messages[m.message].en, '${lb}') and true or false
+ local prefix = (not has_line_break or simplify) and get_prefix(act.category, m.effect, m.message, m.unknown, reaction_lookup) or ''
+ local prefix2 = has_line_break and get_prefix(act.category, m.effect, m.message, m.unknown, reaction_lookup) or ''
+ local message = prefix..make_condensedamage_number(m.number)..( clean_msg((msg or tostring(m.message))
+ :gsub('${spell}',color_it(act.action.spell or 'ERROR 111',color_arr.spellcol))
+ :gsub('${ability}',color_it(act.action.ability or 'ERROR 112',color_arr.abilcol))
+ :gsub('${item}',color_it(act.action.item or 'ERROR 113',color_arr.itemcol))
+ :gsub('${item2}',count..color_it(act.action.item2 or 'ERROR 121',color_arr.itemcol))
+ :gsub('${weapon_skill}',color_it(act.action.weapon_skill or 'ERROR 114',color_arr.wscol))
+ :gsub('${abil}',m.simp_name or 'ERROR 115')
+ :gsub('${numb}',numb..roll or 'ERROR 116')
+ :gsub('${actor}\'s',color_it(act.actor.name or 'ERROR 117',color_arr[act.actor.owner or act.actor.type])..'\'s'..act.actor.owner_name)
+ :gsub('${actor}',color_it(act.actor.name or 'ERROR 117',color_arr[act.actor.owner or act.actor.type])..act.actor.owner_name)
+ :gsub('${target}\'s',targ)
+ :gsub('${target}',targ)
+ :gsub('${lb}','\7'..prefix2)
+ :gsub('${number}',(act.action.number or m.param)..roll)
+ :gsub('${status}',m.status or 'ERROR 120')
+ :gsub('${gil}',m.param..' gil'), m.message))
+ if m.message == 377 and act.actor_id == Self.id then
+ send_delayed_message:schedule(0.5,color,message)
+ else
+ windower.add_to_chat(color,message)
+ end
+ if not non_block_messages:contains(m.message) then
+ m.message = 0
+ end
+ end
+ if m.has_add_effect and m.add_effect_message ~= 0 and add_effect_valid[act.category] then
+ local targ = assemble_targets(act.actor,v.target,act.category,m.add_effect_message)
+ local col = res.action_messages[m.add_effect_message].color
+ local color = color_filt(col,v.target[1].id==Self.id)
+ if m.add_effect_message > 287 and m.add_effect_message < 303 then m.simp_add_name = skillchain_arr[m.add_effect_message-287]
+ elseif m.add_effect_message > 384 and m.add_effect_message < 399 then m.simp_add_name = skillchain_arr[m.add_effect_message-384]
+ elseif m.add_effect_message > 766 and m.add_effect_message < 769 then m.simp_add_name = skillchain_arr[m.add_effect_message-752]
+ elseif m.add_effect_message > 768 and m.add_effect_message < 771 then m.simp_add_name = skillchain_arr[m.add_effect_message-754]
+ elseif m.add_effect_message == 603 then m.simp_add_name = 'AE: TH'
+ elseif m.add_effect_message == 605 then m.simp_add_name = 'AE: Death'
+ elseif m.add_effect_message == 776 then m.simp_add_name = 'AE: Chainbound'
+ else m.simp_add_name = 'AE'
+ end
+ local msg,numb = simplify_message(m.add_effect_message)
+ if not simplify then
+ if col == 'D' or grammar_numb_msg:contains(m.add_effect_message) then
+ msg = grammatical_number_fix(msg, (m.cparam or m.param), m.add_effect_message)
+ end
+ if common_nouns:contains(act.actor.id) then
+ msg = actor_noun(msg)
+ end
+ if plural_entities:contains(act.actor.id) then
+ msg = plural_actor(msg, m.add_effect_message)
+ end
+ if targets_condensed or plural_entities:contains(v.target[1].id) then
+ msg = plural_target(msg, m.add_effect_message)
+ end
+ end
+ if m.add_effect_fields.status then numb = m.add_effect_status else numb = pref_suf((m.cadd_effect_param or m.add_effect_param),m.add_effect_message,act.actor.damage,col) end
+ if not act.action then
+-- windower.add_to_chat(color, 'act.action==nil : '..m.message..' - '..m.add_effect_message..' - '..msg)
+ else
+ windower.add_to_chat(color,make_condensedamage_number(m.add_effect_number)..(clean_msg(msg
+ :gsub('${spell}',act.action.spell or 'ERROR 127')
+ :gsub('${ability}',act.action.ability or 'ERROR 128')
+ :gsub('${item}',act.action.item or 'ERROR 129')
+ :gsub('${weapon_skill}',act.action.weapon_skill or 'ERROR 130')
+ :gsub('${abil}',m.simp_add_name or act.action.name or 'ERROR 131')
+ :gsub('${numb}',numb or 'ERROR 132')
+ :gsub('${actor}\'s',color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])..'\'s'..act.actor.owner_name)
+ :gsub('${actor}',color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])..act.actor.owner_name)
+ :gsub('${target}\'s',targ)
+ :gsub('${target}',targ)
+ :gsub('${lb}','\7')
+ :gsub('${number}',m.add_effect_param)
+ :gsub('${status}',m.add_effect_status or 'ERROR 178'), m.add_effect_message)))
+ if not non_block_messages:contains(m.add_effect_message) then
+ m.add_effect_message = 0
+ end
+ end
+ end
+ if m.has_spike_effect and m.spike_effect_message ~= 0 and spike_effect_valid[act.category] then
+ local targ = assemble_targets(act.actor,v.target,act.category,m.spike_effect_message)
+ local col = res.action_messages[m.spike_effect_message].color
+ local color = color_filt(col,act.actor.id==Self.id)
+
+ local actor = act.actor
+ if m.spike_effect_message == 14 then
+ m.simp_spike_name = 'from counter'
+ elseif T{33,606}:contains(m.spike_effect_message) then
+ m.simp_spike_name = 'counter'
+ actor = v.target[1] --Counter dmg is done by the target, fix for coloring the dmg
+ elseif m.spike_effect_message == 592 then
+ m.simp_spike_name = 'missed counter'
+ elseif m.spike_effect_message == 536 then
+ m.simp_spike_name = 'retaliation'
+ actor = v.target[1] --Retaliation dmg is done by the target, fix for coloring the dmg
+ elseif m.spike_effect_message == 535 then
+ m.simp_spike_name = 'from retaliation'
+ else
+ m.simp_spike_name = 'spikes'
+ actor = v.target[1] --Spikes dmg is done by the target, fix for coloring the dmg
+ end
+
+ local msg = simplify_message(m.spike_effect_message)
+ if not simplify then
+ if col == 'D' or grammar_numb_msg:contains(m.spike_effect_message) then
+ msg = grammatical_number_fix(msg, (m.cparam or m.param), m.spike_effect_message)
+ end
+ if common_nouns:contains(act.actor.id) then
+ msg = actor_noun(msg)
+ end
+ if plural_entities:contains(act.actor.id) then
+ msg = plural_actor(msg, m.spike_effect_message)
+ end
+ if targets_condensed or plural_entities:contains(v.target[1].id) then
+ msg = plural_target(msg, m.spike_effect_message)
+ end
+ end
+ if m.spike_effect_fields.status then numb = m.spike_effect_status else numb = pref_suf((m.cspike_effect_param or m.spike_effect_param),m.spike_effect_message,actor.damage,col) end
+ windower.add_to_chat(color,make_condensedamage_number(m.spike_effect_number)..(clean_msg(msg
+ :gsub('${spell}',act.action.spell or 'ERROR 142')
+ :gsub('${ability}',act.action.ability or 'ERROR 143')
+ :gsub('${item}',act.action.item or 'ERROR 144')
+ :gsub('${weapon_skill}',act.action.weapon_skill or 'ERROR 145')
+ :gsub('${abil}',m.simp_spike_name or act.action.name or 'ERROR 146')
+ :gsub('${numb}',numb or 'ERROR 147')
+ :gsub('${actor}\'s',color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])..'\'s'..act.actor.owner_name)
+ :gsub((simplify and '${target}' or '${actor}'),color_it(act.actor.name,color_arr[act.actor.owner or act.actor.type])..act.actor.owner_name)
+ :gsub('${target}\'s',targ)
+ :gsub((simplify and '${actor}' or '${target}'),targ)
+ :gsub('${lb}','\7')
+ :gsub('${number}',m.spike_effect_param)
+ :gsub('${status}',m.spike_effect_status or 'ERROR 150'), m.spike_effect_message)))
+ if not non_block_messages:contains(m.spike_effect_message) then
+ m.spike_effect_message = 0
+ end
+ end
+ end
+ end
+
+ return act
+end
+
+function pref_suf(param,msg_ID,actor_dmg,col)
+ local outstr = (col == 'D' or dmg_drain_msg:contains(msg_ID)) and color_it(tostring(param),color_arr[actor_dmg]) or tostring(param)
+ local msg = res.action_messages[msg_ID] or nil
+ if msg then
+ if msg.prefix then
+ outstr = msg.prefix..' '..outstr
+ end
+ if msg.suffix then
+ if msg.suffix == 'shadow' and param ~= 1 then
+ outstr = outstr..' shadows'
+ elseif msg.suffix == 'Petra' and param ~= 1 then
+ outstr = outstr..' Petras'
+ elseif msg.suffix == 'effects disappears' and param ~= 1 then
+ outstr = outstr..' effects disappear'
+ elseif msg_ID == 641 then
+ outstr = outstr..' 1 attribute drained'
+ elseif msg.suffix == 'attributes drained' and param == 1 then
+ outstr = outstr..' attribute drained'
+ elseif msg.suffix == 'status effect drained' and param ~= 1 then
+ outstr = outstr..' status effects drained'
+ elseif msg.suffix == 'status ailments disappears' and param ~= 1 then
+ outstr = outstr..' status ailments disappear'
+ elseif msg.suffix == 'status ailments absorbed' and param == 1 then
+ outstr = outstr..' status ailment absorbed'
+ elseif msg.suffix == 'status ailments healed' and param == 1 then
+ outstr = outstr..' status ailment healed'
+ elseif msg.suffix == 'status benefits absorbed' and param == 1 then
+ outstr = outstr..' status benefit absorbed'
+ elseif msg.suffix == 'status effects removed' and param == 1 then
+ outstr = outstr..' status effect removed'
+ elseif msg.suffix == 'magic effects drained' and param == 1 then
+ outstr = outstr..' magic effect drained'
+ elseif msg.suffix == 'magical effects received' and param == 1 then
+ outstr = outstr..' magical effect received'
+ elseif msg.suffix == 'magical effects copied' and param == 1 then
+ outstr = outstr..' magical effect copied'
+ else
+ outstr = outstr..' '..msg.suffix
+ end
+ end
+ end
+ return outstr
+end
+
+function simplify_message(msg_ID)
+ local msg = res.action_messages[msg_ID][language]
+ local fields = fieldsearch(msg)
+
+ if simplify and not T{23,64,133,204,210,211,212,213,214,350,442,516,531,557,565,582}:contains(msg_ID) then
+ if T{93,273,522,653,654,655,656,85,284,75,114,156,189,248,283,312,323,336,351,355,408,422,423,425,453,659,158,245,324,658}:contains(msg_ID) then
+ fields.status = true
+ end
+ if msg_ID == 31 or msg_ID == 798 or msg_ID == 799 then
+ fields.actor = true
+ end
+ if (msg_ID > 287 and msg_ID < 303) or (msg_ID > 384 and msg_ID < 399) or (msg_ID > 766 and msg_ID < 771) or
+ T{129,152,161,162,163,165,229,384,453,603,652,798}:contains(msg_ID) then
+ fields.ability = true
+ end
+
+ if T{125,593,594,595,596,597,598,599}:contains(msg_ID) then
+ fields.ability = true
+ fields.item = true
+ end
+
+ if T{129,152,153,160,161,162,163,164,165,166,167,168,229,244,652}:contains(msg_ID) then
+ fields.actor = true
+ fields.target = true
+ end
+
+ if msg_ID == 139 then
+ fields.number = true
+ end
+
+ local Despoil_msg = {[593] = 'Attack Down', [594] = 'Defense Down', [595] = 'Magic Atk. Down', [596] = 'Magic Def. Down', [597] = 'Evasion Down', [598] = 'Accuracy Down', [599] = 'Slow',}
+ if line_full and fields.number and fields.target and fields.actor then
+ msg = line_full
+ elseif line_aoebuff and fields.status and fields.target then --and fields.actor then -- and (fields.spell or fields.ability or fields.item or fields.weapon_skill) then
+ msg = line_aoebuff
+ elseif line_item and fields.item2 then
+ if fields.number then
+ msg = line_itemnum
+ else
+ msg = line_item
+ end
+ elseif line_steal and fields.item and fields.ability then
+ if T{593,594,595,596,597,598,599}:contains(msg_ID) then
+ msg = line_steal..''..string.char(0x07)..'AE: '..color_it(Despoil_msg[msg_ID],color_arr['statuscol'])
+ else
+ msg = line_steal
+ end
+ elseif line_nonumber and not fields.number then
+ msg = line_nonumber
+ elseif line_aoe and T{264}:contains(msg_ID) then
+ msg = line_aoe
+ elseif line_noactor and not fields.actor and (fields.spell or fields.ability or fields.item or fields.weapon_skill) then
+ msg = line_noactor
+ elseif line_noability and not fields.actor then
+ msg = line_noability
+ elseif line_notarget and fields.actor and fields.number then
+ if msg_ID == 798 then --Maneuver message
+ msg = line_notarget..'%'
+ elseif msg_ID == 799 then --Maneuver message with overload
+ msg = line_notarget..'% (${actor} overloaded)'
+ else
+ msg = line_notarget
+ end
+ end
+ end
+ return msg
+end
+
+function assemble_targets(actor,targs,category,msg)
+ local targets = {}
+ local samename = {}
+ local total = 0
+ for i,v in pairs(targs) do
+ -- Done in two loops so that the ands and commas don't get out of place.
+ -- This loop filters out unwanted targets.
+ if check_filter(actor,v,category,msg) or check_filter(v,actor,category,msg) then
+ if samename[v.name] and condensetargetname then
+ samename[v.name] = samename[v.name] + 1
+ else
+ targets[#targets+1] = v
+ samename[v.name] = 1
+ end
+ total = total + 1
+ end
+ end
+ local out_str
+ if targetnumber and total > 1 then
+ out_str = '{'..total..'}: '
+ else
+ out_str = ''
+ end
+
+ for i,v in pairs(targets) do
+ local name = string.gsub(v.name,' ', string.char(0x81,0x3F)) --fix for ffxi chat splits on space
+ local article = common_nouns:contains(v.id) and (not simplify or msg == 206) and 'The ' or ''
+ local numb = condensetargetname and samename[v.name] > 1 and ' {'..samename[v.name]..'}' or ''
+ if i == 1 then
+ name = color_it(name,color_arr[v.owner or v.type])..v.owner_name
+ if samename[v.name] > 1 then
+ targets_condensed = true
+ else
+ if (not simplify or msg == 206) and #targets == 1 and string.find(res.action_messages[msg][language], '${target}\'s') then
+ name = color_it(name,color_arr[v.owner or v.type])..(plural_entities:contains(v.id) and '\'' or '\'s')..v.owner_name
+ end
+ targets_condensed = false
+ end
+ out_str = out_str..article..name..numb
+ else
+ targets_condensed = true
+ name = color_it(name,color_arr[v.owner or v.type])..v.owner_name
+ out_str = conjunctions(out_str,article..name..numb,#targets,i)
+ end
+ end
+ out_str = string.gsub(out_str,'-', string.char(0x81,0x7C)) --fix for ffxi chat splits on trusts with -
+ return out_str
+end
+
+function make_condensedamage_number(number)
+ if swingnumber and condensedamage and 1 < number then
+ return '['..number..'] '
+ else
+ return ''
+ end
+end
+
+function player_info(id)
+ local player_table = windower.ffxi.get_mob_by_id(id)
+ local typ,dmg,owner,filt,owner_name
+
+ if player_table == nil then
+ return {name=nil,id=nil,is_npc=nil,type='debug',owner=nil, owner_name=nil,race=nil}
+ end
+
+ for i,v in pairs(windower.ffxi.get_party()) do
+ if type(v) == 'table' and v.mob and v.mob.id == player_table.id then
+ typ = i
+ if i == 'p0' then
+ filt = 'me'
+ dmg = 'mydmg'
+ elseif i:sub(1,1) == 'p' then
+ filt = 'party'
+ dmg = 'partydmg'
+ else
+ filt = 'alliance'
+ dmg = 'allydmg'
+ end
+ end
+ end
+
+ if not filt then
+ if player_table.is_npc then
+ if player_table.index>1791 or player_table.charmed then
+ typ = 'other_pets'
+ filt = 'other_pets'
+ owner = 'other'
+ dmg = 'otherdmg'
+ for i,v in pairs(windower.ffxi.get_party()) do
+ if type(v) == 'table' and v.mob and v.mob.pet_index and v.mob.pet_index == player_table.index then
+ if i == 'p0' then
+ typ = 'my_pet'
+ filt = 'my_pet'
+ dmg = 'mydmg'
+ end
+ owner = i
+ owner_name = showownernames and ' ('..color_it(v.mob.name, color_arr[owner or typ])..')'
+ break
+ elseif type(v) == 'table' and v.mob and v.mob.fellow_index and v.mob.fellow_index == player_table.index then
+ if i == 'p0' then
+ typ = 'my_fellow'
+ filt = 'my_fellow'
+ dmg = 'mydmg'
+ end
+ owner = i
+ owner_name = showownernames and ' ('..color_it(v.mob.name, color_arr[owner or typ])..')'
+ break
+ end
+ end
+ else
+ typ = 'mob'
+ filt = 'monsters'
+ dmg = 'mobdmg'
+
+ if filter.enemies then
+ for i,v in pairs(Self.buffs) do
+ if domain_buffs:contains(v) then
+ -- If you are in Domain Invasion, or a Reive, or various other places
+ -- then all monsters should be considered enemies.
+ filt = 'enemies'
+ break
+ end
+ end
+
+ if filt ~= 'enemies' then
+ for i,v in pairs(windower.ffxi.get_party()) do
+ if type(v) == 'table' and nf(v.mob,'id') == player_table.claim_id then
+ filt = 'enemies'
+ break
+ end
+ end
+ end
+ end
+ end
+ else
+ typ = 'other'
+ filt = 'others'
+ dmg = 'otherdmg'
+ end
+ end
+ if not typ then typ = 'debug' end
+ return {name=player_table.monstrosity_name or player_table.name,id=id,is_npc = player_table.is_npc,type=typ,damage=dmg,filter=filt,owner=(owner or nil), owner_name=(owner_name or ''),race = player_table.race}
+end
+
+function get_spell(act)
+ local spell, abil_ID, effect_val = {}
+ local msg_ID = act.targets[1].actions[1].message
+
+ if T{7,8,9}:contains(act['category']) then
+ abil_ID = act.targets[1].actions[1].param
+ elseif T{3,4,5,6,11,13,14,15}:contains(act.category) then
+ abil_ID = act.param
+ effect_val = act.targets[1].actions[1].param
+ end
+
+ if act.category == 1 then
+ spell.english = 'hit'
+ spell.german = spell.english
+ spell.japanese = spell.english
+ spell.french = spell.english
+ elseif act.category == 2 and act.category == 12 then
+ if msg_ID == 77 then
+ spell = res.job_abilities[171] -- Sange
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ end
+ elseif msg_ID == 157 then
+ spell = res.job_abilities[60] -- Barrage
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ end
+ else
+ spell.english = 'Ranged Attack'
+ spell.german = spell.english
+ spell.japanese = spell.english
+ spell.french = spell.english
+ end
+ else
+ if not res.action_messages[msg_ID] then
+ if T{4,8}:contains(act['category']) then
+ spell = res.spells[abil_ID]
+ elseif T{6,14,15}:contains(act['category']) or T{7,13}:contains(act['category']) and false then
+ spell = res.job_abilities[abil_ID] -- May have to correct for charmed pets some day, but I'm not sure there are any monsters with TP moves that give no message.
+ elseif T{3,7,11}:contains(act['category']) then
+ if abil_ID < 256 then
+ spell = res.weapon_skills[abil_ID] -- May have to correct for charmed pets some day, but I'm not sure there are any monsters with TP moves that give no message.
+ else
+ spell = res.monster_abilities[abil_ID]
+ end
+ elseif T{5,9}:contains(act['category']) then
+ spell = res.items[abil_ID]
+ else
+ spell = {none=tostring(msg_ID)} -- Debugging
+ end
+ return spell
+ end
+
+ local fields = fieldsearch(res.action_messages[msg_ID][language])
+
+ if fields.spell then
+ spell = res.spells[abil_ID]
+ if spell then
+ spell.name = color_it(spell[language],color_arr.spellcol)
+ spell.spell = color_it(spell[language],color_arr.spellcol)
+ end
+ elseif fields.ability then
+ spell = res.job_abilities[abil_ID]
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ spell.ability = color_it(spell[language],color_arr.abilcol)
+ if msg_ID == 139 then
+ spell.number = 'Nothing'
+ end
+ end
+ elseif fields.weapon_skill then
+ if abil_ID > 256 then -- WZ_RECOVER_ALL is used by chests in Limbus
+ spell = res.monster_abilities[abil_ID]
+ if not spell then
+ spell = {english= 'Special Attack'}
+ end
+ elseif abil_ID <= 256 then
+ spell = res.weapon_skills[abil_ID]
+ end
+ if spell then
+ spell.name = color_it(spell[language],color_arr.wscol)
+ spell.weapon_skill = color_it(spell[language],color_arr.wscol)
+ end
+ elseif msg_ID == 303 then
+ spell = res.job_abilities[74] -- Divine Seal
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ spell.ability = color_it(spell[language],color_arr.abilcol)
+ end
+ elseif msg_ID == 304 then
+ spell = res.job_abilities[75] -- 'Elemental Seal'
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ spell.ability = color_it(spell[language],color_arr.abilcol)
+ end
+ elseif msg_ID == 305 then
+ spell = res.job_abilities[76] -- 'Trick Attack'
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ spell.ability = color_it(spell[language],color_arr.abilcol)
+ end
+ elseif msg_ID == 311 or msg_ID == 312 then
+ spell = res.job_abilities[79] -- 'Cover'
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ spell.ability = color_it(spell[language],color_arr.abilcol)
+ end
+ elseif msg_ID == 240 or msg_ID == 241 then
+ spell = res.job_abilities[43] -- 'Hide'
+ if spell then
+ spell.name = color_it(spell[language],color_arr.abilcol)
+ spell.ability = color_it(spell[language],color_arr.abilcol)
+ end
+ end
+
+ if fields.item then
+ if T{125,593,594,595,596,597,598,599}:contains(msg_ID) then
+ local item_article = not simplify and add_item_article(effect_val) or ''
+ spell.item = color_it(item_article..res.items[effect_val]['english_log'], color_arr.itemcol)
+ spell.item_id = res.items[effect_val].id
+ else
+ spell = res.items[abil_ID]
+ local item_article = not simplify and add_item_article(spell.id) or ''
+ if spell then
+ spell.name = color_it(item_article..spell['english_log'],color_arr.itemcol)
+ spell.item = color_it(item_article..spell['english_log'],color_arr.itemcol)
+ spell.item_id = abil_ID
+ end
+ end
+ end
+
+ if fields.item2 then
+ local item_article = not simplify and add_item_article(effect_val) or ''
+ local tempspell = (msg_ID == 377 or msg_ID == 674) and res.items_grammar[effect_val] and res.items_grammar[effect_val].plural or item_article..res.items[effect_val].english_log
+ spell.item2 = color_it(tempspell,color_arr.itemcol)
+ spell.item2_id = effect_val
+ if fields.number then
+ spell.number = act.targets[1].actions[1].add_effect_param
+ end
+ end
+ end
+
+ if spell and not spell.name then spell.name = spell[language] end
+ return spell
+end
+
+
+function color_filt(col,is_me)
+ --Used to convert situational colors from the resources into real colors
+ --Depends on whether or not the target is you, the same as using in-game colors
+ -- Returns a color code for windower.add_to_chat()
+ -- Does not currently support a Debuff/Buff distinction
+ if col == 'D' then -- Damage
+ if is_me then
+ return 28
+ else
+ return 20
+ end
+ elseif col == 'M' then -- Misses
+ if is_me then
+ return 29
+ else
+ return 21
+ end
+ elseif col == 'H' then -- Healing
+ if is_me then
+ return 30
+ else
+ return 22
+ end
+ elseif col == 'B' then -- Beneficial effects
+ if is_me then
+ return 56
+ else
+ return 60
+ end
+ elseif col == 'DB' then -- Detrimental effects (I don't know how I'd split these)
+ if is_me then
+ return 57
+ else
+ return 61
+ end
+ elseif col == 'R' then -- Resists
+ if is_me then
+ return 59
+ else
+ return 63
+ end
+ else
+ return col
+ end
+end
+
+function get_prefix(category, effect, message, unknown, reaction_lookup)
+ local prefix = S{1,3,4,6,11,13,14,15}:contains(category) and (bit.band(unknown,1)==1 and 'Cover! ' or '')
+ ..(bit.band(unknown,4)==4 and 'Magic Burst! ' or '') --Used on Swipe/Lunge MB
+ ..(bit.band(unknown,8)==8 and 'Immunobreak! ' or '') --Unused? Displayed directly on message
+ ..(showcritws and bit.band(effect,2)==2 and S{1,3,11}:contains(category) and message~=67 and 'Critical Hit! ' or '') --Unused? Crits have their own message
+ ..(showblocks and reaction_lookup == 4 and 'Blocked! ' or '')
+ ..(showguards and reaction_lookup == 2 and 'Guarded! ' or '')
+ ..(reaction_lookup == 3 and S{3,4,6,11,13,14,15}:contains(category) and 'Parried! ' or '') --Unused? They are send the same as missed
+ return prefix
+end
+
+function condense_actions(action_array)
+ for i,v in pairs(action_array) do
+ local comb_table = {}
+ for n,m in pairs(v) do
+ if comb_table[m.primary.name] then
+ if m.secondary.name == 'number' then
+ comb_table[m.primary.name].secondary.name = tostring(tonumber(comb_table[m.primary.name].secondary.name)+tonumber(m.secondary.name))
+ end
+ comb_table[m.primary.name].count = comb_table[m.primary.name].count + 1
+ else
+ comb_table[m.primary.name] = m
+ comb_table[m.primary.name].count = 1
+ end
+ m = nil -- Could cause next() error
+ end
+ for n,m in pairs(comb_table) do
+ v[#v+1] = m
+ end
+ end
+ return action_array
+end
+
+function condense_targets(action_array)
+ local comb_table = {}
+ for i,v in pairs(action_array) do
+ local was_created = false
+ for n,m in pairs(comb_table) do
+ if table.equal(v,m,3) then -- Compares 3 levels deep
+ n[#n+1] = i[1]
+ was_created = true
+ end
+ end
+ if not was_created then
+ comb_table[{i[1]}] = v
+ end
+ end
+ return comb_table
+end
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/statics.lua b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/statics.lua
new file mode 100644
index 0000000..8abe43e
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/statics.lua
@@ -0,0 +1,699 @@
+ --Copyright © 2013, Byrthnoth
+--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.
+-- * Neither the name of <addon name> 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 <your name> 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.
+language = 'english'
+skillchain_arr = {'Light:','Darkness:','Gravitation:','Fragmentation:','Distortion:','Fusion:','Compression:','Liquefaction:','Induration:','Reverberation:','Transfixion:','Scission:','Detonation:','Impaction:','Radiance:','Umbra:'}
+ratings_arr = {'TW','IEP','EP','DC','EM','T','VT','IT'}
+current_job = 'NONE'
+default_filt = false
+parse_quantity = false
+targets_condensed = false
+common_nouns = T{}
+plural_entities = T{}
+item_quantity = {id = 0, count = ''}
+rcol = string.char(0x1E,0x01)
+non_block_messages = T{1,2,7,14,15,24,25,26,30,31,32,33,44,63,67,69,70,77,102,103,110,122,132,152,157,158,161,162,163,165,167,185,187,188,196,197,223,224,225,226,227,228,229,238,245,252,263,264,265,274,275,276,281,282,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,306,317,318,324,352,353,354,357,358,366,367,373,379,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,409,413,451,452,454,522,535,536,537,539,576,577,587,588,592,603,606,648,650,651,658,732,736,746,747,748,749,750,751,752,753,767,768,769,770,781}
+passed_messages = T{4,5,6,16,17,18,20,34,35,36,38,40,47,48,49,53,62,64,72,78,87,88,89,90,94,97,112,116,154,170,171,172,173,174,175,176,177,178,191,192,198,204,206,215,217,218,219,234,246,249,251,307,308,313,315,328,336,350,523,530,531,558,561,563,575,584,601,609,562,610,611,612,613,614,615,616,617,618,619,620,625,626,627,628,629,630,631,632,633,634,635,636,643,660,661,662,679}
+agg_messages = T{85,653,655,75,156,189,248,323,355,408,422,425,82,93,116,127,131,134,151,144,146,148,150,166,186,194,230,236,237,242,243,268,271,319,320,364,375,412,414,416,420,424,426,432,433,441,602,645,668,435,437,439}
+color_redundant = T{26,33,41,71,72,89,94,109,114,164,173,181,184,186,70,84,104,127,128,129,130,131,132,133,134,135,136,137,138,139,140,64,86,91,106,111,175,178,183,81,101,16,65,87,92,107,112,174,176,182,82,102,67,68,69,170,189,15,208,18,25,32,40,163,185,23,24,27,34,35,42,43,162,165,187,188,30,31,14,205,144,145,146,147,148,149,150,151,152,153,190,13,9,253,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,284,285,286,287,292,293,294,295,300,301,301,303,308,309,310,311,316,317,318,319,324,325,326,327,332,333,334,335,340,341,342,343,344,345,346,347,348,349,350,351,355,357,358,360,361,363,366,369,372,374,375,378,381,384,395,406,409,412,415,416,418,421,424,437,450,453,456,458,459,462,479,490,493,496,499,500,502,505,507,508,10,51,52,55,58,62,66,80,83,85,88,90,93,100,103,105,108,110,113,122,168,169,171,172,177,179,180,12,11,37,291} -- 37 and 291 might be unique colors, but they are not gsubbable.
+block_messages = T{12}
+block_modes = T{20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,40,41,42,43,56,57,59,60,61,63,104,109,114,162,163,164,165,181,185,186,187,188}
+black_colors = T{}--352,354,356,388,390,400,402,430,432,442,444,472,474,484,486}
+dmg_drain_msg = T{132,161,187,227,274,281,736,748,749,802,803}
+grammar_numb_msg = T{14,31,133,231,369,370,382,385,386,387,388,389,390,391,392,393,394,395,396,397,398,400,401,403,404,405,411,417,535,536,557,570,571,589,607,651,757,769,770,778,792}
+
+replacements_map = {
+ actor = {
+ hits = T{1,373},
+ casts = T{2,7,42,82,83,85,86,93,113,114,227,228,230,236,237,252,268,271,274,275,309,329,330,331,332,333,334,335,341,342,430,431,432,433,454,533,534,570,572,642,647,653,655},
+ starts = T{3,327,716},
+ gains = T{8,54,105,166,253,371,372,718,735},
+ apos = T{14,16,33,69,70,75,248,310,312,352,353,354,355,382,493,535,574,575,576,577,592,606,798,799},
+ misses = T{15,63},
+ learns = T{23,45,442},
+ uses = T{28,77,100,101,102,103,108,109,110,115,116,117,118,119,120,121,122,123,125,126,127,129,131,133,134,135,136,137,138,139,140,141,142,143,144,146,148,150,153,156,157,158,159,185,186,187,188,189,194,197,221,224,225,226,231,238,242,243,245,303,304,305,306,317,318,319,320,321,322,323,324,360,362,364,369,370,375,376,377,378,379,399,400,401,402,405,406,407,408,409,412,413,414,416,417,418,420,422,424,425,426,435,
+ 437,439,441,451,452,453,519,520,521,522,526,527,528,529,532,539,560,585,591,593,594,595,596,597,598,599,602,607,608,644,645,646,657,658,663,664,667,668,670,671,672,674,730,734,736,737,738,743,746,747,748,750,752,754,755,758,762,763,764,765,766,778,779,780,792,802,803,804,805,1023},
+ is = T{29,49,84,106,191},
+ does = T{34,91,192},
+ readies = T{43,326,675},
+ earns = T{50,368,719},
+ steals = T{125,133,453,593,594,595,596,597,598,599},
+ recovers = T{152,167},
+ butmissestarget = T{188,245,324,658},
+ eats = T{600,604},
+ leads = T{648,650,651},
+ has = T{515,661,665,688},
+ obtains = T{582,673},
+ },
+ target = {
+ takes = T{2,67,77,110,157,185,196,197,229,252,264,265,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,317,353,379,413,522,648,650,732,747,767,768,800},
+ is = T{4,13,64,78,82,86,107,127,128,130,131,134,136,141,148,149,150,151,154,198,203,204,232,236,242,246,270,271,272,277,279,286,287,313,328,350,519,520,521,529,531,586,591,593,594,595,596,597,598,599,645,754,776},
+ recovers = T{7,24,25,26,74,102,103,224,238,263,276,306,318,367,373,382,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,651,769,770},
+ apos = T{31,38,44,53,73,83,106,112,116,120,121,123,132,159,168,206,221,231,249,285,308,314,321,322,329,330,331,332,333,334,335,341,342,343,344,351,360,361,362,363,364,365,369,374,378,383,399,400,401,402,403,405,407,409,417,418,430,431,435,436,437,438,439,440,459,530,533,534,537,570,571,572,585,606,607,641,642,644,647,676,730,743,756,757,762,792,805,806,1023},
+ falls = T{20,113,406,605,646},
+ uses = T{79,80},
+ resists = T{85,197,284,653,654},
+ vanishes = T{93,273},
+ receives = T{142,144,145,146,147,237,243,267,268,269,278,320,375,412,414,415,416,420,421,424,432,433,441,532,557,602,668,672,739,755,804},
+ seems = T{170,171,172,173,174,175,176,177,178},
+ gains = T{186,194,205,230,266,280,319},
+ regains = T{357,358,439,440,451,452,539,587,588},
+ obtains = T{376,377,565,566,765,766},
+ loses = T{426,427,652},
+ was = T{97,564},
+ has = T{589,684,763},
+ compresists = T{655,656},
+ },
+ number = {
+ points = T{1,2,8,10,33,38,44,54,67,77,105,110,157,163,185,196,197,223,229,252,253,264,265,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,310,317,352,353,371,372,373,379,382,385,386,387,388,389,390,391,392,393,394,395,396,397,398,413,522,536,576,577,648,650,651,718,721,722,723,724,725,726,727,728,729,732,735,747,767,768,769,770,800},
+ absorbs = T{14,31,535},
+ disappears = T{14,31,231,400,401,405,535,570,571,607,757,792,},
+ attributes = T{369,403,417},
+ status = T{370,404},
+
+ },
+ the = {
+ point = T{33,308,536,800},
+ }
+}
+
+corsair_rolls = {
+ [98] = {[5] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Fighter's Roll
+ [99] = {[3] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Monk's Roll
+ [100] = {[3] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Healer's Roll
+ [101] = {[5] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Wizard's Roll
+ [102] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Warlock's Roll
+ [103] = {[5] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Rogue's Roll
+ [104] = {[3] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Gallant's Roll
+ [105] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Chaos Roll
+ [106] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Beast Roll
+ [107] = {[2] = ' (Lucky Roll!)', [6] = ' (Unlucky Roll!)'}, -- Choral Roll
+ [108] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Hunter's Roll
+ [109] = {[2] = ' (Lucky Roll!)', [6] = ' (Unlucky Roll!)'}, -- Samurai Roll
+ [110] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Ninja Roll
+ [111] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Drachen Roll
+ [112] = {[5] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Evoker's Roll
+ [113] = {[2] = ' (Lucky Roll!)', [6] = ' (Unlucky Roll!)'}, -- Magus's Roll
+ [114] = {[5] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Corsair's Roll
+ [115] = {[3] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Puppet Roll
+ [116] = {[3] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Dancer's Roll
+ [117] = {[2] = ' (Lucky Roll!)', [6] = ' (Unlucky Roll!)'}, -- Scholar's Roll
+ [118] = {[3] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Bolter's Roll
+ [119] = {[2] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Caster's Roll
+ [120] = {[3] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Courser's Roll
+ [121] = {[4] = ' (Lucky Roll!)', [9] = ' (Unlucky Roll!)'}, -- Blitzer's Roll
+ [122] = {[5] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Tactician's Roll
+ [302] = {[3] = ' (Lucky Roll!)', [10] = ' (Unlucky Roll!)'}, -- Allies' Roll
+ [303] = {[5] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Miser's Roll
+ [304] = {[2] = ' (Lucky Roll!)', [10] = ' (Unlucky Roll!)'}, -- Companion's Roll
+ [305] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Avenger's Roll
+ [390] = {[3] = ' (Lucky Roll!)', [7] = ' (Unlucky Roll!)'}, -- Naturalit's Roll
+ [391] = {[4] = ' (Lucky Roll!)', [8] = ' (Unlucky Roll!)'}, -- Runeist's Roll
+}
+
+domain_buffs = S{
+ 250, -- EF Badge
+ 257, -- Besieged
+ 267, -- Allied Tags
+ --292, -- Pennant?
+ --475, -- Voidwatcher
+ 511, -- Reive Mark
+ 603, -- Elvorseal
+ } -- EF BadElvorseal, Allied Tags, EF Badge?
+
+-- resists = {85,284}
+-- immunobreaks = {653,654}
+-- complete_resists = {655,656}
+-- no_effects = {75,156,189,248,323,355,408,422,425,283,423,659}
+-- receives = {82,116,127,131,134,151,144,146,148,150,166,186,194,230,236,237,242,243,268,271,319,320,364,375,412,414,416,420,424,426,432,433,441,602,645,668,203,205,266,270,272,277,279,280,285,145,147,149,151,267,269,278,286,287,365,415,421,427}
+-- vanishes = {93,273}
+
+no_effect_map = T{248,355,189,75,408,156,0,0,0,0,189,0,189,156,156}
+receives_map = T{0,0,186,82,375,116,0,0,0,0,186,0,127,116,116}
+stat_ignore = T{66,69,70,71,444,445,446}
+enfeebling = T{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,155,156,157,158,159,167,168,174,175,177,186,189,192,193,194,223,259,260,261,262,263,264,298,378,379,380,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,404,448,449,450,451,452,473,540,557,558,559,560,561,562,563,564,565,566,567}
+
+reaction_offsets = {
+ [1] = 8,
+ [3] = 24,
+ [4] = 0,
+ [6] = 16,
+ [11] = 24,
+ [13] = 24,
+ [14] = 16,
+ [15] = 24,
+}
+
+female_races = T{2,4,6,7}
+male_races = T{1,3,5,8}
+
+color_arr = {}
+default_color_table = {mob=69,other=8,
+p0=501,p1=204,p2=410,p3=492,p4=259,p5=260,
+a10=205,a11=359,a12=167,a13=038,a14=125,a15=185,
+a20=429,a21=257,a22=200,a23=481,a24=483,a25=208,
+mobdmg=0,mydmg=0,partydmg=0,allydmg=0,otherdmg=0,
+spellcol=0,abilcol=0,wscol=0,mobwscol=0,mobspellcol=0,statuscol=191,itemcol=256,enfeebcol=475}
+
+filter = {}
+multi_targs = {}
+multi_actor = {}
+multi_msg = {}
+line_aoe = 'AOE ${numb} '..string.char(129,168)..' ${target}'
+line_aoebuff = '${actor} ${abil} '..string.char(129,168)..' ${target} (${status})'
+line_full = '[${actor}] ${numb} ${abil} '..string.char(129,168)..' ${target}'
+line_itemnum = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${numb} ${item2})'
+line_item = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${item2})'
+line_steal = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${item})'
+line_noability = '${numb} '..string.char(129,168)..' ${target}'
+line_noactor = '${abil} ${numb} '..string.char(129,168)..' ${target}'
+line_nonumber = '[${actor}] ${abil} '..string.char(129,168)..' ${target}'
+line_notarget = '[${actor}] ${abil} '..string.char(129,168)..' ${number}'
+line_roll = '${actor} ${abil} '..string.char(129,168)..' ${target} '..string.char(129,170)..' ${number}'
+
+default_settings_table = {line_aoe = 'AOE ${numb} '..string.char(129,168)..' ${target}',
+ line_aoebuff = '${actor} ${abil} '..string.char(129,168)..' ${target} (${status})',
+ line_full = '[${actor}] ${numb} ${abil} '..string.char(129,168)..' ${target}',
+ line_itemnum = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${numb} ${item2})',
+ line_item = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${item2})',
+ line_steal = '[${actor}] ${abil} '..string.char(129,168)..' ${target} (${item})',
+ line_noability = '${numb} '..string.char(129,168)..' ${target}',
+ line_noactor = '${abil} ${numb} '..string.char(129,168)..' ${target}',
+ line_nonumber = '[${actor}] ${abil} '..string.char(129,168)..' ${target}',
+ line_notarget = '[${actor}] ${abil} '..string.char(129,168)..' ${number}',
+ line_roll = '${actor} ${abil} '..string.char(129,168)..' ${target} '..string.char(129,170)..' ${number}',
+ condensedamage=true,condensetargets=true,cancelmulti=true,oxford=true,commamode=false,targetnumber=true,condensetargetname=false,swingnumber=true,sumdamage=true,condensecrits=false,showownernames=false,crafting=true,showblocks=true,showguards=true,showcritws=false,showrollinfo=false}
+
+message_map = {}
+for n=1,700,1 do
+ message_map[n] = T{}
+end
+
+message_map[85] = T{284} -- resist
+message_map[653] = T{654} -- immunobreak
+message_map[655] = T{656} -- complete resist
+message_map[93] = T{273} -- vanishes
+-- message_map[75] = -- no effect spell
+message_map[156] = T{156,323,422,425} -- no effect ability
+message_map[75] = T{283} -- No Effect: Spell, Target
+-- message_map[189] = -- no effect ws
+-- message_map[408] = -- no effect item
+message_map[248] = T{355} -- no ability of any kind
+message_map['No effect'] = T{283,423,659} -- generic "no effect" messages for sorting by category
+message_map[432] = T{433} -- Receives: Spell, Target
+message_map[82] = T{230,236,237,267,268,271} -- Receives: Spell, Target, Status
+message_map[230] = T{266} -- Receives: Spell, Target, Status
+message_map[319] = T{266} -- Receives: Spell, Target, Status (Generic for avatar buff BPs)
+message_map[134] = T{287} -- Receives: Spell, Target, Status
+message_map[116] = T{131,134,144,146,148,150,364,414,416,441,602,668,285,145,147,149,151,286,287,365,415,421} -- Receives: Ability, Target
+message_map[127]=T{319,320,645} -- Receives: Ability, Target, Status
+message_map[420]=T{424} -- Receives: Ability, Target, Status, Number
+message_map[375] = T{412}-- Receives: Item, Target, Status
+-- message_map[166] = -- receives additional effect
+message_map[186] = T{194,242,243}-- Receives: Weapon skill, Target, Status
+message_map.Receives = T{203,205,270,272,277,279,280,266,267,269,278}
+message_map[426] = T{427} -- Loses
+message_map[320] = T{267}
+message_map[414] = T{415} -- Dream Shroud
+message_map[7] = T{263}
+message_map[148] = T{149}
+message_map[441] = T{421}
+message_map[131] = T{286}
+message_map[150] = T{151}
+message_map[420] = T{421}
+message_map[424] = T{421}
+message_map[437] = T{438}
+message_map[126] = T{676}
+message_map[268] = T{269}
+message_map[271] = T{272}
+message_map[252] = T{265}
+message_map[360] = T{361}
+message_map[362] = T{363}
+message_map[318] = T{263} -- Whispering Wind
+message_map[323] = T{283} -- No effect Soothing Ruby
+message_map[364] = T{365} -- Ecliptic Growl
+message_map[146] = T{147} -- Ecliptic Howl
+message_map[236] = T{270}
+message_map[194] = T{280}
+message_map[185] = T{264}
+message_map[243] = T{278}
+message_map[2] = T{264}
+message_map[668] = T{669} -- Valiance
+message_map[762] = T{365} -- Mix: Samson's Strength
+message_map[242] = T{277}
+message_map[238] = T{367} -- Phototrophic Blessing
+message_map[188] = T{282} -- Misses
+message_map[342] = T{344} -- Dispelga
+message_map[369] = T{403} -- Ultimate Terror
+
+spike_effect_valid = {true,false,false,false,false,false,false,false,false,false,false,false,false,false,false}
+add_effect_valid = {true,true,true,true,false,false,false,false,false,false,true,false,true,false,false}
+
+-- These are the debuffs that are expressed in their log form by battlemod (The status variable when using english log is code 14 while the other one is code 13 so it should be handled by messages)
+--log_form_debuffs = T{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,28,29,30,31,134,135,155,156,157,168,176,177,259,260,261,262,263,264,309,474}
+log_form_messages = T{64,73,82,127,128,130,141,203,204,236,242,270,271,272,277,279,350,374,531,645,754}
+
+
+default_filters = [[
+<?xml version="1.0" ?>
+<settings>
+<!-- Filters are customizable based on the action user. So if you filter other pets, you're going
+ to eliminate all messages initiated by everyone's pet but your own.
+ True means "filter this"
+ False means "don't filter this"
+
+ Generally, the outer tag is the actor and the inner tag is the action.
+ If the monster is the actor, then the inner tag is the target and the tag beyond that is the action.-->
+ <global>
+ <me> <!-- You're doing something -->
+ <melee>false</melee> <!-- Prevents your melee ("white") damage from appearing -->
+ <ranged>false</ranged> <!-- Prevents your ranged damage from appearing -->
+ <damage>false</damage> <!-- Prevents your damage from appearing -->
+ <healing>false</healing> <!-- Prevents your healing from appearing -->
+ <misses>false</misses> <!-- Prevents your misses from appearing -->
+ <items>false</items> <!-- Prevents your "Jim used an item. Jim gains the effect of Reraise." messages from appearing -->
+ <uses>false</uses> <!-- Prevents your "Jim uses an item." messages from appearing -->
+ <readies>false</readies> <!-- Prevents your "Jim readies ____" messages from appearing -->
+ <casting>false</casting> <!-- Prevents your "Jim begins casting ____" messages from appearing -->
+ <all>false</all> <!-- Prevents all of your messages from appearing -->
+
+ <target>true</target> <!-- true = SHOW all actions where I am the target. -->
+ </me>
+ <party> <!-- A party member is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- An alliance member is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- Some guy nearby is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </others>
+ <my_pet> <!-- Your pet is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <my_fellow> <!-- Your adventuring fellow is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_fellow>
+ <other_pets> <!-- Someone else's pet is doing something -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </other_pets>
+
+ <enemies> <!-- Monster that your party has claimed doing something with one of the below targets -->
+ <me> <!-- He's targeting you! -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- He's targeting a party member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- He's targeting an alliance member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- He's targeting some guy nearby -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </others>
+ <my_pet> <!-- He's targeting your pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <my_fellow> <!-- He's targeting your adventuring fellow -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_fellow>
+ <other_pets> <!-- He's targeting someone else's pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </other_pets>
+ <enemies> <!-- He's targeting himself or another monster your party has claimed -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </enemies>
+ <monsters> <!-- He's targeting another monster -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </monsters>
+ </enemies>
+
+ <monsters> <!-- NPC not claimed to your party is doing something with one of the below targets -->
+ <me> <!-- He's targeting you! -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </me>
+ <party> <!-- He's targeting a party member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </party>
+ <alliance> <!-- He's targeting an alliance member -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </alliance>
+ <others> <!-- He's targeting some guy nearby -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </others>
+ <my_pet> <!-- He's targeting your pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_pet>
+ <my_fellow> <!-- He's targeting your adventuring fellow -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </my_fellow>
+ <other_pets> <!-- He's targeting someone else's pet -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </other_pets>
+ <enemies> <!-- He's targeting a monster your party has claimed -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </enemies>
+ <monsters> <!-- He's targeting himself or another monster -->
+ <melee>false</melee>
+ <ranged>false</ranged>
+ <damage>false</damage>
+ <healing>false</healing>
+ <misses>false</misses>
+ <items>false</items>
+ <uses>false</uses>
+ <readies>false</readies>
+ <casting>false</casting>
+ <all>false</all>
+ </monsters>
+ </monsters>
+ </global>
+</settings>
+]]
+
+default_filter_table = {me={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false,target=true},
+party={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false,target=false},
+alliance={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false,target=false},
+others={melee=false,ranged=false,damage=false,healing=false,misses=false,items=false,uses=false,readies=false,casting=false,all=false,target=false},
+my_pet={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false,target=false},
+my_fellow={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false,target=false},
+other_pets={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false,target=false},
+monsters = {
+me={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+party={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+alliance={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+others={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+my_pet={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+my_fellow={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+other_pets={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false},
+monsters={melee=false,ranged=false,damage=false,healing=false,misses=false,readies=false,casting=false,all=false}} }
+
+default_settings = [[
+<?xml version="1.0" ?>
+<settings>
+<!-- For the output customization lines, ${actor} denotes a value to be replaced. The options are actor, number, abil, and target.
+ Options for other modes are either "true" or "false". Other values will not be interpreted.-->
+ <global>
+ <condensedamage>true</condensedamage>
+ <condensetargets>true</condensetargets>
+ <cancelmulti>true</cancelmulti>
+ <oxford>true</oxford>
+ <commamode>false</commamode>
+ <targetnumber>true</targetnumber>
+ <condensetargetname>false</condensetargetname>
+ <swingnumber>true</swingnumber>
+ <sumdamage>true</sumdamage>
+ <condensecrits>false</condensecrits>
+ <tpstatuses>true</tpstatuses>
+ <simplify>true</simplify>
+ <showownernames>false</showownernames>
+ <crafting>true</crafting>
+ <showblocks>true</showblocks>
+ <showguards>true</showguards>
+ <showcritws>false</showcritws>
+ <showrollinfo>false</showrollinfo>
+ <line_aoe>AOE ${numb} ]]..string.char(129,168)..[[ ${target}</line_aoe>
+ <line_aoebuff>${actor} ${abil} ]]..string.char(129,168)..[[ ${target} (${status})</line_aoebuff>
+ <line_full>[${actor}] ${numb} ${abil} ]]..string.char(129,168)..[[ ${target}</line_full>
+ <line_item>[${actor}] ${abil} ]]..string.char(129,168)..[[ ${target} (${item2})</line_item>
+ <line_itemnum>[${actor}] ${abil} ]]..string.char(129,168)..[[ ${target} (${numb} ${item2})</line_itemnum>
+ <line_noability>${numb} ]]..string.char(129,168)..[[ ${target}</line_noability>
+ <line_noactor>${abil} ${numb} ]]..string.char(129,168)..[[ ${target}</line_noactor>
+ <line_nonumber>[${actor}] ${abil} ]]..string.char(129,168)..[[ ${target}</line_nonumber>
+ <line_notarget>[${actor}] ${abil} ]]..string.char(129,168)..[[ ${number}</line_notarget>
+ <line_roll>${actor} ${abil} ]]..string.char(129,168)..[[ ${target} ]]..string.char(129,170)..[[ ${number}</line_roll>
+ </global>
+</settings>
+]]
+
+default_colors = [[
+<? xml version="1.0" ?>
+<settings>
+<!-- Colors are customizable based on party / alliance position. Use the colortest command to view the available colors.
+ If you wish for a color to be unchanged from its normal color, set it to 0. -->
+ <global>
+ <mob>69</mob>
+ <other>8</other>
+
+ <p0>501</p0>
+ <p1>204</p1>
+ <p2>410</p2>
+ <p3>492</p3>
+ <p4>259</p4>
+ <p5>260</p5>
+
+ <a10>205</a10>
+ <a11>359</a11>
+ <a12>167</a12>
+ <a13>038</a13>
+ <a14>125</a14>
+ <a15>185</a15>
+
+ <a20>429</a20>
+ <a21>257</a21>
+ <a22>200</a22>
+ <a23>481</a23>
+ <a24>483</a24>
+ <a25>208</a25>
+
+ <mobdmg>0</mobdmg>
+ <mydmg>0</mydmg>
+ <partydmg>0</partydmg>
+ <allydmg>0</allydmg>
+ <otherdmg>0</otherdmg>
+
+ <spellcol>0</spellcol>
+ <mobspellcol>0</mobspellcol>
+ <abilcol>0</abilcol>
+ <wscol>0</wscol>
+ <mobwscol>0</mobwscol>
+ <statuscol>0</statuscol>
+ <enfeebcol>501</enfeebcol>
+ <itemcol>256</itemcol>
+ </global>
+</settings>
+]]
+
+local item_lag_preventer = table.length(res.items)