summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-11-15 13:53:59 +0800
committerchai <chaifix@163.com>2021-11-15 13:53:59 +0800
commit942a030afd348ab2e02eac8054b43e3c3a72ea48 (patch)
treea13459f39a3d2f1b533fbd1b5ab523d7a621f673 /Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua
parente307051a56a54c27f10438fd2025edf61d0dfeed (diff)
*rename
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua')
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/battlemod/battlemod.lua508
1 files changed, 508 insertions, 0 deletions
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