summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-addons/addons/shortcuts/shortcuts.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/shortcuts/shortcuts.lua
parente307051a56a54c27f10438fd2025edf61d0dfeed (diff)
*rename
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-addons/addons/shortcuts/shortcuts.lua')
-rw-r--r--Data/BuiltIn/Libraries/lua-addons/addons/shortcuts/shortcuts.lua409
1 files changed, 409 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-addons/addons/shortcuts/shortcuts.lua b/Data/BuiltIn/Libraries/lua-addons/addons/shortcuts/shortcuts.lua
new file mode 100644
index 0000000..a2f5da5
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-addons/addons/shortcuts/shortcuts.lua
@@ -0,0 +1,409 @@
+--Copyright (c) 2014, 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.
+
+_addon.version = '2.903'
+_addon.name = 'Shortcuts'
+_addon.author = 'Byrth'
+_addon.commands = {'shortcuts'}
+
+
+debugging = false
+logging = false
+if windower.dir_exists('../addons/shortcuts/data/') and logging then
+ logfile = io.open('../addons/shortcuts/data/NormalLog'..tostring(os.clock())..'.log','w+')
+ logfile:write('\n\n','SHORTCUTS LOGGER HEADER: ',tostring(os.clock()),'\n')
+ logfile:flush()
+end
+
+if windower.file_exists(windower.addon_path..'resources.lua') then
+ local result = os.remove(windower.addon_path..'resources.lua')
+ if not result then
+ os.rename(windower.addon_path..'resources.lua',windower.addon_path..'unnecessary.lua')
+ end
+end
+
+if not windower.dir_exists(windower.addon_path..'data') then
+ windower.create_dir(windower.addon_path..'data')
+end
+
+require 'sets'
+require 'lists'
+require 'helper_functions'
+require 'tables'
+require 'strings'
+res = require 'resources'
+config = require 'config'
+
+default_aliases = {
+ c1="Cure",
+ c2="Cure II",
+ c3="Cure III",
+ c4="Cure IV",
+ c5="Cure V",
+ c6="Cure VI",
+ r1="Raise",
+ r2="Raise II",
+ r3="Raise III",
+ pro1="Protectra",
+ pro2="Protectra II",
+ pro3="Protectra III",
+ pro4="Protectra IV",
+ pro5="Protectra V",
+ sh1="Shellra",
+ sh2="Shellra II",
+ sh3="Shellra III",
+ sh4="Shellra IV",
+ sh5="Shellra V",
+ she1="Shellra",
+ she2="Shellra II",
+ she3="Shellra III",
+ she4="Shellra IV",
+ she5="Shellra V",
+ bl="Blink",
+ ss="Stoneskin",
+ re1="Regen",
+ re2="Regen II",
+ re3="Regen III",
+ re4="Regen IV",
+ re5="Regen V",
+ holla="Teleport-Holla",
+ dem="Teleport-Dem",
+ mea="Teleport-Mea",
+ yhoat="Teleport-Yhoat",
+ altep="Teleport-Altep",
+ vahzl="Teleport-Vahzl",
+ jugner="Recall-Jugner",
+ pashh="Recall-Pashh",
+ meri="Recall-Meriph",
+ pash="Recall-Pashh",
+ meriph="Recall-Meriph",
+ ichi="Utsusemi: Ichi",
+ ni="Utsusemi: Ni",
+ utsu1="Utsusemi: Ichi",
+ utsu2="Utsusemi: Ni",
+ ds="Divine Seal",
+ es="Elemental Seal",
+ la="Light Arts",
+ da="Dark Arts",
+ pen="Penury",
+ cel="Celerity",
+ cw1="Curing Waltz",
+ cw2="Curing Waltz II",
+ cw3="Curing Waltz III",
+ cw4="Curing Waltz IV",
+ cw5="Curing Waltz V",
+ hw="Healing Waltz"
+}
+
+aliases = config.load('data\\aliases.xml',default_aliases)
+config.save(aliases)
+setmetatable(aliases,nil)
+
+
+require 'statics'
+require 'targets'
+
+-----------------------------------------------------------------------------------
+--Name: event_load()
+--Args:
+---- None
+-----------------------------------------------------------------------------------
+--Returns:
+---- None, simply a routine that runs once at the load (after the entire document
+---- is loaded and treated as a script)
+-----------------------------------------------------------------------------------
+windower.register_event('load',function()
+ lastsent = ''
+end)
+
+-----------------------------------------------------------------------------------
+--Name: event_unload()
+--Args:
+---- None
+-----------------------------------------------------------------------------------
+--Returns:
+---- None, simply a routine that runs once at unload.
+-----------------------------------------------------------------------------------
+windower.register_event('unload',function()
+ if logging then logfile:close() end
+end)
+
+
+-----------------------------------------------------------------------------------
+--Name: event_outgoing_text()
+--Args:
+---- original (string): Original command entered by the player
+---- modified (string): Modified command with changes upstream of the addon
+-----------------------------------------------------------------------------------
+--Returns:
+---- string, changed command
+-----------------------------------------------------------------------------------
+windower.register_event('outgoing text',function(original,modified)
+ local temp_org = windower.convert_auto_trans(modified)
+ if modified:sub(1,1) ~= '/' then return modified end
+ debug_chat('outgoing_text: '..modified..' '..tostring(windower.ffxi.get_mob_by_target('st')))
+ temp_org = temp_org:gsub(' <wait %d+>',''):sub(2)
+
+ if logging then
+ logfile:write('\n\n',tostring(os.clock()),'temp_org: ',temp_org,'\nModified: ',modified)
+ logfile:flush()
+ end
+
+ -- If it's the command that was just sent, blank lastsent and pass it through with only the changes applied by other addons
+ if modified == lastsent then
+ lastsent = ''
+ return modified
+ end
+
+ -- Otherwise, dump the inputs into command_logic()
+ return command_logic(temp_org,modified)
+end)
+
+-----------------------------------------------------------------------------------
+--Name: event_unhandled_command()
+--Args:
+---- table of strings: //entries split on ' '
+-----------------------------------------------------------------------------------
+--Returns:
+---- None, but can generate text output through command_logic()
+-----------------------------------------------------------------------------------
+windower.register_event('unhandled command',function(...)
+ local combined = windower.convert_auto_trans(table.concat({...},' ')) -- concat it back together...
+ local cmd,bool = command_logic(combined,combined) -- and then dump it into command_logic()
+ if cmd and bool and cmd ~= '' then
+ if cmd:sub(1,1) ~= '/' then cmd = '/'..cmd end
+ windower.send_command('@input '..cmd)
+ end
+end)
+
+
+-----------------------------------------------------------------------------------
+--Name: command_logic(original,modified)
+--Args:
+---- original (string): Full line entry from event unhandled command/outgoing text
+---- modified (string): Modified line if from event_outgoing_text, otherwise the
+---- same as original
+-----------------------------------------------------------------------------------
+--Returns:
+---- string (sometimes '') depending what the logic says to do.
+-----------------------------------------------------------------------------------
+function command_logic(original,modified)
+ local splitline = alias_replace(string.split(original,' '):filter(-''))
+ local command = splitline[1] -- Treat the first word as a command.
+ local potential_targ = '/nope//'
+ if splitline.n ~= 1 then
+ potential_targ = splitline[splitline.n]
+ end
+ local a,b,spell = string.find(original,'"(.-)"')
+
+ if unhandled_list[command] then
+ return modified,true
+ end
+
+ if spell then
+ spell = spell:lower()
+ elseif splitline.n == 3 then
+ if valid_target(potential_targ) then
+ spell = splitline[2]
+ else
+ spell = splitline[2]..' '..splitline[3]
+ end
+ end
+
+ if targ_reps[potential_targ] then
+ potential_targ = targ_reps[potential_targ]
+ end
+
+ if ignore_list[command] then -- If the command is legitimate and on the blacklist, return it unaltered.
+ lastsent = ''
+ return modified,true
+ elseif command2_list[command] and not valid_target(potential_targ,true) then
+ -- If the command is legitimate and requires target completion but not ability interpretation
+
+ if not command2_list[command].args then -- If there are not any secondary commands
+ local temptarg = valid_target(potential_targ) or target_make(command2_list[command]) -- Complete the target or make one.
+ if temptarg ~= '<me>' then -- These commands, like emotes, check, etc., don't need to default to <me>
+ lastsent = '/'..command..' '..temptarg -- Push the command and target together and send it out.
+ else
+ lastsent = '/'..command
+ end
+
+ debug_chat('258: input '..lastsent)
+ if logging then
+ logfile:write('\n\n',tostring(os.clock()),'Original: ',original,'\n(162) ',lastsent)
+ logfile:flush()
+ end
+ windower.send_command('@input '..lastsent)
+ return '',false
+ else -- If there are secondary commands (like /pcmd add <name>)
+ local tempcmd = command
+ local passback
+ local targs = command2_list[command]
+ for _,v in ipairs(splitline) do -- Iterate over the potential secondary arguments.
+ if command2_list[command]['args'] and command2_list[command]['args'][v] then
+ tempcmd = tempcmd..' '..v
+ passback = v
+ targs = command2_list[command]['args'][v]
+ break
+ end
+ end
+ local temptarg = ''
+ if targs ~= true then
+ -- Target is required
+ if command == potential_targ or passback and passback == potential_targ or potential_targ == '/nope//' then
+ -- No target is provided
+ temptarg = target_make(targs)
+ else
+ -- A target is provided, which is either corrected or (if not possible) used raw
+ temptarg = valid_target(potential_targ) or potential_targ
+ end
+ end
+ lastsent = '/'..tempcmd..' '..temptarg
+ debug_chat('292: input '..lastsent)
+ if logging then
+ logfile:write('\n\n',tostring(os.clock()),'Original: ',original,'\n(193) ',lastsent)
+ logfile:flush()
+ end
+ windower.send_command('@input '..lastsent)
+ return '',false
+ end
+ elseif command2_list[command] then
+ -- If the submitted command does not require ability interpretation and is fine already, send it out.
+ lastsent = ''
+ if logging then
+ logfile:write('\n\n',tostring(os.clock()),'Original: ',original,'\n(146) Legitimate command')
+ logfile:flush()
+ end
+ return modified,true
+ elseif command_list[command] then
+ -- If there is a valid command, then pass the text with an offset of 1 to the text interpretation function
+ return interp_text(splitline,1,modified)
+ else
+ -- If there is not a valid command, then pass the text with an offset of 0 to the text interpretation function
+ return interp_text(splitline,0,modified)
+ end
+end
+
+
+-----------------------------------------------------------------------------------
+--Name: alias_replace(tab)
+--Args:
+---- tab (table of strings): splitline
+-----------------------------------------------------------------------------------
+--Returns:
+---- tab (table of strings): with all the aliased values replaced
+-----------------------------------------------------------------------------------
+function alias_replace(tab)
+ for ind,key in ipairs(tab) do
+ if aliases[key:lower()] then
+ tab[ind] = aliases[key:lower()]
+ end
+ end
+ return tab
+end
+
+
+-----------------------------------------------------------------------------------
+--Name: interp_text()
+--Args:
+---- splitline (table of strings): entire entry, split on spaces.
+---- original (string): Full line entry from event unhandled command/outgoing text
+---- modified (string): Modified line if from event_outgoing_text, otherwise the
+---- same as original
+-----------------------------------------------------------------------------------
+--Returns:
+---- string (sometimes '') depending what the logic says to do.
+---- Sends a command if the command needs to be changed.
+-----------------------------------------------------------------------------------
+function interp_text(splitline,offset,modified)
+ local temptarg,abil
+ local no_targ_abil = strip(table.concat(splitline,' ',1+offset,splitline.n))
+
+ if validabils[no_targ_abil] then
+ abil = no_targ_abil
+ elseif splitline.n > 1 then
+ temptarg = valid_target(targ_reps[splitline[splitline.n]] or splitline[splitline.n])
+ end
+
+ if temptarg then abil = _raw.table.concat(splitline,' ',1+offset,splitline.n-1)
+ elseif not abil then abil = _raw.table.concat(splitline,' ',1+offset,splitline.n) end
+
+ local strippedabil = strip(abil) -- Slug the ability
+
+ if validabils[strippedabil] then
+ local options,nonoptions,num_opts, r_line = {},{},0
+ local player = windower.ffxi.get_player()
+ for v in validabils[strippedabil]:it() do
+ if check_usability(player,v.res,v.id) then
+ options[v.res] = v.id
+ num_opts = num_opts + 1
+ elseif v.res ~= nil then
+ nonoptions[v.res] = v.id
+ end
+ end
+ if num_opts > 0 then
+ -- If there are usable options then prioritize:
+ -- Prefix, if given -> Spells -> Job Abilities -> Weapon Skills -> Monster Skills
+ r_line = res[(offset == 1 and options[command_list[splitline[1]]] and command_list[splitline[1]]) or (options.spells and 'spells') or (options.job_abilities and 'job_abilities') or (options.weapon_skills and 'weapon_skills') or (options.monster_skills and 'monster_skills') or (options.mounts and 'mounts')][options[command_list[splitline[1]]] or options.spells or options.job_abilities or options.weapon_skills or options.monster_skills or options.mounts]
+ elseif num_opts == 0 then
+ r_line = res[(offset == 1 and nonoptions[command_list[splitline[1]]] and command_list[splitline[1]]) or (nonoptions.spells and 'spells') or (nonoptions.weapon_skills and 'weapon_skills') or (nonoptions.job_abilities and 'job_abilities') or (nonoptions.monster_skills and 'monster_skills') or (nonoptions.mounts and 'mounts')][nonoptions[command_list[splitline[1]]] or nonoptions.spells or nonoptions.weapon_skills or nonoptions.job_abilities or nonoptions.monster_skills or nonoptions.mounts]
+ end
+
+ local targets = table.reassign({},r_line.targets)
+
+ -- Handling for abilities that change potential targets.
+ if r_line.skill == 40 and r_line.cast_time == 8 and L(player.buffs):contains(409) then
+ targets.Party = true -- Pianissimo changes the target list of
+ elseif r_line.skill == 44 and r_line.en:find('Indi-') and L(player.buffs):contains(584) then
+ targets.Party = true -- Indi- spells can be cast on others when Entrust is up
+ end
+
+ local abil_name = r_line.english -- Remove spaces at the end of the ability name.
+ while abil_name:sub(-1) == ' ' do
+ abil_name = abil_name:sub(1,-2)
+ end
+
+ local out_tab = {prefix = in_game_res_commands[r_line.prefix:gsub("/","")], name = abil_name, target = temptarg or target_make(targets)}
+ if not out_tab.prefix then print('Could not find prefix',r_line.prefix) end
+ lastsent = out_tab.prefix..' "'..out_tab.name..'" '..out_tab.target
+ if logging then
+ logfile:write('\n\n',tostring(os.clock()),'Original: ',table.concat(splitline,' '),'\n(180) ',lastsent)
+ logfile:flush()
+ end
+ debug_chat('390 comp '..lastsent:sub(2):gsub('"([^ ]+)"', '%1'):lower()..' || '..table.concat(splitline,' ',1,splitline.n):gsub('"([^ ]+)"', '%1'):lower())
+ if offset == 1 and in_game_res_commands[splitline[1]] and in_game_res_commands[splitline[1]] == out_tab.prefix and
+ ('"'..out_tab.name..'" '..out_tab.target):gsub('"([^ ]+)"', '%1'):lower() == table.concat(splitline,' ',2,splitline.n):gsub('"([^ ]+)"', '%1'):lower() then
+ debug_chat('400 return '..lastsent)
+ return lastsent,true
+ else
+ debug_chat('403 input '..lastsent)
+ windower.send_command('@input '..lastsent)
+ return '',false
+ end
+ end
+ lastsent = ''
+ return modified,false
+end \ No newline at end of file